aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
authorIgor M. Liplianin <liplianin@me.by>2008-09-13 09:10:53 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2008-10-12 07:37:06 -0400
commita611d0ca006fe76d88b8dd5ac44f4468293b6760 (patch)
tree316ee524b5aa31f7dc62ed60c8cbf7b7860f39bf /drivers/media
parent83fe92e71ef736a26a6eedd0822b34ed5af077f0 (diff)
V4L/DVB (9010): Add support for SDMC DM1105 PCI chip
Add support for SDMC DM1105 PCI chip. There is a lot of cards based on it, like DvbWorld 2002 DVB-S , 2004 DVB-S2 Signed-off-by: Igor M. Liplianin <liplianin@me.by> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/dvb/Kconfig4
-rw-r--r--drivers/media/dvb/Makefile2
-rw-r--r--drivers/media/dvb/dm1105/Kconfig14
-rw-r--r--drivers/media/dvb/dm1105/Makefile3
-rw-r--r--drivers/media/dvb/dm1105/dm1105.c917
5 files changed, 939 insertions, 1 deletions
diff --git a/drivers/media/dvb/Kconfig b/drivers/media/dvb/Kconfig
index 8bc1445bd33b..5858744e70de 100644
--- a/drivers/media/dvb/Kconfig
+++ b/drivers/media/dvb/Kconfig
@@ -35,6 +35,10 @@ comment "Supported Pluto2 Adapters"
35 depends on DVB_CORE && PCI && I2C 35 depends on DVB_CORE && PCI && I2C
36source "drivers/media/dvb/pluto2/Kconfig" 36source "drivers/media/dvb/pluto2/Kconfig"
37 37
38comment "Supported SDMC DM1105 Adapters"
39 depends on DVB_CORE && PCI && I2C
40source "drivers/media/dvb/dm1105/Kconfig"
41
38comment "Supported DVB Frontends" 42comment "Supported DVB Frontends"
39 depends on DVB_CORE 43 depends on DVB_CORE
40source "drivers/media/dvb/frontends/Kconfig" 44source "drivers/media/dvb/frontends/Kconfig"
diff --git a/drivers/media/dvb/Makefile b/drivers/media/dvb/Makefile
index d6ba4d195201..ea953a03e24d 100644
--- a/drivers/media/dvb/Makefile
+++ b/drivers/media/dvb/Makefile
@@ -2,4 +2,4 @@
2# Makefile for the kernel multimedia device drivers. 2# Makefile for the kernel multimedia device drivers.
3# 3#
4 4
5obj-y := dvb-core/ frontends/ ttpci/ ttusb-dec/ ttusb-budget/ b2c2/ bt8xx/ cinergyT2/ dvb-usb/ pluto2/ siano/ 5obj-y := dvb-core/ frontends/ ttpci/ ttusb-dec/ ttusb-budget/ b2c2/ bt8xx/ cinergyT2/ dvb-usb/ pluto2/ siano/ dm1105/
diff --git a/drivers/media/dvb/dm1105/Kconfig b/drivers/media/dvb/dm1105/Kconfig
new file mode 100644
index 000000000000..fc2ca7dca6b2
--- /dev/null
+++ b/drivers/media/dvb/dm1105/Kconfig
@@ -0,0 +1,14 @@
1config DVB_DM1105
2 tristate "SDMC DM1105 based PCI cards"
3 depends on DVB_CORE && PCI && I2C
4 select DVB_PLL if !DVB_FE_CUSTOMISE
5 select DVB_STV0299 if !DVB_FE_CUSTOMISE
6 help
7 Support for cards based on the SDMC DM1105 PCI chip like
8 DvbWorld 2002
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.
diff --git a/drivers/media/dvb/dm1105/Makefile b/drivers/media/dvb/dm1105/Makefile
new file mode 100644
index 000000000000..8ac28b0546af
--- /dev/null
+++ b/drivers/media/dvb/dm1105/Makefile
@@ -0,0 +1,3 @@
1obj-$(CONFIG_DVB_DM1105) += dm1105.o
2
3EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends
diff --git a/drivers/media/dvb/dm1105/dm1105.c b/drivers/media/dvb/dm1105/dm1105.c
new file mode 100644
index 000000000000..fe8d0e58c0ea
--- /dev/null
+++ b/drivers/media/dvb/dm1105/dm1105.c
@@ -0,0 +1,917 @@
1/*
2 * dm1105.c - driver for DVB cards based on SDMC DM1105 PCI chip
3 *
4 * Copyright (C) 2008 Igor M. Liplianin <liplianin@me.by>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 *
20 */
21
22#include <linux/version.h>
23#include <linux/i2c.h>
24#include <linux/init.h>
25#include <linux/kernel.h>
26#include <linux/module.h>
27#include <linux/proc_fs.h>
28#include <linux/pci.h>
29#include <linux/dma-mapping.h>
30#include <linux/input.h>
31#include <media/ir-common.h>
32
33#include "demux.h"
34#include "dmxdev.h"
35#include "dvb_demux.h"
36#include "dvb_frontend.h"
37#include "dvb_net.h"
38#include "dvbdev.h"
39#include "dvb-pll.h"
40
41#include "stv0299.h"
42/*#include "stv0288.h"
43 *#include "si21xx.h"
44 *#include "stb6000.h"
45 *#include "cx24116.h"*/
46#include "z0194a.h"
47
48/* ----------------------------------------------- */
49/*
50 * PCI ID's
51 */
52#ifndef PCI_VENDOR_ID_TRIGEM
53#define PCI_VENDOR_ID_TRIGEM 0x109f
54#endif
55#ifndef PCI_DEVICE_ID_DM1105
56#define PCI_DEVICE_ID_DM1105 0x036f
57#endif
58#ifndef PCI_DEVICE_ID_DW2002
59#define PCI_DEVICE_ID_DW2002 0x2002
60#endif
61#ifndef PCI_DEVICE_ID_DW2004
62#define PCI_DEVICE_ID_DW2004 0x2004
63#endif
64/* ----------------------------------------------- */
65/* sdmc dm1105 registers */
66
67/* TS Control */
68#define DM1105_TSCTR 0x00
69#define DM1105_DTALENTH 0x04
70
71/* GPIO Interface */
72#define DM1105_GPIOVAL 0x08
73#define DM1105_GPIOCTR 0x0c
74
75/* PID serial number */
76#define DM1105_PIDN 0x10
77
78/* Odd-even secret key select */
79#define DM1105_CWSEL 0x14
80
81/* Host Command Interface */
82#define DM1105_HOST_CTR 0x18
83#define DM1105_HOST_AD 0x1c
84
85/* PCI Interface */
86#define DM1105_CR 0x30
87#define DM1105_RST 0x34
88#define DM1105_STADR 0x38
89#define DM1105_RLEN 0x3c
90#define DM1105_WRP 0x40
91#define DM1105_INTCNT 0x44
92#define DM1105_INTMAK 0x48
93#define DM1105_INTSTS 0x4c
94
95/* CW Value */
96#define DM1105_ODD 0x50
97#define DM1105_EVEN 0x58
98
99/* PID Value */
100#define DM1105_PID 0x60
101
102/* IR Control */
103#define DM1105_IRCTR 0x64
104#define DM1105_IRMODE 0x68
105#define DM1105_SYSTEMCODE 0x6c
106#define DM1105_IRCODE 0x70
107
108/* Unknown Values */
109#define DM1105_ENCRYPT 0x74
110#define DM1105_VER 0x7c
111
112/* I2C Interface */
113#define DM1105_I2CCTR 0x80
114#define DM1105_I2CSTS 0x81
115#define DM1105_I2CDAT 0x82
116#define DM1105_I2C_RA 0x83
117/* ----------------------------------------------- */
118/* Interrupt Mask Bits */
119
120#define INTMAK_TSIRQM 0x01
121#define INTMAK_HIRQM 0x04
122#define INTMAK_IRM 0x08
123#define INTMAK_ALLMASK (INTMAK_TSIRQM | \
124 INTMAK_HIRQM | \
125 INTMAK_IRM)
126#define INTMAK_NONEMASK 0x00
127
128/* Interrupt Status Bits */
129#define INTSTS_TSIRQ 0x01
130#define INTSTS_HIRQ 0x04
131#define INTSTS_IR 0x08
132
133/* IR Control Bits */
134#define DM1105_IR_EN 0x01
135#define DM1105_SYS_CHK 0x02
136#define DM1105_REP_FLG 0x08
137
138/* EEPROM addr */
139#define IIC_24C01_addr 0xa0
140/* Max board count */
141#define DM1105_MAX 0x04
142
143#define DRIVER_NAME "dm1105"
144
145#define DM1105_DMA_PACKETS 47
146#define DM1105_DMA_PACKET_LENGTH (128*4)
147#define DM1105_DMA_BYTES (128 * 4 * DM1105_DMA_PACKETS)
148
149/* GPIO's for LNB power control */
150#define DM1105_LNB_MASK 0x00000000
151#define DM1105_LNB_13V 0x00010100
152#define DM1105_LNB_18V 0x00000100
153
154static int ir_debug;
155module_param(ir_debug, int, 0644);
156MODULE_PARM_DESC(ir_debug, "enable debugging information for IR decoding");
157
158DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
159
160static u16 ir_codes_dm1105_nec[128] = {
161 [0x0a] = KEY_Q, /*power*/
162 [0x0c] = KEY_M, /*mute*/
163 [0x11] = KEY_1,
164 [0x12] = KEY_2,
165 [0x13] = KEY_3,
166 [0x14] = KEY_4,
167 [0x15] = KEY_5,
168 [0x16] = KEY_6,
169 [0x17] = KEY_7,
170 [0x18] = KEY_8,
171 [0x19] = KEY_9,
172 [0x10] = KEY_0,
173 [0x1c] = KEY_PAGEUP, /*ch+*/
174 [0x0f] = KEY_PAGEDOWN, /*ch-*/
175 [0x1a] = KEY_O, /*vol+*/
176 [0x0e] = KEY_Z, /*vol-*/
177 [0x04] = KEY_R, /*rec*/
178 [0x09] = KEY_D, /*fav*/
179 [0x08] = KEY_BACKSPACE, /*rewind*/
180 [0x07] = KEY_A, /*fast*/
181 [0x0b] = KEY_P, /*pause*/
182 [0x02] = KEY_ESC, /*cancel*/
183 [0x03] = KEY_G, /*tab*/
184 [0x00] = KEY_UP, /*up*/
185 [0x1f] = KEY_ENTER, /*ok*/
186 [0x01] = KEY_DOWN, /*down*/
187 [0x05] = KEY_C, /*cap*/
188 [0x06] = KEY_S, /*stop*/
189 [0x40] = KEY_F, /*full*/
190 [0x1e] = KEY_W, /*tvmode*/
191 [0x1b] = KEY_B, /*recall*/
192};
193
194/* infrared remote control */
195struct infrared {
196 u16 key_map[128];
197 struct input_dev *input_dev;
198 char input_phys[32];
199 struct tasklet_struct ir_tasklet;
200 u32 ir_command;
201};
202
203struct dm1105dvb {
204 /* pci */
205 struct pci_dev *pdev;
206 u8 __iomem *io_mem;
207
208 /* ir */
209 struct infrared ir;
210
211 /* dvb */
212 struct dmx_frontend hw_frontend;
213 struct dmx_frontend mem_frontend;
214 struct dmxdev dmxdev;
215 struct dvb_adapter dvb_adapter;
216 struct dvb_demux demux;
217 struct dvb_frontend *fe;
218 struct dvb_net dvbnet;
219 unsigned int full_ts_users;
220
221 /* i2c */
222 struct i2c_adapter i2c_adap;
223
224 /* dma */
225 dma_addr_t dma_addr;
226 unsigned char *ts_buf;
227 u32 wrp;
228 u32 buffer_size;
229 unsigned int PacketErrorCount;
230 unsigned int dmarst;
231 spinlock_t lock;
232
233};
234
235#define dm_io_mem(reg) ((unsigned long)(&dm1105dvb->io_mem[reg]))
236
237static struct dm1105dvb *dm1105dvb_local;
238
239static int dm1105_i2c_xfer(struct i2c_adapter *i2c_adap,
240 struct i2c_msg *msgs, int num)
241{
242 struct dm1105dvb *dm1105dvb ;
243
244 int addr, rc, i, j, k, len, byte, data;
245 u8 status;
246
247 dm1105dvb = i2c_adap->algo_data;
248 for (i = 0; i < num; i++) {
249 outb(0x00, dm_io_mem(DM1105_I2CCTR));
250 if (msgs[i].flags & I2C_M_RD) {
251 /* read bytes */
252 addr = msgs[i].addr << 1;
253 addr |= 1;
254 outb(addr, dm_io_mem(DM1105_I2CDAT));
255 for (byte = 0; byte < msgs[i].len; byte++)
256 outb(0, dm_io_mem(DM1105_I2CDAT + byte + 1));
257
258 outb(0x81 + msgs[i].len, dm_io_mem(DM1105_I2CCTR));
259 for (j = 0; j < 55; j++) {
260 mdelay(10);
261 status = inb(dm_io_mem(DM1105_I2CSTS));
262 if ((status & 0xc0) == 0x40)
263 break;
264 }
265 if (j >= 55)
266 return -1;
267
268 for (byte = 0; byte < msgs[i].len; byte++) {
269 rc = inb(dm_io_mem(DM1105_I2CDAT + byte + 1));
270 if (rc < 0)
271 goto err;
272 msgs[i].buf[byte] = rc;
273 }
274 } else {
275 if ((msgs[i].buf[0] == 0xf7) && (msgs[i].addr == 0x55)) {
276 /* prepaired for cx24116 firmware */
277 /* Write in small blocks */
278 len = msgs[i].len - 1;
279 k = 1;
280 do {
281 outb(msgs[i].addr << 1, dm_io_mem(DM1105_I2CDAT));
282 outb(0xf7, dm_io_mem(DM1105_I2CDAT + 1));
283 for (byte = 0; byte < (len > 48 ? 48 : len); byte++) {
284 data = msgs[i].buf[k+byte];
285 outb(data, dm_io_mem(DM1105_I2CDAT + byte + 2));
286 }
287 outb(0x82 + (len > 48 ? 48 : len), dm_io_mem(DM1105_I2CCTR));
288 for (j = 0; j < 25; j++) {
289 mdelay(10);
290 status = inb(dm_io_mem(DM1105_I2CSTS));
291 if ((status & 0xc0) == 0x40)
292 break;
293 }
294
295 if (j >= 25)
296 return -1;
297
298 k += 48;
299 len -= 48;
300 } while (len > 0);
301 } else {
302 /* write bytes */
303 outb(msgs[i].addr<<1, dm_io_mem(DM1105_I2CDAT));
304 for (byte = 0; byte < msgs[i].len; byte++) {
305 data = msgs[i].buf[byte];
306 outb(data, dm_io_mem(DM1105_I2CDAT + byte + 1));
307 }
308 outb(0x81 + msgs[i].len, dm_io_mem(DM1105_I2CCTR));
309 for (j = 0; j < 25; j++) {
310 mdelay(10);
311 status = inb(dm_io_mem(DM1105_I2CSTS));
312 if ((status & 0xc0) == 0x40)
313 break;
314 }
315
316 if (j >= 25)
317 return -1;
318 }
319 }
320 }
321 return num;
322 err:
323 return rc;
324}
325
326static u32 functionality(struct i2c_adapter *adap)
327{
328 return I2C_FUNC_I2C;
329}
330
331static struct i2c_algorithm dm1105_algo = {
332 .master_xfer = dm1105_i2c_xfer,
333 .functionality = functionality,
334};
335
336static inline struct dm1105dvb *feed_to_dm1105dvb(struct dvb_demux_feed *feed)
337{
338 return container_of(feed->demux, struct dm1105dvb, demux);
339}
340
341static inline struct dm1105dvb *frontend_to_dm1105dvb(struct dvb_frontend *fe)
342{
343 return container_of(fe->dvb, struct dm1105dvb, dvb_adapter);
344}
345
346static int dm1105dvb_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
347{
348 struct dm1105dvb *dm1105dvb = frontend_to_dm1105dvb(fe);
349
350 if (voltage == SEC_VOLTAGE_18) {
351 outl(DM1105_LNB_MASK, dm_io_mem(DM1105_GPIOCTR));
352 outl(DM1105_LNB_18V, dm_io_mem(DM1105_GPIOVAL));
353 } else {
354 /*LNB ON-13V by default!*/
355 outl(DM1105_LNB_MASK, dm_io_mem(DM1105_GPIOCTR));
356 outl(DM1105_LNB_13V, dm_io_mem(DM1105_GPIOVAL));
357 }
358
359 return 0;
360}
361
362static void dm1105dvb_set_dma_addr(struct dm1105dvb *dm1105dvb)
363{
364 outl(cpu_to_le32(dm1105dvb->dma_addr), dm_io_mem(DM1105_STADR));
365}
366
367static int __devinit dm1105dvb_dma_map(struct dm1105dvb *dm1105dvb)
368{
369 dm1105dvb->ts_buf = pci_alloc_consistent(dm1105dvb->pdev, 6*DM1105_DMA_BYTES, &dm1105dvb->dma_addr);
370
371 return pci_dma_mapping_error(dm1105dvb->pdev, dm1105dvb->dma_addr);
372}
373
374static void dm1105dvb_dma_unmap(struct dm1105dvb *dm1105dvb)
375{
376 pci_free_consistent(dm1105dvb->pdev, 6*DM1105_DMA_BYTES, dm1105dvb->ts_buf, dm1105dvb->dma_addr);
377}
378
379static void __devinit dm1105dvb_enable_irqs(struct dm1105dvb *dm1105dvb)
380{
381 outb(INTMAK_ALLMASK, dm_io_mem(DM1105_INTMAK));
382 outb(1, dm_io_mem(DM1105_CR));
383}
384
385static void dm1105dvb_disable_irqs(struct dm1105dvb *dm1105dvb)
386{
387 outb(INTMAK_IRM, dm_io_mem(DM1105_INTMAK));
388 outb(0, dm_io_mem(DM1105_CR));
389}
390
391static int dm1105dvb_start_feed(struct dvb_demux_feed *f)
392{
393 struct dm1105dvb *dm1105dvb = feed_to_dm1105dvb(f);
394
395 if (dm1105dvb->full_ts_users++ == 0)
396 dm1105dvb_enable_irqs(dm1105dvb);
397
398 return 0;
399}
400
401static int dm1105dvb_stop_feed(struct dvb_demux_feed *f)
402{
403 struct dm1105dvb *dm1105dvb = feed_to_dm1105dvb(f);
404
405 if (--dm1105dvb->full_ts_users == 0)
406 dm1105dvb_disable_irqs(dm1105dvb);
407
408 return 0;
409}
410
411/* ir tasklet */
412static void dm1105_emit_key(unsigned long parm)
413{
414 struct infrared *ir = (struct infrared *) parm;
415 u32 ircom = ir->ir_command;
416 u8 data;
417 u16 keycode;
418
419 data = (ircom >> 8) & 0x7f;
420
421 input_event(ir->input_dev, EV_MSC, MSC_RAW, (0x0000f8 << 16) | data);
422 input_event(ir->input_dev, EV_MSC, MSC_SCAN, data);
423 keycode = ir->key_map[data];
424
425 if (!keycode)
426 return;
427
428 input_event(ir->input_dev, EV_KEY, keycode, 1);
429 input_sync(ir->input_dev);
430 input_event(ir->input_dev, EV_KEY, keycode, 0);
431 input_sync(ir->input_dev);
432
433}
434
435static irqreturn_t dm1105dvb_irq(int irq, void *dev_id)
436{
437 struct dm1105dvb *dm1105dvb = dev_id;
438 unsigned int piece;
439 unsigned int nbpackets;
440 u32 command;
441 u32 nextwrp;
442 u32 oldwrp;
443
444 /* Read-Write INSTS Ack's Interrupt for DM1105 chip 16.03.2008 */
445 unsigned int intsts = inb(dm_io_mem(DM1105_INTSTS));
446 outb(intsts, dm_io_mem(DM1105_INTSTS));
447
448 switch (intsts) {
449 case INTSTS_TSIRQ:
450 case (INTSTS_TSIRQ | INTSTS_IR):
451 nextwrp = inl(dm_io_mem(DM1105_WRP)) -
452 inl(dm_io_mem(DM1105_STADR)) ;
453 oldwrp = dm1105dvb->wrp;
454 spin_lock(&dm1105dvb->lock);
455 if (!((dm1105dvb->ts_buf[oldwrp] == 0x47) &&
456 (dm1105dvb->ts_buf[oldwrp + 188] == 0x47) &&
457 (dm1105dvb->ts_buf[oldwrp + 188 * 2] == 0x47))) {
458 dm1105dvb->PacketErrorCount++;
459 /* bad packet found */
460 if ((dm1105dvb->PacketErrorCount >= 2) &&
461 (dm1105dvb->dmarst == 0)) {
462 outb(1, dm_io_mem(DM1105_RST));
463 dm1105dvb->wrp = 0;
464 dm1105dvb->PacketErrorCount = 0;
465 dm1105dvb->dmarst = 0;
466 spin_unlock(&dm1105dvb->lock);
467 return IRQ_HANDLED;
468 }
469 }
470 if (nextwrp < oldwrp) {
471 piece = dm1105dvb->buffer_size - oldwrp;
472 memcpy(dm1105dvb->ts_buf + dm1105dvb->buffer_size, dm1105dvb->ts_buf, nextwrp);
473 nbpackets = (piece + nextwrp)/188;
474 } else {
475 nbpackets = (nextwrp - oldwrp)/188;
476 }
477 dvb_dmx_swfilter_packets(&dm1105dvb->demux, &dm1105dvb->ts_buf[oldwrp], nbpackets);
478 dm1105dvb->wrp = nextwrp;
479 spin_unlock(&dm1105dvb->lock);
480 break;
481 case INTSTS_IR:
482 command = inl(dm_io_mem(DM1105_IRCODE));
483 if (ir_debug)
484 printk("dm1105: received byte 0x%04x\n", command);
485
486 dm1105dvb->ir.ir_command = command;
487 tasklet_schedule(&dm1105dvb->ir.ir_tasklet);
488 break;
489 }
490 return IRQ_HANDLED;
491
492
493}
494
495/* register with input layer */
496static void input_register_keys(struct infrared *ir)
497{
498 int i;
499
500 memset(ir->input_dev->keybit, 0, sizeof(ir->input_dev->keybit));
501
502 for (i = 0; i < ARRAY_SIZE(ir->key_map); i++)
503 set_bit(ir->key_map[i], ir->input_dev->keybit);
504
505 ir->input_dev->keycode = ir->key_map;
506 ir->input_dev->keycodesize = sizeof(ir->key_map[0]);
507 ir->input_dev->keycodemax = ARRAY_SIZE(ir->key_map);
508}
509
510int __devinit dm1105_ir_init(struct dm1105dvb *dm1105)
511{
512 struct input_dev *input_dev;
513 int err;
514
515 dm1105dvb_local = dm1105;
516
517 input_dev = input_allocate_device();
518 if (!input_dev)
519 return -ENOMEM;
520
521 dm1105->ir.input_dev = input_dev;
522 snprintf(dm1105->ir.input_phys, sizeof(dm1105->ir.input_phys),
523 "pci-%s/ir0", pci_name(dm1105->pdev));
524
525 input_dev->evbit[0] = BIT(EV_KEY);
526 input_dev->name = "DVB on-card IR receiver";
527
528 input_dev->phys = dm1105->ir.input_phys;
529 input_dev->id.bustype = BUS_PCI;
530 input_dev->id.version = 2;
531 if (dm1105->pdev->subsystem_vendor) {
532 input_dev->id.vendor = dm1105->pdev->subsystem_vendor;
533 input_dev->id.product = dm1105->pdev->subsystem_device;
534 } else {
535 input_dev->id.vendor = dm1105->pdev->vendor;
536 input_dev->id.product = dm1105->pdev->device;
537 }
538 input_dev->dev.parent = &dm1105->pdev->dev;
539 /* initial keymap */
540 memcpy(dm1105->ir.key_map, ir_codes_dm1105_nec, sizeof dm1105->ir.key_map);
541 input_register_keys(&dm1105->ir);
542 err = input_register_device(input_dev);
543 if (err) {
544 input_free_device(input_dev);
545 return err;
546 }
547
548 tasklet_init(&dm1105->ir.ir_tasklet, dm1105_emit_key, (unsigned long) &dm1105->ir);
549
550 return 0;
551}
552
553
554void __devexit dm1105_ir_exit(struct dm1105dvb *dm1105)
555{
556 tasklet_kill(&dm1105->ir.ir_tasklet);
557 input_unregister_device(dm1105->ir.input_dev);
558
559}
560
561static int __devinit dm1105dvb_hw_init(struct dm1105dvb *dm1105dvb)
562{
563 dm1105dvb_disable_irqs(dm1105dvb);
564
565 outb(0, dm_io_mem(DM1105_HOST_CTR));
566
567 /*DATALEN 188,*/
568 outb(188, dm_io_mem(DM1105_DTALENTH));
569 /*TS_STRT TS_VALP MSBFIRST TS_MODE ALPAS TSPES*/
570 outw(0xc10a, dm_io_mem(DM1105_TSCTR));
571
572 /* map DMA and set address */
573 dm1105dvb_dma_map(dm1105dvb);
574 dm1105dvb_set_dma_addr(dm1105dvb);
575 /* big buffer */
576 outl(5*DM1105_DMA_BYTES, dm_io_mem(DM1105_RLEN));
577 outb(47, dm_io_mem(DM1105_INTCNT));
578
579 /* IR NEC mode enable */
580 outb((DM1105_IR_EN | DM1105_SYS_CHK), dm_io_mem(DM1105_IRCTR));
581 outb(0, dm_io_mem(DM1105_IRMODE));
582 outw(0, dm_io_mem(DM1105_SYSTEMCODE));
583
584 return 0;
585}
586
587static void dm1105dvb_hw_exit(struct dm1105dvb *dm1105dvb)
588{
589 dm1105dvb_disable_irqs(dm1105dvb);
590
591 /* IR disable */
592 outb(0, dm_io_mem(DM1105_IRCTR));
593 outb(INTMAK_NONEMASK, dm_io_mem(DM1105_INTMAK));
594
595 dm1105dvb_dma_unmap(dm1105dvb);
596}
597#if 0
598static struct stv0288_config earda_config = {
599 .demod_address = 0x68,
600 .min_delay_ms = 100,
601};
602
603static struct si21xx_config serit_config = {
604 .demod_address = 0x68,
605 .min_delay_ms = 100,
606
607};
608
609static struct cx24116_config serit_sp2633_config = {
610 .demod_address = 0x55,
611};
612#endif /* keep */
613
614static int __devinit frontend_init(struct dm1105dvb *dm1105dvb)
615{
616 int ret;
617
618 switch (dm1105dvb->pdev->subsystem_device) {
619 case PCI_DEVICE_ID_DW2002:
620 dm1105dvb->fe = dvb_attach(
621 stv0299_attach, &sharp_z0194a_config,
622 &dm1105dvb->i2c_adap);
623
624 if (dm1105dvb->fe) {
625 dm1105dvb->fe->ops.set_voltage =
626 dm1105dvb_set_voltage;
627 dvb_attach(dvb_pll_attach, dm1105dvb->fe, 0x60,
628 &dm1105dvb->i2c_adap, DVB_PLL_OPERA1);
629 }
630#if 0
631 if (!dm1105dvb->fe) {
632 dm1105dvb->fe = dvb_attach(
633 stv0288_attach, &earda_config,
634 &dm1105dvb->i2c_adap);
635 if (dm1105dvb->fe) {
636 dm1105dvb->fe->ops.set_voltage =
637 dm1105dvb_set_voltage;
638 dvb_attach(stb6000_attach, dm1105dvb->fe, 0x61,
639 &dm1105dvb->i2c_adap);
640 }
641 }
642
643 if (!dm1105dvb->fe) {
644 dm1105dvb->fe = dvb_attach(
645 si21xx_attach, &serit_config,
646 &dm1105dvb->i2c_adap);
647 if (dm1105dvb->fe)
648 dm1105dvb->fe->ops.set_voltage =
649 dm1105dvb_set_voltage;
650 }
651#endif /* keep */
652 break;
653 case PCI_DEVICE_ID_DW2004:
654#if 0
655 dm1105dvb->fe = dvb_attach(
656 cx24116_attach, &serit_sp2633_config,
657 &dm1105dvb->i2c_adap);
658 if (dm1105dvb->fe)
659 dm1105dvb->fe->ops.set_voltage = dm1105dvb_set_voltage;
660#else /* keep */
661 dev_err(&dm1105dvb->pdev->dev, "needs cx24116 module\n");
662#endif /* keep */
663 break;
664 }
665
666 if (!dm1105dvb->fe) {
667 dev_err(&dm1105dvb->pdev->dev, "could not attach frontend\n");
668 return -ENODEV;
669 }
670
671 ret = dvb_register_frontend(&dm1105dvb->dvb_adapter, dm1105dvb->fe);
672 if (ret < 0) {
673 if (dm1105dvb->fe->ops.release)
674 dm1105dvb->fe->ops.release(dm1105dvb->fe);
675 dm1105dvb->fe = NULL;
676 return ret;
677 }
678
679 return 0;
680}
681
682static void __devinit dm1105dvb_read_mac(struct dm1105dvb *dm1105dvb, u8 *mac)
683{
684 static u8 command[1] = { 0x28 };
685
686 struct i2c_msg msg[] = {
687 { .addr = IIC_24C01_addr >> 1, .flags = 0,
688 .buf = command, .len = 1 },
689 { .addr = IIC_24C01_addr >> 1, .flags = I2C_M_RD,
690 .buf = mac, .len = 6 },
691 };
692
693 dm1105_i2c_xfer(&dm1105dvb->i2c_adap, msg , 2);
694 dev_info(&dm1105dvb->pdev->dev, "MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
695 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
696}
697
698static int __devinit dm1105_probe(struct pci_dev *pdev,
699 const struct pci_device_id *ent)
700{
701 struct dm1105dvb *dm1105dvb;
702 struct dvb_adapter *dvb_adapter;
703 struct dvb_demux *dvbdemux;
704 struct dmx_demux *dmx;
705 int ret = -ENOMEM;
706
707 dm1105dvb = kzalloc(sizeof(struct dm1105dvb), GFP_KERNEL);
708 if (!dm1105dvb)
709 goto out;
710
711 dm1105dvb->pdev = pdev;
712 dm1105dvb->buffer_size = 5 * DM1105_DMA_BYTES;
713 dm1105dvb->PacketErrorCount = 0;
714 dm1105dvb->dmarst = 0;
715
716 ret = pci_enable_device(pdev);
717 if (ret < 0)
718 goto err_kfree;
719
720 ret = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
721 if (ret < 0)
722 goto err_pci_disable_device;
723
724 pci_set_master(pdev);
725
726 ret = pci_request_regions(pdev, DRIVER_NAME);
727 if (ret < 0)
728 goto err_pci_disable_device;
729
730 dm1105dvb->io_mem = pci_iomap(pdev, 0, pci_resource_len(pdev, 0));
731 if (!dm1105dvb->io_mem) {
732 ret = -EIO;
733 goto err_pci_release_regions;
734 }
735
736 spin_lock_init(&dm1105dvb->lock);
737 pci_set_drvdata(pdev, dm1105dvb);
738
739 ret = request_irq(pdev->irq, dm1105dvb_irq, IRQF_SHARED, DRIVER_NAME, dm1105dvb);
740 if (ret < 0)
741 goto err_pci_iounmap;
742
743 ret = dm1105dvb_hw_init(dm1105dvb);
744 if (ret < 0)
745 goto err_free_irq;
746
747 /* i2c */
748 i2c_set_adapdata(&dm1105dvb->i2c_adap, dm1105dvb);
749 strcpy(dm1105dvb->i2c_adap.name, DRIVER_NAME);
750 dm1105dvb->i2c_adap.owner = THIS_MODULE;
751 dm1105dvb->i2c_adap.class = I2C_CLASS_TV_DIGITAL;
752 dm1105dvb->i2c_adap.dev.parent = &pdev->dev;
753 dm1105dvb->i2c_adap.algo = &dm1105_algo;
754 dm1105dvb->i2c_adap.algo_data = dm1105dvb;
755 ret = i2c_add_adapter(&dm1105dvb->i2c_adap);
756
757 if (ret < 0)
758 goto err_dm1105dvb_hw_exit;
759
760 /* dvb */
761 ret = dvb_register_adapter(&dm1105dvb->dvb_adapter, DRIVER_NAME,
762 THIS_MODULE, &pdev->dev, adapter_nr);
763 if (ret < 0)
764 goto err_i2c_del_adapter;
765
766 dvb_adapter = &dm1105dvb->dvb_adapter;
767
768 dm1105dvb_read_mac(dm1105dvb, dvb_adapter->proposed_mac);
769
770 dvbdemux = &dm1105dvb->demux;
771 dvbdemux->filternum = 256;
772 dvbdemux->feednum = 256;
773 dvbdemux->start_feed = dm1105dvb_start_feed;
774 dvbdemux->stop_feed = dm1105dvb_stop_feed;
775 dvbdemux->dmx.capabilities = (DMX_TS_FILTERING |
776 DMX_SECTION_FILTERING | DMX_MEMORY_BASED_FILTERING);
777 ret = dvb_dmx_init(dvbdemux);
778 if (ret < 0)
779 goto err_dvb_unregister_adapter;
780
781 dmx = &dvbdemux->dmx;
782 dm1105dvb->dmxdev.filternum = 256;
783 dm1105dvb->dmxdev.demux = dmx;
784 dm1105dvb->dmxdev.capabilities = 0;
785
786 ret = dvb_dmxdev_init(&dm1105dvb->dmxdev, dvb_adapter);
787 if (ret < 0)
788 goto err_dvb_dmx_release;
789
790 dm1105dvb->hw_frontend.source = DMX_FRONTEND_0;
791
792 ret = dmx->add_frontend(dmx, &dm1105dvb->hw_frontend);
793 if (ret < 0)
794 goto err_dvb_dmxdev_release;
795
796 dm1105dvb->mem_frontend.source = DMX_MEMORY_FE;
797
798 ret = dmx->add_frontend(dmx, &dm1105dvb->mem_frontend);
799 if (ret < 0)
800 goto err_remove_hw_frontend;
801
802 ret = dmx->connect_frontend(dmx, &dm1105dvb->hw_frontend);
803 if (ret < 0)
804 goto err_remove_mem_frontend;
805
806 ret = frontend_init(dm1105dvb);
807 if (ret < 0)
808 goto err_disconnect_frontend;
809
810 dvb_net_init(dvb_adapter, &dm1105dvb->dvbnet, dmx);
811 dm1105_ir_init(dm1105dvb);
812out:
813 return ret;
814
815err_disconnect_frontend:
816 dmx->disconnect_frontend(dmx);
817err_remove_mem_frontend:
818 dmx->remove_frontend(dmx, &dm1105dvb->mem_frontend);
819err_remove_hw_frontend:
820 dmx->remove_frontend(dmx, &dm1105dvb->hw_frontend);
821err_dvb_dmxdev_release:
822 dvb_dmxdev_release(&dm1105dvb->dmxdev);
823err_dvb_dmx_release:
824 dvb_dmx_release(dvbdemux);
825err_dvb_unregister_adapter:
826 dvb_unregister_adapter(dvb_adapter);
827err_i2c_del_adapter:
828 i2c_del_adapter(&dm1105dvb->i2c_adap);
829err_dm1105dvb_hw_exit:
830 dm1105dvb_hw_exit(dm1105dvb);
831err_free_irq:
832 free_irq(pdev->irq, dm1105dvb);
833err_pci_iounmap:
834 pci_iounmap(pdev, dm1105dvb->io_mem);
835err_pci_release_regions:
836 pci_release_regions(pdev);
837err_pci_disable_device:
838 pci_disable_device(pdev);
839err_kfree:
840 pci_set_drvdata(pdev, NULL);
841 kfree(dm1105dvb);
842 goto out;
843}
844
845static void __devexit dm1105_remove(struct pci_dev *pdev)
846{
847 struct dm1105dvb *dm1105dvb = pci_get_drvdata(pdev);
848 struct dvb_adapter *dvb_adapter = &dm1105dvb->dvb_adapter;
849 struct dvb_demux *dvbdemux = &dm1105dvb->demux;
850 struct dmx_demux *dmx = &dvbdemux->dmx;
851
852 dm1105_ir_exit(dm1105dvb);
853 dmx->close(dmx);
854 dvb_net_release(&dm1105dvb->dvbnet);
855 if (dm1105dvb->fe)
856 dvb_unregister_frontend(dm1105dvb->fe);
857
858 dmx->disconnect_frontend(dmx);
859 dmx->remove_frontend(dmx, &dm1105dvb->mem_frontend);
860 dmx->remove_frontend(dmx, &dm1105dvb->hw_frontend);
861 dvb_dmxdev_release(&dm1105dvb->dmxdev);
862 dvb_dmx_release(dvbdemux);
863 dvb_unregister_adapter(dvb_adapter);
864 if (&dm1105dvb->i2c_adap)
865 i2c_del_adapter(&dm1105dvb->i2c_adap);
866
867 dm1105dvb_hw_exit(dm1105dvb);
868 synchronize_irq(pdev->irq);
869 free_irq(pdev->irq, dm1105dvb);
870 pci_iounmap(pdev, dm1105dvb->io_mem);
871 pci_release_regions(pdev);
872 pci_disable_device(pdev);
873 pci_set_drvdata(pdev, NULL);
874 kfree(dm1105dvb);
875}
876
877static struct pci_device_id dm1105_id_table[] __devinitdata = {
878 {
879 .vendor = PCI_VENDOR_ID_TRIGEM,
880 .device = PCI_DEVICE_ID_DM1105,
881 .subvendor = PCI_ANY_ID,
882 .subdevice = PCI_DEVICE_ID_DW2002,
883 }, {
884 .vendor = PCI_VENDOR_ID_TRIGEM,
885 .device = PCI_DEVICE_ID_DM1105,
886 .subvendor = PCI_ANY_ID,
887 .subdevice = PCI_DEVICE_ID_DW2004,
888 }, {
889 /* empty */
890 },
891};
892
893MODULE_DEVICE_TABLE(pci, dm1105_id_table);
894
895static struct pci_driver dm1105_driver = {
896 .name = DRIVER_NAME,
897 .id_table = dm1105_id_table,
898 .probe = dm1105_probe,
899 .remove = __devexit_p(dm1105_remove),
900};
901
902static int __init dm1105_init(void)
903{
904 return pci_register_driver(&dm1105_driver);
905}
906
907static void __exit dm1105_exit(void)
908{
909 pci_unregister_driver(&dm1105_driver);
910}
911
912module_init(dm1105_init);
913module_exit(dm1105_exit);
914
915MODULE_AUTHOR("Igor M. Liplianin <liplianin@me.by>");
916MODULE_DESCRIPTION("SDMC DM1105 DVB driver");
917MODULE_LICENSE("GPL");