blob: d982a50cdd7fcccbbd67a302aedf65dd8be51bfd [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * driver for the SAA7146 based AV110 cards (like the Fujitsu-Siemens DVB)
3 * av7110.c: initialization and demux stuff
4 *
5 * Copyright (C) 1999-2002 Ralph Metzler
6 * & Marcus Metzler for convergence integrated media GmbH
7 *
8 * originally based on code by:
9 * Copyright (C) 1998,1999 Christian Theiss <mistert@rz.fh-augsburg.de>
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
15 *
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
27 *
28 *
29 * the project's page is at http://www.linuxtv.org/dvb/
30 */
31
32
33#include <linux/config.h>
34#include <linux/module.h>
35#include <linux/kmod.h>
36#include <linux/delay.h>
37#include <linux/fs.h>
38#include <linux/timer.h>
39#include <linux/poll.h>
40#include <linux/byteorder/swabb.h>
41#include <linux/smp_lock.h>
42
43#include <linux/kernel.h>
44#include <linux/moduleparam.h>
45#include <linux/sched.h>
46#include <linux/types.h>
47#include <linux/fcntl.h>
48#include <linux/interrupt.h>
49#include <linux/string.h>
50#include <linux/pci.h>
51#include <linux/vmalloc.h>
52#include <linux/firmware.h>
53#include <linux/crc32.h>
54#include <linux/i2c.h>
55
56#include <asm/system.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070057
58#include <linux/dvb/frontend.h>
59
60#include "dvb_frontend.h"
61
62#include "ttpci-eeprom.h"
63#include "av7110.h"
64#include "av7110_hw.h"
65#include "av7110_av.h"
66#include "av7110_ca.h"
67#include "av7110_ipack.h"
68
69#define TS_WIDTH 376
70#define TS_HEIGHT 512
71#define TS_BUFLEN (TS_WIDTH*TS_HEIGHT)
72#define TS_MAX_PACKETS (TS_BUFLEN/TS_SIZE)
73
74
75int av7110_debug;
76
77static int vidmode = CVBS_RGB_OUT;
78static int pids_off;
79static int adac = DVB_ADAC_TI;
80static int hw_sections;
81static int rgb_on;
82static int volume = 255;
Mauro Carvalho Chehaba5ed4252006-01-13 14:10:19 -020083static int budgetpatch;
Linus Torvalds1da177e2005-04-16 15:20:36 -070084
85module_param_named(debug, av7110_debug, int, 0644);
86MODULE_PARM_DESC(debug, "debug level (bitmask, default 0)");
87module_param(vidmode, int, 0444);
88MODULE_PARM_DESC(vidmode,"analog video out: 0 off, 1 CVBS+RGB (default), 2 CVBS+YC, 3 YC");
89module_param(pids_off, int, 0444);
90MODULE_PARM_DESC(pids_off,"clear video/audio/PCR PID filters when demux is closed");
91module_param(adac, int, 0444);
92MODULE_PARM_DESC(adac,"audio DAC type: 0 TI, 1 CRYSTAL, 2 MSP (use if autodetection fails)");
93module_param(hw_sections, int, 0444);
94MODULE_PARM_DESC(hw_sections, "0 use software section filter, 1 use hardware");
95module_param(rgb_on, int, 0444);
96MODULE_PARM_DESC(rgb_on, "For Siemens DVB-C cards only: Enable RGB control"
97 " signal on SCART pin 16 to switch SCART video mode from CVBS to RGB");
98module_param(volume, int, 0444);
99MODULE_PARM_DESC(volume, "initial volume: default 255 (range 0-255)");
100module_param(budgetpatch, int, 0444);
101MODULE_PARM_DESC(budgetpatch, "use budget-patch hardware modification: default 0 (0 no, 1 autodetect, 2 always)");
102
103static void restart_feeds(struct av7110 *av7110);
104
Mauro Carvalho Chehaba5ed4252006-01-13 14:10:19 -0200105static int av7110_num;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700106
107#define FE_FUNC_OVERRIDE(fe_func, av7110_copy, av7110_func) \
108{\
109 if (fe_func != NULL) { \
110 av7110_copy = fe_func; \
111 fe_func = av7110_func; \
112 } \
113}
114
115
116static void init_av7110_av(struct av7110 *av7110)
117{
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700118 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700119 struct saa7146_dev *dev = av7110->dev;
120
121 /* set internal volume control to maximum */
122 av7110->adac_type = DVB_ADAC_TI;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700123 ret = av7110_set_volume(av7110, av7110->mixer.volume_left, av7110->mixer.volume_right);
Johannes Stezenbach7a2fa902005-07-07 17:58:01 -0700124 if (ret < 0)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700125 printk("dvb-ttpci:cannot set internal volume to maximum:%d\n",ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700127 ret = av7710_set_video_mode(av7110, vidmode);
Johannes Stezenbach7a2fa902005-07-07 17:58:01 -0700128 if (ret < 0)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700129 printk("dvb-ttpci:cannot set video mode:%d\n",ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700130
131 /* handle different card types */
132 /* remaining inits according to card and frontend type */
133 av7110->analog_tuner_flags = 0;
134 av7110->current_input = 0;
Marco Schluessler1c13b952006-01-09 15:25:06 -0200135 if (dev->pci->subsystem_vendor == 0x13c2 && dev->pci->subsystem_device == 0x000a) {
136 printk("dvb-ttpci: MSP3415 audio DAC @ card %d\n",
137 av7110->dvb_adapter.num);
138 av7110->adac_type = DVB_ADAC_MSP34x5;
139 av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, ADSwitch, 1, 0); // SPDIF on
140 }
141 else if (i2c_writereg(av7110, 0x20, 0x00, 0x00) == 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142 printk ("dvb-ttpci: Crystal audio DAC @ card %d detected\n",
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -0700143 av7110->dvb_adapter.num);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700144 av7110->adac_type = DVB_ADAC_CRYSTAL;
145 i2c_writereg(av7110, 0x20, 0x01, 0xd2);
146 i2c_writereg(av7110, 0x20, 0x02, 0x49);
147 i2c_writereg(av7110, 0x20, 0x03, 0x00);
148 i2c_writereg(av7110, 0x20, 0x04, 0x00);
149
150 /**
151 * some special handling for the Siemens DVB-C cards...
152 */
153 } else if (0 == av7110_init_analog_module(av7110)) {
154 /* done. */
155 }
156 else if (dev->pci->subsystem_vendor == 0x110a) {
157 printk("dvb-ttpci: DVB-C w/o analog module @ card %d detected\n",
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -0700158 av7110->dvb_adapter.num);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700159 av7110->adac_type = DVB_ADAC_NONE;
160 }
161 else {
162 av7110->adac_type = adac;
163 printk("dvb-ttpci: adac type set to %d @ card %d\n",
Marco Schluessler1c13b952006-01-09 15:25:06 -0200164 av7110->adac_type, av7110->dvb_adapter.num);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700165 }
166
Marco Schluessler1c13b952006-01-09 15:25:06 -0200167 if (av7110->adac_type == DVB_ADAC_NONE || av7110->adac_type == DVB_ADAC_MSP34x0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700168 // switch DVB SCART on
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700169 ret = av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, MainSwitch, 1, 0);
Johannes Stezenbach7a2fa902005-07-07 17:58:01 -0700170 if (ret < 0)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700171 printk("dvb-ttpci:cannot switch on SCART(Main):%d\n",ret);
172 ret = av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, ADSwitch, 1, 1);
Johannes Stezenbach7a2fa902005-07-07 17:58:01 -0700173 if (ret < 0)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700174 printk("dvb-ttpci:cannot switch on SCART(AD):%d\n",ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700175 if (rgb_on &&
Karl Herz6af4ee12005-09-09 13:03:13 -0700176 ((av7110->dev->pci->subsystem_vendor == 0x110a) ||
177 (av7110->dev->pci->subsystem_vendor == 0x13c2)) &&
178 (av7110->dev->pci->subsystem_device == 0x0000)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700179 saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); // RGB on, SCART pin 16
180 //saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); // SCARTpin 8
181 }
182 }
183
Oliver Endriss60edb132005-12-19 08:54:11 -0200184 if (dev->pci->subsystem_vendor == 0x13c2 && dev->pci->subsystem_device == 0x000e)
185 av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, SpdifSwitch, 1, 0); // SPDIF on
186
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700187 ret = av7110_set_volume(av7110, av7110->mixer.volume_left, av7110->mixer.volume_right);
Johannes Stezenbach7a2fa902005-07-07 17:58:01 -0700188 if (ret < 0)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700189 printk("dvb-ttpci:cannot set volume :%d\n",ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700190}
191
192static void recover_arm(struct av7110 *av7110)
193{
194 dprintk(4, "%p\n",av7110);
195
196 av7110_bootarm(av7110);
197 msleep(100);
Oliver Endriss66190a22006-01-09 15:32:42 -0200198
199 init_av7110_av(av7110);
200
201 /* card-specific recovery */
202 if (av7110->recover)
203 av7110->recover(av7110);
204
Linus Torvalds1da177e2005-04-16 15:20:36 -0700205 restart_feeds(av7110);
206 av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, SetIR, 1, av7110->ir_config);
207}
208
Linus Torvalds1da177e2005-04-16 15:20:36 -0700209static void av7110_arm_sync(struct av7110 *av7110)
210{
211 av7110->arm_rmmod = 1;
212 wake_up_interruptible(&av7110->arm_wait);
213
214 while (av7110->arm_thread)
215 msleep(1);
216}
217
218static int arm_thread(void *data)
219{
220 struct av7110 *av7110 = data;
221 u16 newloops = 0;
222 int timeout;
223
224 dprintk(4, "%p\n",av7110);
225
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -0800226 lock_kernel();
227 daemonize("arm_mon");
228 sigfillset(&current->blocked);
229 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700230
231 av7110->arm_thread = current;
232
233 for (;;) {
234 timeout = wait_event_interruptible_timeout(av7110->arm_wait,
235 av7110->arm_rmmod, 5 * HZ);
236 if (-ERESTARTSYS == timeout || av7110->arm_rmmod) {
237 /* got signal or told to quit*/
238 break;
239 }
240
241 if (!av7110->arm_ready)
242 continue;
243
Ingo Molnar3593cab2006-02-07 06:49:14 -0200244 if (mutex_lock_interruptible(&av7110->dcomlock))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700245 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700246 newloops = rdebi(av7110, DEBINOSWAP, STATUS_LOOPS, 0, 2);
Ingo Molnar3593cab2006-02-07 06:49:14 -0200247 mutex_unlock(&av7110->dcomlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700248
Oliver Endriss66190a22006-01-09 15:32:42 -0200249 if (newloops == av7110->arm_loops || av7110->arm_errors > 3) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700250 printk(KERN_ERR "dvb-ttpci: ARM crashed @ card %d\n",
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -0700251 av7110->dvb_adapter.num);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252
Oliver Endriss66190a22006-01-09 15:32:42 -0200253 recover_arm(av7110);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254
Ingo Molnar3593cab2006-02-07 06:49:14 -0200255 if (mutex_lock_interruptible(&av7110->dcomlock))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700256 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257 newloops = rdebi(av7110, DEBINOSWAP, STATUS_LOOPS, 0, 2) - 1;
Ingo Molnar3593cab2006-02-07 06:49:14 -0200258 mutex_unlock(&av7110->dcomlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700259 }
260 av7110->arm_loops = newloops;
Oliver Endriss66190a22006-01-09 15:32:42 -0200261 av7110->arm_errors = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700262 }
263
264 av7110->arm_thread = NULL;
265 return 0;
266}
267
268
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269/****************************************************************************
270 * IRQ handling
271 ****************************************************************************/
272
273static int DvbDmxFilterCallback(u8 *buffer1, size_t buffer1_len,
274 u8 *buffer2, size_t buffer2_len,
275 struct dvb_demux_filter *dvbdmxfilter,
276 enum dmx_success success,
277 struct av7110 *av7110)
278{
279 if (!dvbdmxfilter->feed->demux->dmx.frontend)
280 return 0;
281 if (dvbdmxfilter->feed->demux->dmx.frontend->source == DMX_MEMORY_FE)
282 return 0;
283
284 switch (dvbdmxfilter->type) {
285 case DMX_TYPE_SEC:
286 if ((((buffer1[1] << 8) | buffer1[2]) & 0xfff) + 3 != buffer1_len)
287 return 0;
288 if (dvbdmxfilter->doneq) {
289 struct dmx_section_filter *filter = &dvbdmxfilter->filter;
290 int i;
291 u8 xor, neq = 0;
292
293 for (i = 0; i < DVB_DEMUX_MASK_MAX; i++) {
294 xor = filter->filter_value[i] ^ buffer1[i];
295 neq |= dvbdmxfilter->maskandnotmode[i] & xor;
296 }
297 if (!neq)
298 return 0;
299 }
300 return dvbdmxfilter->feed->cb.sec(buffer1, buffer1_len,
301 buffer2, buffer2_len,
302 &dvbdmxfilter->filter,
303 DMX_OK);
304 case DMX_TYPE_TS:
305 if (!(dvbdmxfilter->feed->ts_type & TS_PACKET))
306 return 0;
307 if (dvbdmxfilter->feed->ts_type & TS_PAYLOAD_ONLY)
308 return dvbdmxfilter->feed->cb.ts(buffer1, buffer1_len,
309 buffer2, buffer2_len,
310 &dvbdmxfilter->feed->feed.ts,
311 DMX_OK);
312 else
313 av7110_p2t_write(buffer1, buffer1_len,
314 dvbdmxfilter->feed->pid,
315 &av7110->p2t_filter[dvbdmxfilter->index]);
316 default:
317 return 0;
318 }
319}
320
321
322//#define DEBUG_TIMING
323static inline void print_time(char *s)
324{
325#ifdef DEBUG_TIMING
326 struct timeval tv;
327 do_gettimeofday(&tv);
328 printk("%s: %d.%d\n", s, (int)tv.tv_sec, (int)tv.tv_usec);
329#endif
330}
331
332#define DEBI_READ 0
333#define DEBI_WRITE 1
334static inline void start_debi_dma(struct av7110 *av7110, int dir,
335 unsigned long addr, unsigned int len)
336{
337 dprintk(8, "%c %08lx %u\n", dir == DEBI_READ ? 'R' : 'W', addr, len);
338 if (saa7146_wait_for_debi_done(av7110->dev, 0)) {
339 printk(KERN_ERR "%s: saa7146_wait_for_debi_done timed out\n", __FUNCTION__);
340 return;
341 }
342
343 SAA7146_ISR_CLEAR(av7110->dev, MASK_19); /* for good measure */
344 SAA7146_IER_ENABLE(av7110->dev, MASK_19);
345 if (len < 5)
346 len = 5; /* we want a real DEBI DMA */
347 if (dir == DEBI_WRITE)
348 iwdebi(av7110, DEBISWAB, addr, 0, (len + 3) & ~3);
349 else
350 irdebi(av7110, DEBISWAB, addr, 0, len);
351}
352
353static void debiirq(unsigned long data)
354{
355 struct av7110 *av7110 = (struct av7110 *) data;
356 int type = av7110->debitype;
357 int handle = (type >> 8) & 0x1f;
358 unsigned int xfer = 0;
359
360 print_time("debi");
361 dprintk(4, "type 0x%04x\n", type);
362
363 if (type == -1) {
364 printk("DEBI irq oops @ %ld, psr:0x%08x, ssr:0x%08x\n",
365 jiffies, saa7146_read(av7110->dev, PSR),
366 saa7146_read(av7110->dev, SSR));
367 goto debi_done;
368 }
369 av7110->debitype = -1;
370
371 switch (type & 0xff) {
372
373 case DATA_TS_RECORD:
374 dvb_dmx_swfilter_packets(&av7110->demux,
375 (const u8 *) av7110->debi_virt,
376 av7110->debilen / 188);
377 xfer = RX_BUFF;
378 break;
379
380 case DATA_PES_RECORD:
381 if (av7110->demux.recording)
382 av7110_record_cb(&av7110->p2t[handle],
383 (u8 *) av7110->debi_virt,
384 av7110->debilen);
385 xfer = RX_BUFF;
386 break;
387
388 case DATA_IPMPE:
389 case DATA_FSECTION:
390 case DATA_PIPING:
391 if (av7110->handle2filter[handle])
392 DvbDmxFilterCallback((u8 *)av7110->debi_virt,
393 av7110->debilen, NULL, 0,
394 av7110->handle2filter[handle],
395 DMX_OK, av7110);
396 xfer = RX_BUFF;
397 break;
398
399 case DATA_CI_GET:
400 {
401 u8 *data = av7110->debi_virt;
402
403 if ((data[0] < 2) && data[2] == 0xff) {
404 int flags = 0;
405 if (data[5] > 0)
406 flags |= CA_CI_MODULE_PRESENT;
407 if (data[5] > 5)
408 flags |= CA_CI_MODULE_READY;
409 av7110->ci_slot[data[0]].flags = flags;
410 } else
411 ci_get_data(&av7110->ci_rbuffer,
412 av7110->debi_virt,
413 av7110->debilen);
414 xfer = RX_BUFF;
415 break;
416 }
417
418 case DATA_COMMON_INTERFACE:
419 CI_handle(av7110, (u8 *)av7110->debi_virt, av7110->debilen);
420#if 0
421 {
422 int i;
423
424 printk("av7110%d: ", av7110->num);
425 printk("%02x ", *(u8 *)av7110->debi_virt);
426 printk("%02x ", *(1+(u8 *)av7110->debi_virt));
427 for (i = 2; i < av7110->debilen; i++)
428 printk("%02x ", (*(i+(unsigned char *)av7110->debi_virt)));
429 for (i = 2; i < av7110->debilen; i++)
430 printk("%c", chtrans(*(i+(unsigned char *)av7110->debi_virt)));
431
432 printk("\n");
433 }
434#endif
435 xfer = RX_BUFF;
436 break;
437
438 case DATA_DEBUG_MESSAGE:
439 ((s8*)av7110->debi_virt)[Reserved_SIZE - 1] = 0;
440 printk("%s\n", (s8 *) av7110->debi_virt);
441 xfer = RX_BUFF;
442 break;
443
444 case DATA_CI_PUT:
445 dprintk(4, "debi DATA_CI_PUT\n");
446 case DATA_MPEG_PLAY:
447 dprintk(4, "debi DATA_MPEG_PLAY\n");
448 case DATA_BMP_LOAD:
449 dprintk(4, "debi DATA_BMP_LOAD\n");
450 xfer = TX_BUFF;
451 break;
452 default:
453 break;
454 }
455debi_done:
456 spin_lock(&av7110->debilock);
457 if (xfer)
458 iwdebi(av7110, DEBINOSWAP, xfer, 0, 2);
459 ARM_ClearMailBox(av7110);
460 spin_unlock(&av7110->debilock);
461}
462
463/* irq from av7110 firmware writing the mailbox register in the DPRAM */
464static void gpioirq(unsigned long data)
465{
466 struct av7110 *av7110 = (struct av7110 *) data;
467 u32 rxbuf, txbuf;
468 int len;
469
470 if (av7110->debitype != -1)
471 /* we shouldn't get any irq while a debi xfer is running */
472 printk("dvb-ttpci: GPIO0 irq oops @ %ld, psr:0x%08x, ssr:0x%08x\n",
473 jiffies, saa7146_read(av7110->dev, PSR),
474 saa7146_read(av7110->dev, SSR));
475
476 if (saa7146_wait_for_debi_done(av7110->dev, 0)) {
477 printk(KERN_ERR "%s: saa7146_wait_for_debi_done timed out\n", __FUNCTION__);
478 BUG(); /* maybe we should try resetting the debi? */
479 }
480
481 spin_lock(&av7110->debilock);
482 ARM_ClearIrq(av7110);
483
484 /* see what the av7110 wants */
485 av7110->debitype = irdebi(av7110, DEBINOSWAP, IRQ_STATE, 0, 2);
486 av7110->debilen = irdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
487 rxbuf = irdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
488 txbuf = irdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
489 len = (av7110->debilen + 3) & ~3;
490
491 print_time("gpio");
492 dprintk(8, "GPIO0 irq 0x%04x %d\n", av7110->debitype, av7110->debilen);
493
494 switch (av7110->debitype & 0xff) {
495
496 case DATA_TS_PLAY:
497 case DATA_PES_PLAY:
498 break;
499
500 case DATA_MPEG_VIDEO_EVENT:
501 {
502 u32 h_ar;
503 struct video_event event;
504
505 av7110->video_size.w = irdebi(av7110, DEBINOSWAP, STATUS_MPEG_WIDTH, 0, 2);
506 h_ar = irdebi(av7110, DEBINOSWAP, STATUS_MPEG_HEIGHT_AR, 0, 2);
507
508 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
509 iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
510
511 av7110->video_size.h = h_ar & 0xfff;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700512
513 event.type = VIDEO_EVENT_SIZE_CHANGED;
514 event.u.size.w = av7110->video_size.w;
515 event.u.size.h = av7110->video_size.h;
516 switch ((h_ar >> 12) & 0xf)
517 {
518 case 3:
519 av7110->video_size.aspect_ratio = VIDEO_FORMAT_16_9;
520 event.u.size.aspect_ratio = VIDEO_FORMAT_16_9;
521 av7110->videostate.video_format = VIDEO_FORMAT_16_9;
522 break;
523 case 4:
524 av7110->video_size.aspect_ratio = VIDEO_FORMAT_221_1;
525 event.u.size.aspect_ratio = VIDEO_FORMAT_221_1;
526 av7110->videostate.video_format = VIDEO_FORMAT_221_1;
527 break;
528 default:
529 av7110->video_size.aspect_ratio = VIDEO_FORMAT_4_3;
530 event.u.size.aspect_ratio = VIDEO_FORMAT_4_3;
531 av7110->videostate.video_format = VIDEO_FORMAT_4_3;
532 }
Oliver Endriss66190a22006-01-09 15:32:42 -0200533
534 dprintk(8, "GPIO0 irq: DATA_MPEG_VIDEO_EVENT: w/h/ar = %u/%u/%u\n",
535 av7110->video_size.w, av7110->video_size.h,
536 av7110->video_size.aspect_ratio);
537
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538 dvb_video_add_event(av7110, &event);
539 break;
540 }
541
542 case DATA_CI_PUT:
543 {
544 int avail;
545 struct dvb_ringbuffer *cibuf = &av7110->ci_wbuffer;
546
547 avail = dvb_ringbuffer_avail(cibuf);
548 if (avail <= 2) {
549 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
550 iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
551 iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
552 break;
553 }
554 len = DVB_RINGBUFFER_PEEK(cibuf, 0) << 8;
555 len |= DVB_RINGBUFFER_PEEK(cibuf, 1);
556 if (avail < len + 2) {
557 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
558 iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
559 iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
560 break;
561 }
562 DVB_RINGBUFFER_SKIP(cibuf, 2);
563
564 dvb_ringbuffer_read(cibuf, av7110->debi_virt, len, 0);
565
566 iwdebi(av7110, DEBINOSWAP, TX_LEN, len, 2);
567 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, len, 2);
568 dprintk(8, "DMA: CI\n");
569 start_debi_dma(av7110, DEBI_WRITE, DPRAM_BASE + txbuf, len);
570 spin_unlock(&av7110->debilock);
571 wake_up(&cibuf->queue);
572 return;
573 }
574
575 case DATA_MPEG_PLAY:
576 if (!av7110->playing) {
577 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
578 iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
579 iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
580 break;
581 }
582 len = 0;
583 if (av7110->debitype & 0x100) {
584 spin_lock(&av7110->aout.lock);
585 len = av7110_pes_play(av7110->debi_virt, &av7110->aout, 2048);
586 spin_unlock(&av7110->aout.lock);
587 }
588 if (len <= 0 && (av7110->debitype & 0x200)
589 &&av7110->videostate.play_state != VIDEO_FREEZED) {
590 spin_lock(&av7110->avout.lock);
591 len = av7110_pes_play(av7110->debi_virt, &av7110->avout, 2048);
592 spin_unlock(&av7110->avout.lock);
593 }
594 if (len <= 0) {
595 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
596 iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
597 iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
598 break;
599 }
600 dprintk(8, "GPIO0 PES_PLAY len=%04x\n", len);
601 iwdebi(av7110, DEBINOSWAP, TX_LEN, len, 2);
602 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, len, 2);
603 dprintk(8, "DMA: MPEG_PLAY\n");
604 start_debi_dma(av7110, DEBI_WRITE, DPRAM_BASE + txbuf, len);
605 spin_unlock(&av7110->debilock);
606 return;
607
608 case DATA_BMP_LOAD:
609 len = av7110->debilen;
610 dprintk(8, "gpio DATA_BMP_LOAD len %d\n", len);
611 if (!len) {
612 av7110->bmp_state = BMP_LOADED;
613 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
614 iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
615 iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
616 wake_up(&av7110->bmpq);
617 dprintk(8, "gpio DATA_BMP_LOAD done\n");
618 break;
619 }
620 if (len > av7110->bmplen)
621 len = av7110->bmplen;
622 if (len > 2 * 1024)
623 len = 2 * 1024;
624 iwdebi(av7110, DEBINOSWAP, TX_LEN, len, 2);
625 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, len, 2);
626 memcpy(av7110->debi_virt, av7110->bmpbuf+av7110->bmpp, len);
627 av7110->bmpp += len;
628 av7110->bmplen -= len;
629 dprintk(8, "gpio DATA_BMP_LOAD DMA len %d\n", len);
630 start_debi_dma(av7110, DEBI_WRITE, DPRAM_BASE+txbuf, len);
631 spin_unlock(&av7110->debilock);
632 return;
633
634 case DATA_CI_GET:
635 case DATA_COMMON_INTERFACE:
636 case DATA_FSECTION:
637 case DATA_IPMPE:
638 case DATA_PIPING:
639 if (!len || len > 4 * 1024) {
640 iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
641 break;
642 }
643 /* fall through */
644
645 case DATA_TS_RECORD:
646 case DATA_PES_RECORD:
647 dprintk(8, "DMA: TS_REC etc.\n");
648 start_debi_dma(av7110, DEBI_READ, DPRAM_BASE+rxbuf, len);
649 spin_unlock(&av7110->debilock);
650 return;
651
652 case DATA_DEBUG_MESSAGE:
653 if (!len || len > 0xff) {
654 iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
655 break;
656 }
657 start_debi_dma(av7110, DEBI_READ, Reserved, len);
658 spin_unlock(&av7110->debilock);
659 return;
660
661 case DATA_IRCOMMAND:
Oliver Endriss03388ae2005-09-09 13:03:12 -0700662 if (av7110->ir_handler)
663 av7110->ir_handler(av7110,
664 swahw32(irdebi(av7110, DEBINOSWAP, Reserved, 0, 4)));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700665 iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
666 break;
667
668 default:
669 printk("dvb-ttpci: gpioirq unknown type=%d len=%d\n",
670 av7110->debitype, av7110->debilen);
671 break;
672 }
673 av7110->debitype = -1;
674 ARM_ClearMailBox(av7110);
675 spin_unlock(&av7110->debilock);
676}
677
678
679#ifdef CONFIG_DVB_AV7110_OSD
680static int dvb_osd_ioctl(struct inode *inode, struct file *file,
681 unsigned int cmd, void *parg)
682{
683 struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
684 struct av7110 *av7110 = (struct av7110 *) dvbdev->priv;
685
686 dprintk(4, "%p\n", av7110);
687
688 if (cmd == OSD_SEND_CMD)
689 return av7110_osd_cmd(av7110, (osd_cmd_t *) parg);
690 if (cmd == OSD_GET_CAPABILITY)
691 return av7110_osd_capability(av7110, (osd_cap_t *) parg);
692
693 return -EINVAL;
694}
695
696
697static struct file_operations dvb_osd_fops = {
698 .owner = THIS_MODULE,
699 .ioctl = dvb_generic_ioctl,
700 .open = dvb_generic_open,
701 .release = dvb_generic_release,
702};
703
704static struct dvb_device dvbdev_osd = {
705 .priv = NULL,
706 .users = 1,
707 .writers = 1,
708 .fops = &dvb_osd_fops,
709 .kernel_ioctl = dvb_osd_ioctl,
710};
711#endif /* CONFIG_DVB_AV7110_OSD */
712
713
714static inline int SetPIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid,
715 u16 subpid, u16 pcrpid)
716{
Dr. Werner Fink47f36922006-01-09 15:25:07 -0200717 u16 aflags = 0;
718
Linus Torvalds1da177e2005-04-16 15:20:36 -0700719 dprintk(4, "%p\n", av7110);
720
721 if (vpid == 0x1fff || apid == 0x1fff ||
722 ttpid == 0x1fff || subpid == 0x1fff || pcrpid == 0x1fff) {
723 vpid = apid = ttpid = subpid = pcrpid = 0;
724 av7110->pids[DMX_PES_VIDEO] = 0;
725 av7110->pids[DMX_PES_AUDIO] = 0;
726 av7110->pids[DMX_PES_TELETEXT] = 0;
727 av7110->pids[DMX_PES_PCR] = 0;
728 }
729
Dr. Werner Fink47f36922006-01-09 15:25:07 -0200730 if (av7110->audiostate.bypass_mode)
731 aflags |= 0x8000;
732
733 return av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, MultiPID, 6,
734 pcrpid, vpid, apid, ttpid, subpid, aflags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700735}
736
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700737int ChangePIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700738 u16 subpid, u16 pcrpid)
739{
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700740 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700741 dprintk(4, "%p\n", av7110);
742
Ingo Molnar3593cab2006-02-07 06:49:14 -0200743 if (mutex_lock_interruptible(&av7110->pid_mutex))
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700744 return -ERESTARTSYS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700745
746 if (!(vpid & 0x8000))
747 av7110->pids[DMX_PES_VIDEO] = vpid;
748 if (!(apid & 0x8000))
749 av7110->pids[DMX_PES_AUDIO] = apid;
750 if (!(ttpid & 0x8000))
751 av7110->pids[DMX_PES_TELETEXT] = ttpid;
752 if (!(pcrpid & 0x8000))
753 av7110->pids[DMX_PES_PCR] = pcrpid;
754
755 av7110->pids[DMX_PES_SUBTITLE] = 0;
756
757 if (av7110->fe_synced) {
758 pcrpid = av7110->pids[DMX_PES_PCR];
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700759 ret = SetPIDs(av7110, vpid, apid, ttpid, subpid, pcrpid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700760 }
761
Ingo Molnar3593cab2006-02-07 06:49:14 -0200762 mutex_unlock(&av7110->pid_mutex);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700763 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700764}
765
766
767/******************************************************************************
768 * hardware filter functions
769 ******************************************************************************/
770
771static int StartHWFilter(struct dvb_demux_filter *dvbdmxfilter)
772{
773 struct dvb_demux_feed *dvbdmxfeed = dvbdmxfilter->feed;
774 struct av7110 *av7110 = (struct av7110 *) dvbdmxfeed->demux->priv;
775 u16 buf[20];
776 int ret, i;
777 u16 handle;
778// u16 mode = 0x0320;
779 u16 mode = 0xb96a;
780
781 dprintk(4, "%p\n", av7110);
782
783 if (dvbdmxfilter->type == DMX_TYPE_SEC) {
784 if (hw_sections) {
785 buf[4] = (dvbdmxfilter->filter.filter_value[0] << 8) |
786 dvbdmxfilter->maskandmode[0];
787 for (i = 3; i < 18; i++)
788 buf[i + 4 - 2] =
789 (dvbdmxfilter->filter.filter_value[i] << 8) |
790 dvbdmxfilter->maskandmode[i];
791 mode = 4;
792 }
793 } else if ((dvbdmxfeed->ts_type & TS_PACKET) &&
794 !(dvbdmxfeed->ts_type & TS_PAYLOAD_ONLY)) {
795 av7110_p2t_init(&av7110->p2t_filter[dvbdmxfilter->index], dvbdmxfeed);
796 }
797
798 buf[0] = (COMTYPE_PID_FILTER << 8) + AddPIDFilter;
799 buf[1] = 16;
800 buf[2] = dvbdmxfeed->pid;
801 buf[3] = mode;
802
803 ret = av7110_fw_request(av7110, buf, 20, &handle, 1);
804 if (ret != 0 || handle >= 32) {
805 printk("dvb-ttpci: %s error buf %04x %04x %04x %04x "
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700806 "ret %d handle %04x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700807 __FUNCTION__, buf[0], buf[1], buf[2], buf[3],
808 ret, handle);
809 dvbdmxfilter->hw_handle = 0xffff;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700810 if (!ret)
811 ret = -1;
812 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700813 }
814
815 av7110->handle2filter[handle] = dvbdmxfilter;
816 dvbdmxfilter->hw_handle = handle;
817
818 return ret;
819}
820
821static int StopHWFilter(struct dvb_demux_filter *dvbdmxfilter)
822{
823 struct av7110 *av7110 = (struct av7110 *) dvbdmxfilter->feed->demux->priv;
824 u16 buf[3];
825 u16 answ[2];
826 int ret;
827 u16 handle;
828
829 dprintk(4, "%p\n", av7110);
830
831 handle = dvbdmxfilter->hw_handle;
832 if (handle >= 32) {
833 printk("%s tried to stop invalid filter %04x, filter type = %x\n",
834 __FUNCTION__, handle, dvbdmxfilter->type);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700835 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700836 }
837
838 av7110->handle2filter[handle] = NULL;
839
840 buf[0] = (COMTYPE_PID_FILTER << 8) + DelPIDFilter;
841 buf[1] = 1;
842 buf[2] = handle;
843 ret = av7110_fw_request(av7110, buf, 3, answ, 2);
844 if (ret != 0 || answ[1] != handle) {
845 printk("dvb-ttpci: %s error cmd %04x %04x %04x ret %x "
846 "resp %04x %04x pid %d\n",
847 __FUNCTION__, buf[0], buf[1], buf[2], ret,
848 answ[0], answ[1], dvbdmxfilter->feed->pid);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700849 if (!ret)
850 ret = -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700851 }
852 return ret;
853}
854
855
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700856static int dvb_feed_start_pid(struct dvb_demux_feed *dvbdmxfeed)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700857{
858 struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
859 struct av7110 *av7110 = (struct av7110 *) dvbdmx->priv;
860 u16 *pid = dvbdmx->pids, npids[5];
861 int i;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700862 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700863
864 dprintk(4, "%p\n", av7110);
865
866 npids[0] = npids[1] = npids[2] = npids[3] = npids[4] = 0xffff;
867 i = dvbdmxfeed->pes_type;
868 npids[i] = (pid[i]&0x8000) ? 0 : pid[i];
869 if ((i == 2) && npids[i] && (dvbdmxfeed->ts_type & TS_PACKET)) {
870 npids[i] = 0;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700871 ret = ChangePIDs(av7110, npids[1], npids[0], npids[2], npids[3], npids[4]);
872 if (!ret)
873 ret = StartHWFilter(dvbdmxfeed->filter);
874 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700875 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700876 if (dvbdmxfeed->pes_type <= 2 || dvbdmxfeed->pes_type == 4) {
877 ret = ChangePIDs(av7110, npids[1], npids[0], npids[2], npids[3], npids[4]);
878 if (ret)
879 return ret;
880 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700881
882 if (dvbdmxfeed->pes_type < 2 && npids[0])
883 if (av7110->fe_synced)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700884 {
885 ret = av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, Scan, 0);
886 if (ret)
887 return ret;
888 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700889
890 if ((dvbdmxfeed->ts_type & TS_PACKET)) {
891 if (dvbdmxfeed->pes_type == 0 && !(dvbdmx->pids[0] & 0x8000))
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700892 ret = av7110_av_start_record(av7110, RP_AUDIO, dvbdmxfeed);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700893 if (dvbdmxfeed->pes_type == 1 && !(dvbdmx->pids[1] & 0x8000))
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700894 ret = av7110_av_start_record(av7110, RP_VIDEO, dvbdmxfeed);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700895 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700896 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700897}
898
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700899static int dvb_feed_stop_pid(struct dvb_demux_feed *dvbdmxfeed)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700900{
901 struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
902 struct av7110 *av7110 = (struct av7110 *) dvbdmx->priv;
903 u16 *pid = dvbdmx->pids, npids[5];
904 int i;
905
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700906 int ret = 0;
907
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908 dprintk(4, "%p\n", av7110);
909
910 if (dvbdmxfeed->pes_type <= 1) {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700911 ret = av7110_av_stop(av7110, dvbdmxfeed->pes_type ? RP_VIDEO : RP_AUDIO);
912 if (ret)
913 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700914 if (!av7110->rec_mode)
915 dvbdmx->recording = 0;
916 if (!av7110->playing)
917 dvbdmx->playing = 0;
918 }
919 npids[0] = npids[1] = npids[2] = npids[3] = npids[4] = 0xffff;
920 i = dvbdmxfeed->pes_type;
921 switch (i) {
922 case 2: //teletext
923 if (dvbdmxfeed->ts_type & TS_PACKET)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700924 ret = StopHWFilter(dvbdmxfeed->filter);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700925 npids[2] = 0;
926 break;
927 case 0:
928 case 1:
929 case 4:
930 if (!pids_off)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700931 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700932 npids[i] = (pid[i]&0x8000) ? 0 : pid[i];
933 break;
934 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700935 if (!ret)
936 ret = ChangePIDs(av7110, npids[1], npids[0], npids[2], npids[3], npids[4]);
937 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700938}
939
940static int av7110_start_feed(struct dvb_demux_feed *feed)
941{
942 struct dvb_demux *demux = feed->demux;
943 struct av7110 *av7110 = demux->priv;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700944 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700945
946 dprintk(4, "%p\n", av7110);
947
948 if (!demux->dmx.frontend)
949 return -EINVAL;
950
951 if (feed->pid > 0x1fff)
952 return -EINVAL;
953
954 if (feed->type == DMX_TYPE_TS) {
955 if ((feed->ts_type & TS_DECODER) &&
956 (feed->pes_type < DMX_TS_PES_OTHER)) {
957 switch (demux->dmx.frontend->source) {
958 case DMX_MEMORY_FE:
959 if (feed->ts_type & TS_DECODER)
960 if (feed->pes_type < 2 &&
961 !(demux->pids[0] & 0x8000) &&
962 !(demux->pids[1] & 0x8000)) {
963 dvb_ringbuffer_flush_spinlock_wakeup(&av7110->avout);
964 dvb_ringbuffer_flush_spinlock_wakeup(&av7110->aout);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700965 ret = av7110_av_start_play(av7110,RP_AV);
966 if (!ret)
967 demux->playing = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700968 }
969 break;
970 default:
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700971 ret = dvb_feed_start_pid(feed);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700972 break;
973 }
974 } else if ((feed->ts_type & TS_PACKET) &&
975 (demux->dmx.frontend->source != DMX_MEMORY_FE)) {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700976 ret = StartHWFilter(feed->filter);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700977 }
978 }
979
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700980 else if (feed->type == DMX_TYPE_SEC) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700981 int i;
982
983 for (i = 0; i < demux->filternum; i++) {
984 if (demux->filter[i].state != DMX_STATE_READY)
985 continue;
986 if (demux->filter[i].type != DMX_TYPE_SEC)
987 continue;
988 if (demux->filter[i].filter.parent != &feed->feed.sec)
989 continue;
990 demux->filter[i].state = DMX_STATE_GO;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700991 if (demux->dmx.frontend->source != DMX_MEMORY_FE) {
992 ret = StartHWFilter(&demux->filter[i]);
993 if (ret)
994 break;
995 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700996 }
997 }
998
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700999 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001000}
1001
1002
1003static int av7110_stop_feed(struct dvb_demux_feed *feed)
1004{
1005 struct dvb_demux *demux = feed->demux;
1006 struct av7110 *av7110 = demux->priv;
Johannes Stezenbach12ba0502005-07-07 17:58:00 -07001007 int i, rc, ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001008 dprintk(4, "%p\n", av7110);
1009
1010 if (feed->type == DMX_TYPE_TS) {
1011 if (feed->ts_type & TS_DECODER) {
1012 if (feed->pes_type >= DMX_TS_PES_OTHER ||
1013 !demux->pesfilter[feed->pes_type])
1014 return -EINVAL;
1015 demux->pids[feed->pes_type] |= 0x8000;
1016 demux->pesfilter[feed->pes_type] = NULL;
1017 }
1018 if (feed->ts_type & TS_DECODER &&
1019 feed->pes_type < DMX_TS_PES_OTHER) {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001020 ret = dvb_feed_stop_pid(feed);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021 } else
1022 if ((feed->ts_type & TS_PACKET) &&
1023 (demux->dmx.frontend->source != DMX_MEMORY_FE))
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001024 ret = StopHWFilter(feed->filter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001025 }
1026
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001027 if (!ret && feed->type == DMX_TYPE_SEC) {
Johannes Stezenbach12ba0502005-07-07 17:58:00 -07001028 for (i = 0; i<demux->filternum; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029 if (demux->filter[i].state == DMX_STATE_GO &&
1030 demux->filter[i].filter.parent == &feed->feed.sec) {
1031 demux->filter[i].state = DMX_STATE_READY;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001032 if (demux->dmx.frontend->source != DMX_MEMORY_FE) {
Johannes Stezenbach12ba0502005-07-07 17:58:00 -07001033 rc = StopHWFilter(&demux->filter[i]);
1034 if (!ret)
1035 ret = rc;
1036 /* keep going, stop as many filters as possible */
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001037 }
Johannes Stezenbach12ba0502005-07-07 17:58:00 -07001038 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001039 }
1040 }
1041
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001042 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001043}
1044
1045
1046static void restart_feeds(struct av7110 *av7110)
1047{
1048 struct dvb_demux *dvbdmx = &av7110->demux;
1049 struct dvb_demux_feed *feed;
1050 int mode;
Oliver Endriss66190a22006-01-09 15:32:42 -02001051 int i, j;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001052
1053 dprintk(4, "%p\n", av7110);
1054
1055 mode = av7110->playing;
1056 av7110->playing = 0;
1057 av7110->rec_mode = 0;
1058
Oliver Endriss66190a22006-01-09 15:32:42 -02001059 for (i = 0; i < dvbdmx->feednum; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001060 feed = &dvbdmx->feed[i];
Oliver Endriss66190a22006-01-09 15:32:42 -02001061 if (feed->state == DMX_STATE_GO) {
1062 if (feed->type == DMX_TYPE_SEC) {
1063 for (j = 0; j < dvbdmx->filternum; j++) {
1064 if (dvbdmx->filter[j].type != DMX_TYPE_SEC)
1065 continue;
1066 if (dvbdmx->filter[j].filter.parent != &feed->feed.sec)
1067 continue;
1068 if (dvbdmx->filter[j].state == DMX_STATE_GO)
1069 dvbdmx->filter[j].state = DMX_STATE_READY;
1070 }
1071 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001072 av7110_start_feed(feed);
Oliver Endriss66190a22006-01-09 15:32:42 -02001073 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001074 }
1075
1076 if (mode)
1077 av7110_av_start_play(av7110, mode);
1078}
1079
1080static int dvb_get_stc(struct dmx_demux *demux, unsigned int num,
1081 uint64_t *stc, unsigned int *base)
1082{
1083 int ret;
1084 u16 fwstc[4];
1085 u16 tag = ((COMTYPE_REQUEST << 8) + ReqSTC);
1086 struct dvb_demux *dvbdemux;
1087 struct av7110 *av7110;
1088
1089 /* pointer casting paranoia... */
1090 if (!demux)
1091 BUG();
1092 dvbdemux = (struct dvb_demux *) demux->priv;
1093 if (!dvbdemux)
1094 BUG();
1095 av7110 = (struct av7110 *) dvbdemux->priv;
1096
1097 dprintk(4, "%p\n", av7110);
1098
1099 if (num != 0)
1100 return -EINVAL;
1101
1102 ret = av7110_fw_request(av7110, &tag, 0, fwstc, 4);
1103 if (ret) {
1104 printk(KERN_ERR "%s: av7110_fw_request error\n", __FUNCTION__);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001105 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001106 }
1107 dprintk(2, "fwstc = %04hx %04hx %04hx %04hx\n",
1108 fwstc[0], fwstc[1], fwstc[2], fwstc[3]);
1109
1110 *stc = (((uint64_t) ((fwstc[3] & 0x8000) >> 15)) << 32) |
1111 (((uint64_t) fwstc[1]) << 16) | ((uint64_t) fwstc[0]);
1112 *base = 1;
1113
1114 dprintk(4, "stc = %lu\n", (unsigned long)*stc);
1115
1116 return 0;
1117}
1118
1119
1120/******************************************************************************
1121 * SEC device file operations
1122 ******************************************************************************/
1123
1124
1125static int av7110_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
1126{
1127 struct av7110* av7110 = (struct av7110*) fe->dvb->priv;
1128
1129 switch (tone) {
1130 case SEC_TONE_ON:
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001131 return Set22K(av7110, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001132
1133 case SEC_TONE_OFF:
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001134 return Set22K(av7110, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001135
1136 default:
1137 return -EINVAL;
1138 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001139}
1140
1141static int av7110_diseqc_send_master_cmd(struct dvb_frontend* fe,
1142 struct dvb_diseqc_master_cmd* cmd)
1143{
1144 struct av7110* av7110 = fe->dvb->priv;
1145
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001146 return av7110_diseqc_send(av7110, cmd->msg_len, cmd->msg, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001147}
1148
1149static int av7110_diseqc_send_burst(struct dvb_frontend* fe,
1150 fe_sec_mini_cmd_t minicmd)
1151{
1152 struct av7110* av7110 = fe->dvb->priv;
1153
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001154 return av7110_diseqc_send(av7110, 0, NULL, minicmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001155}
1156
1157/* simplified code from budget-core.c */
1158static int stop_ts_capture(struct av7110 *budget)
1159{
1160 dprintk(2, "budget: %p\n", budget);
1161
1162 if (--budget->feeding1)
1163 return budget->feeding1;
1164 saa7146_write(budget->dev, MC1, MASK_20); /* DMA3 off */
1165 SAA7146_IER_DISABLE(budget->dev, MASK_10);
1166 SAA7146_ISR_CLEAR(budget->dev, MASK_10);
1167 return 0;
1168}
1169
1170static int start_ts_capture(struct av7110 *budget)
1171{
1172 dprintk(2, "budget: %p\n", budget);
1173
1174 if (budget->feeding1)
1175 return ++budget->feeding1;
1176 memset(budget->grabbing, 0x00, TS_HEIGHT * TS_WIDTH);
1177 budget->tsf = 0xff;
1178 budget->ttbp = 0;
1179 SAA7146_IER_ENABLE(budget->dev, MASK_10); /* VPE */
1180 saa7146_write(budget->dev, MC1, (MASK_04 | MASK_20)); /* DMA3 on */
1181 return ++budget->feeding1;
1182}
1183
1184static int budget_start_feed(struct dvb_demux_feed *feed)
1185{
1186 struct dvb_demux *demux = feed->demux;
1187 struct av7110 *budget = (struct av7110 *) demux->priv;
1188 int status;
1189
1190 dprintk(2, "av7110: %p\n", budget);
1191
1192 spin_lock(&budget->feedlock1);
1193 feed->pusi_seen = 0; /* have a clean section start */
1194 status = start_ts_capture(budget);
1195 spin_unlock(&budget->feedlock1);
1196 return status;
1197}
1198
1199static int budget_stop_feed(struct dvb_demux_feed *feed)
1200{
1201 struct dvb_demux *demux = feed->demux;
1202 struct av7110 *budget = (struct av7110 *) demux->priv;
1203 int status;
1204
1205 dprintk(2, "budget: %p\n", budget);
1206
1207 spin_lock(&budget->feedlock1);
1208 status = stop_ts_capture(budget);
1209 spin_unlock(&budget->feedlock1);
1210 return status;
1211}
1212
1213static void vpeirq(unsigned long data)
1214{
1215 struct av7110 *budget = (struct av7110 *) data;
1216 u8 *mem = (u8 *) (budget->grabbing);
1217 u32 olddma = budget->ttbp;
1218 u32 newdma = saa7146_read(budget->dev, PCI_VDP3);
1219
1220 if (!budgetpatch) {
1221 printk("av7110.c: vpeirq() called while budgetpatch disabled!"
1222 " check saa7146 IER register\n");
1223 BUG();
1224 }
1225 /* nearest lower position divisible by 188 */
1226 newdma -= newdma % 188;
1227
1228 if (newdma >= TS_BUFLEN)
1229 return;
1230
1231 budget->ttbp = newdma;
1232
1233 if (!budget->feeding1 || (newdma == olddma))
1234 return;
1235
1236#if 0
1237 /* track rps1 activity */
1238 printk("vpeirq: %02x Event Counter 1 0x%04x\n",
1239 mem[olddma],
1240 saa7146_read(budget->dev, EC1R) & 0x3fff);
1241#endif
1242
1243 if (newdma > olddma)
1244 /* no wraparound, dump olddma..newdma */
1245 dvb_dmx_swfilter_packets(&budget->demux1, mem + olddma, (newdma - olddma) / 188);
1246 else {
1247 /* wraparound, dump olddma..buflen and 0..newdma */
1248 dvb_dmx_swfilter_packets(&budget->demux1, mem + olddma, (TS_BUFLEN - olddma) / 188);
1249 dvb_dmx_swfilter_packets(&budget->demux1, mem, newdma / 188);
1250 }
1251}
1252
1253static int av7110_register(struct av7110 *av7110)
1254{
1255 int ret, i;
1256 struct dvb_demux *dvbdemux = &av7110->demux;
1257 struct dvb_demux *dvbdemux1 = &av7110->demux1;
1258
1259 dprintk(4, "%p\n", av7110);
1260
1261 if (av7110->registered)
1262 return -1;
1263
1264 av7110->registered = 1;
1265
1266 dvbdemux->priv = (void *) av7110;
1267
1268 for (i = 0; i < 32; i++)
1269 av7110->handle2filter[i] = NULL;
1270
1271 dvbdemux->filternum = 32;
1272 dvbdemux->feednum = 32;
1273 dvbdemux->start_feed = av7110_start_feed;
1274 dvbdemux->stop_feed = av7110_stop_feed;
1275 dvbdemux->write_to_decoder = av7110_write_to_decoder;
1276 dvbdemux->dmx.capabilities = (DMX_TS_FILTERING | DMX_SECTION_FILTERING |
1277 DMX_MEMORY_BASED_FILTERING);
1278
1279 dvb_dmx_init(&av7110->demux);
1280 av7110->demux.dmx.get_stc = dvb_get_stc;
1281
1282 av7110->dmxdev.filternum = 32;
1283 av7110->dmxdev.demux = &dvbdemux->dmx;
1284 av7110->dmxdev.capabilities = 0;
1285
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001286 dvb_dmxdev_init(&av7110->dmxdev, &av7110->dvb_adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001287
1288 av7110->hw_frontend.source = DMX_FRONTEND_0;
1289
1290 ret = dvbdemux->dmx.add_frontend(&dvbdemux->dmx, &av7110->hw_frontend);
1291
1292 if (ret < 0)
1293 return ret;
1294
1295 av7110->mem_frontend.source = DMX_MEMORY_FE;
1296
1297 ret = dvbdemux->dmx.add_frontend(&dvbdemux->dmx, &av7110->mem_frontend);
1298
1299 if (ret < 0)
1300 return ret;
1301
1302 ret = dvbdemux->dmx.connect_frontend(&dvbdemux->dmx,
1303 &av7110->hw_frontend);
1304 if (ret < 0)
1305 return ret;
1306
1307 av7110_av_register(av7110);
1308 av7110_ca_register(av7110);
1309
1310#ifdef CONFIG_DVB_AV7110_OSD
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001311 dvb_register_device(&av7110->dvb_adapter, &av7110->osd_dev,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001312 &dvbdev_osd, av7110, DVB_DEVICE_OSD);
1313#endif
1314
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001315 dvb_net_init(&av7110->dvb_adapter, &av7110->dvb_net, &dvbdemux->dmx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001316
1317 if (budgetpatch) {
1318 /* initialize software demux1 without its own frontend
1319 * demux1 hardware is connected to frontend0 of demux0
1320 */
1321 dvbdemux1->priv = (void *) av7110;
1322
1323 dvbdemux1->filternum = 256;
1324 dvbdemux1->feednum = 256;
1325 dvbdemux1->start_feed = budget_start_feed;
1326 dvbdemux1->stop_feed = budget_stop_feed;
1327 dvbdemux1->write_to_decoder = NULL;
1328
1329 dvbdemux1->dmx.capabilities = (DMX_TS_FILTERING | DMX_SECTION_FILTERING |
1330 DMX_MEMORY_BASED_FILTERING);
1331
1332 dvb_dmx_init(&av7110->demux1);
1333
1334 av7110->dmxdev1.filternum = 256;
1335 av7110->dmxdev1.demux = &dvbdemux1->dmx;
1336 av7110->dmxdev1.capabilities = 0;
1337
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001338 dvb_dmxdev_init(&av7110->dmxdev1, &av7110->dvb_adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001339
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001340 dvb_net_init(&av7110->dvb_adapter, &av7110->dvb_net1, &dvbdemux1->dmx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001341 printk("dvb-ttpci: additional demux1 for budget-patch registered\n");
1342 }
1343 return 0;
1344}
1345
1346
1347static void dvb_unregister(struct av7110 *av7110)
1348{
1349 struct dvb_demux *dvbdemux = &av7110->demux;
1350 struct dvb_demux *dvbdemux1 = &av7110->demux1;
1351
1352 dprintk(4, "%p\n", av7110);
1353
1354 if (!av7110->registered)
1355 return;
1356
1357 if (budgetpatch) {
1358 dvb_net_release(&av7110->dvb_net1);
1359 dvbdemux->dmx.close(&dvbdemux1->dmx);
1360 dvb_dmxdev_release(&av7110->dmxdev1);
1361 dvb_dmx_release(&av7110->demux1);
1362 }
1363
1364 dvb_net_release(&av7110->dvb_net);
1365
1366 dvbdemux->dmx.close(&dvbdemux->dmx);
1367 dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &av7110->hw_frontend);
1368 dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &av7110->mem_frontend);
1369
1370 dvb_dmxdev_release(&av7110->dmxdev);
1371 dvb_dmx_release(&av7110->demux);
1372
1373 if (av7110->fe != NULL)
1374 dvb_unregister_frontend(av7110->fe);
1375 dvb_unregister_device(av7110->osd_dev);
1376 av7110_av_unregister(av7110);
1377 av7110_ca_unregister(av7110);
1378}
1379
1380
1381/****************************************************************************
1382 * I2C client commands
1383 ****************************************************************************/
1384
1385int i2c_writereg(struct av7110 *av7110, u8 id, u8 reg, u8 val)
1386{
1387 u8 msg[2] = { reg, val };
1388 struct i2c_msg msgs;
1389
1390 msgs.flags = 0;
1391 msgs.addr = id / 2;
1392 msgs.len = 2;
1393 msgs.buf = msg;
1394 return i2c_transfer(&av7110->i2c_adap, &msgs, 1);
1395}
1396
1397#if 0
1398u8 i2c_readreg(struct av7110 *av7110, u8 id, u8 reg)
1399{
1400 u8 mm1[] = {0x00};
1401 u8 mm2[] = {0x00};
1402 struct i2c_msg msgs[2];
1403
1404 msgs[0].flags = 0;
1405 msgs[1].flags = I2C_M_RD;
1406 msgs[0].addr = msgs[1].addr = id / 2;
1407 mm1[0] = reg;
1408 msgs[0].len = 1; msgs[1].len = 1;
1409 msgs[0].buf = mm1; msgs[1].buf = mm2;
1410 i2c_transfer(&av7110->i2c_adap, msgs, 2);
1411
1412 return mm2[0];
1413}
1414#endif
1415
1416/****************************************************************************
1417 * INITIALIZATION
1418 ****************************************************************************/
1419
1420
1421static int check_firmware(struct av7110* av7110)
1422{
1423 u32 crc = 0, len = 0;
1424 unsigned char *ptr;
1425
1426 /* check for firmware magic */
1427 ptr = av7110->bin_fw;
1428 if (ptr[0] != 'A' || ptr[1] != 'V' ||
1429 ptr[2] != 'F' || ptr[3] != 'W') {
1430 printk("dvb-ttpci: this is not an av7110 firmware\n");
1431 return -EINVAL;
1432 }
1433 ptr += 4;
1434
1435 /* check dpram file */
1436 crc = ntohl(*(u32*) ptr);
1437 ptr += 4;
1438 len = ntohl(*(u32*) ptr);
1439 ptr += 4;
1440 if (len >= 512) {
1441 printk("dvb-ttpci: dpram file is way to big.\n");
1442 return -EINVAL;
1443 }
1444 if (crc != crc32_le(0, ptr, len)) {
1445 printk("dvb-ttpci: crc32 of dpram file does not match.\n");
1446 return -EINVAL;
1447 }
1448 av7110->bin_dpram = ptr;
1449 av7110->size_dpram = len;
1450 ptr += len;
1451
1452 /* check root file */
1453 crc = ntohl(*(u32*) ptr);
1454 ptr += 4;
1455 len = ntohl(*(u32*) ptr);
1456 ptr += 4;
1457
1458 if (len <= 200000 || len >= 300000 ||
1459 len > ((av7110->bin_fw + av7110->size_fw) - ptr)) {
1460 printk("dvb-ttpci: root file has strange size (%d). aborting.\n", len);
1461 return -EINVAL;
1462 }
1463 if( crc != crc32_le(0, ptr, len)) {
1464 printk("dvb-ttpci: crc32 of root file does not match.\n");
1465 return -EINVAL;
1466 }
1467 av7110->bin_root = ptr;
1468 av7110->size_root = len;
1469 return 0;
1470}
1471
1472#ifdef CONFIG_DVB_AV7110_FIRMWARE_FILE
1473#include "av7110_firm.h"
1474static void put_firmware(struct av7110* av7110)
1475{
1476 av7110->bin_fw = NULL;
1477}
1478
1479static inline int get_firmware(struct av7110* av7110)
1480{
1481 av7110->bin_fw = dvb_ttpci_fw;
1482 av7110->size_fw = sizeof(dvb_ttpci_fw);
1483 return check_firmware(av7110);
1484}
1485#else
1486static void put_firmware(struct av7110* av7110)
1487{
1488 vfree(av7110->bin_fw);
1489}
1490
1491static int get_firmware(struct av7110* av7110)
1492{
1493 int ret;
1494 const struct firmware *fw;
1495
1496 /* request the av7110 firmware, this will block until someone uploads it */
1497 ret = request_firmware(&fw, "dvb-ttpci-01.fw", &av7110->dev->pci->dev);
1498 if (ret) {
1499 if (ret == -ENOENT) {
1500 printk(KERN_ERR "dvb-ttpci: could not load firmware,"
1501 " file not found: dvb-ttpci-01.fw\n");
Ville Skytt\ä12e66f62006-01-09 15:25:38 -02001502 printk(KERN_ERR "dvb-ttpci: usually this should be in "
1503 "/usr/lib/hotplug/firmware or /lib/firmware\n");
1504 printk(KERN_ERR "dvb-ttpci: and can be downloaded from"
Linus Torvalds1da177e2005-04-16 15:20:36 -07001505 " http://www.linuxtv.org/download/dvb/firmware/\n");
1506 } else
1507 printk(KERN_ERR "dvb-ttpci: cannot request firmware"
1508 " (error %i)\n", ret);
1509 return -EINVAL;
1510 }
1511
1512 if (fw->size <= 200000) {
1513 printk("dvb-ttpci: this firmware is way too small.\n");
1514 release_firmware(fw);
1515 return -EINVAL;
1516 }
1517
1518 /* check if the firmware is available */
1519 av7110->bin_fw = (unsigned char *) vmalloc(fw->size);
1520 if (NULL == av7110->bin_fw) {
1521 dprintk(1, "out of memory\n");
1522 release_firmware(fw);
1523 return -ENOMEM;
1524 }
1525
1526 memcpy(av7110->bin_fw, fw->data, fw->size);
1527 av7110->size_fw = fw->size;
1528 if ((ret = check_firmware(av7110)))
1529 vfree(av7110->bin_fw);
1530
1531 release_firmware(fw);
1532 return ret;
1533}
1534#endif
1535
1536
1537static int alps_bsrv2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
1538{
1539 struct av7110* av7110 = (struct av7110*) fe->dvb->priv;
1540 u8 pwr = 0;
1541 u8 buf[4];
1542 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
1543 u32 div = (params->frequency + 479500) / 125;
1544
1545 if (params->frequency > 2000000) pwr = 3;
1546 else if (params->frequency > 1800000) pwr = 2;
1547 else if (params->frequency > 1600000) pwr = 1;
1548 else if (params->frequency > 1200000) pwr = 0;
1549 else if (params->frequency >= 1100000) pwr = 1;
1550 else pwr = 2;
1551
1552 buf[0] = (div >> 8) & 0x7f;
1553 buf[1] = div & 0xff;
1554 buf[2] = ((div & 0x18000) >> 10) | 0x95;
1555 buf[3] = (pwr << 6) | 0x30;
1556
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -08001557 // NOTE: since we're using a prescaler of 2, we set the
Linus Torvalds1da177e2005-04-16 15:20:36 -07001558 // divisor frequency to 62.5kHz and divide by 125 above
1559
1560 if (i2c_transfer (&av7110->i2c_adap, &msg, 1) != 1)
1561 return -EIO;
1562 return 0;
1563}
1564
1565static struct ves1x93_config alps_bsrv2_config = {
1566 .demod_address = 0x08,
1567 .xin = 90100000UL,
1568 .invert_pwm = 0,
1569 .pll_set = alps_bsrv2_pll_set,
1570};
1571
1572
1573static u8 alps_bsru6_inittab[] = {
1574 0x01, 0x15,
1575 0x02, 0x30,
1576 0x03, 0x00,
1577 0x04, 0x7d, /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */
1578 0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */
1579 0x06, 0x40, /* DAC not used, set to high impendance mode */
1580 0x07, 0x00, /* DAC LSB */
1581 0x08, 0x40, /* DiSEqC off, LNB power on OP2/LOCK pin on */
1582 0x09, 0x00, /* FIFO */
1583 0x0c, 0x51, /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */
1584 0x0d, 0x82, /* DC offset compensation = ON, beta_agc1 = 2 */
1585 0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */
1586 0x10, 0x3f, // AGC2 0x3d
1587 0x11, 0x84,
Oliver Endrissff29d062005-11-08 21:35:43 -08001588 0x12, 0xb9,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001589 0x15, 0xc9, // lock detector threshold
1590 0x16, 0x00,
1591 0x17, 0x00,
1592 0x18, 0x00,
1593 0x19, 0x00,
1594 0x1a, 0x00,
1595 0x1f, 0x50,
1596 0x20, 0x00,
1597 0x21, 0x00,
1598 0x22, 0x00,
1599 0x23, 0x00,
1600 0x28, 0x00, // out imp: normal out type: parallel FEC mode:0
1601 0x29, 0x1e, // 1/2 threshold
1602 0x2a, 0x14, // 2/3 threshold
1603 0x2b, 0x0f, // 3/4 threshold
1604 0x2c, 0x09, // 5/6 threshold
1605 0x2d, 0x05, // 7/8 threshold
1606 0x2e, 0x01,
1607 0x31, 0x1f, // test all FECs
1608 0x32, 0x19, // viterbi and synchro search
1609 0x33, 0xfc, // rs control
1610 0x34, 0x93, // error control
1611 0x0f, 0x52,
1612 0xff, 0xff
1613};
1614
1615static int alps_bsru6_set_symbol_rate(struct dvb_frontend* fe, u32 srate, u32 ratio)
1616{
1617 u8 aclk = 0;
1618 u8 bclk = 0;
1619
1620 if (srate < 1500000) { aclk = 0xb7; bclk = 0x47; }
1621 else if (srate < 3000000) { aclk = 0xb7; bclk = 0x4b; }
1622 else if (srate < 7000000) { aclk = 0xb7; bclk = 0x4f; }
1623 else if (srate < 14000000) { aclk = 0xb7; bclk = 0x53; }
1624 else if (srate < 30000000) { aclk = 0xb6; bclk = 0x53; }
1625 else if (srate < 45000000) { aclk = 0xb4; bclk = 0x51; }
1626
1627 stv0299_writereg(fe, 0x13, aclk);
1628 stv0299_writereg(fe, 0x14, bclk);
1629 stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);
1630 stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff);
1631 stv0299_writereg(fe, 0x21, (ratio ) & 0xf0);
1632
1633 return 0;
1634}
1635
Andreas Oberrittercfbfce12005-09-09 13:02:30 -07001636static int alps_bsru6_pll_set(struct dvb_frontend* fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters* params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001637{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001638 int ret;
1639 u8 data[4];
1640 u32 div;
1641 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
1642
1643 if ((params->frequency < 950000) || (params->frequency > 2150000))
1644 return -EINVAL;
1645
1646 div = (params->frequency + (125 - 1)) / 125; // round correctly
1647 data[0] = (div >> 8) & 0x7f;
1648 data[1] = div & 0xff;
1649 data[2] = 0x80 | ((div & 0x18000) >> 10) | 4;
1650 data[3] = 0xC4;
1651
1652 if (params->frequency > 1530000) data[3] = 0xc0;
1653
Andreas Oberrittercfbfce12005-09-09 13:02:30 -07001654 ret = i2c_transfer(i2c, &msg, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001655 if (ret != 1)
1656 return -EIO;
1657 return 0;
1658}
1659
1660static struct stv0299_config alps_bsru6_config = {
1661
1662 .demod_address = 0x68,
1663 .inittab = alps_bsru6_inittab,
1664 .mclk = 88000000UL,
1665 .invert = 1,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001666 .skip_reinit = 0,
1667 .lock_output = STV0229_LOCKOUTPUT_1,
1668 .volt13_op0_op1 = STV0299_VOLT13_OP1,
1669 .min_delay_ms = 100,
1670 .set_symbol_rate = alps_bsru6_set_symbol_rate,
1671 .pll_set = alps_bsru6_pll_set,
1672};
1673
1674
Johannes Stezenbach3dfaebd2005-05-16 21:54:19 -07001675static u8 alps_bsbe1_inittab[] = {
1676 0x01, 0x15,
1677 0x02, 0x30,
1678 0x03, 0x00,
1679 0x04, 0x7d, /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */
1680 0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */
1681 0x06, 0x40, /* DAC not used, set to high impendance mode */
1682 0x07, 0x00, /* DAC LSB */
1683 0x08, 0x40, /* DiSEqC off, LNB power on OP2/LOCK pin on */
1684 0x09, 0x00, /* FIFO */
1685 0x0c, 0x51, /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */
1686 0x0d, 0x82, /* DC offset compensation = ON, beta_agc1 = 2 */
1687 0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */
1688 0x10, 0x3f, // AGC2 0x3d
1689 0x11, 0x84,
Oliver Endrissff29d062005-11-08 21:35:43 -08001690 0x12, 0xb9,
Johannes Stezenbach3dfaebd2005-05-16 21:54:19 -07001691 0x15, 0xc9, // lock detector threshold
1692 0x16, 0x00,
1693 0x17, 0x00,
1694 0x18, 0x00,
1695 0x19, 0x00,
1696 0x1a, 0x00,
1697 0x1f, 0x50,
1698 0x20, 0x00,
1699 0x21, 0x00,
1700 0x22, 0x00,
1701 0x23, 0x00,
1702 0x28, 0x00, // out imp: normal out type: parallel FEC mode:0
1703 0x29, 0x1e, // 1/2 threshold
1704 0x2a, 0x14, // 2/3 threshold
1705 0x2b, 0x0f, // 3/4 threshold
1706 0x2c, 0x09, // 5/6 threshold
1707 0x2d, 0x05, // 7/8 threshold
1708 0x2e, 0x01,
1709 0x31, 0x1f, // test all FECs
1710 0x32, 0x19, // viterbi and synchro search
1711 0x33, 0xfc, // rs control
1712 0x34, 0x93, // error control
1713 0x0f, 0x92,
1714 0xff, 0xff
1715};
1716
Andreas Oberrittercfbfce12005-09-09 13:02:30 -07001717static int alps_bsbe1_pll_set(struct dvb_frontend* fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters* params)
Johannes Stezenbach3dfaebd2005-05-16 21:54:19 -07001718{
Johannes Stezenbach3dfaebd2005-05-16 21:54:19 -07001719 int ret;
1720 u8 data[4];
1721 u32 div;
1722 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
1723
1724 if ((params->frequency < 950000) || (params->frequency > 2150000))
1725 return -EINVAL;
1726
1727 div = (params->frequency + (125 - 1)) / 125; // round correctly
1728 data[0] = (div >> 8) & 0x7f;
1729 data[1] = div & 0xff;
1730 data[2] = 0x80 | ((div & 0x18000) >> 10) | 4;
1731 data[3] = (params->frequency > 1530000) ? 0xE0 : 0xE4;
1732
Andreas Oberrittercfbfce12005-09-09 13:02:30 -07001733 ret = i2c_transfer(i2c, &msg, 1);
Johannes Stezenbach3dfaebd2005-05-16 21:54:19 -07001734 return (ret != 1) ? -EIO : 0;
1735}
1736
1737static struct stv0299_config alps_bsbe1_config = {
1738 .demod_address = 0x68,
1739 .inittab = alps_bsbe1_inittab,
1740 .mclk = 88000000UL,
1741 .invert = 1,
Johannes Stezenbach3dfaebd2005-05-16 21:54:19 -07001742 .skip_reinit = 0,
1743 .min_delay_ms = 100,
1744 .set_symbol_rate = alps_bsru6_set_symbol_rate,
1745 .pll_set = alps_bsbe1_pll_set,
1746};
1747
1748static int lnbp21_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
1749{
1750 struct av7110* av7110 = (struct av7110*) fe->dvb->priv;
1751 int ret;
1752 u8 data[1];
1753 struct i2c_msg msg = { .addr = 0x08, .flags = 0, .buf = data, .len = sizeof(data) };
1754
1755 switch(voltage) {
1756 case SEC_VOLTAGE_OFF:
1757 data[0] = 0x00;
1758 break;
1759 case SEC_VOLTAGE_13:
1760 data[0] = 0x44;
1761 break;
1762 case SEC_VOLTAGE_18:
1763 data[0] = 0x4c;
1764 break;
1765 default:
1766 return -EINVAL;
1767 };
1768
1769 ret = i2c_transfer(&av7110->i2c_adap, &msg, 1);
1770 return (ret != 1) ? -EIO : 0;
1771}
1772
Linus Torvalds1da177e2005-04-16 15:20:36 -07001773
1774static int alps_tdbe2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
1775{
1776 struct av7110* av7110 = fe->dvb->priv;
1777 u32 div;
1778 u8 data[4];
1779 struct i2c_msg msg = { .addr = 0x62, .flags = 0, .buf = data, .len = sizeof(data) };
1780
1781 div = (params->frequency + 35937500 + 31250) / 62500;
1782
1783 data[0] = (div >> 8) & 0x7f;
1784 data[1] = div & 0xff;
1785 data[2] = 0x85 | ((div >> 10) & 0x60);
1786 data[3] = (params->frequency < 174000000 ? 0x88 : params->frequency < 470000000 ? 0x84 : 0x81);
1787
1788 if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
1789 return -EIO;
1790 return 0;
1791}
1792
1793static struct ves1820_config alps_tdbe2_config = {
1794 .demod_address = 0x09,
1795 .xin = 57840000UL,
1796 .invert = 1,
1797 .selagc = VES1820_SELAGC_SIGNAMPERR,
1798 .pll_set = alps_tdbe2_pll_set,
1799};
1800
1801
1802
1803
1804static int grundig_29504_451_pll_set(struct dvb_frontend* fe,
1805 struct dvb_frontend_parameters* params)
1806{
1807 struct av7110* av7110 = fe->dvb->priv;
1808 u32 div;
1809 u8 data[4];
1810 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
1811
1812 div = params->frequency / 125;
1813 data[0] = (div >> 8) & 0x7f;
1814 data[1] = div & 0xff;
1815 data[2] = 0x8e;
1816 data[3] = 0x00;
1817
1818 if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
1819 return -EIO;
1820 return 0;
1821}
1822
1823static struct tda8083_config grundig_29504_451_config = {
1824 .demod_address = 0x68,
1825 .pll_set = grundig_29504_451_pll_set,
1826};
1827
1828
1829
1830static int philips_cd1516_pll_set(struct dvb_frontend* fe,
1831 struct dvb_frontend_parameters* params)
1832{
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -08001833 struct av7110* av7110 = fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001834 u32 div;
1835 u32 f = params->frequency;
1836 u8 data[4];
1837 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
1838
1839 div = (f + 36125000 + 31250) / 62500;
1840
1841 data[0] = (div >> 8) & 0x7f;
1842 data[1] = div & 0xff;
1843 data[2] = 0x8e;
1844 data[3] = (f < 174000000 ? 0xa1 : f < 470000000 ? 0x92 : 0x34);
1845
1846 if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
1847 return -EIO;
1848 return 0;
1849}
1850
1851static struct ves1820_config philips_cd1516_config = {
1852 .demod_address = 0x09,
1853 .xin = 57840000UL,
1854 .invert = 1,
1855 .selagc = VES1820_SELAGC_SIGNAMPERR,
1856 .pll_set = philips_cd1516_pll_set,
1857};
1858
1859
1860
1861static int alps_tdlb7_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
1862{
1863 struct av7110* av7110 = fe->dvb->priv;
1864 u32 div, pwr;
1865 u8 data[4];
1866 struct i2c_msg msg = { .addr = 0x60, .flags = 0, .buf = data, .len = sizeof(data) };
1867
1868 div = (params->frequency + 36200000) / 166666;
1869
1870 if (params->frequency <= 782000000)
1871 pwr = 1;
1872 else
1873 pwr = 2;
1874
1875 data[0] = (div >> 8) & 0x7f;
1876 data[1] = div & 0xff;
1877 data[2] = 0x85;
1878 data[3] = pwr << 6;
1879
1880 if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
1881 return -EIO;
1882 return 0;
1883}
1884
1885static int alps_tdlb7_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name)
1886{
1887 struct av7110* av7110 = (struct av7110*) fe->dvb->priv;
1888
1889 return request_firmware(fw, name, &av7110->dev->pci->dev);
1890}
1891
1892static struct sp8870_config alps_tdlb7_config = {
1893
1894 .demod_address = 0x71,
1895 .pll_set = alps_tdlb7_pll_set,
1896 .request_firmware = alps_tdlb7_request_firmware,
1897};
1898
1899
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001900static u8 nexusca_stv0297_inittab[] = {
1901 0x80, 0x01,
1902 0x80, 0x00,
1903 0x81, 0x01,
1904 0x81, 0x00,
1905 0x00, 0x09,
1906 0x01, 0x69,
1907 0x03, 0x00,
1908 0x04, 0x00,
1909 0x07, 0x00,
1910 0x08, 0x00,
1911 0x20, 0x00,
1912 0x21, 0x40,
1913 0x22, 0x00,
1914 0x23, 0x00,
1915 0x24, 0x40,
1916 0x25, 0x88,
1917 0x30, 0xff,
1918 0x31, 0x00,
1919 0x32, 0xff,
1920 0x33, 0x00,
1921 0x34, 0x50,
1922 0x35, 0x7f,
1923 0x36, 0x00,
1924 0x37, 0x20,
1925 0x38, 0x00,
1926 0x40, 0x1c,
1927 0x41, 0xff,
1928 0x42, 0x29,
1929 0x43, 0x00,
1930 0x44, 0xff,
1931 0x45, 0x00,
1932 0x46, 0x00,
1933 0x49, 0x04,
1934 0x4a, 0x00,
1935 0x4b, 0x7b,
1936 0x52, 0x30,
1937 0x55, 0xae,
1938 0x56, 0x47,
1939 0x57, 0xe1,
1940 0x58, 0x3a,
1941 0x5a, 0x1e,
1942 0x5b, 0x34,
1943 0x60, 0x00,
1944 0x63, 0x00,
1945 0x64, 0x00,
1946 0x65, 0x00,
1947 0x66, 0x00,
1948 0x67, 0x00,
1949 0x68, 0x00,
1950 0x69, 0x00,
1951 0x6a, 0x02,
1952 0x6b, 0x00,
1953 0x70, 0xff,
1954 0x71, 0x00,
1955 0x72, 0x00,
1956 0x73, 0x00,
1957 0x74, 0x0c,
1958 0x80, 0x00,
1959 0x81, 0x00,
1960 0x82, 0x00,
1961 0x83, 0x00,
1962 0x84, 0x04,
1963 0x85, 0x80,
1964 0x86, 0x24,
1965 0x87, 0x78,
1966 0x88, 0x10,
1967 0x89, 0x00,
1968 0x90, 0x01,
1969 0x91, 0x01,
1970 0xa0, 0x04,
1971 0xa1, 0x00,
1972 0xa2, 0x00,
1973 0xb0, 0x91,
1974 0xb1, 0x0b,
1975 0xc0, 0x53,
1976 0xc1, 0x70,
1977 0xc2, 0x12,
1978 0xd0, 0x00,
1979 0xd1, 0x00,
1980 0xd2, 0x00,
1981 0xd3, 0x00,
1982 0xd4, 0x00,
1983 0xd5, 0x00,
1984 0xde, 0x00,
1985 0xdf, 0x00,
1986 0x61, 0x49,
1987 0x62, 0x0b,
1988 0x53, 0x08,
1989 0x59, 0x08,
1990 0xff, 0xff,
1991};
Linus Torvalds1da177e2005-04-16 15:20:36 -07001992
1993static int nexusca_stv0297_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
1994{
1995 struct av7110* av7110 = fe->dvb->priv;
1996 u32 div;
1997 u8 data[4];
1998 struct i2c_msg msg = { .addr = 0x63, .flags = 0, .buf = data, .len = sizeof(data) };
1999 struct i2c_msg readmsg = { .addr = 0x63, .flags = I2C_M_RD, .buf = data, .len = 1 };
2000 int i;
2001
2002 div = (params->frequency + 36150000 + 31250) / 62500;
2003
2004 data[0] = (div >> 8) & 0x7f;
2005 data[1] = div & 0xff;
2006 data[2] = 0xce;
2007
2008 if (params->frequency < 45000000)
2009 return -EINVAL;
2010 else if (params->frequency < 137000000)
2011 data[3] = 0x01;
2012 else if (params->frequency < 403000000)
2013 data[3] = 0x02;
2014 else if (params->frequency < 860000000)
2015 data[3] = 0x04;
2016 else
2017 return -EINVAL;
2018
2019 stv0297_enable_plli2c(fe);
2020 if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1) {
2021 printk("nexusca: pll transfer failed!\n");
2022 return -EIO;
2023 }
2024
2025 // wait for PLL lock
2026 for(i = 0; i < 20; i++) {
2027
2028 stv0297_enable_plli2c(fe);
2029 if (i2c_transfer(&av7110->i2c_adap, &readmsg, 1) == 1)
2030 if (data[0] & 0x40) break;
2031 msleep(10);
2032 }
2033
2034 return 0;
2035}
2036
2037static struct stv0297_config nexusca_stv0297_config = {
2038
2039 .demod_address = 0x1C,
Andrew de Quinceydc27a162005-09-09 13:03:07 -07002040 .inittab = nexusca_stv0297_inittab,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002041 .invert = 1,
2042 .pll_set = nexusca_stv0297_pll_set,
2043};
2044
2045
2046
2047static int grundig_29504_401_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
2048{
2049 struct av7110* av7110 = (struct av7110*) fe->dvb->priv;
2050 u32 div;
2051 u8 cfg, cpump, band_select;
2052 u8 data[4];
2053 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
2054
2055 div = (36125000 + params->frequency) / 166666;
2056
2057 cfg = 0x88;
2058
2059 if (params->frequency < 175000000) cpump = 2;
2060 else if (params->frequency < 390000000) cpump = 1;
2061 else if (params->frequency < 470000000) cpump = 2;
2062 else if (params->frequency < 750000000) cpump = 1;
2063 else cpump = 3;
2064
2065 if (params->frequency < 175000000) band_select = 0x0e;
2066 else if (params->frequency < 470000000) band_select = 0x05;
2067 else band_select = 0x03;
2068
2069 data[0] = (div >> 8) & 0x7f;
2070 data[1] = div & 0xff;
2071 data[2] = ((div >> 10) & 0x60) | cfg;
2072 data[3] = (cpump << 6) | band_select;
2073
2074 if (i2c_transfer (&av7110->i2c_adap, &msg, 1) != 1) return -EIO;
2075 return 0;
2076}
2077
2078static struct l64781_config grundig_29504_401_config = {
2079 .demod_address = 0x55,
2080 .pll_set = grundig_29504_401_pll_set,
2081};
2082
2083
2084
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002085static int av7110_fe_lock_fix(struct av7110* av7110, fe_status_t status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002086{
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002087 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002088 int synced = (status & FE_HAS_LOCK) ? 1 : 0;
2089
2090 av7110->fe_status = status;
2091
2092 if (av7110->fe_synced == synced)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002093 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002094
Linus Torvalds1da177e2005-04-16 15:20:36 -07002095 if (av7110->playing)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002096 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002097
Ingo Molnar3593cab2006-02-07 06:49:14 -02002098 if (mutex_lock_interruptible(&av7110->pid_mutex))
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002099 return -ERESTARTSYS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002100
Oliver Endriss34612152005-07-07 17:58:02 -07002101 if (synced) {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002102 ret = SetPIDs(av7110, av7110->pids[DMX_PES_VIDEO],
Linus Torvalds1da177e2005-04-16 15:20:36 -07002103 av7110->pids[DMX_PES_AUDIO],
2104 av7110->pids[DMX_PES_TELETEXT], 0,
2105 av7110->pids[DMX_PES_PCR]);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002106 if (!ret)
2107 ret = av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, Scan, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002108 } else {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002109 ret = SetPIDs(av7110, 0, 0, 0, 0, 0);
2110 if (!ret) {
2111 ret = av7110_fw_cmd(av7110, COMTYPE_PID_FILTER, FlushTSQueue, 0);
2112 if (!ret)
2113 ret = av7110_wait_msgstate(av7110, GPMQBusy);
2114 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002115 }
2116
Oliver Endriss34612152005-07-07 17:58:02 -07002117 if (!ret)
2118 av7110->fe_synced = synced;
2119
Ingo Molnar3593cab2006-02-07 06:49:14 -02002120 mutex_unlock(&av7110->pid_mutex);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002121 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002122}
2123
2124static int av7110_fe_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
2125{
2126 struct av7110* av7110 = fe->dvb->priv;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002127
2128 int ret = av7110_fe_lock_fix(av7110, 0);
Oliver Endriss66190a22006-01-09 15:32:42 -02002129 if (!ret) {
2130 av7110->saved_fe_params = *params;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002131 ret = av7110->fe_set_frontend(fe, params);
Oliver Endriss66190a22006-01-09 15:32:42 -02002132 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002133 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002134}
2135
2136static int av7110_fe_init(struct dvb_frontend* fe)
2137{
2138 struct av7110* av7110 = fe->dvb->priv;
2139
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002140 int ret = av7110_fe_lock_fix(av7110, 0);
2141 if (!ret)
2142 ret = av7110->fe_init(fe);
2143 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002144}
2145
2146static int av7110_fe_read_status(struct dvb_frontend* fe, fe_status_t* status)
2147{
2148 struct av7110* av7110 = fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002149
2150 /* call the real implementation */
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002151 int ret = av7110->fe_read_status(fe, status);
2152 if (!ret)
2153 if (((*status ^ av7110->fe_status) & FE_HAS_LOCK) && (*status & FE_HAS_LOCK))
2154 ret = av7110_fe_lock_fix(av7110, *status);
2155 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002156}
2157
2158static int av7110_fe_diseqc_reset_overload(struct dvb_frontend* fe)
2159{
2160 struct av7110* av7110 = fe->dvb->priv;
2161
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002162 int ret = av7110_fe_lock_fix(av7110, 0);
2163 if (!ret)
2164 ret = av7110->fe_diseqc_reset_overload(fe);
2165 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002166}
2167
2168static int av7110_fe_diseqc_send_master_cmd(struct dvb_frontend* fe,
2169 struct dvb_diseqc_master_cmd* cmd)
2170{
2171 struct av7110* av7110 = fe->dvb->priv;
2172
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002173 int ret = av7110_fe_lock_fix(av7110, 0);
Oliver Endriss66190a22006-01-09 15:32:42 -02002174 if (!ret) {
2175 av7110->saved_master_cmd = *cmd;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002176 ret = av7110->fe_diseqc_send_master_cmd(fe, cmd);
Oliver Endriss66190a22006-01-09 15:32:42 -02002177 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002178 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002179}
2180
2181static int av7110_fe_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd)
2182{
2183 struct av7110* av7110 = fe->dvb->priv;
2184
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002185 int ret = av7110_fe_lock_fix(av7110, 0);
Oliver Endriss66190a22006-01-09 15:32:42 -02002186 if (!ret) {
2187 av7110->saved_minicmd = minicmd;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002188 ret = av7110->fe_diseqc_send_burst(fe, minicmd);
Oliver Endriss66190a22006-01-09 15:32:42 -02002189 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002190 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002191}
2192
2193static int av7110_fe_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
2194{
2195 struct av7110* av7110 = fe->dvb->priv;
2196
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002197 int ret = av7110_fe_lock_fix(av7110, 0);
Oliver Endriss66190a22006-01-09 15:32:42 -02002198 if (!ret) {
2199 av7110->saved_tone = tone;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002200 ret = av7110->fe_set_tone(fe, tone);
Oliver Endriss66190a22006-01-09 15:32:42 -02002201 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002202 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002203}
2204
2205static int av7110_fe_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
2206{
2207 struct av7110* av7110 = fe->dvb->priv;
2208
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002209 int ret = av7110_fe_lock_fix(av7110, 0);
Oliver Endriss66190a22006-01-09 15:32:42 -02002210 if (!ret) {
2211 av7110->saved_voltage = voltage;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002212 ret = av7110->fe_set_voltage(fe, voltage);
Oliver Endriss66190a22006-01-09 15:32:42 -02002213 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002214 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002215}
2216
Peter Beutner400b7082006-01-09 15:32:43 -02002217static int av7110_fe_dishnetwork_send_legacy_command(struct dvb_frontend* fe, unsigned long cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002218{
2219 struct av7110* av7110 = fe->dvb->priv;
2220
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002221 int ret = av7110_fe_lock_fix(av7110, 0);
2222 if (!ret)
2223 ret = av7110->fe_dishnetwork_send_legacy_command(fe, cmd);
2224 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002225}
2226
Oliver Endriss66190a22006-01-09 15:32:42 -02002227static void dvb_s_recover(struct av7110* av7110)
2228{
2229 av7110_fe_init(av7110->fe);
2230
2231 av7110_fe_set_voltage(av7110->fe, av7110->saved_voltage);
2232 if (av7110->saved_master_cmd.msg_len) {
2233 msleep(20);
2234 av7110_fe_diseqc_send_master_cmd(av7110->fe, &av7110->saved_master_cmd);
2235 }
2236 msleep(20);
2237 av7110_fe_diseqc_send_burst(av7110->fe, av7110->saved_minicmd);
2238 msleep(20);
2239 av7110_fe_set_tone(av7110->fe, av7110->saved_tone);
2240
2241 av7110_fe_set_frontend(av7110->fe, &av7110->saved_fe_params);
2242}
2243
Linus Torvalds1da177e2005-04-16 15:20:36 -07002244static u8 read_pwm(struct av7110* av7110)
2245{
2246 u8 b = 0xff;
2247 u8 pwm;
2248 struct i2c_msg msg[] = { { .addr = 0x50,.flags = 0,.buf = &b,.len = 1 },
2249 { .addr = 0x50,.flags = I2C_M_RD,.buf = &pwm,.len = 1} };
2250
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -08002251 if ((i2c_transfer(&av7110->i2c_adap, msg, 2) != 2) || (pwm == 0xff))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002252 pwm = 0x48;
2253
2254 return pwm;
2255}
2256
2257static int frontend_init(struct av7110 *av7110)
2258{
2259 int ret;
2260
2261 if (av7110->dev->pci->subsystem_vendor == 0x110a) {
2262 switch(av7110->dev->pci->subsystem_device) {
2263 case 0x0000: // Fujitsu/Siemens DVB-Cable (ves1820/Philips CD1516(??))
2264 av7110->fe = ves1820_attach(&philips_cd1516_config,
2265 &av7110->i2c_adap, read_pwm(av7110));
2266 break;
2267 }
2268
2269 } else if (av7110->dev->pci->subsystem_vendor == 0x13c2) {
2270 switch(av7110->dev->pci->subsystem_device) {
2271 case 0x0000: // Hauppauge/TT WinTV DVB-S rev1.X
2272 case 0x0003: // Hauppauge/TT WinTV Nexus-S Rev 2.X
2273 case 0x1002: // Hauppauge/TT WinTV DVB-S rev1.3SE
2274
2275 // try the ALPS BSRV2 first of all
2276 av7110->fe = ves1x93_attach(&alps_bsrv2_config, &av7110->i2c_adap);
2277 if (av7110->fe) {
2278 av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
2279 av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst;
2280 av7110->fe->ops->set_tone = av7110_set_tone;
Oliver Endriss66190a22006-01-09 15:32:42 -02002281 av7110->recover = dvb_s_recover;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002282 break;
2283 }
2284
2285 // try the ALPS BSRU6 now
2286 av7110->fe = stv0299_attach(&alps_bsru6_config, &av7110->i2c_adap);
2287 if (av7110->fe) {
2288 av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
2289 av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst;
2290 av7110->fe->ops->set_tone = av7110_set_tone;
Oliver Endriss66190a22006-01-09 15:32:42 -02002291 av7110->recover = dvb_s_recover;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002292 break;
2293 }
2294
2295 // Try the grundig 29504-451
Michael Krufky50c25ff2006-01-09 15:25:34 -02002296 av7110->fe = tda8083_attach(&grundig_29504_451_config, &av7110->i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002297 if (av7110->fe) {
2298 av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
2299 av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst;
2300 av7110->fe->ops->set_tone = av7110_set_tone;
Oliver Endriss66190a22006-01-09 15:32:42 -02002301 av7110->recover = dvb_s_recover;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002302 break;
2303 }
2304
2305 /* Try DVB-C cards */
2306 switch(av7110->dev->pci->subsystem_device) {
2307 case 0x0000:
2308 /* Siemens DVB-C (full-length card) VES1820/Philips CD1516 */
2309 av7110->fe = ves1820_attach(&philips_cd1516_config, &av7110->i2c_adap,
2310 read_pwm(av7110));
2311 break;
2312 case 0x0003:
2313 /* Haupauge DVB-C 2.1 VES1820/ALPS TDBE2 */
2314 av7110->fe = ves1820_attach(&alps_tdbe2_config, &av7110->i2c_adap,
2315 read_pwm(av7110));
2316 break;
2317 }
2318 break;
2319
2320 case 0x0001: // Hauppauge/TT Nexus-T premium rev1.X
2321
2322 // ALPS TDLB7
Michael Krufky50c25ff2006-01-09 15:25:34 -02002323 av7110->fe = sp8870_attach(&alps_tdlb7_config, &av7110->i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002324 break;
2325
2326 case 0x0002: // Hauppauge/TT DVB-C premium rev2.X
2327
Michael Krufky50c25ff2006-01-09 15:25:34 -02002328 av7110->fe = ves1820_attach(&alps_tdbe2_config, &av7110->i2c_adap, read_pwm(av7110));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002329 break;
2330
Oliver Endriss8bd63012006-02-07 06:49:11 -02002331 case 0x0004: // Galaxis DVB-S rev1.3
2332 /* ALPS BSRV2 */
2333 av7110->fe = ves1x93_attach(&alps_bsrv2_config, &av7110->i2c_adap);
2334 if (av7110->fe) {
2335 av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
2336 av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst;
2337 av7110->fe->ops->set_tone = av7110_set_tone;
2338 av7110->recover = dvb_s_recover;
2339 }
2340 break;
2341
Linus Torvalds1da177e2005-04-16 15:20:36 -07002342 case 0x0006: /* Fujitsu-Siemens DVB-S rev 1.6 */
2343 /* Grundig 29504-451 */
2344 av7110->fe = tda8083_attach(&grundig_29504_451_config, &av7110->i2c_adap);
2345 if (av7110->fe) {
2346 av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
2347 av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst;
2348 av7110->fe->ops->set_tone = av7110_set_tone;
Oliver Endriss66190a22006-01-09 15:32:42 -02002349 av7110->recover = dvb_s_recover;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002350 }
2351 break;
2352
2353 case 0x0008: // Hauppauge/TT DVB-T
2354
2355 av7110->fe = l64781_attach(&grundig_29504_401_config, &av7110->i2c_adap);
2356 break;
2357
2358 case 0x000A: // Hauppauge/TT Nexus-CA rev1.X
2359
Andrew de Quinceydc27a162005-09-09 13:03:07 -07002360 av7110->fe = stv0297_attach(&nexusca_stv0297_config, &av7110->i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002361 if (av7110->fe) {
2362 /* set TDA9819 into DVB mode */
2363 saa7146_setgpio(av7110->dev, 1, SAA7146_GPIO_OUTLO); // TDA9198 pin9(STD)
2364 saa7146_setgpio(av7110->dev, 3, SAA7146_GPIO_OUTLO); // TDA9198 pin30(VIF)
2365
2366 /* tuner on this needs a slower i2c bus speed */
2367 av7110->dev->i2c_bitrate = SAA7146_I2C_BUS_BIT_RATE_240;
2368 break;
2369 }
Johannes Stezenbach3dfaebd2005-05-16 21:54:19 -07002370 break;
2371
2372 case 0x000E: /* Hauppauge/TT Nexus-S rev 2.3 */
2373 /* ALPS BSBE1 */
2374 av7110->fe = stv0299_attach(&alps_bsbe1_config, &av7110->i2c_adap);
Oliver Endrisseb3daf32006-01-09 15:25:05 -02002375 if (av7110->fe) {
Johannes Stezenbach3dfaebd2005-05-16 21:54:19 -07002376 av7110->fe->ops->set_voltage = lnbp21_set_voltage;
Oliver Endrisseb3daf32006-01-09 15:25:05 -02002377 av7110->fe->ops->dishnetwork_send_legacy_command = NULL;
Oliver Endriss66190a22006-01-09 15:32:42 -02002378 av7110->recover = dvb_s_recover;
Oliver Endrisseb3daf32006-01-09 15:25:05 -02002379 }
Johannes Stezenbach3dfaebd2005-05-16 21:54:19 -07002380 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002381 }
2382 }
2383
2384 if (!av7110->fe) {
2385 /* FIXME: propagate the failure code from the lower layers */
2386 ret = -ENOMEM;
2387 printk("dvb-ttpci: A frontend driver was not found for device %04x/%04x subsystem %04x/%04x\n",
2388 av7110->dev->pci->vendor,
2389 av7110->dev->pci->device,
2390 av7110->dev->pci->subsystem_vendor,
2391 av7110->dev->pci->subsystem_device);
2392 } else {
2393 FE_FUNC_OVERRIDE(av7110->fe->ops->init, av7110->fe_init, av7110_fe_init);
2394 FE_FUNC_OVERRIDE(av7110->fe->ops->read_status, av7110->fe_read_status, av7110_fe_read_status);
2395 FE_FUNC_OVERRIDE(av7110->fe->ops->diseqc_reset_overload, av7110->fe_diseqc_reset_overload, av7110_fe_diseqc_reset_overload);
2396 FE_FUNC_OVERRIDE(av7110->fe->ops->diseqc_send_master_cmd, av7110->fe_diseqc_send_master_cmd, av7110_fe_diseqc_send_master_cmd);
2397 FE_FUNC_OVERRIDE(av7110->fe->ops->diseqc_send_burst, av7110->fe_diseqc_send_burst, av7110_fe_diseqc_send_burst);
2398 FE_FUNC_OVERRIDE(av7110->fe->ops->set_tone, av7110->fe_set_tone, av7110_fe_set_tone);
2399 FE_FUNC_OVERRIDE(av7110->fe->ops->set_voltage, av7110->fe_set_voltage, av7110_fe_set_voltage;)
2400 FE_FUNC_OVERRIDE(av7110->fe->ops->dishnetwork_send_legacy_command, av7110->fe_dishnetwork_send_legacy_command, av7110_fe_dishnetwork_send_legacy_command);
2401 FE_FUNC_OVERRIDE(av7110->fe->ops->set_frontend, av7110->fe_set_frontend, av7110_fe_set_frontend);
2402
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07002403 ret = dvb_register_frontend(&av7110->dvb_adapter, av7110->fe);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002404 if (ret < 0) {
2405 printk("av7110: Frontend registration failed!\n");
2406 if (av7110->fe->ops->release)
2407 av7110->fe->ops->release(av7110->fe);
2408 av7110->fe = NULL;
2409 }
2410 }
2411 return ret;
2412}
2413
2414/* Budgetpatch note:
2415 * Original hardware design by Roberto Deza:
2416 * There is a DVB_Wiki at
2417 * http://212.227.36.83/linuxtv/wiki/index.php/Main_Page
2418 * where is described this 'DVB TT Budget Patch', on Card Modding:
2419 * http://212.227.36.83/linuxtv/wiki/index.php/DVB_TT_Budget_Patch
2420 * On the short description there is also a link to a external file,
2421 * with more details:
2422 * http://perso.wanadoo.es/jesussolano/Ttf_tsc1.zip
2423 *
2424 * New software triggering design by Emard that works on
2425 * original Roberto Deza's hardware:
2426 *
2427 * rps1 code for budgetpatch will copy internal HS event to GPIO3 pin.
2428 * GPIO3 is in budget-patch hardware connectd to port B VSYNC
2429 * HS is an internal event of 7146, accessible with RPS
2430 * and temporarily raised high every n lines
2431 * (n in defined in the RPS_THRESH1 counter threshold)
2432 * I think HS is raised high on the beginning of the n-th line
2433 * and remains high until this n-th line that triggered
2434 * it is completely received. When the receiption of n-th line
2435 * ends, HS is lowered.
2436 *
2437 * To transmit data over DMA, 7146 needs changing state at
2438 * port B VSYNC pin. Any changing of port B VSYNC will
2439 * cause some DMA data transfer, with more or less packets loss.
2440 * It depends on the phase and frequency of VSYNC and
2441 * the way of 7146 is instructed to trigger on port B (defined
2442 * in DD1_INIT register, 3rd nibble from the right valid
2443 * numbers are 0-7, see datasheet)
2444 *
2445 * The correct triggering can minimize packet loss,
2446 * dvbtraffic should give this stable bandwidths:
2447 * 22k transponder = 33814 kbit/s
2448 * 27.5k transponder = 38045 kbit/s
2449 * by experiment it is found that the best results
2450 * (stable bandwidths and almost no packet loss)
2451 * are obtained using DD1_INIT triggering number 2
2452 * (Va at rising edge of VS Fa = HS x VS-failing forced toggle)
2453 * and a VSYNC phase that occurs in the middle of DMA transfer
2454 * (about byte 188*512=96256 in the DMA window).
2455 *
2456 * Phase of HS is still not clear to me how to control,
2457 * It just happens to be so. It can be seen if one enables
2458 * RPS_IRQ and print Event Counter 1 in vpeirq(). Every
2459 * time RPS_INTERRUPT is called, the Event Counter 1 will
2460 * increment. That's how the 7146 is programmed to do event
2461 * counting in this budget-patch.c
2462 * I *think* HPS setting has something to do with the phase
2463 * of HS but I cant be 100% sure in that.
2464 *
2465 * hardware debug note: a working budget card (including budget patch)
2466 * with vpeirq() interrupt setup in mode "0x90" (every 64K) will
2467 * generate 3 interrupts per 25-Hz DMA frame of 2*188*512 bytes
2468 * and that means 3*25=75 Hz of interrupt freqency, as seen by
2469 * watch cat /proc/interrupts
2470 *
2471 * If this frequency is 3x lower (and data received in the DMA
2472 * buffer don't start with 0x47, but in the middle of packets,
2473 * whose lengths appear to be like 188 292 188 104 etc.
2474 * this means VSYNC line is not connected in the hardware.
2475 * (check soldering pcb and pins)
2476 * The same behaviour of missing VSYNC can be duplicated on budget
2477 * cards, by seting DD1_INIT trigger mode 7 in 3rd nibble.
2478 */
Johannes Stezenbach1be11e32006-02-27 00:09:20 -03002479static int __devinit av7110_attach(struct saa7146_dev* dev,
2480 struct saa7146_pci_extension_data *pci_ext)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002481{
2482 const int length = TS_WIDTH * TS_HEIGHT;
2483 struct pci_dev *pdev = dev->pci;
2484 struct av7110 *av7110;
2485 int ret, count = 0;
2486
2487 dprintk(4, "dev: %p\n", dev);
2488
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -08002489 /* Set RPS_IRQ to 1 to track rps1 activity.
2490 * Enabling this won't send any interrupt to PC CPU.
2491 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002492#define RPS_IRQ 0
2493
2494 if (budgetpatch == 1) {
2495 budgetpatch = 0;
2496 /* autodetect the presence of budget patch
2497 * this only works if saa7146 has been recently
2498 * reset with with MASK_31 to MC1
2499 *
2500 * will wait for VBI_B event (vertical blank at port B)
2501 * and will reset GPIO3 after VBI_B is detected.
2502 * (GPIO3 should be raised high by CPU to
2503 * test if GPIO3 will generate vertical blank signal
2504 * in budget patch GPIO3 is connected to VSYNC_B
2505 */
2506
2507 /* RESET SAA7146 */
2508 saa7146_write(dev, MC1, MASK_31);
2509 /* autodetection success seems to be time-dependend after reset */
2510
2511 /* Fix VSYNC level */
2512 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
2513 /* set vsync_b triggering */
2514 saa7146_write(dev, DD1_STREAM_B, 0);
2515 /* port B VSYNC at rising edge */
2516 saa7146_write(dev, DD1_INIT, 0x00000200);
2517 saa7146_write(dev, BRS_CTRL, 0x00000000); // VBI
2518 saa7146_write(dev, MC2,
2519 1 * (MASK_08 | MASK_24) | // BRS control
2520 0 * (MASK_09 | MASK_25) | // a
2521 1 * (MASK_10 | MASK_26) | // b
2522 0 * (MASK_06 | MASK_22) | // HPS_CTRL1
2523 0 * (MASK_05 | MASK_21) | // HPS_CTRL2
2524 0 * (MASK_01 | MASK_15) // DEBI
2525 );
2526
2527 /* start writing RPS1 code from beginning */
2528 count = 0;
2529 /* Disable RPS1 */
2530 saa7146_write(dev, MC1, MASK_29);
2531 /* RPS1 timeout disable */
2532 saa7146_write(dev, RPS_TOV1, 0);
2533 WRITE_RPS1(cpu_to_le32(CMD_PAUSE | EVT_VBI_B));
2534 WRITE_RPS1(cpu_to_le32(CMD_WR_REG_MASK | (GPIO_CTRL>>2)));
2535 WRITE_RPS1(cpu_to_le32(GPIO3_MSK));
2536 WRITE_RPS1(cpu_to_le32(SAA7146_GPIO_OUTLO<<24));
2537#if RPS_IRQ
2538 /* issue RPS1 interrupt to increment counter */
2539 WRITE_RPS1(cpu_to_le32(CMD_INTERRUPT));
2540#endif
2541 WRITE_RPS1(cpu_to_le32(CMD_STOP));
2542 /* Jump to begin of RPS program as safety measure (p37) */
2543 WRITE_RPS1(cpu_to_le32(CMD_JUMP));
2544 WRITE_RPS1(cpu_to_le32(dev->d_rps1.dma_handle));
2545
2546#if RPS_IRQ
2547 /* set event counter 1 source as RPS1 interrupt (0x03) (rE4 p53)
2548 * use 0x03 to track RPS1 interrupts - increase by 1 every gpio3 is toggled
2549 * use 0x15 to track VPE interrupts - increase by 1 every vpeirq() is called
2550 */
2551 saa7146_write(dev, EC1SSR, (0x03<<2) | 3 );
2552 /* set event counter 1 treshold to maximum allowed value (rEC p55) */
2553 saa7146_write(dev, ECT1R, 0x3fff );
2554#endif
2555 /* Set RPS1 Address register to point to RPS code (r108 p42) */
2556 saa7146_write(dev, RPS_ADDR1, dev->d_rps1.dma_handle);
2557 /* Enable RPS1, (rFC p33) */
2558 saa7146_write(dev, MC1, (MASK_13 | MASK_29 ));
2559
2560 mdelay(10);
2561 /* now send VSYNC_B to rps1 by rising GPIO3 */
2562 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI);
2563 mdelay(10);
2564 /* if rps1 responded by lowering the GPIO3,
2565 * then we have budgetpatch hardware
2566 */
2567 if ((saa7146_read(dev, GPIO_CTRL) & 0x10000000) == 0) {
2568 budgetpatch = 1;
2569 printk("dvb-ttpci: BUDGET-PATCH DETECTED.\n");
2570 }
2571 /* Disable RPS1 */
2572 saa7146_write(dev, MC1, ( MASK_29 ));
2573#if RPS_IRQ
2574 printk("dvb-ttpci: Event Counter 1 0x%04x\n", saa7146_read(dev, EC1R) & 0x3fff );
2575#endif
2576 }
2577
2578 /* prepare the av7110 device struct */
Panagiotis Issaris74081872006-01-11 19:40:56 -02002579 av7110 = kzalloc(sizeof(struct av7110), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002580 if (!av7110) {
2581 dprintk(1, "out of memory\n");
2582 return -ENOMEM;
2583 }
2584
Linus Torvalds1da177e2005-04-16 15:20:36 -07002585 av7110->card_name = (char*) pci_ext->ext_priv;
2586 av7110->dev = dev;
2587 dev->ext_priv = av7110;
2588
2589 ret = get_firmware(av7110);
2590 if (ret < 0)
2591 goto err_kfree_0;
2592
2593 ret = dvb_register_adapter(&av7110->dvb_adapter, av7110->card_name,
2594 THIS_MODULE);
2595 if (ret < 0)
2596 goto err_put_firmware_1;
2597
2598 /* the Siemens DVB needs this if you want to have the i2c chips
2599 get recognized before the main driver is fully loaded */
2600 saa7146_write(dev, GPIO_CTRL, 0x500000);
2601
2602#ifdef I2C_ADAP_CLASS_TV_DIGITAL
2603 av7110->i2c_adap.class = I2C_ADAP_CLASS_TV_DIGITAL;
2604#else
2605 av7110->i2c_adap.class = I2C_CLASS_TV_DIGITAL;
2606#endif
2607 strlcpy(av7110->i2c_adap.name, pci_ext->ext_priv, sizeof(av7110->i2c_adap.name));
2608
2609 saa7146_i2c_adapter_prepare(dev, &av7110->i2c_adap, SAA7146_I2C_BUS_BIT_RATE_120); /* 275 kHz */
2610
2611 ret = i2c_add_adapter(&av7110->i2c_adap);
2612 if (ret < 0)
2613 goto err_dvb_unregister_adapter_2;
2614
2615 ttpci_eeprom_parse_mac(&av7110->i2c_adap,
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07002616 av7110->dvb_adapter.proposed_mac);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002617 ret = -ENOMEM;
2618
2619 if (budgetpatch) {
2620 spin_lock_init(&av7110->feedlock1);
2621 av7110->grabbing = saa7146_vmalloc_build_pgtable(pdev, length,
2622 &av7110->pt);
2623 if (!av7110->grabbing)
2624 goto err_i2c_del_3;
2625
2626 saa7146_write(dev, PCI_BT_V1, 0x1c1f101f);
2627 saa7146_write(dev, BCS_CTRL, 0x80400040);
2628 /* set dd1 stream a & b */
2629 saa7146_write(dev, DD1_STREAM_B, 0x00000000);
2630 saa7146_write(dev, DD1_INIT, 0x03000200);
2631 saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
2632 saa7146_write(dev, BRS_CTRL, 0x60000000);
2633 saa7146_write(dev, BASE_ODD3, 0);
2634 saa7146_write(dev, BASE_EVEN3, 0);
2635 saa7146_write(dev, PROT_ADDR3, TS_WIDTH * TS_HEIGHT);
2636 saa7146_write(dev, BASE_PAGE3, av7110->pt.dma | ME1 | 0x90);
2637
2638 saa7146_write(dev, PITCH3, TS_WIDTH);
2639 saa7146_write(dev, NUM_LINE_BYTE3, (TS_HEIGHT << 16) | TS_WIDTH);
2640
2641 /* upload all */
2642 saa7146_write(dev, MC2, 0x077c077c);
2643 saa7146_write(dev, GPIO_CTRL, 0x000000);
2644#if RPS_IRQ
2645 /* set event counter 1 source as RPS1 interrupt (0x03) (rE4 p53)
2646 * use 0x03 to track RPS1 interrupts - increase by 1 every gpio3 is toggled
2647 * use 0x15 to track VPE interrupts - increase by 1 every vpeirq() is called
2648 */
2649 saa7146_write(dev, EC1SSR, (0x03<<2) | 3 );
2650 /* set event counter 1 treshold to maximum allowed value (rEC p55) */
2651 saa7146_write(dev, ECT1R, 0x3fff );
2652#endif
2653 /* Setup BUDGETPATCH MAIN RPS1 "program" (p35) */
2654 count = 0;
2655
2656 /* Wait Source Line Counter Threshold (p36) */
2657 WRITE_RPS1(cpu_to_le32(CMD_PAUSE | EVT_HS));
2658 /* Set GPIO3=1 (p42) */
2659 WRITE_RPS1(cpu_to_le32(CMD_WR_REG_MASK | (GPIO_CTRL>>2)));
2660 WRITE_RPS1(cpu_to_le32(GPIO3_MSK));
2661 WRITE_RPS1(cpu_to_le32(SAA7146_GPIO_OUTHI<<24));
2662#if RPS_IRQ
2663 /* issue RPS1 interrupt */
2664 WRITE_RPS1(cpu_to_le32(CMD_INTERRUPT));
2665#endif
2666 /* Wait reset Source Line Counter Threshold (p36) */
2667 WRITE_RPS1(cpu_to_le32(CMD_PAUSE | RPS_INV | EVT_HS));
2668 /* Set GPIO3=0 (p42) */
2669 WRITE_RPS1(cpu_to_le32(CMD_WR_REG_MASK | (GPIO_CTRL>>2)));
2670 WRITE_RPS1(cpu_to_le32(GPIO3_MSK));
2671 WRITE_RPS1(cpu_to_le32(SAA7146_GPIO_OUTLO<<24));
2672#if RPS_IRQ
2673 /* issue RPS1 interrupt */
2674 WRITE_RPS1(cpu_to_le32(CMD_INTERRUPT));
2675#endif
2676 /* Jump to begin of RPS program (p37) */
2677 WRITE_RPS1(cpu_to_le32(CMD_JUMP));
2678 WRITE_RPS1(cpu_to_le32(dev->d_rps1.dma_handle));
2679
2680 /* Fix VSYNC level */
2681 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
2682 /* Set RPS1 Address register to point to RPS code (r108 p42) */
2683 saa7146_write(dev, RPS_ADDR1, dev->d_rps1.dma_handle);
2684 /* Set Source Line Counter Threshold, using BRS (rCC p43)
2685 * It generates HS event every TS_HEIGHT lines
2686 * this is related to TS_WIDTH set in register
2687 * NUM_LINE_BYTE3. If NUM_LINE_BYTE low 16 bits
2688 * are set to TS_WIDTH bytes (TS_WIDTH=2*188),
2689 * then RPS_THRESH1 should be set to trigger
2690 * every TS_HEIGHT (512) lines.
2691 */
2692 saa7146_write(dev, RPS_THRESH1, (TS_HEIGHT*1) | MASK_12 );
2693
2694 /* Enable RPS1 (rFC p33) */
2695 saa7146_write(dev, MC1, (MASK_13 | MASK_29));
2696
2697 /* end of budgetpatch register initialization */
2698 tasklet_init (&av7110->vpe_tasklet, vpeirq, (unsigned long) av7110);
2699 } else {
2700 saa7146_write(dev, PCI_BT_V1, 0x1c00101f);
2701 saa7146_write(dev, BCS_CTRL, 0x80400040);
2702
2703 /* set dd1 stream a & b */
2704 saa7146_write(dev, DD1_STREAM_B, 0x00000000);
2705 saa7146_write(dev, DD1_INIT, 0x03000000);
2706 saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
2707
2708 /* upload all */
2709 saa7146_write(dev, MC2, 0x077c077c);
2710 saa7146_write(dev, GPIO_CTRL, 0x000000);
2711 }
2712
2713 tasklet_init (&av7110->debi_tasklet, debiirq, (unsigned long) av7110);
2714 tasklet_init (&av7110->gpio_tasklet, gpioirq, (unsigned long) av7110);
2715
Ingo Molnar3593cab2006-02-07 06:49:14 -02002716 mutex_init(&av7110->pid_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002717
2718 /* locks for data transfers from/to AV7110 */
2719 spin_lock_init(&av7110->debilock);
Ingo Molnar3593cab2006-02-07 06:49:14 -02002720 mutex_init(&av7110->dcomlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002721 av7110->debitype = -1;
2722
2723 /* default OSD window */
2724 av7110->osdwin = 1;
Ingo Molnar3593cab2006-02-07 06:49:14 -02002725 mutex_init(&av7110->osd_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002726
2727 /* ARM "watchdog" */
2728 init_waitqueue_head(&av7110->arm_wait);
2729 av7110->arm_thread = NULL;
2730
2731 /* allocate and init buffers */
2732 av7110->debi_virt = pci_alloc_consistent(pdev, 8192, &av7110->debi_bus);
2733 if (!av7110->debi_virt)
2734 goto err_saa71466_vfree_4;
2735
2736
2737 av7110->iobuf = vmalloc(AVOUTLEN+AOUTLEN+BMPLEN+4*IPACKS);
2738 if (!av7110->iobuf)
2739 goto err_pci_free_5;
2740
2741 ret = av7110_av_init(av7110);
2742 if (ret < 0)
2743 goto err_iobuf_vfree_6;
2744
2745 /* init BMP buffer */
2746 av7110->bmpbuf = av7110->iobuf+AVOUTLEN+AOUTLEN;
2747 init_waitqueue_head(&av7110->bmpq);
2748
2749 ret = av7110_ca_init(av7110);
2750 if (ret < 0)
2751 goto err_av7110_av_exit_7;
2752
2753 /* load firmware into AV7110 cards */
2754 ret = av7110_bootarm(av7110);
2755 if (ret < 0)
2756 goto err_av7110_ca_exit_8;
2757
2758 ret = av7110_firmversion(av7110);
2759 if (ret < 0)
2760 goto err_stop_arm_9;
2761
2762 if (FW_VERSION(av7110->arm_app)<0x2501)
2763 printk ("dvb-ttpci: Warning, firmware version 0x%04x is too old. "
2764 "System might be unstable!\n", FW_VERSION(av7110->arm_app));
2765
2766 ret = kernel_thread(arm_thread, (void *) av7110, 0);
2767 if (ret < 0)
2768 goto err_stop_arm_9;
2769
2770 /* set initial volume in mixer struct */
2771 av7110->mixer.volume_left = volume;
2772 av7110->mixer.volume_right = volume;
2773
2774 init_av7110_av(av7110);
2775
2776 ret = av7110_register(av7110);
2777 if (ret < 0)
2778 goto err_arm_thread_stop_10;
2779
2780 /* special case DVB-C: these cards have an analog tuner
2781 plus need some special handling, so we have separate
2782 saa7146_ext_vv data for these... */
2783 ret = av7110_init_v4l(av7110);
2784 if (ret < 0)
2785 goto err_av7110_unregister_11;
2786
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07002787 av7110->dvb_adapter.priv = av7110;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002788 ret = frontend_init(av7110);
2789 if (ret < 0)
2790 goto err_av7110_exit_v4l_12;
2791
2792#if defined(CONFIG_INPUT_EVDEV) || defined(CONFIG_INPUT_EVDEV_MODULE)
Oliver Endriss03388ae2005-09-09 13:03:12 -07002793 av7110_ir_init(av7110);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002794#endif
2795 printk(KERN_INFO "dvb-ttpci: found av7110-%d.\n", av7110_num);
2796 av7110_num++;
2797out:
2798 return ret;
2799
2800err_av7110_exit_v4l_12:
2801 av7110_exit_v4l(av7110);
2802err_av7110_unregister_11:
2803 dvb_unregister(av7110);
2804err_arm_thread_stop_10:
2805 av7110_arm_sync(av7110);
2806err_stop_arm_9:
2807 /* Nothing to do. Rejoice. */
2808err_av7110_ca_exit_8:
2809 av7110_ca_exit(av7110);
2810err_av7110_av_exit_7:
2811 av7110_av_exit(av7110);
2812err_iobuf_vfree_6:
2813 vfree(av7110->iobuf);
2814err_pci_free_5:
2815 pci_free_consistent(pdev, 8192, av7110->debi_virt, av7110->debi_bus);
2816err_saa71466_vfree_4:
2817 if (!av7110->grabbing)
2818 saa7146_pgtable_free(pdev, &av7110->pt);
2819err_i2c_del_3:
2820 i2c_del_adapter(&av7110->i2c_adap);
2821err_dvb_unregister_adapter_2:
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07002822 dvb_unregister_adapter(&av7110->dvb_adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002823err_put_firmware_1:
2824 put_firmware(av7110);
2825err_kfree_0:
2826 kfree(av7110);
2827 goto out;
2828}
2829
Johannes Stezenbach1be11e32006-02-27 00:09:20 -03002830static int __devexit av7110_detach(struct saa7146_dev* saa)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002831{
2832 struct av7110 *av7110 = saa->ext_priv;
2833 dprintk(4, "%p\n", av7110);
2834
Oliver Endriss03388ae2005-09-09 13:03:12 -07002835#if defined(CONFIG_INPUT_EVDEV) || defined(CONFIG_INPUT_EVDEV_MODULE)
2836 av7110_ir_exit(av7110);
2837#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07002838 if (budgetpatch) {
2839 /* Disable RPS1 */
2840 saa7146_write(saa, MC1, MASK_29);
2841 /* VSYNC LOW (inactive) */
2842 saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);
2843 saa7146_write(saa, MC1, MASK_20); /* DMA3 off */
2844 SAA7146_IER_DISABLE(saa, MASK_10);
2845 SAA7146_ISR_CLEAR(saa, MASK_10);
2846 msleep(50);
2847 tasklet_kill(&av7110->vpe_tasklet);
2848 saa7146_pgtable_free(saa->pci, &av7110->pt);
2849 }
2850 av7110_exit_v4l(av7110);
2851
2852 av7110_arm_sync(av7110);
2853
2854 tasklet_kill(&av7110->debi_tasklet);
2855 tasklet_kill(&av7110->gpio_tasklet);
2856
2857 dvb_unregister(av7110);
2858
2859 SAA7146_IER_DISABLE(saa, MASK_19 | MASK_03);
2860 SAA7146_ISR_CLEAR(saa, MASK_19 | MASK_03);
2861
2862 av7110_ca_exit(av7110);
2863 av7110_av_exit(av7110);
2864
2865 vfree(av7110->iobuf);
2866 pci_free_consistent(saa->pci, 8192, av7110->debi_virt,
2867 av7110->debi_bus);
2868
2869 i2c_del_adapter(&av7110->i2c_adap);
2870
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07002871 dvb_unregister_adapter (&av7110->dvb_adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002872
2873 av7110_num--;
2874
2875 put_firmware(av7110);
2876
2877 kfree(av7110);
2878
2879 saa->ext_priv = NULL;
2880
2881 return 0;
2882}
2883
2884
2885static void av7110_irq(struct saa7146_dev* dev, u32 *isr)
2886{
2887 struct av7110 *av7110 = dev->ext_priv;
2888
2889 //print_time("av7110_irq");
2890
2891 /* Note: Don't try to handle the DEBI error irq (MASK_18), in
2892 * intel mode the timeout is asserted all the time...
2893 */
2894
2895 if (*isr & MASK_19) {
2896 //printk("av7110_irq: DEBI\n");
2897 /* Note 1: The DEBI irq is level triggered: We must enable it
2898 * only after we started a DMA xfer, and disable it here
2899 * immediately, or it will be signalled all the time while
2900 * DEBI is idle.
2901 * Note 2: You would think that an irq which is masked is
2902 * not signalled by the hardware. Not so for the SAA7146:
2903 * An irq is signalled as long as the corresponding bit
2904 * in the ISR is set, and disabling irqs just prevents the
2905 * hardware from setting the ISR bit. This means a) that we
2906 * must clear the ISR *after* disabling the irq (which is why
2907 * we must do it here even though saa7146_core did it already),
2908 * and b) that if we were to disable an edge triggered irq
2909 * (like the gpio irqs sadly are) temporarily we would likely
2910 * loose some. This sucks :-(
2911 */
2912 SAA7146_IER_DISABLE(av7110->dev, MASK_19);
2913 SAA7146_ISR_CLEAR(av7110->dev, MASK_19);
2914 tasklet_schedule(&av7110->debi_tasklet);
2915 }
2916
2917 if (*isr & MASK_03) {
2918 //printk("av7110_irq: GPIO\n");
2919 tasklet_schedule(&av7110->gpio_tasklet);
2920 }
2921
2922 if ((*isr & MASK_10) && budgetpatch)
2923 tasklet_schedule(&av7110->vpe_tasklet);
2924}
2925
2926
2927static struct saa7146_extension av7110_extension;
2928
2929#define MAKE_AV7110_INFO(x_var,x_name) \
2930static struct saa7146_pci_extension_data x_var = { \
2931 .ext_priv = x_name, \
2932 .ext = &av7110_extension }
2933
Karl Herz6af4ee12005-09-09 13:03:13 -07002934MAKE_AV7110_INFO(tts_1_X_fsc,"Technotrend/Hauppauge WinTV DVB-S rev1.X or Fujitsu Siemens DVB-C");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002935MAKE_AV7110_INFO(ttt_1_X, "Technotrend/Hauppauge WinTV DVB-T rev1.X");
2936MAKE_AV7110_INFO(ttc_1_X, "Technotrend/Hauppauge WinTV Nexus-CA rev1.X");
2937MAKE_AV7110_INFO(ttc_2_X, "Technotrend/Hauppauge WinTV DVB-C rev2.X");
2938MAKE_AV7110_INFO(tts_2_X, "Technotrend/Hauppauge WinTV Nexus-S rev2.X");
Johannes Stezenbach3dfaebd2005-05-16 21:54:19 -07002939MAKE_AV7110_INFO(tts_2_3, "Technotrend/Hauppauge WinTV Nexus-S rev2.3");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002940MAKE_AV7110_INFO(tts_1_3se, "Technotrend/Hauppauge WinTV DVB-S rev1.3 SE");
2941MAKE_AV7110_INFO(ttt, "Technotrend/Hauppauge DVB-T");
2942MAKE_AV7110_INFO(fsc, "Fujitsu Siemens DVB-C");
2943MAKE_AV7110_INFO(fss, "Fujitsu Siemens DVB-S rev1.6");
Oliver Endriss8bd63012006-02-07 06:49:11 -02002944MAKE_AV7110_INFO(gxs_1_3, "Galaxis DVB-S rev1.3");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002945
2946static struct pci_device_id pci_tbl[] = {
Karl Herz6af4ee12005-09-09 13:03:13 -07002947 MAKE_EXTENSION_PCI(fsc, 0x110a, 0x0000),
2948 MAKE_EXTENSION_PCI(tts_1_X_fsc, 0x13c2, 0x0000),
2949 MAKE_EXTENSION_PCI(ttt_1_X, 0x13c2, 0x0001),
2950 MAKE_EXTENSION_PCI(ttc_2_X, 0x13c2, 0x0002),
2951 MAKE_EXTENSION_PCI(tts_2_X, 0x13c2, 0x0003),
Oliver Endriss8bd63012006-02-07 06:49:11 -02002952 MAKE_EXTENSION_PCI(gxs_1_3, 0x13c2, 0x0004),
Karl Herz6af4ee12005-09-09 13:03:13 -07002953 MAKE_EXTENSION_PCI(fss, 0x13c2, 0x0006),
2954 MAKE_EXTENSION_PCI(ttt, 0x13c2, 0x0008),
2955 MAKE_EXTENSION_PCI(ttc_1_X, 0x13c2, 0x000a),
2956 MAKE_EXTENSION_PCI(tts_2_3, 0x13c2, 0x000e),
2957 MAKE_EXTENSION_PCI(tts_1_3se, 0x13c2, 0x1002),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002958
Linus Torvalds1da177e2005-04-16 15:20:36 -07002959/* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0005), UNDEFINED CARD */ // Technisat SkyStar1
2960/* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0009), UNDEFINED CARD */ // TT/Hauppauge WinTV Nexus-CA v????
2961
2962 {
2963 .vendor = 0,
2964 }
2965};
2966
2967MODULE_DEVICE_TABLE(pci, pci_tbl);
2968
2969
2970static struct saa7146_extension av7110_extension = {
2971 .name = "dvb\0",
2972 .flags = SAA7146_I2C_SHORT_DELAY,
2973
2974 .module = THIS_MODULE,
2975 .pci_tbl = &pci_tbl[0],
2976 .attach = av7110_attach,
Johannes Stezenbach1be11e32006-02-27 00:09:20 -03002977 .detach = __devexit_p(av7110_detach),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002978
2979 .irq_mask = MASK_19 | MASK_03 | MASK_10,
2980 .irq_func = av7110_irq,
2981};
2982
2983
2984static int __init av7110_init(void)
2985{
2986 int retval;
2987 retval = saa7146_register_extension(&av7110_extension);
2988 return retval;
2989}
2990
2991
2992static void __exit av7110_exit(void)
2993{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002994 saa7146_unregister_extension(&av7110_extension);
2995}
2996
2997module_init(av7110_init);
2998module_exit(av7110_exit);
2999
3000MODULE_DESCRIPTION("driver for the SAA7146 based AV110 PCI DVB cards by "
3001 "Siemens, Technotrend, Hauppauge");
3002MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, others");
3003MODULE_LICENSE("GPL");