blob: 7a5c99c200e8e2a33e913c377d0fc89adecd3344 [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
Oliver Endrissdb5d91e2006-02-28 10:32:25 -030069#include "bsbe1.h"
70#include "lnbp21.h"
Perceval Anichini265366e2006-03-16 11:22:47 -030071#include "bsru6.h"
Oliver Endrissdb5d91e2006-02-28 10:32:25 -030072
Linus Torvalds1da177e2005-04-16 15:20:36 -070073#define TS_WIDTH 376
74#define TS_HEIGHT 512
75#define TS_BUFLEN (TS_WIDTH*TS_HEIGHT)
76#define TS_MAX_PACKETS (TS_BUFLEN/TS_SIZE)
77
78
79int av7110_debug;
80
81static int vidmode = CVBS_RGB_OUT;
82static int pids_off;
83static int adac = DVB_ADAC_TI;
84static int hw_sections;
85static int rgb_on;
86static int volume = 255;
Mauro Carvalho Chehaba5ed4252006-01-13 14:10:19 -020087static int budgetpatch;
Oliver Endriss4caba422006-03-17 05:29:15 -030088static int wss_cfg_4_3 = 0x4008;
89static int wss_cfg_16_9 = 0x0007;
C.Y.M2f03ee82006-03-30 04:31:48 -030090static int tv_standard;
Linus Torvalds1da177e2005-04-16 15:20:36 -070091
92module_param_named(debug, av7110_debug, int, 0644);
93MODULE_PARM_DESC(debug, "debug level (bitmask, default 0)");
94module_param(vidmode, int, 0444);
95MODULE_PARM_DESC(vidmode,"analog video out: 0 off, 1 CVBS+RGB (default), 2 CVBS+YC, 3 YC");
96module_param(pids_off, int, 0444);
97MODULE_PARM_DESC(pids_off,"clear video/audio/PCR PID filters when demux is closed");
98module_param(adac, int, 0444);
99MODULE_PARM_DESC(adac,"audio DAC type: 0 TI, 1 CRYSTAL, 2 MSP (use if autodetection fails)");
100module_param(hw_sections, int, 0444);
101MODULE_PARM_DESC(hw_sections, "0 use software section filter, 1 use hardware");
102module_param(rgb_on, int, 0444);
103MODULE_PARM_DESC(rgb_on, "For Siemens DVB-C cards only: Enable RGB control"
104 " signal on SCART pin 16 to switch SCART video mode from CVBS to RGB");
105module_param(volume, int, 0444);
106MODULE_PARM_DESC(volume, "initial volume: default 255 (range 0-255)");
107module_param(budgetpatch, int, 0444);
108MODULE_PARM_DESC(budgetpatch, "use budget-patch hardware modification: default 0 (0 no, 1 autodetect, 2 always)");
Oliver Endriss4caba422006-03-17 05:29:15 -0300109module_param(wss_cfg_4_3, int, 0444);
110MODULE_PARM_DESC(wss_cfg_4_3, "WSS 4:3 - default 0x4008 - bit 15: disable, 14: burst mode, 13..0: wss data");
111module_param(wss_cfg_16_9, int, 0444);
112MODULE_PARM_DESC(wss_cfg_16_9, "WSS 16:9 - default 0x0007 - bit 15: disable, 14: burst mode, 13..0: wss data");
C.Y.M2f03ee82006-03-30 04:31:48 -0300113module_param(tv_standard, int, 0444);
114MODULE_PARM_DESC(tv_standard, "TV standard: 0 PAL (default), 1 NTSC");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700115
116static void restart_feeds(struct av7110 *av7110);
117
Mauro Carvalho Chehaba5ed4252006-01-13 14:10:19 -0200118static int av7110_num;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700119
120#define FE_FUNC_OVERRIDE(fe_func, av7110_copy, av7110_func) \
121{\
122 if (fe_func != NULL) { \
123 av7110_copy = fe_func; \
124 fe_func = av7110_func; \
125 } \
126}
127
128
129static void init_av7110_av(struct av7110 *av7110)
130{
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700131 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700132 struct saa7146_dev *dev = av7110->dev;
133
134 /* set internal volume control to maximum */
135 av7110->adac_type = DVB_ADAC_TI;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700136 ret = av7110_set_volume(av7110, av7110->mixer.volume_left, av7110->mixer.volume_right);
Johannes Stezenbach7a2fa902005-07-07 17:58:01 -0700137 if (ret < 0)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700138 printk("dvb-ttpci:cannot set internal volume to maximum:%d\n",ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139
Oliver Endriss4caba422006-03-17 05:29:15 -0300140 ret = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetWSSConfig, 2, 2, wss_cfg_4_3);
141 if (ret < 0)
142 printk("dvb-ttpci: unable to configure 4:3 wss\n");
143 ret = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetWSSConfig, 2, 3, wss_cfg_16_9);
144 if (ret < 0)
145 printk("dvb-ttpci: unable to configure 16:9 wss\n");
146
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700147 ret = av7710_set_video_mode(av7110, vidmode);
Johannes Stezenbach7a2fa902005-07-07 17:58:01 -0700148 if (ret < 0)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700149 printk("dvb-ttpci:cannot set video mode:%d\n",ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700150
151 /* handle different card types */
152 /* remaining inits according to card and frontend type */
153 av7110->analog_tuner_flags = 0;
154 av7110->current_input = 0;
Tim Kaiser61391e02006-06-25 09:14:07 -0300155 if (dev->pci->subsystem_vendor == 0x13c2 && dev->pci->subsystem_device == 0x000a)
Marco Schluessler1c13b952006-01-09 15:25:06 -0200156 av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, ADSwitch, 1, 0); // SPDIF on
Tim Kaiser61391e02006-06-25 09:14:07 -0300157 if (i2c_writereg(av7110, 0x20, 0x00, 0x00) == 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700158 printk ("dvb-ttpci: Crystal audio DAC @ card %d detected\n",
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -0700159 av7110->dvb_adapter.num);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700160 av7110->adac_type = DVB_ADAC_CRYSTAL;
161 i2c_writereg(av7110, 0x20, 0x01, 0xd2);
162 i2c_writereg(av7110, 0x20, 0x02, 0x49);
163 i2c_writereg(av7110, 0x20, 0x03, 0x00);
164 i2c_writereg(av7110, 0x20, 0x04, 0x00);
165
166 /**
167 * some special handling for the Siemens DVB-C cards...
168 */
169 } else if (0 == av7110_init_analog_module(av7110)) {
170 /* done. */
171 }
172 else if (dev->pci->subsystem_vendor == 0x110a) {
173 printk("dvb-ttpci: DVB-C w/o analog module @ card %d detected\n",
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -0700174 av7110->dvb_adapter.num);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700175 av7110->adac_type = DVB_ADAC_NONE;
176 }
177 else {
178 av7110->adac_type = adac;
179 printk("dvb-ttpci: adac type set to %d @ card %d\n",
Marco Schluessler1c13b952006-01-09 15:25:06 -0200180 av7110->adac_type, av7110->dvb_adapter.num);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700181 }
182
Marco Schluessler1c13b952006-01-09 15:25:06 -0200183 if (av7110->adac_type == DVB_ADAC_NONE || av7110->adac_type == DVB_ADAC_MSP34x0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700184 // switch DVB SCART on
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700185 ret = av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, MainSwitch, 1, 0);
Johannes Stezenbach7a2fa902005-07-07 17:58:01 -0700186 if (ret < 0)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700187 printk("dvb-ttpci:cannot switch on SCART(Main):%d\n",ret);
188 ret = av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, ADSwitch, 1, 1);
Johannes Stezenbach7a2fa902005-07-07 17:58:01 -0700189 if (ret < 0)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700190 printk("dvb-ttpci:cannot switch on SCART(AD):%d\n",ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700191 if (rgb_on &&
Karl Herz6af4ee12005-09-09 13:03:13 -0700192 ((av7110->dev->pci->subsystem_vendor == 0x110a) ||
193 (av7110->dev->pci->subsystem_vendor == 0x13c2)) &&
194 (av7110->dev->pci->subsystem_device == 0x0000)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700195 saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); // RGB on, SCART pin 16
196 //saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); // SCARTpin 8
197 }
198 }
199
Oliver Endriss60edb132005-12-19 08:54:11 -0200200 if (dev->pci->subsystem_vendor == 0x13c2 && dev->pci->subsystem_device == 0x000e)
201 av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, SpdifSwitch, 1, 0); // SPDIF on
202
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700203 ret = av7110_set_volume(av7110, av7110->mixer.volume_left, av7110->mixer.volume_right);
Johannes Stezenbach7a2fa902005-07-07 17:58:01 -0700204 if (ret < 0)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700205 printk("dvb-ttpci:cannot set volume :%d\n",ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700206}
207
208static void recover_arm(struct av7110 *av7110)
209{
210 dprintk(4, "%p\n",av7110);
211
212 av7110_bootarm(av7110);
213 msleep(100);
Oliver Endriss66190a22006-01-09 15:32:42 -0200214
215 init_av7110_av(av7110);
216
217 /* card-specific recovery */
218 if (av7110->recover)
219 av7110->recover(av7110);
220
Linus Torvalds1da177e2005-04-16 15:20:36 -0700221 restart_feeds(av7110);
222 av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, SetIR, 1, av7110->ir_config);
223}
224
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225static void av7110_arm_sync(struct av7110 *av7110)
226{
227 av7110->arm_rmmod = 1;
228 wake_up_interruptible(&av7110->arm_wait);
229
230 while (av7110->arm_thread)
231 msleep(1);
232}
233
234static int arm_thread(void *data)
235{
236 struct av7110 *av7110 = data;
237 u16 newloops = 0;
238 int timeout;
239
240 dprintk(4, "%p\n",av7110);
241
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -0800242 lock_kernel();
243 daemonize("arm_mon");
244 sigfillset(&current->blocked);
245 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700246
247 av7110->arm_thread = current;
248
249 for (;;) {
250 timeout = wait_event_interruptible_timeout(av7110->arm_wait,
251 av7110->arm_rmmod, 5 * HZ);
252 if (-ERESTARTSYS == timeout || av7110->arm_rmmod) {
253 /* got signal or told to quit*/
254 break;
255 }
256
257 if (!av7110->arm_ready)
258 continue;
259
Ingo Molnar3593cab2006-02-07 06:49:14 -0200260 if (mutex_lock_interruptible(&av7110->dcomlock))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700262 newloops = rdebi(av7110, DEBINOSWAP, STATUS_LOOPS, 0, 2);
Ingo Molnar3593cab2006-02-07 06:49:14 -0200263 mutex_unlock(&av7110->dcomlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700264
Oliver Endriss66190a22006-01-09 15:32:42 -0200265 if (newloops == av7110->arm_loops || av7110->arm_errors > 3) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266 printk(KERN_ERR "dvb-ttpci: ARM crashed @ card %d\n",
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -0700267 av7110->dvb_adapter.num);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268
Oliver Endriss66190a22006-01-09 15:32:42 -0200269 recover_arm(av7110);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700270
Ingo Molnar3593cab2006-02-07 06:49:14 -0200271 if (mutex_lock_interruptible(&av7110->dcomlock))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700272 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273 newloops = rdebi(av7110, DEBINOSWAP, STATUS_LOOPS, 0, 2) - 1;
Ingo Molnar3593cab2006-02-07 06:49:14 -0200274 mutex_unlock(&av7110->dcomlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275 }
276 av7110->arm_loops = newloops;
Oliver Endriss66190a22006-01-09 15:32:42 -0200277 av7110->arm_errors = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278 }
279
280 av7110->arm_thread = NULL;
281 return 0;
282}
283
284
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285/****************************************************************************
286 * IRQ handling
287 ****************************************************************************/
288
289static int DvbDmxFilterCallback(u8 *buffer1, size_t buffer1_len,
290 u8 *buffer2, size_t buffer2_len,
291 struct dvb_demux_filter *dvbdmxfilter,
292 enum dmx_success success,
293 struct av7110 *av7110)
294{
295 if (!dvbdmxfilter->feed->demux->dmx.frontend)
296 return 0;
297 if (dvbdmxfilter->feed->demux->dmx.frontend->source == DMX_MEMORY_FE)
298 return 0;
299
300 switch (dvbdmxfilter->type) {
301 case DMX_TYPE_SEC:
302 if ((((buffer1[1] << 8) | buffer1[2]) & 0xfff) + 3 != buffer1_len)
303 return 0;
304 if (dvbdmxfilter->doneq) {
305 struct dmx_section_filter *filter = &dvbdmxfilter->filter;
306 int i;
307 u8 xor, neq = 0;
308
309 for (i = 0; i < DVB_DEMUX_MASK_MAX; i++) {
310 xor = filter->filter_value[i] ^ buffer1[i];
311 neq |= dvbdmxfilter->maskandnotmode[i] & xor;
312 }
313 if (!neq)
314 return 0;
315 }
316 return dvbdmxfilter->feed->cb.sec(buffer1, buffer1_len,
317 buffer2, buffer2_len,
318 &dvbdmxfilter->filter,
319 DMX_OK);
320 case DMX_TYPE_TS:
321 if (!(dvbdmxfilter->feed->ts_type & TS_PACKET))
322 return 0;
323 if (dvbdmxfilter->feed->ts_type & TS_PAYLOAD_ONLY)
324 return dvbdmxfilter->feed->cb.ts(buffer1, buffer1_len,
325 buffer2, buffer2_len,
326 &dvbdmxfilter->feed->feed.ts,
327 DMX_OK);
328 else
329 av7110_p2t_write(buffer1, buffer1_len,
330 dvbdmxfilter->feed->pid,
331 &av7110->p2t_filter[dvbdmxfilter->index]);
332 default:
333 return 0;
334 }
335}
336
337
338//#define DEBUG_TIMING
339static inline void print_time(char *s)
340{
341#ifdef DEBUG_TIMING
342 struct timeval tv;
343 do_gettimeofday(&tv);
344 printk("%s: %d.%d\n", s, (int)tv.tv_sec, (int)tv.tv_usec);
345#endif
346}
347
348#define DEBI_READ 0
349#define DEBI_WRITE 1
350static inline void start_debi_dma(struct av7110 *av7110, int dir,
351 unsigned long addr, unsigned int len)
352{
353 dprintk(8, "%c %08lx %u\n", dir == DEBI_READ ? 'R' : 'W', addr, len);
354 if (saa7146_wait_for_debi_done(av7110->dev, 0)) {
355 printk(KERN_ERR "%s: saa7146_wait_for_debi_done timed out\n", __FUNCTION__);
356 return;
357 }
358
359 SAA7146_ISR_CLEAR(av7110->dev, MASK_19); /* for good measure */
360 SAA7146_IER_ENABLE(av7110->dev, MASK_19);
361 if (len < 5)
362 len = 5; /* we want a real DEBI DMA */
363 if (dir == DEBI_WRITE)
364 iwdebi(av7110, DEBISWAB, addr, 0, (len + 3) & ~3);
365 else
366 irdebi(av7110, DEBISWAB, addr, 0, len);
367}
368
369static void debiirq(unsigned long data)
370{
371 struct av7110 *av7110 = (struct av7110 *) data;
372 int type = av7110->debitype;
373 int handle = (type >> 8) & 0x1f;
374 unsigned int xfer = 0;
375
376 print_time("debi");
377 dprintk(4, "type 0x%04x\n", type);
378
379 if (type == -1) {
380 printk("DEBI irq oops @ %ld, psr:0x%08x, ssr:0x%08x\n",
381 jiffies, saa7146_read(av7110->dev, PSR),
382 saa7146_read(av7110->dev, SSR));
383 goto debi_done;
384 }
385 av7110->debitype = -1;
386
387 switch (type & 0xff) {
388
389 case DATA_TS_RECORD:
390 dvb_dmx_swfilter_packets(&av7110->demux,
391 (const u8 *) av7110->debi_virt,
392 av7110->debilen / 188);
393 xfer = RX_BUFF;
394 break;
395
396 case DATA_PES_RECORD:
397 if (av7110->demux.recording)
398 av7110_record_cb(&av7110->p2t[handle],
399 (u8 *) av7110->debi_virt,
400 av7110->debilen);
401 xfer = RX_BUFF;
402 break;
403
404 case DATA_IPMPE:
405 case DATA_FSECTION:
406 case DATA_PIPING:
407 if (av7110->handle2filter[handle])
408 DvbDmxFilterCallback((u8 *)av7110->debi_virt,
409 av7110->debilen, NULL, 0,
410 av7110->handle2filter[handle],
411 DMX_OK, av7110);
412 xfer = RX_BUFF;
413 break;
414
415 case DATA_CI_GET:
416 {
417 u8 *data = av7110->debi_virt;
418
419 if ((data[0] < 2) && data[2] == 0xff) {
420 int flags = 0;
421 if (data[5] > 0)
422 flags |= CA_CI_MODULE_PRESENT;
423 if (data[5] > 5)
424 flags |= CA_CI_MODULE_READY;
425 av7110->ci_slot[data[0]].flags = flags;
426 } else
427 ci_get_data(&av7110->ci_rbuffer,
428 av7110->debi_virt,
429 av7110->debilen);
430 xfer = RX_BUFF;
431 break;
432 }
433
434 case DATA_COMMON_INTERFACE:
435 CI_handle(av7110, (u8 *)av7110->debi_virt, av7110->debilen);
436#if 0
437 {
438 int i;
439
440 printk("av7110%d: ", av7110->num);
441 printk("%02x ", *(u8 *)av7110->debi_virt);
442 printk("%02x ", *(1+(u8 *)av7110->debi_virt));
443 for (i = 2; i < av7110->debilen; i++)
444 printk("%02x ", (*(i+(unsigned char *)av7110->debi_virt)));
445 for (i = 2; i < av7110->debilen; i++)
446 printk("%c", chtrans(*(i+(unsigned char *)av7110->debi_virt)));
447
448 printk("\n");
449 }
450#endif
451 xfer = RX_BUFF;
452 break;
453
454 case DATA_DEBUG_MESSAGE:
455 ((s8*)av7110->debi_virt)[Reserved_SIZE - 1] = 0;
456 printk("%s\n", (s8 *) av7110->debi_virt);
457 xfer = RX_BUFF;
458 break;
459
460 case DATA_CI_PUT:
461 dprintk(4, "debi DATA_CI_PUT\n");
462 case DATA_MPEG_PLAY:
463 dprintk(4, "debi DATA_MPEG_PLAY\n");
464 case DATA_BMP_LOAD:
465 dprintk(4, "debi DATA_BMP_LOAD\n");
466 xfer = TX_BUFF;
467 break;
468 default:
469 break;
470 }
471debi_done:
472 spin_lock(&av7110->debilock);
473 if (xfer)
474 iwdebi(av7110, DEBINOSWAP, xfer, 0, 2);
475 ARM_ClearMailBox(av7110);
476 spin_unlock(&av7110->debilock);
477}
478
479/* irq from av7110 firmware writing the mailbox register in the DPRAM */
480static void gpioirq(unsigned long data)
481{
482 struct av7110 *av7110 = (struct av7110 *) data;
483 u32 rxbuf, txbuf;
484 int len;
485
486 if (av7110->debitype != -1)
487 /* we shouldn't get any irq while a debi xfer is running */
488 printk("dvb-ttpci: GPIO0 irq oops @ %ld, psr:0x%08x, ssr:0x%08x\n",
489 jiffies, saa7146_read(av7110->dev, PSR),
490 saa7146_read(av7110->dev, SSR));
491
492 if (saa7146_wait_for_debi_done(av7110->dev, 0)) {
493 printk(KERN_ERR "%s: saa7146_wait_for_debi_done timed out\n", __FUNCTION__);
494 BUG(); /* maybe we should try resetting the debi? */
495 }
496
497 spin_lock(&av7110->debilock);
498 ARM_ClearIrq(av7110);
499
500 /* see what the av7110 wants */
501 av7110->debitype = irdebi(av7110, DEBINOSWAP, IRQ_STATE, 0, 2);
502 av7110->debilen = irdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
503 rxbuf = irdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
504 txbuf = irdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
505 len = (av7110->debilen + 3) & ~3;
506
507 print_time("gpio");
508 dprintk(8, "GPIO0 irq 0x%04x %d\n", av7110->debitype, av7110->debilen);
509
510 switch (av7110->debitype & 0xff) {
511
512 case DATA_TS_PLAY:
513 case DATA_PES_PLAY:
514 break;
515
516 case DATA_MPEG_VIDEO_EVENT:
517 {
518 u32 h_ar;
519 struct video_event event;
520
521 av7110->video_size.w = irdebi(av7110, DEBINOSWAP, STATUS_MPEG_WIDTH, 0, 2);
522 h_ar = irdebi(av7110, DEBINOSWAP, STATUS_MPEG_HEIGHT_AR, 0, 2);
523
524 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
525 iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
526
527 av7110->video_size.h = h_ar & 0xfff;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700528
529 event.type = VIDEO_EVENT_SIZE_CHANGED;
530 event.u.size.w = av7110->video_size.w;
531 event.u.size.h = av7110->video_size.h;
532 switch ((h_ar >> 12) & 0xf)
533 {
534 case 3:
535 av7110->video_size.aspect_ratio = VIDEO_FORMAT_16_9;
536 event.u.size.aspect_ratio = VIDEO_FORMAT_16_9;
537 av7110->videostate.video_format = VIDEO_FORMAT_16_9;
538 break;
539 case 4:
540 av7110->video_size.aspect_ratio = VIDEO_FORMAT_221_1;
541 event.u.size.aspect_ratio = VIDEO_FORMAT_221_1;
542 av7110->videostate.video_format = VIDEO_FORMAT_221_1;
543 break;
544 default:
545 av7110->video_size.aspect_ratio = VIDEO_FORMAT_4_3;
546 event.u.size.aspect_ratio = VIDEO_FORMAT_4_3;
547 av7110->videostate.video_format = VIDEO_FORMAT_4_3;
548 }
Oliver Endriss66190a22006-01-09 15:32:42 -0200549
550 dprintk(8, "GPIO0 irq: DATA_MPEG_VIDEO_EVENT: w/h/ar = %u/%u/%u\n",
551 av7110->video_size.w, av7110->video_size.h,
552 av7110->video_size.aspect_ratio);
553
Linus Torvalds1da177e2005-04-16 15:20:36 -0700554 dvb_video_add_event(av7110, &event);
555 break;
556 }
557
558 case DATA_CI_PUT:
559 {
560 int avail;
561 struct dvb_ringbuffer *cibuf = &av7110->ci_wbuffer;
562
563 avail = dvb_ringbuffer_avail(cibuf);
564 if (avail <= 2) {
565 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
566 iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
567 iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
568 break;
569 }
570 len = DVB_RINGBUFFER_PEEK(cibuf, 0) << 8;
571 len |= DVB_RINGBUFFER_PEEK(cibuf, 1);
572 if (avail < len + 2) {
573 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
574 iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
575 iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
576 break;
577 }
578 DVB_RINGBUFFER_SKIP(cibuf, 2);
579
580 dvb_ringbuffer_read(cibuf, av7110->debi_virt, len, 0);
581
582 iwdebi(av7110, DEBINOSWAP, TX_LEN, len, 2);
583 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, len, 2);
584 dprintk(8, "DMA: CI\n");
585 start_debi_dma(av7110, DEBI_WRITE, DPRAM_BASE + txbuf, len);
586 spin_unlock(&av7110->debilock);
587 wake_up(&cibuf->queue);
588 return;
589 }
590
591 case DATA_MPEG_PLAY:
592 if (!av7110->playing) {
593 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
594 iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
595 iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
596 break;
597 }
598 len = 0;
599 if (av7110->debitype & 0x100) {
600 spin_lock(&av7110->aout.lock);
601 len = av7110_pes_play(av7110->debi_virt, &av7110->aout, 2048);
602 spin_unlock(&av7110->aout.lock);
603 }
604 if (len <= 0 && (av7110->debitype & 0x200)
605 &&av7110->videostate.play_state != VIDEO_FREEZED) {
606 spin_lock(&av7110->avout.lock);
607 len = av7110_pes_play(av7110->debi_virt, &av7110->avout, 2048);
608 spin_unlock(&av7110->avout.lock);
609 }
610 if (len <= 0) {
611 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
612 iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
613 iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
614 break;
615 }
616 dprintk(8, "GPIO0 PES_PLAY len=%04x\n", len);
617 iwdebi(av7110, DEBINOSWAP, TX_LEN, len, 2);
618 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, len, 2);
619 dprintk(8, "DMA: MPEG_PLAY\n");
620 start_debi_dma(av7110, DEBI_WRITE, DPRAM_BASE + txbuf, len);
621 spin_unlock(&av7110->debilock);
622 return;
623
624 case DATA_BMP_LOAD:
625 len = av7110->debilen;
626 dprintk(8, "gpio DATA_BMP_LOAD len %d\n", len);
627 if (!len) {
628 av7110->bmp_state = BMP_LOADED;
629 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
630 iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
631 iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
632 wake_up(&av7110->bmpq);
633 dprintk(8, "gpio DATA_BMP_LOAD done\n");
634 break;
635 }
636 if (len > av7110->bmplen)
637 len = av7110->bmplen;
638 if (len > 2 * 1024)
639 len = 2 * 1024;
640 iwdebi(av7110, DEBINOSWAP, TX_LEN, len, 2);
641 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, len, 2);
642 memcpy(av7110->debi_virt, av7110->bmpbuf+av7110->bmpp, len);
643 av7110->bmpp += len;
644 av7110->bmplen -= len;
645 dprintk(8, "gpio DATA_BMP_LOAD DMA len %d\n", len);
646 start_debi_dma(av7110, DEBI_WRITE, DPRAM_BASE+txbuf, len);
647 spin_unlock(&av7110->debilock);
648 return;
649
650 case DATA_CI_GET:
651 case DATA_COMMON_INTERFACE:
652 case DATA_FSECTION:
653 case DATA_IPMPE:
654 case DATA_PIPING:
655 if (!len || len > 4 * 1024) {
656 iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
657 break;
658 }
659 /* fall through */
660
661 case DATA_TS_RECORD:
662 case DATA_PES_RECORD:
663 dprintk(8, "DMA: TS_REC etc.\n");
664 start_debi_dma(av7110, DEBI_READ, DPRAM_BASE+rxbuf, len);
665 spin_unlock(&av7110->debilock);
666 return;
667
668 case DATA_DEBUG_MESSAGE:
669 if (!len || len > 0xff) {
670 iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
671 break;
672 }
673 start_debi_dma(av7110, DEBI_READ, Reserved, len);
674 spin_unlock(&av7110->debilock);
675 return;
676
677 case DATA_IRCOMMAND:
Oliver Endriss03388ae2005-09-09 13:03:12 -0700678 if (av7110->ir_handler)
679 av7110->ir_handler(av7110,
680 swahw32(irdebi(av7110, DEBINOSWAP, Reserved, 0, 4)));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700681 iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
682 break;
683
684 default:
685 printk("dvb-ttpci: gpioirq unknown type=%d len=%d\n",
686 av7110->debitype, av7110->debilen);
687 break;
688 }
689 av7110->debitype = -1;
690 ARM_ClearMailBox(av7110);
691 spin_unlock(&av7110->debilock);
692}
693
694
695#ifdef CONFIG_DVB_AV7110_OSD
696static int dvb_osd_ioctl(struct inode *inode, struct file *file,
697 unsigned int cmd, void *parg)
698{
699 struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
700 struct av7110 *av7110 = (struct av7110 *) dvbdev->priv;
701
702 dprintk(4, "%p\n", av7110);
703
704 if (cmd == OSD_SEND_CMD)
705 return av7110_osd_cmd(av7110, (osd_cmd_t *) parg);
706 if (cmd == OSD_GET_CAPABILITY)
707 return av7110_osd_capability(av7110, (osd_cap_t *) parg);
708
709 return -EINVAL;
710}
711
712
713static struct file_operations dvb_osd_fops = {
714 .owner = THIS_MODULE,
715 .ioctl = dvb_generic_ioctl,
716 .open = dvb_generic_open,
717 .release = dvb_generic_release,
718};
719
720static struct dvb_device dvbdev_osd = {
721 .priv = NULL,
722 .users = 1,
723 .writers = 1,
724 .fops = &dvb_osd_fops,
725 .kernel_ioctl = dvb_osd_ioctl,
726};
727#endif /* CONFIG_DVB_AV7110_OSD */
728
729
730static inline int SetPIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid,
731 u16 subpid, u16 pcrpid)
732{
Dr. Werner Fink47f36922006-01-09 15:25:07 -0200733 u16 aflags = 0;
734
Linus Torvalds1da177e2005-04-16 15:20:36 -0700735 dprintk(4, "%p\n", av7110);
736
737 if (vpid == 0x1fff || apid == 0x1fff ||
738 ttpid == 0x1fff || subpid == 0x1fff || pcrpid == 0x1fff) {
739 vpid = apid = ttpid = subpid = pcrpid = 0;
740 av7110->pids[DMX_PES_VIDEO] = 0;
741 av7110->pids[DMX_PES_AUDIO] = 0;
742 av7110->pids[DMX_PES_TELETEXT] = 0;
743 av7110->pids[DMX_PES_PCR] = 0;
744 }
745
Dr. Werner Fink47f36922006-01-09 15:25:07 -0200746 if (av7110->audiostate.bypass_mode)
747 aflags |= 0x8000;
748
749 return av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, MultiPID, 6,
750 pcrpid, vpid, apid, ttpid, subpid, aflags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700751}
752
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700753int ChangePIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700754 u16 subpid, u16 pcrpid)
755{
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700756 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700757 dprintk(4, "%p\n", av7110);
758
Ingo Molnar3593cab2006-02-07 06:49:14 -0200759 if (mutex_lock_interruptible(&av7110->pid_mutex))
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700760 return -ERESTARTSYS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761
762 if (!(vpid & 0x8000))
763 av7110->pids[DMX_PES_VIDEO] = vpid;
764 if (!(apid & 0x8000))
765 av7110->pids[DMX_PES_AUDIO] = apid;
766 if (!(ttpid & 0x8000))
767 av7110->pids[DMX_PES_TELETEXT] = ttpid;
768 if (!(pcrpid & 0x8000))
769 av7110->pids[DMX_PES_PCR] = pcrpid;
770
771 av7110->pids[DMX_PES_SUBTITLE] = 0;
772
773 if (av7110->fe_synced) {
774 pcrpid = av7110->pids[DMX_PES_PCR];
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700775 ret = SetPIDs(av7110, vpid, apid, ttpid, subpid, pcrpid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700776 }
777
Ingo Molnar3593cab2006-02-07 06:49:14 -0200778 mutex_unlock(&av7110->pid_mutex);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700779 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700780}
781
782
783/******************************************************************************
784 * hardware filter functions
785 ******************************************************************************/
786
787static int StartHWFilter(struct dvb_demux_filter *dvbdmxfilter)
788{
789 struct dvb_demux_feed *dvbdmxfeed = dvbdmxfilter->feed;
790 struct av7110 *av7110 = (struct av7110 *) dvbdmxfeed->demux->priv;
791 u16 buf[20];
792 int ret, i;
793 u16 handle;
794// u16 mode = 0x0320;
795 u16 mode = 0xb96a;
796
797 dprintk(4, "%p\n", av7110);
798
799 if (dvbdmxfilter->type == DMX_TYPE_SEC) {
800 if (hw_sections) {
801 buf[4] = (dvbdmxfilter->filter.filter_value[0] << 8) |
802 dvbdmxfilter->maskandmode[0];
803 for (i = 3; i < 18; i++)
804 buf[i + 4 - 2] =
805 (dvbdmxfilter->filter.filter_value[i] << 8) |
806 dvbdmxfilter->maskandmode[i];
807 mode = 4;
808 }
809 } else if ((dvbdmxfeed->ts_type & TS_PACKET) &&
810 !(dvbdmxfeed->ts_type & TS_PAYLOAD_ONLY)) {
811 av7110_p2t_init(&av7110->p2t_filter[dvbdmxfilter->index], dvbdmxfeed);
812 }
813
814 buf[0] = (COMTYPE_PID_FILTER << 8) + AddPIDFilter;
815 buf[1] = 16;
816 buf[2] = dvbdmxfeed->pid;
817 buf[3] = mode;
818
819 ret = av7110_fw_request(av7110, buf, 20, &handle, 1);
820 if (ret != 0 || handle >= 32) {
821 printk("dvb-ttpci: %s error buf %04x %04x %04x %04x "
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700822 "ret %d handle %04x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700823 __FUNCTION__, buf[0], buf[1], buf[2], buf[3],
824 ret, handle);
825 dvbdmxfilter->hw_handle = 0xffff;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700826 if (!ret)
827 ret = -1;
828 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700829 }
830
831 av7110->handle2filter[handle] = dvbdmxfilter;
832 dvbdmxfilter->hw_handle = handle;
833
834 return ret;
835}
836
837static int StopHWFilter(struct dvb_demux_filter *dvbdmxfilter)
838{
839 struct av7110 *av7110 = (struct av7110 *) dvbdmxfilter->feed->demux->priv;
840 u16 buf[3];
841 u16 answ[2];
842 int ret;
843 u16 handle;
844
845 dprintk(4, "%p\n", av7110);
846
847 handle = dvbdmxfilter->hw_handle;
848 if (handle >= 32) {
849 printk("%s tried to stop invalid filter %04x, filter type = %x\n",
850 __FUNCTION__, handle, dvbdmxfilter->type);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700851 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700852 }
853
854 av7110->handle2filter[handle] = NULL;
855
856 buf[0] = (COMTYPE_PID_FILTER << 8) + DelPIDFilter;
857 buf[1] = 1;
858 buf[2] = handle;
859 ret = av7110_fw_request(av7110, buf, 3, answ, 2);
860 if (ret != 0 || answ[1] != handle) {
861 printk("dvb-ttpci: %s error cmd %04x %04x %04x ret %x "
862 "resp %04x %04x pid %d\n",
863 __FUNCTION__, buf[0], buf[1], buf[2], ret,
864 answ[0], answ[1], dvbdmxfilter->feed->pid);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700865 if (!ret)
866 ret = -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700867 }
868 return ret;
869}
870
871
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700872static int dvb_feed_start_pid(struct dvb_demux_feed *dvbdmxfeed)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700873{
874 struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
875 struct av7110 *av7110 = (struct av7110 *) dvbdmx->priv;
876 u16 *pid = dvbdmx->pids, npids[5];
877 int i;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700878 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700879
880 dprintk(4, "%p\n", av7110);
881
882 npids[0] = npids[1] = npids[2] = npids[3] = npids[4] = 0xffff;
883 i = dvbdmxfeed->pes_type;
884 npids[i] = (pid[i]&0x8000) ? 0 : pid[i];
885 if ((i == 2) && npids[i] && (dvbdmxfeed->ts_type & TS_PACKET)) {
886 npids[i] = 0;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700887 ret = ChangePIDs(av7110, npids[1], npids[0], npids[2], npids[3], npids[4]);
888 if (!ret)
889 ret = StartHWFilter(dvbdmxfeed->filter);
890 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700891 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700892 if (dvbdmxfeed->pes_type <= 2 || dvbdmxfeed->pes_type == 4) {
893 ret = ChangePIDs(av7110, npids[1], npids[0], npids[2], npids[3], npids[4]);
894 if (ret)
895 return ret;
896 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700897
898 if (dvbdmxfeed->pes_type < 2 && npids[0])
899 if (av7110->fe_synced)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700900 {
901 ret = av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, Scan, 0);
902 if (ret)
903 return ret;
904 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905
906 if ((dvbdmxfeed->ts_type & TS_PACKET)) {
907 if (dvbdmxfeed->pes_type == 0 && !(dvbdmx->pids[0] & 0x8000))
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700908 ret = av7110_av_start_record(av7110, RP_AUDIO, dvbdmxfeed);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700909 if (dvbdmxfeed->pes_type == 1 && !(dvbdmx->pids[1] & 0x8000))
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700910 ret = av7110_av_start_record(av7110, RP_VIDEO, dvbdmxfeed);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700911 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700912 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913}
914
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700915static int dvb_feed_stop_pid(struct dvb_demux_feed *dvbdmxfeed)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700916{
917 struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
918 struct av7110 *av7110 = (struct av7110 *) dvbdmx->priv;
919 u16 *pid = dvbdmx->pids, npids[5];
920 int i;
921
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700922 int ret = 0;
923
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924 dprintk(4, "%p\n", av7110);
925
926 if (dvbdmxfeed->pes_type <= 1) {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700927 ret = av7110_av_stop(av7110, dvbdmxfeed->pes_type ? RP_VIDEO : RP_AUDIO);
928 if (ret)
929 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700930 if (!av7110->rec_mode)
931 dvbdmx->recording = 0;
932 if (!av7110->playing)
933 dvbdmx->playing = 0;
934 }
935 npids[0] = npids[1] = npids[2] = npids[3] = npids[4] = 0xffff;
936 i = dvbdmxfeed->pes_type;
937 switch (i) {
938 case 2: //teletext
939 if (dvbdmxfeed->ts_type & TS_PACKET)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700940 ret = StopHWFilter(dvbdmxfeed->filter);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700941 npids[2] = 0;
942 break;
943 case 0:
944 case 1:
945 case 4:
946 if (!pids_off)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700947 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700948 npids[i] = (pid[i]&0x8000) ? 0 : pid[i];
949 break;
950 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700951 if (!ret)
952 ret = ChangePIDs(av7110, npids[1], npids[0], npids[2], npids[3], npids[4]);
953 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700954}
955
956static int av7110_start_feed(struct dvb_demux_feed *feed)
957{
958 struct dvb_demux *demux = feed->demux;
959 struct av7110 *av7110 = demux->priv;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700960 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700961
962 dprintk(4, "%p\n", av7110);
963
964 if (!demux->dmx.frontend)
965 return -EINVAL;
966
967 if (feed->pid > 0x1fff)
968 return -EINVAL;
969
970 if (feed->type == DMX_TYPE_TS) {
971 if ((feed->ts_type & TS_DECODER) &&
972 (feed->pes_type < DMX_TS_PES_OTHER)) {
973 switch (demux->dmx.frontend->source) {
974 case DMX_MEMORY_FE:
975 if (feed->ts_type & TS_DECODER)
976 if (feed->pes_type < 2 &&
977 !(demux->pids[0] & 0x8000) &&
978 !(demux->pids[1] & 0x8000)) {
979 dvb_ringbuffer_flush_spinlock_wakeup(&av7110->avout);
980 dvb_ringbuffer_flush_spinlock_wakeup(&av7110->aout);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700981 ret = av7110_av_start_play(av7110,RP_AV);
982 if (!ret)
983 demux->playing = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700984 }
985 break;
986 default:
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700987 ret = dvb_feed_start_pid(feed);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700988 break;
989 }
990 } else if ((feed->ts_type & TS_PACKET) &&
991 (demux->dmx.frontend->source != DMX_MEMORY_FE)) {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700992 ret = StartHWFilter(feed->filter);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700993 }
994 }
995
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700996 else if (feed->type == DMX_TYPE_SEC) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700997 int i;
998
999 for (i = 0; i < demux->filternum; i++) {
1000 if (demux->filter[i].state != DMX_STATE_READY)
1001 continue;
1002 if (demux->filter[i].type != DMX_TYPE_SEC)
1003 continue;
1004 if (demux->filter[i].filter.parent != &feed->feed.sec)
1005 continue;
1006 demux->filter[i].state = DMX_STATE_GO;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001007 if (demux->dmx.frontend->source != DMX_MEMORY_FE) {
1008 ret = StartHWFilter(&demux->filter[i]);
1009 if (ret)
1010 break;
1011 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001012 }
1013 }
1014
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001015 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001016}
1017
1018
1019static int av7110_stop_feed(struct dvb_demux_feed *feed)
1020{
1021 struct dvb_demux *demux = feed->demux;
1022 struct av7110 *av7110 = demux->priv;
Johannes Stezenbach12ba0502005-07-07 17:58:00 -07001023 int i, rc, ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001024 dprintk(4, "%p\n", av7110);
1025
1026 if (feed->type == DMX_TYPE_TS) {
1027 if (feed->ts_type & TS_DECODER) {
1028 if (feed->pes_type >= DMX_TS_PES_OTHER ||
1029 !demux->pesfilter[feed->pes_type])
1030 return -EINVAL;
1031 demux->pids[feed->pes_type] |= 0x8000;
1032 demux->pesfilter[feed->pes_type] = NULL;
1033 }
1034 if (feed->ts_type & TS_DECODER &&
1035 feed->pes_type < DMX_TS_PES_OTHER) {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001036 ret = dvb_feed_stop_pid(feed);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001037 } else
1038 if ((feed->ts_type & TS_PACKET) &&
1039 (demux->dmx.frontend->source != DMX_MEMORY_FE))
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001040 ret = StopHWFilter(feed->filter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001041 }
1042
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001043 if (!ret && feed->type == DMX_TYPE_SEC) {
Johannes Stezenbach12ba0502005-07-07 17:58:00 -07001044 for (i = 0; i<demux->filternum; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001045 if (demux->filter[i].state == DMX_STATE_GO &&
1046 demux->filter[i].filter.parent == &feed->feed.sec) {
1047 demux->filter[i].state = DMX_STATE_READY;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001048 if (demux->dmx.frontend->source != DMX_MEMORY_FE) {
Johannes Stezenbach12ba0502005-07-07 17:58:00 -07001049 rc = StopHWFilter(&demux->filter[i]);
1050 if (!ret)
1051 ret = rc;
1052 /* keep going, stop as many filters as possible */
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001053 }
Johannes Stezenbach12ba0502005-07-07 17:58:00 -07001054 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001055 }
1056 }
1057
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001058 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001059}
1060
1061
1062static void restart_feeds(struct av7110 *av7110)
1063{
1064 struct dvb_demux *dvbdmx = &av7110->demux;
1065 struct dvb_demux_feed *feed;
1066 int mode;
Oliver Endriss66190a22006-01-09 15:32:42 -02001067 int i, j;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068
1069 dprintk(4, "%p\n", av7110);
1070
1071 mode = av7110->playing;
1072 av7110->playing = 0;
1073 av7110->rec_mode = 0;
1074
Oliver Endriss66190a22006-01-09 15:32:42 -02001075 for (i = 0; i < dvbdmx->feednum; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076 feed = &dvbdmx->feed[i];
Oliver Endriss66190a22006-01-09 15:32:42 -02001077 if (feed->state == DMX_STATE_GO) {
1078 if (feed->type == DMX_TYPE_SEC) {
1079 for (j = 0; j < dvbdmx->filternum; j++) {
1080 if (dvbdmx->filter[j].type != DMX_TYPE_SEC)
1081 continue;
1082 if (dvbdmx->filter[j].filter.parent != &feed->feed.sec)
1083 continue;
1084 if (dvbdmx->filter[j].state == DMX_STATE_GO)
1085 dvbdmx->filter[j].state = DMX_STATE_READY;
1086 }
1087 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001088 av7110_start_feed(feed);
Oliver Endriss66190a22006-01-09 15:32:42 -02001089 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001090 }
1091
1092 if (mode)
1093 av7110_av_start_play(av7110, mode);
1094}
1095
1096static int dvb_get_stc(struct dmx_demux *demux, unsigned int num,
1097 uint64_t *stc, unsigned int *base)
1098{
1099 int ret;
1100 u16 fwstc[4];
1101 u16 tag = ((COMTYPE_REQUEST << 8) + ReqSTC);
1102 struct dvb_demux *dvbdemux;
1103 struct av7110 *av7110;
1104
1105 /* pointer casting paranoia... */
Eric Sesterhennae246012006-03-13 13:17:11 -03001106 BUG_ON(!demux);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107 dvbdemux = (struct dvb_demux *) demux->priv;
Eric Sesterhennae246012006-03-13 13:17:11 -03001108 BUG_ON(!dvbdemux);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109 av7110 = (struct av7110 *) dvbdemux->priv;
1110
1111 dprintk(4, "%p\n", av7110);
1112
1113 if (num != 0)
1114 return -EINVAL;
1115
1116 ret = av7110_fw_request(av7110, &tag, 0, fwstc, 4);
1117 if (ret) {
1118 printk(KERN_ERR "%s: av7110_fw_request error\n", __FUNCTION__);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001119 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120 }
1121 dprintk(2, "fwstc = %04hx %04hx %04hx %04hx\n",
1122 fwstc[0], fwstc[1], fwstc[2], fwstc[3]);
1123
1124 *stc = (((uint64_t) ((fwstc[3] & 0x8000) >> 15)) << 32) |
1125 (((uint64_t) fwstc[1]) << 16) | ((uint64_t) fwstc[0]);
1126 *base = 1;
1127
1128 dprintk(4, "stc = %lu\n", (unsigned long)*stc);
1129
1130 return 0;
1131}
1132
1133
1134/******************************************************************************
1135 * SEC device file operations
1136 ******************************************************************************/
1137
1138
1139static int av7110_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
1140{
1141 struct av7110* av7110 = (struct av7110*) fe->dvb->priv;
1142
1143 switch (tone) {
1144 case SEC_TONE_ON:
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001145 return Set22K(av7110, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001146
1147 case SEC_TONE_OFF:
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001148 return Set22K(av7110, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001149
1150 default:
1151 return -EINVAL;
1152 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001153}
1154
1155static int av7110_diseqc_send_master_cmd(struct dvb_frontend* fe,
1156 struct dvb_diseqc_master_cmd* cmd)
1157{
1158 struct av7110* av7110 = fe->dvb->priv;
1159
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001160 return av7110_diseqc_send(av7110, cmd->msg_len, cmd->msg, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001161}
1162
1163static int av7110_diseqc_send_burst(struct dvb_frontend* fe,
1164 fe_sec_mini_cmd_t minicmd)
1165{
1166 struct av7110* av7110 = fe->dvb->priv;
1167
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001168 return av7110_diseqc_send(av7110, 0, NULL, minicmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001169}
1170
1171/* simplified code from budget-core.c */
1172static int stop_ts_capture(struct av7110 *budget)
1173{
1174 dprintk(2, "budget: %p\n", budget);
1175
1176 if (--budget->feeding1)
1177 return budget->feeding1;
1178 saa7146_write(budget->dev, MC1, MASK_20); /* DMA3 off */
1179 SAA7146_IER_DISABLE(budget->dev, MASK_10);
1180 SAA7146_ISR_CLEAR(budget->dev, MASK_10);
1181 return 0;
1182}
1183
1184static int start_ts_capture(struct av7110 *budget)
1185{
1186 dprintk(2, "budget: %p\n", budget);
1187
1188 if (budget->feeding1)
1189 return ++budget->feeding1;
1190 memset(budget->grabbing, 0x00, TS_HEIGHT * TS_WIDTH);
1191 budget->tsf = 0xff;
1192 budget->ttbp = 0;
1193 SAA7146_IER_ENABLE(budget->dev, MASK_10); /* VPE */
1194 saa7146_write(budget->dev, MC1, (MASK_04 | MASK_20)); /* DMA3 on */
1195 return ++budget->feeding1;
1196}
1197
1198static int budget_start_feed(struct dvb_demux_feed *feed)
1199{
1200 struct dvb_demux *demux = feed->demux;
1201 struct av7110 *budget = (struct av7110 *) demux->priv;
1202 int status;
1203
1204 dprintk(2, "av7110: %p\n", budget);
1205
1206 spin_lock(&budget->feedlock1);
1207 feed->pusi_seen = 0; /* have a clean section start */
1208 status = start_ts_capture(budget);
1209 spin_unlock(&budget->feedlock1);
1210 return status;
1211}
1212
1213static int budget_stop_feed(struct dvb_demux_feed *feed)
1214{
1215 struct dvb_demux *demux = feed->demux;
1216 struct av7110 *budget = (struct av7110 *) demux->priv;
1217 int status;
1218
1219 dprintk(2, "budget: %p\n", budget);
1220
1221 spin_lock(&budget->feedlock1);
1222 status = stop_ts_capture(budget);
1223 spin_unlock(&budget->feedlock1);
1224 return status;
1225}
1226
1227static void vpeirq(unsigned long data)
1228{
1229 struct av7110 *budget = (struct av7110 *) data;
1230 u8 *mem = (u8 *) (budget->grabbing);
1231 u32 olddma = budget->ttbp;
1232 u32 newdma = saa7146_read(budget->dev, PCI_VDP3);
1233
1234 if (!budgetpatch) {
1235 printk("av7110.c: vpeirq() called while budgetpatch disabled!"
1236 " check saa7146 IER register\n");
1237 BUG();
1238 }
1239 /* nearest lower position divisible by 188 */
1240 newdma -= newdma % 188;
1241
1242 if (newdma >= TS_BUFLEN)
1243 return;
1244
1245 budget->ttbp = newdma;
1246
1247 if (!budget->feeding1 || (newdma == olddma))
1248 return;
1249
1250#if 0
1251 /* track rps1 activity */
1252 printk("vpeirq: %02x Event Counter 1 0x%04x\n",
1253 mem[olddma],
1254 saa7146_read(budget->dev, EC1R) & 0x3fff);
1255#endif
1256
1257 if (newdma > olddma)
1258 /* no wraparound, dump olddma..newdma */
1259 dvb_dmx_swfilter_packets(&budget->demux1, mem + olddma, (newdma - olddma) / 188);
1260 else {
1261 /* wraparound, dump olddma..buflen and 0..newdma */
1262 dvb_dmx_swfilter_packets(&budget->demux1, mem + olddma, (TS_BUFLEN - olddma) / 188);
1263 dvb_dmx_swfilter_packets(&budget->demux1, mem, newdma / 188);
1264 }
1265}
1266
1267static int av7110_register(struct av7110 *av7110)
1268{
1269 int ret, i;
1270 struct dvb_demux *dvbdemux = &av7110->demux;
1271 struct dvb_demux *dvbdemux1 = &av7110->demux1;
1272
1273 dprintk(4, "%p\n", av7110);
1274
1275 if (av7110->registered)
1276 return -1;
1277
1278 av7110->registered = 1;
1279
1280 dvbdemux->priv = (void *) av7110;
1281
1282 for (i = 0; i < 32; i++)
1283 av7110->handle2filter[i] = NULL;
1284
1285 dvbdemux->filternum = 32;
1286 dvbdemux->feednum = 32;
1287 dvbdemux->start_feed = av7110_start_feed;
1288 dvbdemux->stop_feed = av7110_stop_feed;
1289 dvbdemux->write_to_decoder = av7110_write_to_decoder;
1290 dvbdemux->dmx.capabilities = (DMX_TS_FILTERING | DMX_SECTION_FILTERING |
1291 DMX_MEMORY_BASED_FILTERING);
1292
1293 dvb_dmx_init(&av7110->demux);
1294 av7110->demux.dmx.get_stc = dvb_get_stc;
1295
1296 av7110->dmxdev.filternum = 32;
1297 av7110->dmxdev.demux = &dvbdemux->dmx;
1298 av7110->dmxdev.capabilities = 0;
1299
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001300 dvb_dmxdev_init(&av7110->dmxdev, &av7110->dvb_adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001301
1302 av7110->hw_frontend.source = DMX_FRONTEND_0;
1303
1304 ret = dvbdemux->dmx.add_frontend(&dvbdemux->dmx, &av7110->hw_frontend);
1305
1306 if (ret < 0)
1307 return ret;
1308
1309 av7110->mem_frontend.source = DMX_MEMORY_FE;
1310
1311 ret = dvbdemux->dmx.add_frontend(&dvbdemux->dmx, &av7110->mem_frontend);
1312
1313 if (ret < 0)
1314 return ret;
1315
1316 ret = dvbdemux->dmx.connect_frontend(&dvbdemux->dmx,
1317 &av7110->hw_frontend);
1318 if (ret < 0)
1319 return ret;
1320
1321 av7110_av_register(av7110);
1322 av7110_ca_register(av7110);
1323
1324#ifdef CONFIG_DVB_AV7110_OSD
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001325 dvb_register_device(&av7110->dvb_adapter, &av7110->osd_dev,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001326 &dvbdev_osd, av7110, DVB_DEVICE_OSD);
1327#endif
1328
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001329 dvb_net_init(&av7110->dvb_adapter, &av7110->dvb_net, &dvbdemux->dmx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001330
1331 if (budgetpatch) {
1332 /* initialize software demux1 without its own frontend
1333 * demux1 hardware is connected to frontend0 of demux0
1334 */
1335 dvbdemux1->priv = (void *) av7110;
1336
1337 dvbdemux1->filternum = 256;
1338 dvbdemux1->feednum = 256;
1339 dvbdemux1->start_feed = budget_start_feed;
1340 dvbdemux1->stop_feed = budget_stop_feed;
1341 dvbdemux1->write_to_decoder = NULL;
1342
1343 dvbdemux1->dmx.capabilities = (DMX_TS_FILTERING | DMX_SECTION_FILTERING |
1344 DMX_MEMORY_BASED_FILTERING);
1345
1346 dvb_dmx_init(&av7110->demux1);
1347
1348 av7110->dmxdev1.filternum = 256;
1349 av7110->dmxdev1.demux = &dvbdemux1->dmx;
1350 av7110->dmxdev1.capabilities = 0;
1351
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001352 dvb_dmxdev_init(&av7110->dmxdev1, &av7110->dvb_adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001353
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001354 dvb_net_init(&av7110->dvb_adapter, &av7110->dvb_net1, &dvbdemux1->dmx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001355 printk("dvb-ttpci: additional demux1 for budget-patch registered\n");
1356 }
1357 return 0;
1358}
1359
1360
1361static void dvb_unregister(struct av7110 *av7110)
1362{
1363 struct dvb_demux *dvbdemux = &av7110->demux;
1364 struct dvb_demux *dvbdemux1 = &av7110->demux1;
1365
1366 dprintk(4, "%p\n", av7110);
1367
1368 if (!av7110->registered)
1369 return;
1370
1371 if (budgetpatch) {
1372 dvb_net_release(&av7110->dvb_net1);
1373 dvbdemux->dmx.close(&dvbdemux1->dmx);
1374 dvb_dmxdev_release(&av7110->dmxdev1);
1375 dvb_dmx_release(&av7110->demux1);
1376 }
1377
1378 dvb_net_release(&av7110->dvb_net);
1379
1380 dvbdemux->dmx.close(&dvbdemux->dmx);
1381 dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &av7110->hw_frontend);
1382 dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &av7110->mem_frontend);
1383
1384 dvb_dmxdev_release(&av7110->dmxdev);
1385 dvb_dmx_release(&av7110->demux);
1386
1387 if (av7110->fe != NULL)
1388 dvb_unregister_frontend(av7110->fe);
1389 dvb_unregister_device(av7110->osd_dev);
1390 av7110_av_unregister(av7110);
1391 av7110_ca_unregister(av7110);
1392}
1393
1394
1395/****************************************************************************
1396 * I2C client commands
1397 ****************************************************************************/
1398
1399int i2c_writereg(struct av7110 *av7110, u8 id, u8 reg, u8 val)
1400{
1401 u8 msg[2] = { reg, val };
1402 struct i2c_msg msgs;
1403
1404 msgs.flags = 0;
1405 msgs.addr = id / 2;
1406 msgs.len = 2;
1407 msgs.buf = msg;
1408 return i2c_transfer(&av7110->i2c_adap, &msgs, 1);
1409}
1410
1411#if 0
1412u8 i2c_readreg(struct av7110 *av7110, u8 id, u8 reg)
1413{
1414 u8 mm1[] = {0x00};
1415 u8 mm2[] = {0x00};
1416 struct i2c_msg msgs[2];
1417
1418 msgs[0].flags = 0;
1419 msgs[1].flags = I2C_M_RD;
1420 msgs[0].addr = msgs[1].addr = id / 2;
1421 mm1[0] = reg;
1422 msgs[0].len = 1; msgs[1].len = 1;
1423 msgs[0].buf = mm1; msgs[1].buf = mm2;
1424 i2c_transfer(&av7110->i2c_adap, msgs, 2);
1425
1426 return mm2[0];
1427}
1428#endif
1429
1430/****************************************************************************
1431 * INITIALIZATION
1432 ****************************************************************************/
1433
1434
1435static int check_firmware(struct av7110* av7110)
1436{
1437 u32 crc = 0, len = 0;
1438 unsigned char *ptr;
1439
1440 /* check for firmware magic */
1441 ptr = av7110->bin_fw;
1442 if (ptr[0] != 'A' || ptr[1] != 'V' ||
1443 ptr[2] != 'F' || ptr[3] != 'W') {
1444 printk("dvb-ttpci: this is not an av7110 firmware\n");
1445 return -EINVAL;
1446 }
1447 ptr += 4;
1448
1449 /* check dpram file */
1450 crc = ntohl(*(u32*) ptr);
1451 ptr += 4;
1452 len = ntohl(*(u32*) ptr);
1453 ptr += 4;
1454 if (len >= 512) {
Alexey Dobriyanbe787ac2006-03-07 22:20:23 -03001455 printk("dvb-ttpci: dpram file is way too big.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001456 return -EINVAL;
1457 }
1458 if (crc != crc32_le(0, ptr, len)) {
1459 printk("dvb-ttpci: crc32 of dpram file does not match.\n");
1460 return -EINVAL;
1461 }
1462 av7110->bin_dpram = ptr;
1463 av7110->size_dpram = len;
1464 ptr += len;
1465
1466 /* check root file */
1467 crc = ntohl(*(u32*) ptr);
1468 ptr += 4;
1469 len = ntohl(*(u32*) ptr);
1470 ptr += 4;
1471
1472 if (len <= 200000 || len >= 300000 ||
1473 len > ((av7110->bin_fw + av7110->size_fw) - ptr)) {
1474 printk("dvb-ttpci: root file has strange size (%d). aborting.\n", len);
1475 return -EINVAL;
1476 }
1477 if( crc != crc32_le(0, ptr, len)) {
1478 printk("dvb-ttpci: crc32 of root file does not match.\n");
1479 return -EINVAL;
1480 }
1481 av7110->bin_root = ptr;
1482 av7110->size_root = len;
1483 return 0;
1484}
1485
1486#ifdef CONFIG_DVB_AV7110_FIRMWARE_FILE
1487#include "av7110_firm.h"
1488static void put_firmware(struct av7110* av7110)
1489{
1490 av7110->bin_fw = NULL;
1491}
1492
1493static inline int get_firmware(struct av7110* av7110)
1494{
1495 av7110->bin_fw = dvb_ttpci_fw;
1496 av7110->size_fw = sizeof(dvb_ttpci_fw);
1497 return check_firmware(av7110);
1498}
1499#else
1500static void put_firmware(struct av7110* av7110)
1501{
1502 vfree(av7110->bin_fw);
1503}
1504
1505static int get_firmware(struct av7110* av7110)
1506{
1507 int ret;
1508 const struct firmware *fw;
1509
1510 /* request the av7110 firmware, this will block until someone uploads it */
1511 ret = request_firmware(&fw, "dvb-ttpci-01.fw", &av7110->dev->pci->dev);
1512 if (ret) {
1513 if (ret == -ENOENT) {
1514 printk(KERN_ERR "dvb-ttpci: could not load firmware,"
1515 " file not found: dvb-ttpci-01.fw\n");
Ville Skytt\ä12e66f62006-01-09 15:25:38 -02001516 printk(KERN_ERR "dvb-ttpci: usually this should be in "
1517 "/usr/lib/hotplug/firmware or /lib/firmware\n");
1518 printk(KERN_ERR "dvb-ttpci: and can be downloaded from"
Linus Torvalds1da177e2005-04-16 15:20:36 -07001519 " http://www.linuxtv.org/download/dvb/firmware/\n");
1520 } else
1521 printk(KERN_ERR "dvb-ttpci: cannot request firmware"
1522 " (error %i)\n", ret);
1523 return -EINVAL;
1524 }
1525
1526 if (fw->size <= 200000) {
1527 printk("dvb-ttpci: this firmware is way too small.\n");
1528 release_firmware(fw);
1529 return -EINVAL;
1530 }
1531
1532 /* check if the firmware is available */
1533 av7110->bin_fw = (unsigned char *) vmalloc(fw->size);
1534 if (NULL == av7110->bin_fw) {
1535 dprintk(1, "out of memory\n");
1536 release_firmware(fw);
1537 return -ENOMEM;
1538 }
1539
1540 memcpy(av7110->bin_fw, fw->data, fw->size);
1541 av7110->size_fw = fw->size;
1542 if ((ret = check_firmware(av7110)))
1543 vfree(av7110->bin_fw);
1544
1545 release_firmware(fw);
1546 return ret;
1547}
1548#endif
1549
1550
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001551static int alps_bsrv2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001552{
1553 struct av7110* av7110 = (struct av7110*) fe->dvb->priv;
1554 u8 pwr = 0;
1555 u8 buf[4];
1556 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
1557 u32 div = (params->frequency + 479500) / 125;
1558
1559 if (params->frequency > 2000000) pwr = 3;
1560 else if (params->frequency > 1800000) pwr = 2;
1561 else if (params->frequency > 1600000) pwr = 1;
1562 else if (params->frequency > 1200000) pwr = 0;
1563 else if (params->frequency >= 1100000) pwr = 1;
1564 else pwr = 2;
1565
1566 buf[0] = (div >> 8) & 0x7f;
1567 buf[1] = div & 0xff;
1568 buf[2] = ((div & 0x18000) >> 10) | 0x95;
1569 buf[3] = (pwr << 6) | 0x30;
1570
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -08001571 // NOTE: since we're using a prescaler of 2, we set the
Linus Torvalds1da177e2005-04-16 15:20:36 -07001572 // divisor frequency to 62.5kHz and divide by 125 above
1573
Patrick Boettcherdea74862006-05-14 05:01:31 -03001574 if (fe->ops.i2c_gate_ctrl)
1575 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001576 if (i2c_transfer (&av7110->i2c_adap, &msg, 1) != 1)
1577 return -EIO;
1578 return 0;
1579}
1580
1581static struct ves1x93_config alps_bsrv2_config = {
1582 .demod_address = 0x08,
1583 .xin = 90100000UL,
1584 .invert_pwm = 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001585};
1586
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001587static int alps_tdbe2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001588{
1589 struct av7110* av7110 = fe->dvb->priv;
1590 u32 div;
1591 u8 data[4];
1592 struct i2c_msg msg = { .addr = 0x62, .flags = 0, .buf = data, .len = sizeof(data) };
1593
1594 div = (params->frequency + 35937500 + 31250) / 62500;
1595
1596 data[0] = (div >> 8) & 0x7f;
1597 data[1] = div & 0xff;
1598 data[2] = 0x85 | ((div >> 10) & 0x60);
1599 data[3] = (params->frequency < 174000000 ? 0x88 : params->frequency < 470000000 ? 0x84 : 0x81);
1600
Patrick Boettcherdea74862006-05-14 05:01:31 -03001601 if (fe->ops.i2c_gate_ctrl)
1602 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001603 if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
1604 return -EIO;
1605 return 0;
1606}
1607
1608static struct ves1820_config alps_tdbe2_config = {
1609 .demod_address = 0x09,
1610 .xin = 57840000UL,
1611 .invert = 1,
1612 .selagc = VES1820_SELAGC_SIGNAMPERR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001613};
1614
1615
1616
1617
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001618static int grundig_29504_451_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001619{
1620 struct av7110* av7110 = fe->dvb->priv;
1621 u32 div;
1622 u8 data[4];
1623 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
1624
1625 div = params->frequency / 125;
1626 data[0] = (div >> 8) & 0x7f;
1627 data[1] = div & 0xff;
1628 data[2] = 0x8e;
1629 data[3] = 0x00;
1630
Patrick Boettcherdea74862006-05-14 05:01:31 -03001631 if (fe->ops.i2c_gate_ctrl)
1632 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001633 if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
1634 return -EIO;
1635 return 0;
1636}
1637
1638static struct tda8083_config grundig_29504_451_config = {
1639 .demod_address = 0x68,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001640};
1641
1642
1643
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001644static int philips_cd1516_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001645{
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -08001646 struct av7110* av7110 = fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001647 u32 div;
1648 u32 f = params->frequency;
1649 u8 data[4];
1650 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
1651
1652 div = (f + 36125000 + 31250) / 62500;
1653
1654 data[0] = (div >> 8) & 0x7f;
1655 data[1] = div & 0xff;
1656 data[2] = 0x8e;
1657 data[3] = (f < 174000000 ? 0xa1 : f < 470000000 ? 0x92 : 0x34);
1658
Patrick Boettcherdea74862006-05-14 05:01:31 -03001659 if (fe->ops.i2c_gate_ctrl)
1660 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001661 if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
1662 return -EIO;
1663 return 0;
1664}
1665
1666static struct ves1820_config philips_cd1516_config = {
1667 .demod_address = 0x09,
1668 .xin = 57840000UL,
1669 .invert = 1,
1670 .selagc = VES1820_SELAGC_SIGNAMPERR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001671};
1672
1673
1674
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001675static int alps_tdlb7_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001676{
1677 struct av7110* av7110 = fe->dvb->priv;
1678 u32 div, pwr;
1679 u8 data[4];
1680 struct i2c_msg msg = { .addr = 0x60, .flags = 0, .buf = data, .len = sizeof(data) };
1681
1682 div = (params->frequency + 36200000) / 166666;
1683
1684 if (params->frequency <= 782000000)
1685 pwr = 1;
1686 else
1687 pwr = 2;
1688
1689 data[0] = (div >> 8) & 0x7f;
1690 data[1] = div & 0xff;
1691 data[2] = 0x85;
1692 data[3] = pwr << 6;
1693
Patrick Boettcherdea74862006-05-14 05:01:31 -03001694 if (fe->ops.i2c_gate_ctrl)
1695 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001696 if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
1697 return -EIO;
1698 return 0;
1699}
1700
1701static int alps_tdlb7_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name)
1702{
1703 struct av7110* av7110 = (struct av7110*) fe->dvb->priv;
1704
1705 return request_firmware(fw, name, &av7110->dev->pci->dev);
1706}
1707
1708static struct sp8870_config alps_tdlb7_config = {
1709
1710 .demod_address = 0x71,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001711 .request_firmware = alps_tdlb7_request_firmware,
1712};
1713
1714
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001715static u8 nexusca_stv0297_inittab[] = {
1716 0x80, 0x01,
1717 0x80, 0x00,
1718 0x81, 0x01,
1719 0x81, 0x00,
1720 0x00, 0x09,
1721 0x01, 0x69,
1722 0x03, 0x00,
1723 0x04, 0x00,
1724 0x07, 0x00,
1725 0x08, 0x00,
1726 0x20, 0x00,
1727 0x21, 0x40,
1728 0x22, 0x00,
1729 0x23, 0x00,
1730 0x24, 0x40,
1731 0x25, 0x88,
1732 0x30, 0xff,
1733 0x31, 0x00,
1734 0x32, 0xff,
1735 0x33, 0x00,
1736 0x34, 0x50,
1737 0x35, 0x7f,
1738 0x36, 0x00,
1739 0x37, 0x20,
1740 0x38, 0x00,
1741 0x40, 0x1c,
1742 0x41, 0xff,
1743 0x42, 0x29,
1744 0x43, 0x00,
1745 0x44, 0xff,
1746 0x45, 0x00,
1747 0x46, 0x00,
1748 0x49, 0x04,
1749 0x4a, 0x00,
1750 0x4b, 0x7b,
1751 0x52, 0x30,
1752 0x55, 0xae,
1753 0x56, 0x47,
1754 0x57, 0xe1,
1755 0x58, 0x3a,
1756 0x5a, 0x1e,
1757 0x5b, 0x34,
1758 0x60, 0x00,
1759 0x63, 0x00,
1760 0x64, 0x00,
1761 0x65, 0x00,
1762 0x66, 0x00,
1763 0x67, 0x00,
1764 0x68, 0x00,
1765 0x69, 0x00,
1766 0x6a, 0x02,
1767 0x6b, 0x00,
1768 0x70, 0xff,
1769 0x71, 0x00,
1770 0x72, 0x00,
1771 0x73, 0x00,
1772 0x74, 0x0c,
1773 0x80, 0x00,
1774 0x81, 0x00,
1775 0x82, 0x00,
1776 0x83, 0x00,
1777 0x84, 0x04,
1778 0x85, 0x80,
1779 0x86, 0x24,
1780 0x87, 0x78,
1781 0x88, 0x10,
1782 0x89, 0x00,
1783 0x90, 0x01,
1784 0x91, 0x01,
1785 0xa0, 0x04,
1786 0xa1, 0x00,
1787 0xa2, 0x00,
1788 0xb0, 0x91,
1789 0xb1, 0x0b,
1790 0xc0, 0x53,
1791 0xc1, 0x70,
1792 0xc2, 0x12,
1793 0xd0, 0x00,
1794 0xd1, 0x00,
1795 0xd2, 0x00,
1796 0xd3, 0x00,
1797 0xd4, 0x00,
1798 0xd5, 0x00,
1799 0xde, 0x00,
1800 0xdf, 0x00,
1801 0x61, 0x49,
1802 0x62, 0x0b,
1803 0x53, 0x08,
1804 0x59, 0x08,
1805 0xff, 0xff,
1806};
Linus Torvalds1da177e2005-04-16 15:20:36 -07001807
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001808static int nexusca_stv0297_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001809{
1810 struct av7110* av7110 = fe->dvb->priv;
1811 u32 div;
1812 u8 data[4];
1813 struct i2c_msg msg = { .addr = 0x63, .flags = 0, .buf = data, .len = sizeof(data) };
1814 struct i2c_msg readmsg = { .addr = 0x63, .flags = I2C_M_RD, .buf = data, .len = 1 };
1815 int i;
1816
1817 div = (params->frequency + 36150000 + 31250) / 62500;
1818
1819 data[0] = (div >> 8) & 0x7f;
1820 data[1] = div & 0xff;
1821 data[2] = 0xce;
1822
1823 if (params->frequency < 45000000)
1824 return -EINVAL;
1825 else if (params->frequency < 137000000)
1826 data[3] = 0x01;
1827 else if (params->frequency < 403000000)
1828 data[3] = 0x02;
1829 else if (params->frequency < 860000000)
1830 data[3] = 0x04;
1831 else
1832 return -EINVAL;
1833
Patrick Boettcherdea74862006-05-14 05:01:31 -03001834 if (fe->ops.i2c_gate_ctrl)
1835 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001836 if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1) {
1837 printk("nexusca: pll transfer failed!\n");
1838 return -EIO;
1839 }
1840
1841 // wait for PLL lock
1842 for(i = 0; i < 20; i++) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001843 if (fe->ops.i2c_gate_ctrl)
1844 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001845 if (i2c_transfer(&av7110->i2c_adap, &readmsg, 1) == 1)
1846 if (data[0] & 0x40) break;
1847 msleep(10);
1848 }
1849
1850 return 0;
1851}
1852
1853static struct stv0297_config nexusca_stv0297_config = {
1854
1855 .demod_address = 0x1C,
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001856 .inittab = nexusca_stv0297_inittab,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001857 .invert = 1,
Thomas Kaiserb8d4c232006-04-27 21:45:20 -03001858 .stop_during_read = 1,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001859};
1860
1861
1862
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001863static int grundig_29504_401_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001864{
1865 struct av7110* av7110 = (struct av7110*) fe->dvb->priv;
1866 u32 div;
1867 u8 cfg, cpump, band_select;
1868 u8 data[4];
1869 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
1870
1871 div = (36125000 + params->frequency) / 166666;
1872
1873 cfg = 0x88;
1874
1875 if (params->frequency < 175000000) cpump = 2;
1876 else if (params->frequency < 390000000) cpump = 1;
1877 else if (params->frequency < 470000000) cpump = 2;
1878 else if (params->frequency < 750000000) cpump = 1;
1879 else cpump = 3;
1880
1881 if (params->frequency < 175000000) band_select = 0x0e;
1882 else if (params->frequency < 470000000) band_select = 0x05;
1883 else band_select = 0x03;
1884
1885 data[0] = (div >> 8) & 0x7f;
1886 data[1] = div & 0xff;
1887 data[2] = ((div >> 10) & 0x60) | cfg;
1888 data[3] = (cpump << 6) | band_select;
1889
Patrick Boettcherdea74862006-05-14 05:01:31 -03001890 if (fe->ops.i2c_gate_ctrl)
1891 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001892 if (i2c_transfer (&av7110->i2c_adap, &msg, 1) != 1) return -EIO;
1893 return 0;
1894}
1895
1896static struct l64781_config grundig_29504_401_config = {
1897 .demod_address = 0x55,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001898};
1899
1900
1901
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001902static int av7110_fe_lock_fix(struct av7110* av7110, fe_status_t status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001903{
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001904 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001905 int synced = (status & FE_HAS_LOCK) ? 1 : 0;
1906
1907 av7110->fe_status = status;
1908
1909 if (av7110->fe_synced == synced)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001910 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001911
Linus Torvalds1da177e2005-04-16 15:20:36 -07001912 if (av7110->playing)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001913 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001914
Ingo Molnar3593cab2006-02-07 06:49:14 -02001915 if (mutex_lock_interruptible(&av7110->pid_mutex))
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001916 return -ERESTARTSYS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001917
Oliver Endriss34612152005-07-07 17:58:02 -07001918 if (synced) {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001919 ret = SetPIDs(av7110, av7110->pids[DMX_PES_VIDEO],
Linus Torvalds1da177e2005-04-16 15:20:36 -07001920 av7110->pids[DMX_PES_AUDIO],
1921 av7110->pids[DMX_PES_TELETEXT], 0,
1922 av7110->pids[DMX_PES_PCR]);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001923 if (!ret)
1924 ret = av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, Scan, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001925 } else {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001926 ret = SetPIDs(av7110, 0, 0, 0, 0, 0);
1927 if (!ret) {
1928 ret = av7110_fw_cmd(av7110, COMTYPE_PID_FILTER, FlushTSQueue, 0);
1929 if (!ret)
1930 ret = av7110_wait_msgstate(av7110, GPMQBusy);
1931 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001932 }
1933
Oliver Endriss34612152005-07-07 17:58:02 -07001934 if (!ret)
1935 av7110->fe_synced = synced;
1936
Ingo Molnar3593cab2006-02-07 06:49:14 -02001937 mutex_unlock(&av7110->pid_mutex);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001938 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001939}
1940
1941static int av7110_fe_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
1942{
1943 struct av7110* av7110 = fe->dvb->priv;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001944
1945 int ret = av7110_fe_lock_fix(av7110, 0);
Oliver Endriss66190a22006-01-09 15:32:42 -02001946 if (!ret) {
1947 av7110->saved_fe_params = *params;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001948 ret = av7110->fe_set_frontend(fe, params);
Oliver Endriss66190a22006-01-09 15:32:42 -02001949 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001950 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001951}
1952
1953static int av7110_fe_init(struct dvb_frontend* fe)
1954{
1955 struct av7110* av7110 = fe->dvb->priv;
1956
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001957 int ret = av7110_fe_lock_fix(av7110, 0);
1958 if (!ret)
1959 ret = av7110->fe_init(fe);
1960 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001961}
1962
1963static int av7110_fe_read_status(struct dvb_frontend* fe, fe_status_t* status)
1964{
1965 struct av7110* av7110 = fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001966
1967 /* call the real implementation */
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001968 int ret = av7110->fe_read_status(fe, status);
1969 if (!ret)
1970 if (((*status ^ av7110->fe_status) & FE_HAS_LOCK) && (*status & FE_HAS_LOCK))
1971 ret = av7110_fe_lock_fix(av7110, *status);
1972 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001973}
1974
1975static int av7110_fe_diseqc_reset_overload(struct dvb_frontend* fe)
1976{
1977 struct av7110* av7110 = fe->dvb->priv;
1978
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001979 int ret = av7110_fe_lock_fix(av7110, 0);
1980 if (!ret)
1981 ret = av7110->fe_diseqc_reset_overload(fe);
1982 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001983}
1984
1985static int av7110_fe_diseqc_send_master_cmd(struct dvb_frontend* fe,
1986 struct dvb_diseqc_master_cmd* cmd)
1987{
1988 struct av7110* av7110 = fe->dvb->priv;
1989
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001990 int ret = av7110_fe_lock_fix(av7110, 0);
Oliver Endriss66190a22006-01-09 15:32:42 -02001991 if (!ret) {
1992 av7110->saved_master_cmd = *cmd;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001993 ret = av7110->fe_diseqc_send_master_cmd(fe, cmd);
Oliver Endriss66190a22006-01-09 15:32:42 -02001994 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001995 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001996}
1997
1998static int av7110_fe_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd)
1999{
2000 struct av7110* av7110 = fe->dvb->priv;
2001
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002002 int ret = av7110_fe_lock_fix(av7110, 0);
Oliver Endriss66190a22006-01-09 15:32:42 -02002003 if (!ret) {
2004 av7110->saved_minicmd = minicmd;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002005 ret = av7110->fe_diseqc_send_burst(fe, minicmd);
Oliver Endriss66190a22006-01-09 15:32:42 -02002006 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002007 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002008}
2009
2010static int av7110_fe_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
2011{
2012 struct av7110* av7110 = fe->dvb->priv;
2013
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002014 int ret = av7110_fe_lock_fix(av7110, 0);
Oliver Endriss66190a22006-01-09 15:32:42 -02002015 if (!ret) {
2016 av7110->saved_tone = tone;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002017 ret = av7110->fe_set_tone(fe, tone);
Oliver Endriss66190a22006-01-09 15:32:42 -02002018 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002019 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002020}
2021
2022static int av7110_fe_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
2023{
2024 struct av7110* av7110 = fe->dvb->priv;
2025
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002026 int ret = av7110_fe_lock_fix(av7110, 0);
Oliver Endriss66190a22006-01-09 15:32:42 -02002027 if (!ret) {
2028 av7110->saved_voltage = voltage;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002029 ret = av7110->fe_set_voltage(fe, voltage);
Oliver Endriss66190a22006-01-09 15:32:42 -02002030 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002031 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002032}
2033
Peter Beutner400b7082006-01-09 15:32:43 -02002034static int av7110_fe_dishnetwork_send_legacy_command(struct dvb_frontend* fe, unsigned long cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002035{
2036 struct av7110* av7110 = fe->dvb->priv;
2037
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002038 int ret = av7110_fe_lock_fix(av7110, 0);
2039 if (!ret)
2040 ret = av7110->fe_dishnetwork_send_legacy_command(fe, cmd);
2041 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002042}
2043
Oliver Endriss66190a22006-01-09 15:32:42 -02002044static void dvb_s_recover(struct av7110* av7110)
2045{
2046 av7110_fe_init(av7110->fe);
2047
2048 av7110_fe_set_voltage(av7110->fe, av7110->saved_voltage);
2049 if (av7110->saved_master_cmd.msg_len) {
2050 msleep(20);
2051 av7110_fe_diseqc_send_master_cmd(av7110->fe, &av7110->saved_master_cmd);
2052 }
2053 msleep(20);
2054 av7110_fe_diseqc_send_burst(av7110->fe, av7110->saved_minicmd);
2055 msleep(20);
2056 av7110_fe_set_tone(av7110->fe, av7110->saved_tone);
2057
2058 av7110_fe_set_frontend(av7110->fe, &av7110->saved_fe_params);
2059}
2060
Linus Torvalds1da177e2005-04-16 15:20:36 -07002061static u8 read_pwm(struct av7110* av7110)
2062{
2063 u8 b = 0xff;
2064 u8 pwm;
2065 struct i2c_msg msg[] = { { .addr = 0x50,.flags = 0,.buf = &b,.len = 1 },
2066 { .addr = 0x50,.flags = I2C_M_RD,.buf = &pwm,.len = 1} };
2067
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -08002068 if ((i2c_transfer(&av7110->i2c_adap, msg, 2) != 2) || (pwm == 0xff))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002069 pwm = 0x48;
2070
2071 return pwm;
2072}
2073
2074static int frontend_init(struct av7110 *av7110)
2075{
2076 int ret;
2077
2078 if (av7110->dev->pci->subsystem_vendor == 0x110a) {
2079 switch(av7110->dev->pci->subsystem_device) {
2080 case 0x0000: // Fujitsu/Siemens DVB-Cable (ves1820/Philips CD1516(??))
2081 av7110->fe = ves1820_attach(&philips_cd1516_config,
2082 &av7110->i2c_adap, read_pwm(av7110));
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002083 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002084 av7110->fe->ops.tuner_ops.set_params = philips_cd1516_tuner_set_params;
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002085 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002086 break;
2087 }
2088
2089 } else if (av7110->dev->pci->subsystem_vendor == 0x13c2) {
2090 switch(av7110->dev->pci->subsystem_device) {
2091 case 0x0000: // Hauppauge/TT WinTV DVB-S rev1.X
2092 case 0x0003: // Hauppauge/TT WinTV Nexus-S Rev 2.X
2093 case 0x1002: // Hauppauge/TT WinTV DVB-S rev1.3SE
2094
2095 // try the ALPS BSRV2 first of all
2096 av7110->fe = ves1x93_attach(&alps_bsrv2_config, &av7110->i2c_adap);
2097 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002098 av7110->fe->ops.tuner_ops.set_params = alps_bsrv2_tuner_set_params;
2099 av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
2100 av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
2101 av7110->fe->ops.set_tone = av7110_set_tone;
Oliver Endriss66190a22006-01-09 15:32:42 -02002102 av7110->recover = dvb_s_recover;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002103 break;
2104 }
2105
2106 // try the ALPS BSRU6 now
2107 av7110->fe = stv0299_attach(&alps_bsru6_config, &av7110->i2c_adap);
2108 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002109 av7110->fe->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03002110 av7110->fe->tuner_priv = &av7110->i2c_adap;
2111
Patrick Boettcherdea74862006-05-14 05:01:31 -03002112 av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
2113 av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
2114 av7110->fe->ops.set_tone = av7110_set_tone;
Oliver Endriss66190a22006-01-09 15:32:42 -02002115 av7110->recover = dvb_s_recover;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002116 break;
2117 }
2118
2119 // Try the grundig 29504-451
Michael Krufky50c25ff2006-01-09 15:25:34 -02002120 av7110->fe = tda8083_attach(&grundig_29504_451_config, &av7110->i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002121 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002122 av7110->fe->ops.tuner_ops.set_params = grundig_29504_451_tuner_set_params;
2123 av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
2124 av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
2125 av7110->fe->ops.set_tone = av7110_set_tone;
Oliver Endriss66190a22006-01-09 15:32:42 -02002126 av7110->recover = dvb_s_recover;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002127 break;
2128 }
2129
2130 /* Try DVB-C cards */
2131 switch(av7110->dev->pci->subsystem_device) {
2132 case 0x0000:
2133 /* Siemens DVB-C (full-length card) VES1820/Philips CD1516 */
2134 av7110->fe = ves1820_attach(&philips_cd1516_config, &av7110->i2c_adap,
2135 read_pwm(av7110));
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002136 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002137 av7110->fe->ops.tuner_ops.set_params = philips_cd1516_tuner_set_params;
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002138 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002139 break;
2140 case 0x0003:
Adrian Bunkf3688fc2006-03-29 22:46:12 -03002141 /* Hauppauge DVB-C 2.1 VES1820/ALPS TDBE2 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002142 av7110->fe = ves1820_attach(&alps_tdbe2_config, &av7110->i2c_adap,
2143 read_pwm(av7110));
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002144 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002145 av7110->fe->ops.tuner_ops.set_params = alps_tdbe2_tuner_set_params;
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002146 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002147 break;
2148 }
2149 break;
2150
2151 case 0x0001: // Hauppauge/TT Nexus-T premium rev1.X
2152
2153 // ALPS TDLB7
Michael Krufky50c25ff2006-01-09 15:25:34 -02002154 av7110->fe = sp8870_attach(&alps_tdlb7_config, &av7110->i2c_adap);
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002155 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002156 av7110->fe->ops.tuner_ops.set_params = alps_tdlb7_tuner_set_params;
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002157 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002158 break;
2159
2160 case 0x0002: // Hauppauge/TT DVB-C premium rev2.X
2161
Michael Krufky50c25ff2006-01-09 15:25:34 -02002162 av7110->fe = ves1820_attach(&alps_tdbe2_config, &av7110->i2c_adap, read_pwm(av7110));
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002163 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002164 av7110->fe->ops.tuner_ops.set_params = alps_tdbe2_tuner_set_params;
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002165 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002166 break;
2167
Oliver Endriss8bd63012006-02-07 06:49:11 -02002168 case 0x0004: // Galaxis DVB-S rev1.3
2169 /* ALPS BSRV2 */
2170 av7110->fe = ves1x93_attach(&alps_bsrv2_config, &av7110->i2c_adap);
2171 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002172 av7110->fe->ops.tuner_ops.set_params = alps_bsrv2_tuner_set_params;
2173 av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
2174 av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
2175 av7110->fe->ops.set_tone = av7110_set_tone;
Oliver Endriss8bd63012006-02-07 06:49:11 -02002176 av7110->recover = dvb_s_recover;
2177 }
2178 break;
2179
Linus Torvalds1da177e2005-04-16 15:20:36 -07002180 case 0x0006: /* Fujitsu-Siemens DVB-S rev 1.6 */
2181 /* Grundig 29504-451 */
2182 av7110->fe = tda8083_attach(&grundig_29504_451_config, &av7110->i2c_adap);
2183 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002184 av7110->fe->ops.tuner_ops.set_params = grundig_29504_451_tuner_set_params;
2185 av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
2186 av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
2187 av7110->fe->ops.set_tone = av7110_set_tone;
Oliver Endriss66190a22006-01-09 15:32:42 -02002188 av7110->recover = dvb_s_recover;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002189 }
2190 break;
2191
2192 case 0x0008: // Hauppauge/TT DVB-T
2193
2194 av7110->fe = l64781_attach(&grundig_29504_401_config, &av7110->i2c_adap);
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002195 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002196 av7110->fe->ops.tuner_ops.set_params = grundig_29504_401_tuner_set_params;
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002197 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002198 break;
2199
2200 case 0x000A: // Hauppauge/TT Nexus-CA rev1.X
2201
Andrew de Quinceydc27a162005-09-09 13:03:07 -07002202 av7110->fe = stv0297_attach(&nexusca_stv0297_config, &av7110->i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002203 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002204 av7110->fe->ops.tuner_ops.set_params = nexusca_stv0297_tuner_set_params;
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03002205
Linus Torvalds1da177e2005-04-16 15:20:36 -07002206 /* set TDA9819 into DVB mode */
2207 saa7146_setgpio(av7110->dev, 1, SAA7146_GPIO_OUTLO); // TDA9198 pin9(STD)
2208 saa7146_setgpio(av7110->dev, 3, SAA7146_GPIO_OUTLO); // TDA9198 pin30(VIF)
2209
2210 /* tuner on this needs a slower i2c bus speed */
2211 av7110->dev->i2c_bitrate = SAA7146_I2C_BUS_BIT_RATE_240;
2212 break;
2213 }
Johannes Stezenbach3dfaebd2005-05-16 21:54:19 -07002214 break;
2215
2216 case 0x000E: /* Hauppauge/TT Nexus-S rev 2.3 */
2217 /* ALPS BSBE1 */
2218 av7110->fe = stv0299_attach(&alps_bsbe1_config, &av7110->i2c_adap);
Oliver Endrisseb3daf32006-01-09 15:25:05 -02002219 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002220 av7110->fe->ops.tuner_ops.set_params = alps_bsbe1_tuner_set_params;
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03002221 av7110->fe->tuner_priv = &av7110->i2c_adap;
2222
Andrew de Quinceyd0205422006-04-27 21:45:01 -03002223 if (lnbp21_attach(av7110->fe, &av7110->i2c_adap, 0, 0)) {
Oliver Endrissdb5d91e2006-02-28 10:32:25 -03002224 printk("dvb-ttpci: LNBP21 not found!\n");
Patrick Boettcherdea74862006-05-14 05:01:31 -03002225 if (av7110->fe->ops.release)
2226 av7110->fe->ops.release(av7110->fe);
Oliver Endrissdb5d91e2006-02-28 10:32:25 -03002227 av7110->fe = NULL;
2228 } else {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002229 av7110->fe->ops.dishnetwork_send_legacy_command = NULL;
Oliver Endrissdb5d91e2006-02-28 10:32:25 -03002230 av7110->recover = dvb_s_recover;
2231 }
Oliver Endrisseb3daf32006-01-09 15:25:05 -02002232 }
Johannes Stezenbach3dfaebd2005-05-16 21:54:19 -07002233 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002234 }
2235 }
2236
2237 if (!av7110->fe) {
2238 /* FIXME: propagate the failure code from the lower layers */
2239 ret = -ENOMEM;
2240 printk("dvb-ttpci: A frontend driver was not found for device %04x/%04x subsystem %04x/%04x\n",
2241 av7110->dev->pci->vendor,
2242 av7110->dev->pci->device,
2243 av7110->dev->pci->subsystem_vendor,
2244 av7110->dev->pci->subsystem_device);
2245 } else {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002246 FE_FUNC_OVERRIDE(av7110->fe->ops.init, av7110->fe_init, av7110_fe_init);
2247 FE_FUNC_OVERRIDE(av7110->fe->ops.read_status, av7110->fe_read_status, av7110_fe_read_status);
2248 FE_FUNC_OVERRIDE(av7110->fe->ops.diseqc_reset_overload, av7110->fe_diseqc_reset_overload, av7110_fe_diseqc_reset_overload);
2249 FE_FUNC_OVERRIDE(av7110->fe->ops.diseqc_send_master_cmd, av7110->fe_diseqc_send_master_cmd, av7110_fe_diseqc_send_master_cmd);
2250 FE_FUNC_OVERRIDE(av7110->fe->ops.diseqc_send_burst, av7110->fe_diseqc_send_burst, av7110_fe_diseqc_send_burst);
2251 FE_FUNC_OVERRIDE(av7110->fe->ops.set_tone, av7110->fe_set_tone, av7110_fe_set_tone);
2252 FE_FUNC_OVERRIDE(av7110->fe->ops.set_voltage, av7110->fe_set_voltage, av7110_fe_set_voltage;)
2253 FE_FUNC_OVERRIDE(av7110->fe->ops.dishnetwork_send_legacy_command, av7110->fe_dishnetwork_send_legacy_command, av7110_fe_dishnetwork_send_legacy_command);
2254 FE_FUNC_OVERRIDE(av7110->fe->ops.set_frontend, av7110->fe_set_frontend, av7110_fe_set_frontend);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002255
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07002256 ret = dvb_register_frontend(&av7110->dvb_adapter, av7110->fe);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002257 if (ret < 0) {
2258 printk("av7110: Frontend registration failed!\n");
Patrick Boettcherdea74862006-05-14 05:01:31 -03002259 if (av7110->fe->ops.release)
2260 av7110->fe->ops.release(av7110->fe);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002261 av7110->fe = NULL;
2262 }
2263 }
2264 return ret;
2265}
2266
2267/* Budgetpatch note:
2268 * Original hardware design by Roberto Deza:
2269 * There is a DVB_Wiki at
2270 * http://212.227.36.83/linuxtv/wiki/index.php/Main_Page
2271 * where is described this 'DVB TT Budget Patch', on Card Modding:
2272 * http://212.227.36.83/linuxtv/wiki/index.php/DVB_TT_Budget_Patch
2273 * On the short description there is also a link to a external file,
2274 * with more details:
2275 * http://perso.wanadoo.es/jesussolano/Ttf_tsc1.zip
2276 *
2277 * New software triggering design by Emard that works on
2278 * original Roberto Deza's hardware:
2279 *
2280 * rps1 code for budgetpatch will copy internal HS event to GPIO3 pin.
2281 * GPIO3 is in budget-patch hardware connectd to port B VSYNC
2282 * HS is an internal event of 7146, accessible with RPS
2283 * and temporarily raised high every n lines
2284 * (n in defined in the RPS_THRESH1 counter threshold)
2285 * I think HS is raised high on the beginning of the n-th line
2286 * and remains high until this n-th line that triggered
2287 * it is completely received. When the receiption of n-th line
2288 * ends, HS is lowered.
2289 *
2290 * To transmit data over DMA, 7146 needs changing state at
2291 * port B VSYNC pin. Any changing of port B VSYNC will
2292 * cause some DMA data transfer, with more or less packets loss.
2293 * It depends on the phase and frequency of VSYNC and
2294 * the way of 7146 is instructed to trigger on port B (defined
2295 * in DD1_INIT register, 3rd nibble from the right valid
2296 * numbers are 0-7, see datasheet)
2297 *
2298 * The correct triggering can minimize packet loss,
2299 * dvbtraffic should give this stable bandwidths:
2300 * 22k transponder = 33814 kbit/s
2301 * 27.5k transponder = 38045 kbit/s
2302 * by experiment it is found that the best results
2303 * (stable bandwidths and almost no packet loss)
2304 * are obtained using DD1_INIT triggering number 2
2305 * (Va at rising edge of VS Fa = HS x VS-failing forced toggle)
2306 * and a VSYNC phase that occurs in the middle of DMA transfer
2307 * (about byte 188*512=96256 in the DMA window).
2308 *
2309 * Phase of HS is still not clear to me how to control,
2310 * It just happens to be so. It can be seen if one enables
2311 * RPS_IRQ and print Event Counter 1 in vpeirq(). Every
2312 * time RPS_INTERRUPT is called, the Event Counter 1 will
2313 * increment. That's how the 7146 is programmed to do event
2314 * counting in this budget-patch.c
2315 * I *think* HPS setting has something to do with the phase
2316 * of HS but I cant be 100% sure in that.
2317 *
2318 * hardware debug note: a working budget card (including budget patch)
2319 * with vpeirq() interrupt setup in mode "0x90" (every 64K) will
2320 * generate 3 interrupts per 25-Hz DMA frame of 2*188*512 bytes
2321 * and that means 3*25=75 Hz of interrupt freqency, as seen by
2322 * watch cat /proc/interrupts
2323 *
2324 * If this frequency is 3x lower (and data received in the DMA
2325 * buffer don't start with 0x47, but in the middle of packets,
2326 * whose lengths appear to be like 188 292 188 104 etc.
2327 * this means VSYNC line is not connected in the hardware.
2328 * (check soldering pcb and pins)
2329 * The same behaviour of missing VSYNC can be duplicated on budget
2330 * cards, by seting DD1_INIT trigger mode 7 in 3rd nibble.
2331 */
Johannes Stezenbach1be11e32006-02-27 00:09:20 -03002332static int __devinit av7110_attach(struct saa7146_dev* dev,
2333 struct saa7146_pci_extension_data *pci_ext)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002334{
2335 const int length = TS_WIDTH * TS_HEIGHT;
2336 struct pci_dev *pdev = dev->pci;
2337 struct av7110 *av7110;
2338 int ret, count = 0;
2339
2340 dprintk(4, "dev: %p\n", dev);
2341
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -08002342 /* Set RPS_IRQ to 1 to track rps1 activity.
2343 * Enabling this won't send any interrupt to PC CPU.
2344 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002345#define RPS_IRQ 0
2346
2347 if (budgetpatch == 1) {
2348 budgetpatch = 0;
2349 /* autodetect the presence of budget patch
2350 * this only works if saa7146 has been recently
2351 * reset with with MASK_31 to MC1
2352 *
2353 * will wait for VBI_B event (vertical blank at port B)
2354 * and will reset GPIO3 after VBI_B is detected.
2355 * (GPIO3 should be raised high by CPU to
2356 * test if GPIO3 will generate vertical blank signal
2357 * in budget patch GPIO3 is connected to VSYNC_B
2358 */
2359
2360 /* RESET SAA7146 */
2361 saa7146_write(dev, MC1, MASK_31);
2362 /* autodetection success seems to be time-dependend after reset */
2363
2364 /* Fix VSYNC level */
2365 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
2366 /* set vsync_b triggering */
2367 saa7146_write(dev, DD1_STREAM_B, 0);
2368 /* port B VSYNC at rising edge */
2369 saa7146_write(dev, DD1_INIT, 0x00000200);
2370 saa7146_write(dev, BRS_CTRL, 0x00000000); // VBI
2371 saa7146_write(dev, MC2,
2372 1 * (MASK_08 | MASK_24) | // BRS control
2373 0 * (MASK_09 | MASK_25) | // a
2374 1 * (MASK_10 | MASK_26) | // b
2375 0 * (MASK_06 | MASK_22) | // HPS_CTRL1
2376 0 * (MASK_05 | MASK_21) | // HPS_CTRL2
2377 0 * (MASK_01 | MASK_15) // DEBI
2378 );
2379
2380 /* start writing RPS1 code from beginning */
2381 count = 0;
2382 /* Disable RPS1 */
2383 saa7146_write(dev, MC1, MASK_29);
2384 /* RPS1 timeout disable */
2385 saa7146_write(dev, RPS_TOV1, 0);
2386 WRITE_RPS1(cpu_to_le32(CMD_PAUSE | EVT_VBI_B));
2387 WRITE_RPS1(cpu_to_le32(CMD_WR_REG_MASK | (GPIO_CTRL>>2)));
2388 WRITE_RPS1(cpu_to_le32(GPIO3_MSK));
2389 WRITE_RPS1(cpu_to_le32(SAA7146_GPIO_OUTLO<<24));
2390#if RPS_IRQ
2391 /* issue RPS1 interrupt to increment counter */
2392 WRITE_RPS1(cpu_to_le32(CMD_INTERRUPT));
2393#endif
2394 WRITE_RPS1(cpu_to_le32(CMD_STOP));
2395 /* Jump to begin of RPS program as safety measure (p37) */
2396 WRITE_RPS1(cpu_to_le32(CMD_JUMP));
2397 WRITE_RPS1(cpu_to_le32(dev->d_rps1.dma_handle));
2398
2399#if RPS_IRQ
2400 /* set event counter 1 source as RPS1 interrupt (0x03) (rE4 p53)
2401 * use 0x03 to track RPS1 interrupts - increase by 1 every gpio3 is toggled
2402 * use 0x15 to track VPE interrupts - increase by 1 every vpeirq() is called
2403 */
2404 saa7146_write(dev, EC1SSR, (0x03<<2) | 3 );
2405 /* set event counter 1 treshold to maximum allowed value (rEC p55) */
2406 saa7146_write(dev, ECT1R, 0x3fff );
2407#endif
2408 /* Set RPS1 Address register to point to RPS code (r108 p42) */
2409 saa7146_write(dev, RPS_ADDR1, dev->d_rps1.dma_handle);
2410 /* Enable RPS1, (rFC p33) */
2411 saa7146_write(dev, MC1, (MASK_13 | MASK_29 ));
2412
2413 mdelay(10);
2414 /* now send VSYNC_B to rps1 by rising GPIO3 */
2415 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI);
2416 mdelay(10);
2417 /* if rps1 responded by lowering the GPIO3,
2418 * then we have budgetpatch hardware
2419 */
2420 if ((saa7146_read(dev, GPIO_CTRL) & 0x10000000) == 0) {
2421 budgetpatch = 1;
2422 printk("dvb-ttpci: BUDGET-PATCH DETECTED.\n");
2423 }
2424 /* Disable RPS1 */
2425 saa7146_write(dev, MC1, ( MASK_29 ));
2426#if RPS_IRQ
2427 printk("dvb-ttpci: Event Counter 1 0x%04x\n", saa7146_read(dev, EC1R) & 0x3fff );
2428#endif
2429 }
2430
2431 /* prepare the av7110 device struct */
Panagiotis Issaris74081872006-01-11 19:40:56 -02002432 av7110 = kzalloc(sizeof(struct av7110), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002433 if (!av7110) {
2434 dprintk(1, "out of memory\n");
2435 return -ENOMEM;
2436 }
2437
Linus Torvalds1da177e2005-04-16 15:20:36 -07002438 av7110->card_name = (char*) pci_ext->ext_priv;
2439 av7110->dev = dev;
2440 dev->ext_priv = av7110;
2441
2442 ret = get_firmware(av7110);
2443 if (ret < 0)
2444 goto err_kfree_0;
2445
2446 ret = dvb_register_adapter(&av7110->dvb_adapter, av7110->card_name,
Andrew de Quinceyd09dbf92006-04-10 09:27:37 -03002447 THIS_MODULE, &dev->pci->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002448 if (ret < 0)
2449 goto err_put_firmware_1;
2450
2451 /* the Siemens DVB needs this if you want to have the i2c chips
2452 get recognized before the main driver is fully loaded */
2453 saa7146_write(dev, GPIO_CTRL, 0x500000);
2454
2455#ifdef I2C_ADAP_CLASS_TV_DIGITAL
2456 av7110->i2c_adap.class = I2C_ADAP_CLASS_TV_DIGITAL;
2457#else
2458 av7110->i2c_adap.class = I2C_CLASS_TV_DIGITAL;
2459#endif
2460 strlcpy(av7110->i2c_adap.name, pci_ext->ext_priv, sizeof(av7110->i2c_adap.name));
2461
2462 saa7146_i2c_adapter_prepare(dev, &av7110->i2c_adap, SAA7146_I2C_BUS_BIT_RATE_120); /* 275 kHz */
2463
2464 ret = i2c_add_adapter(&av7110->i2c_adap);
2465 if (ret < 0)
2466 goto err_dvb_unregister_adapter_2;
2467
2468 ttpci_eeprom_parse_mac(&av7110->i2c_adap,
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07002469 av7110->dvb_adapter.proposed_mac);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002470 ret = -ENOMEM;
2471
2472 if (budgetpatch) {
2473 spin_lock_init(&av7110->feedlock1);
2474 av7110->grabbing = saa7146_vmalloc_build_pgtable(pdev, length,
2475 &av7110->pt);
2476 if (!av7110->grabbing)
2477 goto err_i2c_del_3;
2478
2479 saa7146_write(dev, PCI_BT_V1, 0x1c1f101f);
2480 saa7146_write(dev, BCS_CTRL, 0x80400040);
2481 /* set dd1 stream a & b */
2482 saa7146_write(dev, DD1_STREAM_B, 0x00000000);
2483 saa7146_write(dev, DD1_INIT, 0x03000200);
2484 saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
2485 saa7146_write(dev, BRS_CTRL, 0x60000000);
2486 saa7146_write(dev, BASE_ODD3, 0);
2487 saa7146_write(dev, BASE_EVEN3, 0);
2488 saa7146_write(dev, PROT_ADDR3, TS_WIDTH * TS_HEIGHT);
2489 saa7146_write(dev, BASE_PAGE3, av7110->pt.dma | ME1 | 0x90);
2490
2491 saa7146_write(dev, PITCH3, TS_WIDTH);
2492 saa7146_write(dev, NUM_LINE_BYTE3, (TS_HEIGHT << 16) | TS_WIDTH);
2493
2494 /* upload all */
2495 saa7146_write(dev, MC2, 0x077c077c);
2496 saa7146_write(dev, GPIO_CTRL, 0x000000);
2497#if RPS_IRQ
2498 /* set event counter 1 source as RPS1 interrupt (0x03) (rE4 p53)
2499 * use 0x03 to track RPS1 interrupts - increase by 1 every gpio3 is toggled
2500 * use 0x15 to track VPE interrupts - increase by 1 every vpeirq() is called
2501 */
2502 saa7146_write(dev, EC1SSR, (0x03<<2) | 3 );
2503 /* set event counter 1 treshold to maximum allowed value (rEC p55) */
2504 saa7146_write(dev, ECT1R, 0x3fff );
2505#endif
2506 /* Setup BUDGETPATCH MAIN RPS1 "program" (p35) */
2507 count = 0;
2508
2509 /* Wait Source Line Counter Threshold (p36) */
2510 WRITE_RPS1(cpu_to_le32(CMD_PAUSE | EVT_HS));
2511 /* Set GPIO3=1 (p42) */
2512 WRITE_RPS1(cpu_to_le32(CMD_WR_REG_MASK | (GPIO_CTRL>>2)));
2513 WRITE_RPS1(cpu_to_le32(GPIO3_MSK));
2514 WRITE_RPS1(cpu_to_le32(SAA7146_GPIO_OUTHI<<24));
2515#if RPS_IRQ
2516 /* issue RPS1 interrupt */
2517 WRITE_RPS1(cpu_to_le32(CMD_INTERRUPT));
2518#endif
2519 /* Wait reset Source Line Counter Threshold (p36) */
2520 WRITE_RPS1(cpu_to_le32(CMD_PAUSE | RPS_INV | EVT_HS));
2521 /* Set GPIO3=0 (p42) */
2522 WRITE_RPS1(cpu_to_le32(CMD_WR_REG_MASK | (GPIO_CTRL>>2)));
2523 WRITE_RPS1(cpu_to_le32(GPIO3_MSK));
2524 WRITE_RPS1(cpu_to_le32(SAA7146_GPIO_OUTLO<<24));
2525#if RPS_IRQ
2526 /* issue RPS1 interrupt */
2527 WRITE_RPS1(cpu_to_le32(CMD_INTERRUPT));
2528#endif
2529 /* Jump to begin of RPS program (p37) */
2530 WRITE_RPS1(cpu_to_le32(CMD_JUMP));
2531 WRITE_RPS1(cpu_to_le32(dev->d_rps1.dma_handle));
2532
2533 /* Fix VSYNC level */
2534 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
2535 /* Set RPS1 Address register to point to RPS code (r108 p42) */
2536 saa7146_write(dev, RPS_ADDR1, dev->d_rps1.dma_handle);
2537 /* Set Source Line Counter Threshold, using BRS (rCC p43)
2538 * It generates HS event every TS_HEIGHT lines
2539 * this is related to TS_WIDTH set in register
2540 * NUM_LINE_BYTE3. If NUM_LINE_BYTE low 16 bits
2541 * are set to TS_WIDTH bytes (TS_WIDTH=2*188),
2542 * then RPS_THRESH1 should be set to trigger
2543 * every TS_HEIGHT (512) lines.
2544 */
2545 saa7146_write(dev, RPS_THRESH1, (TS_HEIGHT*1) | MASK_12 );
2546
2547 /* Enable RPS1 (rFC p33) */
2548 saa7146_write(dev, MC1, (MASK_13 | MASK_29));
2549
2550 /* end of budgetpatch register initialization */
2551 tasklet_init (&av7110->vpe_tasklet, vpeirq, (unsigned long) av7110);
2552 } else {
2553 saa7146_write(dev, PCI_BT_V1, 0x1c00101f);
2554 saa7146_write(dev, BCS_CTRL, 0x80400040);
2555
2556 /* set dd1 stream a & b */
2557 saa7146_write(dev, DD1_STREAM_B, 0x00000000);
2558 saa7146_write(dev, DD1_INIT, 0x03000000);
2559 saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
2560
2561 /* upload all */
2562 saa7146_write(dev, MC2, 0x077c077c);
2563 saa7146_write(dev, GPIO_CTRL, 0x000000);
2564 }
2565
2566 tasklet_init (&av7110->debi_tasklet, debiirq, (unsigned long) av7110);
2567 tasklet_init (&av7110->gpio_tasklet, gpioirq, (unsigned long) av7110);
2568
Ingo Molnar3593cab2006-02-07 06:49:14 -02002569 mutex_init(&av7110->pid_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002570
2571 /* locks for data transfers from/to AV7110 */
2572 spin_lock_init(&av7110->debilock);
Ingo Molnar3593cab2006-02-07 06:49:14 -02002573 mutex_init(&av7110->dcomlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002574 av7110->debitype = -1;
2575
2576 /* default OSD window */
2577 av7110->osdwin = 1;
Ingo Molnar3593cab2006-02-07 06:49:14 -02002578 mutex_init(&av7110->osd_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002579
C.Y.M2f03ee82006-03-30 04:31:48 -03002580 /* TV standard */
2581 av7110->vidmode = tv_standard == 1 ? VIDEO_MODE_NTSC : VIDEO_MODE_PAL;
2582
Linus Torvalds1da177e2005-04-16 15:20:36 -07002583 /* ARM "watchdog" */
2584 init_waitqueue_head(&av7110->arm_wait);
2585 av7110->arm_thread = NULL;
2586
2587 /* allocate and init buffers */
2588 av7110->debi_virt = pci_alloc_consistent(pdev, 8192, &av7110->debi_bus);
2589 if (!av7110->debi_virt)
2590 goto err_saa71466_vfree_4;
2591
2592
2593 av7110->iobuf = vmalloc(AVOUTLEN+AOUTLEN+BMPLEN+4*IPACKS);
2594 if (!av7110->iobuf)
2595 goto err_pci_free_5;
2596
2597 ret = av7110_av_init(av7110);
2598 if (ret < 0)
2599 goto err_iobuf_vfree_6;
2600
2601 /* init BMP buffer */
2602 av7110->bmpbuf = av7110->iobuf+AVOUTLEN+AOUTLEN;
2603 init_waitqueue_head(&av7110->bmpq);
2604
2605 ret = av7110_ca_init(av7110);
2606 if (ret < 0)
2607 goto err_av7110_av_exit_7;
2608
2609 /* load firmware into AV7110 cards */
2610 ret = av7110_bootarm(av7110);
2611 if (ret < 0)
2612 goto err_av7110_ca_exit_8;
2613
2614 ret = av7110_firmversion(av7110);
2615 if (ret < 0)
2616 goto err_stop_arm_9;
2617
2618 if (FW_VERSION(av7110->arm_app)<0x2501)
2619 printk ("dvb-ttpci: Warning, firmware version 0x%04x is too old. "
2620 "System might be unstable!\n", FW_VERSION(av7110->arm_app));
2621
2622 ret = kernel_thread(arm_thread, (void *) av7110, 0);
2623 if (ret < 0)
2624 goto err_stop_arm_9;
2625
2626 /* set initial volume in mixer struct */
2627 av7110->mixer.volume_left = volume;
2628 av7110->mixer.volume_right = volume;
2629
2630 init_av7110_av(av7110);
2631
2632 ret = av7110_register(av7110);
2633 if (ret < 0)
2634 goto err_arm_thread_stop_10;
2635
2636 /* special case DVB-C: these cards have an analog tuner
2637 plus need some special handling, so we have separate
2638 saa7146_ext_vv data for these... */
2639 ret = av7110_init_v4l(av7110);
2640 if (ret < 0)
2641 goto err_av7110_unregister_11;
2642
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07002643 av7110->dvb_adapter.priv = av7110;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002644 ret = frontend_init(av7110);
2645 if (ret < 0)
2646 goto err_av7110_exit_v4l_12;
2647
2648#if defined(CONFIG_INPUT_EVDEV) || defined(CONFIG_INPUT_EVDEV_MODULE)
Oliver Endriss03388ae2005-09-09 13:03:12 -07002649 av7110_ir_init(av7110);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002650#endif
2651 printk(KERN_INFO "dvb-ttpci: found av7110-%d.\n", av7110_num);
2652 av7110_num++;
2653out:
2654 return ret;
2655
2656err_av7110_exit_v4l_12:
2657 av7110_exit_v4l(av7110);
2658err_av7110_unregister_11:
2659 dvb_unregister(av7110);
2660err_arm_thread_stop_10:
2661 av7110_arm_sync(av7110);
2662err_stop_arm_9:
2663 /* Nothing to do. Rejoice. */
2664err_av7110_ca_exit_8:
2665 av7110_ca_exit(av7110);
2666err_av7110_av_exit_7:
2667 av7110_av_exit(av7110);
2668err_iobuf_vfree_6:
2669 vfree(av7110->iobuf);
2670err_pci_free_5:
2671 pci_free_consistent(pdev, 8192, av7110->debi_virt, av7110->debi_bus);
2672err_saa71466_vfree_4:
2673 if (!av7110->grabbing)
2674 saa7146_pgtable_free(pdev, &av7110->pt);
2675err_i2c_del_3:
2676 i2c_del_adapter(&av7110->i2c_adap);
2677err_dvb_unregister_adapter_2:
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07002678 dvb_unregister_adapter(&av7110->dvb_adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002679err_put_firmware_1:
2680 put_firmware(av7110);
2681err_kfree_0:
2682 kfree(av7110);
2683 goto out;
2684}
2685
Johannes Stezenbach1be11e32006-02-27 00:09:20 -03002686static int __devexit av7110_detach(struct saa7146_dev* saa)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002687{
2688 struct av7110 *av7110 = saa->ext_priv;
2689 dprintk(4, "%p\n", av7110);
2690
Oliver Endriss03388ae2005-09-09 13:03:12 -07002691#if defined(CONFIG_INPUT_EVDEV) || defined(CONFIG_INPUT_EVDEV_MODULE)
2692 av7110_ir_exit(av7110);
2693#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07002694 if (budgetpatch) {
2695 /* Disable RPS1 */
2696 saa7146_write(saa, MC1, MASK_29);
2697 /* VSYNC LOW (inactive) */
2698 saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);
2699 saa7146_write(saa, MC1, MASK_20); /* DMA3 off */
2700 SAA7146_IER_DISABLE(saa, MASK_10);
2701 SAA7146_ISR_CLEAR(saa, MASK_10);
2702 msleep(50);
2703 tasklet_kill(&av7110->vpe_tasklet);
2704 saa7146_pgtable_free(saa->pci, &av7110->pt);
2705 }
2706 av7110_exit_v4l(av7110);
2707
2708 av7110_arm_sync(av7110);
2709
2710 tasklet_kill(&av7110->debi_tasklet);
2711 tasklet_kill(&av7110->gpio_tasklet);
2712
2713 dvb_unregister(av7110);
2714
2715 SAA7146_IER_DISABLE(saa, MASK_19 | MASK_03);
2716 SAA7146_ISR_CLEAR(saa, MASK_19 | MASK_03);
2717
2718 av7110_ca_exit(av7110);
2719 av7110_av_exit(av7110);
2720
2721 vfree(av7110->iobuf);
2722 pci_free_consistent(saa->pci, 8192, av7110->debi_virt,
2723 av7110->debi_bus);
2724
2725 i2c_del_adapter(&av7110->i2c_adap);
2726
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07002727 dvb_unregister_adapter (&av7110->dvb_adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002728
2729 av7110_num--;
2730
2731 put_firmware(av7110);
2732
2733 kfree(av7110);
2734
2735 saa->ext_priv = NULL;
2736
2737 return 0;
2738}
2739
2740
2741static void av7110_irq(struct saa7146_dev* dev, u32 *isr)
2742{
2743 struct av7110 *av7110 = dev->ext_priv;
2744
2745 //print_time("av7110_irq");
2746
2747 /* Note: Don't try to handle the DEBI error irq (MASK_18), in
2748 * intel mode the timeout is asserted all the time...
2749 */
2750
2751 if (*isr & MASK_19) {
2752 //printk("av7110_irq: DEBI\n");
2753 /* Note 1: The DEBI irq is level triggered: We must enable it
2754 * only after we started a DMA xfer, and disable it here
2755 * immediately, or it will be signalled all the time while
2756 * DEBI is idle.
2757 * Note 2: You would think that an irq which is masked is
2758 * not signalled by the hardware. Not so for the SAA7146:
2759 * An irq is signalled as long as the corresponding bit
2760 * in the ISR is set, and disabling irqs just prevents the
2761 * hardware from setting the ISR bit. This means a) that we
2762 * must clear the ISR *after* disabling the irq (which is why
2763 * we must do it here even though saa7146_core did it already),
2764 * and b) that if we were to disable an edge triggered irq
2765 * (like the gpio irqs sadly are) temporarily we would likely
2766 * loose some. This sucks :-(
2767 */
2768 SAA7146_IER_DISABLE(av7110->dev, MASK_19);
2769 SAA7146_ISR_CLEAR(av7110->dev, MASK_19);
2770 tasklet_schedule(&av7110->debi_tasklet);
2771 }
2772
2773 if (*isr & MASK_03) {
2774 //printk("av7110_irq: GPIO\n");
2775 tasklet_schedule(&av7110->gpio_tasklet);
2776 }
2777
2778 if ((*isr & MASK_10) && budgetpatch)
2779 tasklet_schedule(&av7110->vpe_tasklet);
2780}
2781
2782
2783static struct saa7146_extension av7110_extension;
2784
2785#define MAKE_AV7110_INFO(x_var,x_name) \
2786static struct saa7146_pci_extension_data x_var = { \
2787 .ext_priv = x_name, \
2788 .ext = &av7110_extension }
2789
Karl Herz6af4ee12005-09-09 13:03:13 -07002790MAKE_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 -07002791MAKE_AV7110_INFO(ttt_1_X, "Technotrend/Hauppauge WinTV DVB-T rev1.X");
2792MAKE_AV7110_INFO(ttc_1_X, "Technotrend/Hauppauge WinTV Nexus-CA rev1.X");
2793MAKE_AV7110_INFO(ttc_2_X, "Technotrend/Hauppauge WinTV DVB-C rev2.X");
2794MAKE_AV7110_INFO(tts_2_X, "Technotrend/Hauppauge WinTV Nexus-S rev2.X");
Johannes Stezenbach3dfaebd2005-05-16 21:54:19 -07002795MAKE_AV7110_INFO(tts_2_3, "Technotrend/Hauppauge WinTV Nexus-S rev2.3");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002796MAKE_AV7110_INFO(tts_1_3se, "Technotrend/Hauppauge WinTV DVB-S rev1.3 SE");
2797MAKE_AV7110_INFO(ttt, "Technotrend/Hauppauge DVB-T");
2798MAKE_AV7110_INFO(fsc, "Fujitsu Siemens DVB-C");
2799MAKE_AV7110_INFO(fss, "Fujitsu Siemens DVB-S rev1.6");
Oliver Endriss8bd63012006-02-07 06:49:11 -02002800MAKE_AV7110_INFO(gxs_1_3, "Galaxis DVB-S rev1.3");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002801
2802static struct pci_device_id pci_tbl[] = {
Karl Herz6af4ee12005-09-09 13:03:13 -07002803 MAKE_EXTENSION_PCI(fsc, 0x110a, 0x0000),
2804 MAKE_EXTENSION_PCI(tts_1_X_fsc, 0x13c2, 0x0000),
2805 MAKE_EXTENSION_PCI(ttt_1_X, 0x13c2, 0x0001),
2806 MAKE_EXTENSION_PCI(ttc_2_X, 0x13c2, 0x0002),
2807 MAKE_EXTENSION_PCI(tts_2_X, 0x13c2, 0x0003),
Oliver Endriss8bd63012006-02-07 06:49:11 -02002808 MAKE_EXTENSION_PCI(gxs_1_3, 0x13c2, 0x0004),
Karl Herz6af4ee12005-09-09 13:03:13 -07002809 MAKE_EXTENSION_PCI(fss, 0x13c2, 0x0006),
2810 MAKE_EXTENSION_PCI(ttt, 0x13c2, 0x0008),
2811 MAKE_EXTENSION_PCI(ttc_1_X, 0x13c2, 0x000a),
2812 MAKE_EXTENSION_PCI(tts_2_3, 0x13c2, 0x000e),
2813 MAKE_EXTENSION_PCI(tts_1_3se, 0x13c2, 0x1002),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002814
Linus Torvalds1da177e2005-04-16 15:20:36 -07002815/* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0005), UNDEFINED CARD */ // Technisat SkyStar1
2816/* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0009), UNDEFINED CARD */ // TT/Hauppauge WinTV Nexus-CA v????
2817
2818 {
2819 .vendor = 0,
2820 }
2821};
2822
2823MODULE_DEVICE_TABLE(pci, pci_tbl);
2824
2825
2826static struct saa7146_extension av7110_extension = {
2827 .name = "dvb\0",
2828 .flags = SAA7146_I2C_SHORT_DELAY,
2829
2830 .module = THIS_MODULE,
2831 .pci_tbl = &pci_tbl[0],
2832 .attach = av7110_attach,
Johannes Stezenbach1be11e32006-02-27 00:09:20 -03002833 .detach = __devexit_p(av7110_detach),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002834
2835 .irq_mask = MASK_19 | MASK_03 | MASK_10,
2836 .irq_func = av7110_irq,
2837};
2838
2839
2840static int __init av7110_init(void)
2841{
2842 int retval;
2843 retval = saa7146_register_extension(&av7110_extension);
2844 return retval;
2845}
2846
2847
2848static void __exit av7110_exit(void)
2849{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002850 saa7146_unregister_extension(&av7110_extension);
2851}
2852
2853module_init(av7110_init);
2854module_exit(av7110_exit);
2855
2856MODULE_DESCRIPTION("driver for the SAA7146 based AV110 PCI DVB cards by "
2857 "Siemens, Technotrend, Hauppauge");
2858MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, others");
2859MODULE_LICENSE("GPL");