blob: 8832f80c05f7a92b7a5a5af8cf4d5fc8af4006ee [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;
Marco Schluessler1c13b952006-01-09 15:25:06 -0200155 if (dev->pci->subsystem_vendor == 0x13c2 && dev->pci->subsystem_device == 0x000a) {
156 printk("dvb-ttpci: MSP3415 audio DAC @ card %d\n",
157 av7110->dvb_adapter.num);
158 av7110->adac_type = DVB_ADAC_MSP34x5;
159 av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, ADSwitch, 1, 0); // SPDIF on
160 }
161 else if (i2c_writereg(av7110, 0x20, 0x00, 0x00) == 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700162 printk ("dvb-ttpci: Crystal audio DAC @ card %d detected\n",
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -0700163 av7110->dvb_adapter.num);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700164 av7110->adac_type = DVB_ADAC_CRYSTAL;
165 i2c_writereg(av7110, 0x20, 0x01, 0xd2);
166 i2c_writereg(av7110, 0x20, 0x02, 0x49);
167 i2c_writereg(av7110, 0x20, 0x03, 0x00);
168 i2c_writereg(av7110, 0x20, 0x04, 0x00);
169
170 /**
171 * some special handling for the Siemens DVB-C cards...
172 */
173 } else if (0 == av7110_init_analog_module(av7110)) {
174 /* done. */
175 }
176 else if (dev->pci->subsystem_vendor == 0x110a) {
177 printk("dvb-ttpci: DVB-C w/o analog module @ card %d detected\n",
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -0700178 av7110->dvb_adapter.num);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700179 av7110->adac_type = DVB_ADAC_NONE;
180 }
181 else {
182 av7110->adac_type = adac;
183 printk("dvb-ttpci: adac type set to %d @ card %d\n",
Marco Schluessler1c13b952006-01-09 15:25:06 -0200184 av7110->adac_type, av7110->dvb_adapter.num);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700185 }
186
Marco Schluessler1c13b952006-01-09 15:25:06 -0200187 if (av7110->adac_type == DVB_ADAC_NONE || av7110->adac_type == DVB_ADAC_MSP34x0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700188 // switch DVB SCART on
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700189 ret = av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, MainSwitch, 1, 0);
Johannes Stezenbach7a2fa902005-07-07 17:58:01 -0700190 if (ret < 0)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700191 printk("dvb-ttpci:cannot switch on SCART(Main):%d\n",ret);
192 ret = av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, ADSwitch, 1, 1);
Johannes Stezenbach7a2fa902005-07-07 17:58:01 -0700193 if (ret < 0)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700194 printk("dvb-ttpci:cannot switch on SCART(AD):%d\n",ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700195 if (rgb_on &&
Karl Herz6af4ee12005-09-09 13:03:13 -0700196 ((av7110->dev->pci->subsystem_vendor == 0x110a) ||
197 (av7110->dev->pci->subsystem_vendor == 0x13c2)) &&
198 (av7110->dev->pci->subsystem_device == 0x0000)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700199 saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); // RGB on, SCART pin 16
200 //saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); // SCARTpin 8
201 }
202 }
203
Oliver Endriss60edb132005-12-19 08:54:11 -0200204 if (dev->pci->subsystem_vendor == 0x13c2 && dev->pci->subsystem_device == 0x000e)
205 av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, SpdifSwitch, 1, 0); // SPDIF on
206
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700207 ret = av7110_set_volume(av7110, av7110->mixer.volume_left, av7110->mixer.volume_right);
Johannes Stezenbach7a2fa902005-07-07 17:58:01 -0700208 if (ret < 0)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700209 printk("dvb-ttpci:cannot set volume :%d\n",ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210}
211
212static void recover_arm(struct av7110 *av7110)
213{
214 dprintk(4, "%p\n",av7110);
215
216 av7110_bootarm(av7110);
217 msleep(100);
Oliver Endriss66190a22006-01-09 15:32:42 -0200218
219 init_av7110_av(av7110);
220
221 /* card-specific recovery */
222 if (av7110->recover)
223 av7110->recover(av7110);
224
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225 restart_feeds(av7110);
226 av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, SetIR, 1, av7110->ir_config);
227}
228
Linus Torvalds1da177e2005-04-16 15:20:36 -0700229static void av7110_arm_sync(struct av7110 *av7110)
230{
231 av7110->arm_rmmod = 1;
232 wake_up_interruptible(&av7110->arm_wait);
233
234 while (av7110->arm_thread)
235 msleep(1);
236}
237
238static int arm_thread(void *data)
239{
240 struct av7110 *av7110 = data;
241 u16 newloops = 0;
242 int timeout;
243
244 dprintk(4, "%p\n",av7110);
245
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -0800246 lock_kernel();
247 daemonize("arm_mon");
248 sigfillset(&current->blocked);
249 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700250
251 av7110->arm_thread = current;
252
253 for (;;) {
254 timeout = wait_event_interruptible_timeout(av7110->arm_wait,
255 av7110->arm_rmmod, 5 * HZ);
256 if (-ERESTARTSYS == timeout || av7110->arm_rmmod) {
257 /* got signal or told to quit*/
258 break;
259 }
260
261 if (!av7110->arm_ready)
262 continue;
263
Ingo Molnar3593cab2006-02-07 06:49:14 -0200264 if (mutex_lock_interruptible(&av7110->dcomlock))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700265 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266 newloops = rdebi(av7110, DEBINOSWAP, STATUS_LOOPS, 0, 2);
Ingo Molnar3593cab2006-02-07 06:49:14 -0200267 mutex_unlock(&av7110->dcomlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268
Oliver Endriss66190a22006-01-09 15:32:42 -0200269 if (newloops == av7110->arm_loops || av7110->arm_errors > 3) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700270 printk(KERN_ERR "dvb-ttpci: ARM crashed @ card %d\n",
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -0700271 av7110->dvb_adapter.num);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700272
Oliver Endriss66190a22006-01-09 15:32:42 -0200273 recover_arm(av7110);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700274
Ingo Molnar3593cab2006-02-07 06:49:14 -0200275 if (mutex_lock_interruptible(&av7110->dcomlock))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700276 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700277 newloops = rdebi(av7110, DEBINOSWAP, STATUS_LOOPS, 0, 2) - 1;
Ingo Molnar3593cab2006-02-07 06:49:14 -0200278 mutex_unlock(&av7110->dcomlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279 }
280 av7110->arm_loops = newloops;
Oliver Endriss66190a22006-01-09 15:32:42 -0200281 av7110->arm_errors = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700282 }
283
284 av7110->arm_thread = NULL;
285 return 0;
286}
287
288
Linus Torvalds1da177e2005-04-16 15:20:36 -0700289/****************************************************************************
290 * IRQ handling
291 ****************************************************************************/
292
293static int DvbDmxFilterCallback(u8 *buffer1, size_t buffer1_len,
294 u8 *buffer2, size_t buffer2_len,
295 struct dvb_demux_filter *dvbdmxfilter,
296 enum dmx_success success,
297 struct av7110 *av7110)
298{
299 if (!dvbdmxfilter->feed->demux->dmx.frontend)
300 return 0;
301 if (dvbdmxfilter->feed->demux->dmx.frontend->source == DMX_MEMORY_FE)
302 return 0;
303
304 switch (dvbdmxfilter->type) {
305 case DMX_TYPE_SEC:
306 if ((((buffer1[1] << 8) | buffer1[2]) & 0xfff) + 3 != buffer1_len)
307 return 0;
308 if (dvbdmxfilter->doneq) {
309 struct dmx_section_filter *filter = &dvbdmxfilter->filter;
310 int i;
311 u8 xor, neq = 0;
312
313 for (i = 0; i < DVB_DEMUX_MASK_MAX; i++) {
314 xor = filter->filter_value[i] ^ buffer1[i];
315 neq |= dvbdmxfilter->maskandnotmode[i] & xor;
316 }
317 if (!neq)
318 return 0;
319 }
320 return dvbdmxfilter->feed->cb.sec(buffer1, buffer1_len,
321 buffer2, buffer2_len,
322 &dvbdmxfilter->filter,
323 DMX_OK);
324 case DMX_TYPE_TS:
325 if (!(dvbdmxfilter->feed->ts_type & TS_PACKET))
326 return 0;
327 if (dvbdmxfilter->feed->ts_type & TS_PAYLOAD_ONLY)
328 return dvbdmxfilter->feed->cb.ts(buffer1, buffer1_len,
329 buffer2, buffer2_len,
330 &dvbdmxfilter->feed->feed.ts,
331 DMX_OK);
332 else
333 av7110_p2t_write(buffer1, buffer1_len,
334 dvbdmxfilter->feed->pid,
335 &av7110->p2t_filter[dvbdmxfilter->index]);
336 default:
337 return 0;
338 }
339}
340
341
342//#define DEBUG_TIMING
343static inline void print_time(char *s)
344{
345#ifdef DEBUG_TIMING
346 struct timeval tv;
347 do_gettimeofday(&tv);
348 printk("%s: %d.%d\n", s, (int)tv.tv_sec, (int)tv.tv_usec);
349#endif
350}
351
352#define DEBI_READ 0
353#define DEBI_WRITE 1
354static inline void start_debi_dma(struct av7110 *av7110, int dir,
355 unsigned long addr, unsigned int len)
356{
357 dprintk(8, "%c %08lx %u\n", dir == DEBI_READ ? 'R' : 'W', addr, len);
358 if (saa7146_wait_for_debi_done(av7110->dev, 0)) {
359 printk(KERN_ERR "%s: saa7146_wait_for_debi_done timed out\n", __FUNCTION__);
360 return;
361 }
362
363 SAA7146_ISR_CLEAR(av7110->dev, MASK_19); /* for good measure */
364 SAA7146_IER_ENABLE(av7110->dev, MASK_19);
365 if (len < 5)
366 len = 5; /* we want a real DEBI DMA */
367 if (dir == DEBI_WRITE)
368 iwdebi(av7110, DEBISWAB, addr, 0, (len + 3) & ~3);
369 else
370 irdebi(av7110, DEBISWAB, addr, 0, len);
371}
372
373static void debiirq(unsigned long data)
374{
375 struct av7110 *av7110 = (struct av7110 *) data;
376 int type = av7110->debitype;
377 int handle = (type >> 8) & 0x1f;
378 unsigned int xfer = 0;
379
380 print_time("debi");
381 dprintk(4, "type 0x%04x\n", type);
382
383 if (type == -1) {
384 printk("DEBI irq oops @ %ld, psr:0x%08x, ssr:0x%08x\n",
385 jiffies, saa7146_read(av7110->dev, PSR),
386 saa7146_read(av7110->dev, SSR));
387 goto debi_done;
388 }
389 av7110->debitype = -1;
390
391 switch (type & 0xff) {
392
393 case DATA_TS_RECORD:
394 dvb_dmx_swfilter_packets(&av7110->demux,
395 (const u8 *) av7110->debi_virt,
396 av7110->debilen / 188);
397 xfer = RX_BUFF;
398 break;
399
400 case DATA_PES_RECORD:
401 if (av7110->demux.recording)
402 av7110_record_cb(&av7110->p2t[handle],
403 (u8 *) av7110->debi_virt,
404 av7110->debilen);
405 xfer = RX_BUFF;
406 break;
407
408 case DATA_IPMPE:
409 case DATA_FSECTION:
410 case DATA_PIPING:
411 if (av7110->handle2filter[handle])
412 DvbDmxFilterCallback((u8 *)av7110->debi_virt,
413 av7110->debilen, NULL, 0,
414 av7110->handle2filter[handle],
415 DMX_OK, av7110);
416 xfer = RX_BUFF;
417 break;
418
419 case DATA_CI_GET:
420 {
421 u8 *data = av7110->debi_virt;
422
423 if ((data[0] < 2) && data[2] == 0xff) {
424 int flags = 0;
425 if (data[5] > 0)
426 flags |= CA_CI_MODULE_PRESENT;
427 if (data[5] > 5)
428 flags |= CA_CI_MODULE_READY;
429 av7110->ci_slot[data[0]].flags = flags;
430 } else
431 ci_get_data(&av7110->ci_rbuffer,
432 av7110->debi_virt,
433 av7110->debilen);
434 xfer = RX_BUFF;
435 break;
436 }
437
438 case DATA_COMMON_INTERFACE:
439 CI_handle(av7110, (u8 *)av7110->debi_virt, av7110->debilen);
440#if 0
441 {
442 int i;
443
444 printk("av7110%d: ", av7110->num);
445 printk("%02x ", *(u8 *)av7110->debi_virt);
446 printk("%02x ", *(1+(u8 *)av7110->debi_virt));
447 for (i = 2; i < av7110->debilen; i++)
448 printk("%02x ", (*(i+(unsigned char *)av7110->debi_virt)));
449 for (i = 2; i < av7110->debilen; i++)
450 printk("%c", chtrans(*(i+(unsigned char *)av7110->debi_virt)));
451
452 printk("\n");
453 }
454#endif
455 xfer = RX_BUFF;
456 break;
457
458 case DATA_DEBUG_MESSAGE:
459 ((s8*)av7110->debi_virt)[Reserved_SIZE - 1] = 0;
460 printk("%s\n", (s8 *) av7110->debi_virt);
461 xfer = RX_BUFF;
462 break;
463
464 case DATA_CI_PUT:
465 dprintk(4, "debi DATA_CI_PUT\n");
466 case DATA_MPEG_PLAY:
467 dprintk(4, "debi DATA_MPEG_PLAY\n");
468 case DATA_BMP_LOAD:
469 dprintk(4, "debi DATA_BMP_LOAD\n");
470 xfer = TX_BUFF;
471 break;
472 default:
473 break;
474 }
475debi_done:
476 spin_lock(&av7110->debilock);
477 if (xfer)
478 iwdebi(av7110, DEBINOSWAP, xfer, 0, 2);
479 ARM_ClearMailBox(av7110);
480 spin_unlock(&av7110->debilock);
481}
482
483/* irq from av7110 firmware writing the mailbox register in the DPRAM */
484static void gpioirq(unsigned long data)
485{
486 struct av7110 *av7110 = (struct av7110 *) data;
487 u32 rxbuf, txbuf;
488 int len;
489
490 if (av7110->debitype != -1)
491 /* we shouldn't get any irq while a debi xfer is running */
492 printk("dvb-ttpci: GPIO0 irq oops @ %ld, psr:0x%08x, ssr:0x%08x\n",
493 jiffies, saa7146_read(av7110->dev, PSR),
494 saa7146_read(av7110->dev, SSR));
495
496 if (saa7146_wait_for_debi_done(av7110->dev, 0)) {
497 printk(KERN_ERR "%s: saa7146_wait_for_debi_done timed out\n", __FUNCTION__);
498 BUG(); /* maybe we should try resetting the debi? */
499 }
500
501 spin_lock(&av7110->debilock);
502 ARM_ClearIrq(av7110);
503
504 /* see what the av7110 wants */
505 av7110->debitype = irdebi(av7110, DEBINOSWAP, IRQ_STATE, 0, 2);
506 av7110->debilen = irdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
507 rxbuf = irdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
508 txbuf = irdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
509 len = (av7110->debilen + 3) & ~3;
510
511 print_time("gpio");
512 dprintk(8, "GPIO0 irq 0x%04x %d\n", av7110->debitype, av7110->debilen);
513
514 switch (av7110->debitype & 0xff) {
515
516 case DATA_TS_PLAY:
517 case DATA_PES_PLAY:
518 break;
519
520 case DATA_MPEG_VIDEO_EVENT:
521 {
522 u32 h_ar;
523 struct video_event event;
524
525 av7110->video_size.w = irdebi(av7110, DEBINOSWAP, STATUS_MPEG_WIDTH, 0, 2);
526 h_ar = irdebi(av7110, DEBINOSWAP, STATUS_MPEG_HEIGHT_AR, 0, 2);
527
528 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
529 iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
530
531 av7110->video_size.h = h_ar & 0xfff;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700532
533 event.type = VIDEO_EVENT_SIZE_CHANGED;
534 event.u.size.w = av7110->video_size.w;
535 event.u.size.h = av7110->video_size.h;
536 switch ((h_ar >> 12) & 0xf)
537 {
538 case 3:
539 av7110->video_size.aspect_ratio = VIDEO_FORMAT_16_9;
540 event.u.size.aspect_ratio = VIDEO_FORMAT_16_9;
541 av7110->videostate.video_format = VIDEO_FORMAT_16_9;
542 break;
543 case 4:
544 av7110->video_size.aspect_ratio = VIDEO_FORMAT_221_1;
545 event.u.size.aspect_ratio = VIDEO_FORMAT_221_1;
546 av7110->videostate.video_format = VIDEO_FORMAT_221_1;
547 break;
548 default:
549 av7110->video_size.aspect_ratio = VIDEO_FORMAT_4_3;
550 event.u.size.aspect_ratio = VIDEO_FORMAT_4_3;
551 av7110->videostate.video_format = VIDEO_FORMAT_4_3;
552 }
Oliver Endriss66190a22006-01-09 15:32:42 -0200553
554 dprintk(8, "GPIO0 irq: DATA_MPEG_VIDEO_EVENT: w/h/ar = %u/%u/%u\n",
555 av7110->video_size.w, av7110->video_size.h,
556 av7110->video_size.aspect_ratio);
557
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558 dvb_video_add_event(av7110, &event);
559 break;
560 }
561
562 case DATA_CI_PUT:
563 {
564 int avail;
565 struct dvb_ringbuffer *cibuf = &av7110->ci_wbuffer;
566
567 avail = dvb_ringbuffer_avail(cibuf);
568 if (avail <= 2) {
569 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
570 iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
571 iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
572 break;
573 }
574 len = DVB_RINGBUFFER_PEEK(cibuf, 0) << 8;
575 len |= DVB_RINGBUFFER_PEEK(cibuf, 1);
576 if (avail < len + 2) {
577 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
578 iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
579 iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
580 break;
581 }
582 DVB_RINGBUFFER_SKIP(cibuf, 2);
583
584 dvb_ringbuffer_read(cibuf, av7110->debi_virt, len, 0);
585
586 iwdebi(av7110, DEBINOSWAP, TX_LEN, len, 2);
587 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, len, 2);
588 dprintk(8, "DMA: CI\n");
589 start_debi_dma(av7110, DEBI_WRITE, DPRAM_BASE + txbuf, len);
590 spin_unlock(&av7110->debilock);
591 wake_up(&cibuf->queue);
592 return;
593 }
594
595 case DATA_MPEG_PLAY:
596 if (!av7110->playing) {
597 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
598 iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
599 iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
600 break;
601 }
602 len = 0;
603 if (av7110->debitype & 0x100) {
604 spin_lock(&av7110->aout.lock);
605 len = av7110_pes_play(av7110->debi_virt, &av7110->aout, 2048);
606 spin_unlock(&av7110->aout.lock);
607 }
608 if (len <= 0 && (av7110->debitype & 0x200)
609 &&av7110->videostate.play_state != VIDEO_FREEZED) {
610 spin_lock(&av7110->avout.lock);
611 len = av7110_pes_play(av7110->debi_virt, &av7110->avout, 2048);
612 spin_unlock(&av7110->avout.lock);
613 }
614 if (len <= 0) {
615 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
616 iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
617 iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
618 break;
619 }
620 dprintk(8, "GPIO0 PES_PLAY len=%04x\n", len);
621 iwdebi(av7110, DEBINOSWAP, TX_LEN, len, 2);
622 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, len, 2);
623 dprintk(8, "DMA: MPEG_PLAY\n");
624 start_debi_dma(av7110, DEBI_WRITE, DPRAM_BASE + txbuf, len);
625 spin_unlock(&av7110->debilock);
626 return;
627
628 case DATA_BMP_LOAD:
629 len = av7110->debilen;
630 dprintk(8, "gpio DATA_BMP_LOAD len %d\n", len);
631 if (!len) {
632 av7110->bmp_state = BMP_LOADED;
633 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
634 iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
635 iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
636 wake_up(&av7110->bmpq);
637 dprintk(8, "gpio DATA_BMP_LOAD done\n");
638 break;
639 }
640 if (len > av7110->bmplen)
641 len = av7110->bmplen;
642 if (len > 2 * 1024)
643 len = 2 * 1024;
644 iwdebi(av7110, DEBINOSWAP, TX_LEN, len, 2);
645 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, len, 2);
646 memcpy(av7110->debi_virt, av7110->bmpbuf+av7110->bmpp, len);
647 av7110->bmpp += len;
648 av7110->bmplen -= len;
649 dprintk(8, "gpio DATA_BMP_LOAD DMA len %d\n", len);
650 start_debi_dma(av7110, DEBI_WRITE, DPRAM_BASE+txbuf, len);
651 spin_unlock(&av7110->debilock);
652 return;
653
654 case DATA_CI_GET:
655 case DATA_COMMON_INTERFACE:
656 case DATA_FSECTION:
657 case DATA_IPMPE:
658 case DATA_PIPING:
659 if (!len || len > 4 * 1024) {
660 iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
661 break;
662 }
663 /* fall through */
664
665 case DATA_TS_RECORD:
666 case DATA_PES_RECORD:
667 dprintk(8, "DMA: TS_REC etc.\n");
668 start_debi_dma(av7110, DEBI_READ, DPRAM_BASE+rxbuf, len);
669 spin_unlock(&av7110->debilock);
670 return;
671
672 case DATA_DEBUG_MESSAGE:
673 if (!len || len > 0xff) {
674 iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
675 break;
676 }
677 start_debi_dma(av7110, DEBI_READ, Reserved, len);
678 spin_unlock(&av7110->debilock);
679 return;
680
681 case DATA_IRCOMMAND:
Oliver Endriss03388ae2005-09-09 13:03:12 -0700682 if (av7110->ir_handler)
683 av7110->ir_handler(av7110,
684 swahw32(irdebi(av7110, DEBINOSWAP, Reserved, 0, 4)));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700685 iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
686 break;
687
688 default:
689 printk("dvb-ttpci: gpioirq unknown type=%d len=%d\n",
690 av7110->debitype, av7110->debilen);
691 break;
692 }
693 av7110->debitype = -1;
694 ARM_ClearMailBox(av7110);
695 spin_unlock(&av7110->debilock);
696}
697
698
699#ifdef CONFIG_DVB_AV7110_OSD
700static int dvb_osd_ioctl(struct inode *inode, struct file *file,
701 unsigned int cmd, void *parg)
702{
703 struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
704 struct av7110 *av7110 = (struct av7110 *) dvbdev->priv;
705
706 dprintk(4, "%p\n", av7110);
707
708 if (cmd == OSD_SEND_CMD)
709 return av7110_osd_cmd(av7110, (osd_cmd_t *) parg);
710 if (cmd == OSD_GET_CAPABILITY)
711 return av7110_osd_capability(av7110, (osd_cap_t *) parg);
712
713 return -EINVAL;
714}
715
716
717static struct file_operations dvb_osd_fops = {
718 .owner = THIS_MODULE,
719 .ioctl = dvb_generic_ioctl,
720 .open = dvb_generic_open,
721 .release = dvb_generic_release,
722};
723
724static struct dvb_device dvbdev_osd = {
725 .priv = NULL,
726 .users = 1,
727 .writers = 1,
728 .fops = &dvb_osd_fops,
729 .kernel_ioctl = dvb_osd_ioctl,
730};
731#endif /* CONFIG_DVB_AV7110_OSD */
732
733
734static inline int SetPIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid,
735 u16 subpid, u16 pcrpid)
736{
Dr. Werner Fink47f36922006-01-09 15:25:07 -0200737 u16 aflags = 0;
738
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739 dprintk(4, "%p\n", av7110);
740
741 if (vpid == 0x1fff || apid == 0x1fff ||
742 ttpid == 0x1fff || subpid == 0x1fff || pcrpid == 0x1fff) {
743 vpid = apid = ttpid = subpid = pcrpid = 0;
744 av7110->pids[DMX_PES_VIDEO] = 0;
745 av7110->pids[DMX_PES_AUDIO] = 0;
746 av7110->pids[DMX_PES_TELETEXT] = 0;
747 av7110->pids[DMX_PES_PCR] = 0;
748 }
749
Dr. Werner Fink47f36922006-01-09 15:25:07 -0200750 if (av7110->audiostate.bypass_mode)
751 aflags |= 0x8000;
752
753 return av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, MultiPID, 6,
754 pcrpid, vpid, apid, ttpid, subpid, aflags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700755}
756
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700757int ChangePIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700758 u16 subpid, u16 pcrpid)
759{
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700760 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761 dprintk(4, "%p\n", av7110);
762
Ingo Molnar3593cab2006-02-07 06:49:14 -0200763 if (mutex_lock_interruptible(&av7110->pid_mutex))
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700764 return -ERESTARTSYS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700765
766 if (!(vpid & 0x8000))
767 av7110->pids[DMX_PES_VIDEO] = vpid;
768 if (!(apid & 0x8000))
769 av7110->pids[DMX_PES_AUDIO] = apid;
770 if (!(ttpid & 0x8000))
771 av7110->pids[DMX_PES_TELETEXT] = ttpid;
772 if (!(pcrpid & 0x8000))
773 av7110->pids[DMX_PES_PCR] = pcrpid;
774
775 av7110->pids[DMX_PES_SUBTITLE] = 0;
776
777 if (av7110->fe_synced) {
778 pcrpid = av7110->pids[DMX_PES_PCR];
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700779 ret = SetPIDs(av7110, vpid, apid, ttpid, subpid, pcrpid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700780 }
781
Ingo Molnar3593cab2006-02-07 06:49:14 -0200782 mutex_unlock(&av7110->pid_mutex);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700783 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700784}
785
786
787/******************************************************************************
788 * hardware filter functions
789 ******************************************************************************/
790
791static int StartHWFilter(struct dvb_demux_filter *dvbdmxfilter)
792{
793 struct dvb_demux_feed *dvbdmxfeed = dvbdmxfilter->feed;
794 struct av7110 *av7110 = (struct av7110 *) dvbdmxfeed->demux->priv;
795 u16 buf[20];
796 int ret, i;
797 u16 handle;
798// u16 mode = 0x0320;
799 u16 mode = 0xb96a;
800
801 dprintk(4, "%p\n", av7110);
802
803 if (dvbdmxfilter->type == DMX_TYPE_SEC) {
804 if (hw_sections) {
805 buf[4] = (dvbdmxfilter->filter.filter_value[0] << 8) |
806 dvbdmxfilter->maskandmode[0];
807 for (i = 3; i < 18; i++)
808 buf[i + 4 - 2] =
809 (dvbdmxfilter->filter.filter_value[i] << 8) |
810 dvbdmxfilter->maskandmode[i];
811 mode = 4;
812 }
813 } else if ((dvbdmxfeed->ts_type & TS_PACKET) &&
814 !(dvbdmxfeed->ts_type & TS_PAYLOAD_ONLY)) {
815 av7110_p2t_init(&av7110->p2t_filter[dvbdmxfilter->index], dvbdmxfeed);
816 }
817
818 buf[0] = (COMTYPE_PID_FILTER << 8) + AddPIDFilter;
819 buf[1] = 16;
820 buf[2] = dvbdmxfeed->pid;
821 buf[3] = mode;
822
823 ret = av7110_fw_request(av7110, buf, 20, &handle, 1);
824 if (ret != 0 || handle >= 32) {
825 printk("dvb-ttpci: %s error buf %04x %04x %04x %04x "
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700826 "ret %d handle %04x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827 __FUNCTION__, buf[0], buf[1], buf[2], buf[3],
828 ret, handle);
829 dvbdmxfilter->hw_handle = 0xffff;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700830 if (!ret)
831 ret = -1;
832 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700833 }
834
835 av7110->handle2filter[handle] = dvbdmxfilter;
836 dvbdmxfilter->hw_handle = handle;
837
838 return ret;
839}
840
841static int StopHWFilter(struct dvb_demux_filter *dvbdmxfilter)
842{
843 struct av7110 *av7110 = (struct av7110 *) dvbdmxfilter->feed->demux->priv;
844 u16 buf[3];
845 u16 answ[2];
846 int ret;
847 u16 handle;
848
849 dprintk(4, "%p\n", av7110);
850
851 handle = dvbdmxfilter->hw_handle;
852 if (handle >= 32) {
853 printk("%s tried to stop invalid filter %04x, filter type = %x\n",
854 __FUNCTION__, handle, dvbdmxfilter->type);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700855 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700856 }
857
858 av7110->handle2filter[handle] = NULL;
859
860 buf[0] = (COMTYPE_PID_FILTER << 8) + DelPIDFilter;
861 buf[1] = 1;
862 buf[2] = handle;
863 ret = av7110_fw_request(av7110, buf, 3, answ, 2);
864 if (ret != 0 || answ[1] != handle) {
865 printk("dvb-ttpci: %s error cmd %04x %04x %04x ret %x "
866 "resp %04x %04x pid %d\n",
867 __FUNCTION__, buf[0], buf[1], buf[2], ret,
868 answ[0], answ[1], dvbdmxfilter->feed->pid);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700869 if (!ret)
870 ret = -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700871 }
872 return ret;
873}
874
875
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700876static int dvb_feed_start_pid(struct dvb_demux_feed *dvbdmxfeed)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700877{
878 struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
879 struct av7110 *av7110 = (struct av7110 *) dvbdmx->priv;
880 u16 *pid = dvbdmx->pids, npids[5];
881 int i;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700882 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700883
884 dprintk(4, "%p\n", av7110);
885
886 npids[0] = npids[1] = npids[2] = npids[3] = npids[4] = 0xffff;
887 i = dvbdmxfeed->pes_type;
888 npids[i] = (pid[i]&0x8000) ? 0 : pid[i];
889 if ((i == 2) && npids[i] && (dvbdmxfeed->ts_type & TS_PACKET)) {
890 npids[i] = 0;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700891 ret = ChangePIDs(av7110, npids[1], npids[0], npids[2], npids[3], npids[4]);
892 if (!ret)
893 ret = StartHWFilter(dvbdmxfeed->filter);
894 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700895 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700896 if (dvbdmxfeed->pes_type <= 2 || dvbdmxfeed->pes_type == 4) {
897 ret = ChangePIDs(av7110, npids[1], npids[0], npids[2], npids[3], npids[4]);
898 if (ret)
899 return ret;
900 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901
902 if (dvbdmxfeed->pes_type < 2 && npids[0])
903 if (av7110->fe_synced)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700904 {
905 ret = av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, Scan, 0);
906 if (ret)
907 return ret;
908 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700909
910 if ((dvbdmxfeed->ts_type & TS_PACKET)) {
911 if (dvbdmxfeed->pes_type == 0 && !(dvbdmx->pids[0] & 0x8000))
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700912 ret = av7110_av_start_record(av7110, RP_AUDIO, dvbdmxfeed);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913 if (dvbdmxfeed->pes_type == 1 && !(dvbdmx->pids[1] & 0x8000))
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700914 ret = av7110_av_start_record(av7110, RP_VIDEO, dvbdmxfeed);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700915 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700916 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700917}
918
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700919static int dvb_feed_stop_pid(struct dvb_demux_feed *dvbdmxfeed)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700920{
921 struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
922 struct av7110 *av7110 = (struct av7110 *) dvbdmx->priv;
923 u16 *pid = dvbdmx->pids, npids[5];
924 int i;
925
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700926 int ret = 0;
927
Linus Torvalds1da177e2005-04-16 15:20:36 -0700928 dprintk(4, "%p\n", av7110);
929
930 if (dvbdmxfeed->pes_type <= 1) {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700931 ret = av7110_av_stop(av7110, dvbdmxfeed->pes_type ? RP_VIDEO : RP_AUDIO);
932 if (ret)
933 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700934 if (!av7110->rec_mode)
935 dvbdmx->recording = 0;
936 if (!av7110->playing)
937 dvbdmx->playing = 0;
938 }
939 npids[0] = npids[1] = npids[2] = npids[3] = npids[4] = 0xffff;
940 i = dvbdmxfeed->pes_type;
941 switch (i) {
942 case 2: //teletext
943 if (dvbdmxfeed->ts_type & TS_PACKET)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700944 ret = StopHWFilter(dvbdmxfeed->filter);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700945 npids[2] = 0;
946 break;
947 case 0:
948 case 1:
949 case 4:
950 if (!pids_off)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700951 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700952 npids[i] = (pid[i]&0x8000) ? 0 : pid[i];
953 break;
954 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700955 if (!ret)
956 ret = ChangePIDs(av7110, npids[1], npids[0], npids[2], npids[3], npids[4]);
957 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700958}
959
960static int av7110_start_feed(struct dvb_demux_feed *feed)
961{
962 struct dvb_demux *demux = feed->demux;
963 struct av7110 *av7110 = demux->priv;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700964 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700965
966 dprintk(4, "%p\n", av7110);
967
968 if (!demux->dmx.frontend)
969 return -EINVAL;
970
971 if (feed->pid > 0x1fff)
972 return -EINVAL;
973
974 if (feed->type == DMX_TYPE_TS) {
975 if ((feed->ts_type & TS_DECODER) &&
976 (feed->pes_type < DMX_TS_PES_OTHER)) {
977 switch (demux->dmx.frontend->source) {
978 case DMX_MEMORY_FE:
979 if (feed->ts_type & TS_DECODER)
980 if (feed->pes_type < 2 &&
981 !(demux->pids[0] & 0x8000) &&
982 !(demux->pids[1] & 0x8000)) {
983 dvb_ringbuffer_flush_spinlock_wakeup(&av7110->avout);
984 dvb_ringbuffer_flush_spinlock_wakeup(&av7110->aout);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700985 ret = av7110_av_start_play(av7110,RP_AV);
986 if (!ret)
987 demux->playing = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700988 }
989 break;
990 default:
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700991 ret = dvb_feed_start_pid(feed);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700992 break;
993 }
994 } else if ((feed->ts_type & TS_PACKET) &&
995 (demux->dmx.frontend->source != DMX_MEMORY_FE)) {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700996 ret = StartHWFilter(feed->filter);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700997 }
998 }
999
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001000 else if (feed->type == DMX_TYPE_SEC) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001001 int i;
1002
1003 for (i = 0; i < demux->filternum; i++) {
1004 if (demux->filter[i].state != DMX_STATE_READY)
1005 continue;
1006 if (demux->filter[i].type != DMX_TYPE_SEC)
1007 continue;
1008 if (demux->filter[i].filter.parent != &feed->feed.sec)
1009 continue;
1010 demux->filter[i].state = DMX_STATE_GO;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001011 if (demux->dmx.frontend->source != DMX_MEMORY_FE) {
1012 ret = StartHWFilter(&demux->filter[i]);
1013 if (ret)
1014 break;
1015 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001016 }
1017 }
1018
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001019 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001020}
1021
1022
1023static int av7110_stop_feed(struct dvb_demux_feed *feed)
1024{
1025 struct dvb_demux *demux = feed->demux;
1026 struct av7110 *av7110 = demux->priv;
Johannes Stezenbach12ba0502005-07-07 17:58:00 -07001027 int i, rc, ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001028 dprintk(4, "%p\n", av7110);
1029
1030 if (feed->type == DMX_TYPE_TS) {
1031 if (feed->ts_type & TS_DECODER) {
1032 if (feed->pes_type >= DMX_TS_PES_OTHER ||
1033 !demux->pesfilter[feed->pes_type])
1034 return -EINVAL;
1035 demux->pids[feed->pes_type] |= 0x8000;
1036 demux->pesfilter[feed->pes_type] = NULL;
1037 }
1038 if (feed->ts_type & TS_DECODER &&
1039 feed->pes_type < DMX_TS_PES_OTHER) {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001040 ret = dvb_feed_stop_pid(feed);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001041 } else
1042 if ((feed->ts_type & TS_PACKET) &&
1043 (demux->dmx.frontend->source != DMX_MEMORY_FE))
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001044 ret = StopHWFilter(feed->filter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001045 }
1046
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001047 if (!ret && feed->type == DMX_TYPE_SEC) {
Johannes Stezenbach12ba0502005-07-07 17:58:00 -07001048 for (i = 0; i<demux->filternum; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049 if (demux->filter[i].state == DMX_STATE_GO &&
1050 demux->filter[i].filter.parent == &feed->feed.sec) {
1051 demux->filter[i].state = DMX_STATE_READY;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001052 if (demux->dmx.frontend->source != DMX_MEMORY_FE) {
Johannes Stezenbach12ba0502005-07-07 17:58:00 -07001053 rc = StopHWFilter(&demux->filter[i]);
1054 if (!ret)
1055 ret = rc;
1056 /* keep going, stop as many filters as possible */
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001057 }
Johannes Stezenbach12ba0502005-07-07 17:58:00 -07001058 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001059 }
1060 }
1061
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001062 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001063}
1064
1065
1066static void restart_feeds(struct av7110 *av7110)
1067{
1068 struct dvb_demux *dvbdmx = &av7110->demux;
1069 struct dvb_demux_feed *feed;
1070 int mode;
Oliver Endriss66190a22006-01-09 15:32:42 -02001071 int i, j;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001072
1073 dprintk(4, "%p\n", av7110);
1074
1075 mode = av7110->playing;
1076 av7110->playing = 0;
1077 av7110->rec_mode = 0;
1078
Oliver Endriss66190a22006-01-09 15:32:42 -02001079 for (i = 0; i < dvbdmx->feednum; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001080 feed = &dvbdmx->feed[i];
Oliver Endriss66190a22006-01-09 15:32:42 -02001081 if (feed->state == DMX_STATE_GO) {
1082 if (feed->type == DMX_TYPE_SEC) {
1083 for (j = 0; j < dvbdmx->filternum; j++) {
1084 if (dvbdmx->filter[j].type != DMX_TYPE_SEC)
1085 continue;
1086 if (dvbdmx->filter[j].filter.parent != &feed->feed.sec)
1087 continue;
1088 if (dvbdmx->filter[j].state == DMX_STATE_GO)
1089 dvbdmx->filter[j].state = DMX_STATE_READY;
1090 }
1091 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001092 av7110_start_feed(feed);
Oliver Endriss66190a22006-01-09 15:32:42 -02001093 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094 }
1095
1096 if (mode)
1097 av7110_av_start_play(av7110, mode);
1098}
1099
1100static int dvb_get_stc(struct dmx_demux *demux, unsigned int num,
1101 uint64_t *stc, unsigned int *base)
1102{
1103 int ret;
1104 u16 fwstc[4];
1105 u16 tag = ((COMTYPE_REQUEST << 8) + ReqSTC);
1106 struct dvb_demux *dvbdemux;
1107 struct av7110 *av7110;
1108
1109 /* pointer casting paranoia... */
Eric Sesterhennae246012006-03-13 13:17:11 -03001110 BUG_ON(!demux);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001111 dvbdemux = (struct dvb_demux *) demux->priv;
Eric Sesterhennae246012006-03-13 13:17:11 -03001112 BUG_ON(!dvbdemux);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001113 av7110 = (struct av7110 *) dvbdemux->priv;
1114
1115 dprintk(4, "%p\n", av7110);
1116
1117 if (num != 0)
1118 return -EINVAL;
1119
1120 ret = av7110_fw_request(av7110, &tag, 0, fwstc, 4);
1121 if (ret) {
1122 printk(KERN_ERR "%s: av7110_fw_request error\n", __FUNCTION__);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001123 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001124 }
1125 dprintk(2, "fwstc = %04hx %04hx %04hx %04hx\n",
1126 fwstc[0], fwstc[1], fwstc[2], fwstc[3]);
1127
1128 *stc = (((uint64_t) ((fwstc[3] & 0x8000) >> 15)) << 32) |
1129 (((uint64_t) fwstc[1]) << 16) | ((uint64_t) fwstc[0]);
1130 *base = 1;
1131
1132 dprintk(4, "stc = %lu\n", (unsigned long)*stc);
1133
1134 return 0;
1135}
1136
1137
1138/******************************************************************************
1139 * SEC device file operations
1140 ******************************************************************************/
1141
1142
1143static int av7110_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
1144{
1145 struct av7110* av7110 = (struct av7110*) fe->dvb->priv;
1146
1147 switch (tone) {
1148 case SEC_TONE_ON:
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001149 return Set22K(av7110, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001150
1151 case SEC_TONE_OFF:
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001152 return Set22K(av7110, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001153
1154 default:
1155 return -EINVAL;
1156 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001157}
1158
1159static int av7110_diseqc_send_master_cmd(struct dvb_frontend* fe,
1160 struct dvb_diseqc_master_cmd* cmd)
1161{
1162 struct av7110* av7110 = fe->dvb->priv;
1163
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001164 return av7110_diseqc_send(av7110, cmd->msg_len, cmd->msg, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001165}
1166
1167static int av7110_diseqc_send_burst(struct dvb_frontend* fe,
1168 fe_sec_mini_cmd_t minicmd)
1169{
1170 struct av7110* av7110 = fe->dvb->priv;
1171
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001172 return av7110_diseqc_send(av7110, 0, NULL, minicmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001173}
1174
1175/* simplified code from budget-core.c */
1176static int stop_ts_capture(struct av7110 *budget)
1177{
1178 dprintk(2, "budget: %p\n", budget);
1179
1180 if (--budget->feeding1)
1181 return budget->feeding1;
1182 saa7146_write(budget->dev, MC1, MASK_20); /* DMA3 off */
1183 SAA7146_IER_DISABLE(budget->dev, MASK_10);
1184 SAA7146_ISR_CLEAR(budget->dev, MASK_10);
1185 return 0;
1186}
1187
1188static int start_ts_capture(struct av7110 *budget)
1189{
1190 dprintk(2, "budget: %p\n", budget);
1191
1192 if (budget->feeding1)
1193 return ++budget->feeding1;
1194 memset(budget->grabbing, 0x00, TS_HEIGHT * TS_WIDTH);
1195 budget->tsf = 0xff;
1196 budget->ttbp = 0;
1197 SAA7146_IER_ENABLE(budget->dev, MASK_10); /* VPE */
1198 saa7146_write(budget->dev, MC1, (MASK_04 | MASK_20)); /* DMA3 on */
1199 return ++budget->feeding1;
1200}
1201
1202static int budget_start_feed(struct dvb_demux_feed *feed)
1203{
1204 struct dvb_demux *demux = feed->demux;
1205 struct av7110 *budget = (struct av7110 *) demux->priv;
1206 int status;
1207
1208 dprintk(2, "av7110: %p\n", budget);
1209
1210 spin_lock(&budget->feedlock1);
1211 feed->pusi_seen = 0; /* have a clean section start */
1212 status = start_ts_capture(budget);
1213 spin_unlock(&budget->feedlock1);
1214 return status;
1215}
1216
1217static int budget_stop_feed(struct dvb_demux_feed *feed)
1218{
1219 struct dvb_demux *demux = feed->demux;
1220 struct av7110 *budget = (struct av7110 *) demux->priv;
1221 int status;
1222
1223 dprintk(2, "budget: %p\n", budget);
1224
1225 spin_lock(&budget->feedlock1);
1226 status = stop_ts_capture(budget);
1227 spin_unlock(&budget->feedlock1);
1228 return status;
1229}
1230
1231static void vpeirq(unsigned long data)
1232{
1233 struct av7110 *budget = (struct av7110 *) data;
1234 u8 *mem = (u8 *) (budget->grabbing);
1235 u32 olddma = budget->ttbp;
1236 u32 newdma = saa7146_read(budget->dev, PCI_VDP3);
1237
1238 if (!budgetpatch) {
1239 printk("av7110.c: vpeirq() called while budgetpatch disabled!"
1240 " check saa7146 IER register\n");
1241 BUG();
1242 }
1243 /* nearest lower position divisible by 188 */
1244 newdma -= newdma % 188;
1245
1246 if (newdma >= TS_BUFLEN)
1247 return;
1248
1249 budget->ttbp = newdma;
1250
1251 if (!budget->feeding1 || (newdma == olddma))
1252 return;
1253
1254#if 0
1255 /* track rps1 activity */
1256 printk("vpeirq: %02x Event Counter 1 0x%04x\n",
1257 mem[olddma],
1258 saa7146_read(budget->dev, EC1R) & 0x3fff);
1259#endif
1260
1261 if (newdma > olddma)
1262 /* no wraparound, dump olddma..newdma */
1263 dvb_dmx_swfilter_packets(&budget->demux1, mem + olddma, (newdma - olddma) / 188);
1264 else {
1265 /* wraparound, dump olddma..buflen and 0..newdma */
1266 dvb_dmx_swfilter_packets(&budget->demux1, mem + olddma, (TS_BUFLEN - olddma) / 188);
1267 dvb_dmx_swfilter_packets(&budget->demux1, mem, newdma / 188);
1268 }
1269}
1270
1271static int av7110_register(struct av7110 *av7110)
1272{
1273 int ret, i;
1274 struct dvb_demux *dvbdemux = &av7110->demux;
1275 struct dvb_demux *dvbdemux1 = &av7110->demux1;
1276
1277 dprintk(4, "%p\n", av7110);
1278
1279 if (av7110->registered)
1280 return -1;
1281
1282 av7110->registered = 1;
1283
1284 dvbdemux->priv = (void *) av7110;
1285
1286 for (i = 0; i < 32; i++)
1287 av7110->handle2filter[i] = NULL;
1288
1289 dvbdemux->filternum = 32;
1290 dvbdemux->feednum = 32;
1291 dvbdemux->start_feed = av7110_start_feed;
1292 dvbdemux->stop_feed = av7110_stop_feed;
1293 dvbdemux->write_to_decoder = av7110_write_to_decoder;
1294 dvbdemux->dmx.capabilities = (DMX_TS_FILTERING | DMX_SECTION_FILTERING |
1295 DMX_MEMORY_BASED_FILTERING);
1296
1297 dvb_dmx_init(&av7110->demux);
1298 av7110->demux.dmx.get_stc = dvb_get_stc;
1299
1300 av7110->dmxdev.filternum = 32;
1301 av7110->dmxdev.demux = &dvbdemux->dmx;
1302 av7110->dmxdev.capabilities = 0;
1303
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001304 dvb_dmxdev_init(&av7110->dmxdev, &av7110->dvb_adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001305
1306 av7110->hw_frontend.source = DMX_FRONTEND_0;
1307
1308 ret = dvbdemux->dmx.add_frontend(&dvbdemux->dmx, &av7110->hw_frontend);
1309
1310 if (ret < 0)
1311 return ret;
1312
1313 av7110->mem_frontend.source = DMX_MEMORY_FE;
1314
1315 ret = dvbdemux->dmx.add_frontend(&dvbdemux->dmx, &av7110->mem_frontend);
1316
1317 if (ret < 0)
1318 return ret;
1319
1320 ret = dvbdemux->dmx.connect_frontend(&dvbdemux->dmx,
1321 &av7110->hw_frontend);
1322 if (ret < 0)
1323 return ret;
1324
1325 av7110_av_register(av7110);
1326 av7110_ca_register(av7110);
1327
1328#ifdef CONFIG_DVB_AV7110_OSD
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001329 dvb_register_device(&av7110->dvb_adapter, &av7110->osd_dev,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001330 &dvbdev_osd, av7110, DVB_DEVICE_OSD);
1331#endif
1332
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001333 dvb_net_init(&av7110->dvb_adapter, &av7110->dvb_net, &dvbdemux->dmx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001334
1335 if (budgetpatch) {
1336 /* initialize software demux1 without its own frontend
1337 * demux1 hardware is connected to frontend0 of demux0
1338 */
1339 dvbdemux1->priv = (void *) av7110;
1340
1341 dvbdemux1->filternum = 256;
1342 dvbdemux1->feednum = 256;
1343 dvbdemux1->start_feed = budget_start_feed;
1344 dvbdemux1->stop_feed = budget_stop_feed;
1345 dvbdemux1->write_to_decoder = NULL;
1346
1347 dvbdemux1->dmx.capabilities = (DMX_TS_FILTERING | DMX_SECTION_FILTERING |
1348 DMX_MEMORY_BASED_FILTERING);
1349
1350 dvb_dmx_init(&av7110->demux1);
1351
1352 av7110->dmxdev1.filternum = 256;
1353 av7110->dmxdev1.demux = &dvbdemux1->dmx;
1354 av7110->dmxdev1.capabilities = 0;
1355
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001356 dvb_dmxdev_init(&av7110->dmxdev1, &av7110->dvb_adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001357
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001358 dvb_net_init(&av7110->dvb_adapter, &av7110->dvb_net1, &dvbdemux1->dmx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001359 printk("dvb-ttpci: additional demux1 for budget-patch registered\n");
1360 }
1361 return 0;
1362}
1363
1364
1365static void dvb_unregister(struct av7110 *av7110)
1366{
1367 struct dvb_demux *dvbdemux = &av7110->demux;
1368 struct dvb_demux *dvbdemux1 = &av7110->demux1;
1369
1370 dprintk(4, "%p\n", av7110);
1371
1372 if (!av7110->registered)
1373 return;
1374
1375 if (budgetpatch) {
1376 dvb_net_release(&av7110->dvb_net1);
1377 dvbdemux->dmx.close(&dvbdemux1->dmx);
1378 dvb_dmxdev_release(&av7110->dmxdev1);
1379 dvb_dmx_release(&av7110->demux1);
1380 }
1381
1382 dvb_net_release(&av7110->dvb_net);
1383
1384 dvbdemux->dmx.close(&dvbdemux->dmx);
1385 dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &av7110->hw_frontend);
1386 dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &av7110->mem_frontend);
1387
1388 dvb_dmxdev_release(&av7110->dmxdev);
1389 dvb_dmx_release(&av7110->demux);
1390
1391 if (av7110->fe != NULL)
1392 dvb_unregister_frontend(av7110->fe);
1393 dvb_unregister_device(av7110->osd_dev);
1394 av7110_av_unregister(av7110);
1395 av7110_ca_unregister(av7110);
1396}
1397
1398
1399/****************************************************************************
1400 * I2C client commands
1401 ****************************************************************************/
1402
1403int i2c_writereg(struct av7110 *av7110, u8 id, u8 reg, u8 val)
1404{
1405 u8 msg[2] = { reg, val };
1406 struct i2c_msg msgs;
1407
1408 msgs.flags = 0;
1409 msgs.addr = id / 2;
1410 msgs.len = 2;
1411 msgs.buf = msg;
1412 return i2c_transfer(&av7110->i2c_adap, &msgs, 1);
1413}
1414
1415#if 0
1416u8 i2c_readreg(struct av7110 *av7110, u8 id, u8 reg)
1417{
1418 u8 mm1[] = {0x00};
1419 u8 mm2[] = {0x00};
1420 struct i2c_msg msgs[2];
1421
1422 msgs[0].flags = 0;
1423 msgs[1].flags = I2C_M_RD;
1424 msgs[0].addr = msgs[1].addr = id / 2;
1425 mm1[0] = reg;
1426 msgs[0].len = 1; msgs[1].len = 1;
1427 msgs[0].buf = mm1; msgs[1].buf = mm2;
1428 i2c_transfer(&av7110->i2c_adap, msgs, 2);
1429
1430 return mm2[0];
1431}
1432#endif
1433
1434/****************************************************************************
1435 * INITIALIZATION
1436 ****************************************************************************/
1437
1438
1439static int check_firmware(struct av7110* av7110)
1440{
1441 u32 crc = 0, len = 0;
1442 unsigned char *ptr;
1443
1444 /* check for firmware magic */
1445 ptr = av7110->bin_fw;
1446 if (ptr[0] != 'A' || ptr[1] != 'V' ||
1447 ptr[2] != 'F' || ptr[3] != 'W') {
1448 printk("dvb-ttpci: this is not an av7110 firmware\n");
1449 return -EINVAL;
1450 }
1451 ptr += 4;
1452
1453 /* check dpram file */
1454 crc = ntohl(*(u32*) ptr);
1455 ptr += 4;
1456 len = ntohl(*(u32*) ptr);
1457 ptr += 4;
1458 if (len >= 512) {
Alexey Dobriyanbe787ac2006-03-07 22:20:23 -03001459 printk("dvb-ttpci: dpram file is way too big.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001460 return -EINVAL;
1461 }
1462 if (crc != crc32_le(0, ptr, len)) {
1463 printk("dvb-ttpci: crc32 of dpram file does not match.\n");
1464 return -EINVAL;
1465 }
1466 av7110->bin_dpram = ptr;
1467 av7110->size_dpram = len;
1468 ptr += len;
1469
1470 /* check root file */
1471 crc = ntohl(*(u32*) ptr);
1472 ptr += 4;
1473 len = ntohl(*(u32*) ptr);
1474 ptr += 4;
1475
1476 if (len <= 200000 || len >= 300000 ||
1477 len > ((av7110->bin_fw + av7110->size_fw) - ptr)) {
1478 printk("dvb-ttpci: root file has strange size (%d). aborting.\n", len);
1479 return -EINVAL;
1480 }
1481 if( crc != crc32_le(0, ptr, len)) {
1482 printk("dvb-ttpci: crc32 of root file does not match.\n");
1483 return -EINVAL;
1484 }
1485 av7110->bin_root = ptr;
1486 av7110->size_root = len;
1487 return 0;
1488}
1489
1490#ifdef CONFIG_DVB_AV7110_FIRMWARE_FILE
1491#include "av7110_firm.h"
1492static void put_firmware(struct av7110* av7110)
1493{
1494 av7110->bin_fw = NULL;
1495}
1496
1497static inline int get_firmware(struct av7110* av7110)
1498{
1499 av7110->bin_fw = dvb_ttpci_fw;
1500 av7110->size_fw = sizeof(dvb_ttpci_fw);
1501 return check_firmware(av7110);
1502}
1503#else
1504static void put_firmware(struct av7110* av7110)
1505{
1506 vfree(av7110->bin_fw);
1507}
1508
1509static int get_firmware(struct av7110* av7110)
1510{
1511 int ret;
1512 const struct firmware *fw;
1513
1514 /* request the av7110 firmware, this will block until someone uploads it */
1515 ret = request_firmware(&fw, "dvb-ttpci-01.fw", &av7110->dev->pci->dev);
1516 if (ret) {
1517 if (ret == -ENOENT) {
1518 printk(KERN_ERR "dvb-ttpci: could not load firmware,"
1519 " file not found: dvb-ttpci-01.fw\n");
Ville Skytt\ä12e66f62006-01-09 15:25:38 -02001520 printk(KERN_ERR "dvb-ttpci: usually this should be in "
1521 "/usr/lib/hotplug/firmware or /lib/firmware\n");
1522 printk(KERN_ERR "dvb-ttpci: and can be downloaded from"
Linus Torvalds1da177e2005-04-16 15:20:36 -07001523 " http://www.linuxtv.org/download/dvb/firmware/\n");
1524 } else
1525 printk(KERN_ERR "dvb-ttpci: cannot request firmware"
1526 " (error %i)\n", ret);
1527 return -EINVAL;
1528 }
1529
1530 if (fw->size <= 200000) {
1531 printk("dvb-ttpci: this firmware is way too small.\n");
1532 release_firmware(fw);
1533 return -EINVAL;
1534 }
1535
1536 /* check if the firmware is available */
1537 av7110->bin_fw = (unsigned char *) vmalloc(fw->size);
1538 if (NULL == av7110->bin_fw) {
1539 dprintk(1, "out of memory\n");
1540 release_firmware(fw);
1541 return -ENOMEM;
1542 }
1543
1544 memcpy(av7110->bin_fw, fw->data, fw->size);
1545 av7110->size_fw = fw->size;
1546 if ((ret = check_firmware(av7110)))
1547 vfree(av7110->bin_fw);
1548
1549 release_firmware(fw);
1550 return ret;
1551}
1552#endif
1553
1554
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001555static int alps_bsrv2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001556{
1557 struct av7110* av7110 = (struct av7110*) fe->dvb->priv;
1558 u8 pwr = 0;
1559 u8 buf[4];
1560 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
1561 u32 div = (params->frequency + 479500) / 125;
1562
1563 if (params->frequency > 2000000) pwr = 3;
1564 else if (params->frequency > 1800000) pwr = 2;
1565 else if (params->frequency > 1600000) pwr = 1;
1566 else if (params->frequency > 1200000) pwr = 0;
1567 else if (params->frequency >= 1100000) pwr = 1;
1568 else pwr = 2;
1569
1570 buf[0] = (div >> 8) & 0x7f;
1571 buf[1] = div & 0xff;
1572 buf[2] = ((div & 0x18000) >> 10) | 0x95;
1573 buf[3] = (pwr << 6) | 0x30;
1574
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -08001575 // NOTE: since we're using a prescaler of 2, we set the
Linus Torvalds1da177e2005-04-16 15:20:36 -07001576 // divisor frequency to 62.5kHz and divide by 125 above
1577
Patrick Boettcherdea74862006-05-14 05:01:31 -03001578 if (fe->ops.i2c_gate_ctrl)
1579 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001580 if (i2c_transfer (&av7110->i2c_adap, &msg, 1) != 1)
1581 return -EIO;
1582 return 0;
1583}
1584
1585static struct ves1x93_config alps_bsrv2_config = {
1586 .demod_address = 0x08,
1587 .xin = 90100000UL,
1588 .invert_pwm = 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001589};
1590
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001591static int alps_tdbe2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001592{
1593 struct av7110* av7110 = fe->dvb->priv;
1594 u32 div;
1595 u8 data[4];
1596 struct i2c_msg msg = { .addr = 0x62, .flags = 0, .buf = data, .len = sizeof(data) };
1597
1598 div = (params->frequency + 35937500 + 31250) / 62500;
1599
1600 data[0] = (div >> 8) & 0x7f;
1601 data[1] = div & 0xff;
1602 data[2] = 0x85 | ((div >> 10) & 0x60);
1603 data[3] = (params->frequency < 174000000 ? 0x88 : params->frequency < 470000000 ? 0x84 : 0x81);
1604
Patrick Boettcherdea74862006-05-14 05:01:31 -03001605 if (fe->ops.i2c_gate_ctrl)
1606 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001607 if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
1608 return -EIO;
1609 return 0;
1610}
1611
1612static struct ves1820_config alps_tdbe2_config = {
1613 .demod_address = 0x09,
1614 .xin = 57840000UL,
1615 .invert = 1,
1616 .selagc = VES1820_SELAGC_SIGNAMPERR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001617};
1618
1619
1620
1621
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001622static int grundig_29504_451_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001623{
1624 struct av7110* av7110 = fe->dvb->priv;
1625 u32 div;
1626 u8 data[4];
1627 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
1628
1629 div = params->frequency / 125;
1630 data[0] = (div >> 8) & 0x7f;
1631 data[1] = div & 0xff;
1632 data[2] = 0x8e;
1633 data[3] = 0x00;
1634
Patrick Boettcherdea74862006-05-14 05:01:31 -03001635 if (fe->ops.i2c_gate_ctrl)
1636 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001637 if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
1638 return -EIO;
1639 return 0;
1640}
1641
1642static struct tda8083_config grundig_29504_451_config = {
1643 .demod_address = 0x68,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001644};
1645
1646
1647
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001648static int philips_cd1516_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001649{
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -08001650 struct av7110* av7110 = fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001651 u32 div;
1652 u32 f = params->frequency;
1653 u8 data[4];
1654 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
1655
1656 div = (f + 36125000 + 31250) / 62500;
1657
1658 data[0] = (div >> 8) & 0x7f;
1659 data[1] = div & 0xff;
1660 data[2] = 0x8e;
1661 data[3] = (f < 174000000 ? 0xa1 : f < 470000000 ? 0x92 : 0x34);
1662
Patrick Boettcherdea74862006-05-14 05:01:31 -03001663 if (fe->ops.i2c_gate_ctrl)
1664 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001665 if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
1666 return -EIO;
1667 return 0;
1668}
1669
1670static struct ves1820_config philips_cd1516_config = {
1671 .demod_address = 0x09,
1672 .xin = 57840000UL,
1673 .invert = 1,
1674 .selagc = VES1820_SELAGC_SIGNAMPERR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001675};
1676
1677
1678
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001679static int alps_tdlb7_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001680{
1681 struct av7110* av7110 = fe->dvb->priv;
1682 u32 div, pwr;
1683 u8 data[4];
1684 struct i2c_msg msg = { .addr = 0x60, .flags = 0, .buf = data, .len = sizeof(data) };
1685
1686 div = (params->frequency + 36200000) / 166666;
1687
1688 if (params->frequency <= 782000000)
1689 pwr = 1;
1690 else
1691 pwr = 2;
1692
1693 data[0] = (div >> 8) & 0x7f;
1694 data[1] = div & 0xff;
1695 data[2] = 0x85;
1696 data[3] = pwr << 6;
1697
Patrick Boettcherdea74862006-05-14 05:01:31 -03001698 if (fe->ops.i2c_gate_ctrl)
1699 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001700 if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
1701 return -EIO;
1702 return 0;
1703}
1704
1705static int alps_tdlb7_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name)
1706{
1707 struct av7110* av7110 = (struct av7110*) fe->dvb->priv;
1708
1709 return request_firmware(fw, name, &av7110->dev->pci->dev);
1710}
1711
1712static struct sp8870_config alps_tdlb7_config = {
1713
1714 .demod_address = 0x71,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001715 .request_firmware = alps_tdlb7_request_firmware,
1716};
1717
1718
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001719static u8 nexusca_stv0297_inittab[] = {
1720 0x80, 0x01,
1721 0x80, 0x00,
1722 0x81, 0x01,
1723 0x81, 0x00,
1724 0x00, 0x09,
1725 0x01, 0x69,
1726 0x03, 0x00,
1727 0x04, 0x00,
1728 0x07, 0x00,
1729 0x08, 0x00,
1730 0x20, 0x00,
1731 0x21, 0x40,
1732 0x22, 0x00,
1733 0x23, 0x00,
1734 0x24, 0x40,
1735 0x25, 0x88,
1736 0x30, 0xff,
1737 0x31, 0x00,
1738 0x32, 0xff,
1739 0x33, 0x00,
1740 0x34, 0x50,
1741 0x35, 0x7f,
1742 0x36, 0x00,
1743 0x37, 0x20,
1744 0x38, 0x00,
1745 0x40, 0x1c,
1746 0x41, 0xff,
1747 0x42, 0x29,
1748 0x43, 0x00,
1749 0x44, 0xff,
1750 0x45, 0x00,
1751 0x46, 0x00,
1752 0x49, 0x04,
1753 0x4a, 0x00,
1754 0x4b, 0x7b,
1755 0x52, 0x30,
1756 0x55, 0xae,
1757 0x56, 0x47,
1758 0x57, 0xe1,
1759 0x58, 0x3a,
1760 0x5a, 0x1e,
1761 0x5b, 0x34,
1762 0x60, 0x00,
1763 0x63, 0x00,
1764 0x64, 0x00,
1765 0x65, 0x00,
1766 0x66, 0x00,
1767 0x67, 0x00,
1768 0x68, 0x00,
1769 0x69, 0x00,
1770 0x6a, 0x02,
1771 0x6b, 0x00,
1772 0x70, 0xff,
1773 0x71, 0x00,
1774 0x72, 0x00,
1775 0x73, 0x00,
1776 0x74, 0x0c,
1777 0x80, 0x00,
1778 0x81, 0x00,
1779 0x82, 0x00,
1780 0x83, 0x00,
1781 0x84, 0x04,
1782 0x85, 0x80,
1783 0x86, 0x24,
1784 0x87, 0x78,
1785 0x88, 0x10,
1786 0x89, 0x00,
1787 0x90, 0x01,
1788 0x91, 0x01,
1789 0xa0, 0x04,
1790 0xa1, 0x00,
1791 0xa2, 0x00,
1792 0xb0, 0x91,
1793 0xb1, 0x0b,
1794 0xc0, 0x53,
1795 0xc1, 0x70,
1796 0xc2, 0x12,
1797 0xd0, 0x00,
1798 0xd1, 0x00,
1799 0xd2, 0x00,
1800 0xd3, 0x00,
1801 0xd4, 0x00,
1802 0xd5, 0x00,
1803 0xde, 0x00,
1804 0xdf, 0x00,
1805 0x61, 0x49,
1806 0x62, 0x0b,
1807 0x53, 0x08,
1808 0x59, 0x08,
1809 0xff, 0xff,
1810};
Linus Torvalds1da177e2005-04-16 15:20:36 -07001811
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001812static int nexusca_stv0297_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001813{
1814 struct av7110* av7110 = fe->dvb->priv;
1815 u32 div;
1816 u8 data[4];
1817 struct i2c_msg msg = { .addr = 0x63, .flags = 0, .buf = data, .len = sizeof(data) };
1818 struct i2c_msg readmsg = { .addr = 0x63, .flags = I2C_M_RD, .buf = data, .len = 1 };
1819 int i;
1820
1821 div = (params->frequency + 36150000 + 31250) / 62500;
1822
1823 data[0] = (div >> 8) & 0x7f;
1824 data[1] = div & 0xff;
1825 data[2] = 0xce;
1826
1827 if (params->frequency < 45000000)
1828 return -EINVAL;
1829 else if (params->frequency < 137000000)
1830 data[3] = 0x01;
1831 else if (params->frequency < 403000000)
1832 data[3] = 0x02;
1833 else if (params->frequency < 860000000)
1834 data[3] = 0x04;
1835 else
1836 return -EINVAL;
1837
Patrick Boettcherdea74862006-05-14 05:01:31 -03001838 if (fe->ops.i2c_gate_ctrl)
1839 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001840 if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1) {
1841 printk("nexusca: pll transfer failed!\n");
1842 return -EIO;
1843 }
1844
1845 // wait for PLL lock
1846 for(i = 0; i < 20; i++) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001847 if (fe->ops.i2c_gate_ctrl)
1848 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001849 if (i2c_transfer(&av7110->i2c_adap, &readmsg, 1) == 1)
1850 if (data[0] & 0x40) break;
1851 msleep(10);
1852 }
1853
1854 return 0;
1855}
1856
1857static struct stv0297_config nexusca_stv0297_config = {
1858
1859 .demod_address = 0x1C,
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001860 .inittab = nexusca_stv0297_inittab,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001861 .invert = 1,
Thomas Kaiserb8d4c232006-04-27 21:45:20 -03001862 .stop_during_read = 1,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001863};
1864
1865
1866
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001867static int grundig_29504_401_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001868{
1869 struct av7110* av7110 = (struct av7110*) fe->dvb->priv;
1870 u32 div;
1871 u8 cfg, cpump, band_select;
1872 u8 data[4];
1873 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
1874
1875 div = (36125000 + params->frequency) / 166666;
1876
1877 cfg = 0x88;
1878
1879 if (params->frequency < 175000000) cpump = 2;
1880 else if (params->frequency < 390000000) cpump = 1;
1881 else if (params->frequency < 470000000) cpump = 2;
1882 else if (params->frequency < 750000000) cpump = 1;
1883 else cpump = 3;
1884
1885 if (params->frequency < 175000000) band_select = 0x0e;
1886 else if (params->frequency < 470000000) band_select = 0x05;
1887 else band_select = 0x03;
1888
1889 data[0] = (div >> 8) & 0x7f;
1890 data[1] = div & 0xff;
1891 data[2] = ((div >> 10) & 0x60) | cfg;
1892 data[3] = (cpump << 6) | band_select;
1893
Patrick Boettcherdea74862006-05-14 05:01:31 -03001894 if (fe->ops.i2c_gate_ctrl)
1895 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001896 if (i2c_transfer (&av7110->i2c_adap, &msg, 1) != 1) return -EIO;
1897 return 0;
1898}
1899
1900static struct l64781_config grundig_29504_401_config = {
1901 .demod_address = 0x55,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001902};
1903
1904
1905
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001906static int av7110_fe_lock_fix(struct av7110* av7110, fe_status_t status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001907{
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001908 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001909 int synced = (status & FE_HAS_LOCK) ? 1 : 0;
1910
1911 av7110->fe_status = status;
1912
1913 if (av7110->fe_synced == synced)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001914 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001915
Linus Torvalds1da177e2005-04-16 15:20:36 -07001916 if (av7110->playing)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001917 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001918
Ingo Molnar3593cab2006-02-07 06:49:14 -02001919 if (mutex_lock_interruptible(&av7110->pid_mutex))
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001920 return -ERESTARTSYS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001921
Oliver Endriss34612152005-07-07 17:58:02 -07001922 if (synced) {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001923 ret = SetPIDs(av7110, av7110->pids[DMX_PES_VIDEO],
Linus Torvalds1da177e2005-04-16 15:20:36 -07001924 av7110->pids[DMX_PES_AUDIO],
1925 av7110->pids[DMX_PES_TELETEXT], 0,
1926 av7110->pids[DMX_PES_PCR]);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001927 if (!ret)
1928 ret = av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, Scan, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001929 } else {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001930 ret = SetPIDs(av7110, 0, 0, 0, 0, 0);
1931 if (!ret) {
1932 ret = av7110_fw_cmd(av7110, COMTYPE_PID_FILTER, FlushTSQueue, 0);
1933 if (!ret)
1934 ret = av7110_wait_msgstate(av7110, GPMQBusy);
1935 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001936 }
1937
Oliver Endriss34612152005-07-07 17:58:02 -07001938 if (!ret)
1939 av7110->fe_synced = synced;
1940
Ingo Molnar3593cab2006-02-07 06:49:14 -02001941 mutex_unlock(&av7110->pid_mutex);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001942 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001943}
1944
1945static int av7110_fe_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
1946{
1947 struct av7110* av7110 = fe->dvb->priv;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001948
1949 int ret = av7110_fe_lock_fix(av7110, 0);
Oliver Endriss66190a22006-01-09 15:32:42 -02001950 if (!ret) {
1951 av7110->saved_fe_params = *params;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001952 ret = av7110->fe_set_frontend(fe, params);
Oliver Endriss66190a22006-01-09 15:32:42 -02001953 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001954 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001955}
1956
1957static int av7110_fe_init(struct dvb_frontend* fe)
1958{
1959 struct av7110* av7110 = fe->dvb->priv;
1960
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001961 int ret = av7110_fe_lock_fix(av7110, 0);
1962 if (!ret)
1963 ret = av7110->fe_init(fe);
1964 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001965}
1966
1967static int av7110_fe_read_status(struct dvb_frontend* fe, fe_status_t* status)
1968{
1969 struct av7110* av7110 = fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001970
1971 /* call the real implementation */
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001972 int ret = av7110->fe_read_status(fe, status);
1973 if (!ret)
1974 if (((*status ^ av7110->fe_status) & FE_HAS_LOCK) && (*status & FE_HAS_LOCK))
1975 ret = av7110_fe_lock_fix(av7110, *status);
1976 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001977}
1978
1979static int av7110_fe_diseqc_reset_overload(struct dvb_frontend* fe)
1980{
1981 struct av7110* av7110 = fe->dvb->priv;
1982
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001983 int ret = av7110_fe_lock_fix(av7110, 0);
1984 if (!ret)
1985 ret = av7110->fe_diseqc_reset_overload(fe);
1986 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001987}
1988
1989static int av7110_fe_diseqc_send_master_cmd(struct dvb_frontend* fe,
1990 struct dvb_diseqc_master_cmd* cmd)
1991{
1992 struct av7110* av7110 = fe->dvb->priv;
1993
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001994 int ret = av7110_fe_lock_fix(av7110, 0);
Oliver Endriss66190a22006-01-09 15:32:42 -02001995 if (!ret) {
1996 av7110->saved_master_cmd = *cmd;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001997 ret = av7110->fe_diseqc_send_master_cmd(fe, cmd);
Oliver Endriss66190a22006-01-09 15:32:42 -02001998 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001999 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002000}
2001
2002static int av7110_fe_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd)
2003{
2004 struct av7110* av7110 = fe->dvb->priv;
2005
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002006 int ret = av7110_fe_lock_fix(av7110, 0);
Oliver Endriss66190a22006-01-09 15:32:42 -02002007 if (!ret) {
2008 av7110->saved_minicmd = minicmd;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002009 ret = av7110->fe_diseqc_send_burst(fe, minicmd);
Oliver Endriss66190a22006-01-09 15:32:42 -02002010 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002011 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002012}
2013
2014static int av7110_fe_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
2015{
2016 struct av7110* av7110 = fe->dvb->priv;
2017
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002018 int ret = av7110_fe_lock_fix(av7110, 0);
Oliver Endriss66190a22006-01-09 15:32:42 -02002019 if (!ret) {
2020 av7110->saved_tone = tone;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002021 ret = av7110->fe_set_tone(fe, tone);
Oliver Endriss66190a22006-01-09 15:32:42 -02002022 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002023 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002024}
2025
2026static int av7110_fe_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
2027{
2028 struct av7110* av7110 = fe->dvb->priv;
2029
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002030 int ret = av7110_fe_lock_fix(av7110, 0);
Oliver Endriss66190a22006-01-09 15:32:42 -02002031 if (!ret) {
2032 av7110->saved_voltage = voltage;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002033 ret = av7110->fe_set_voltage(fe, voltage);
Oliver Endriss66190a22006-01-09 15:32:42 -02002034 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002035 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002036}
2037
Peter Beutner400b7082006-01-09 15:32:43 -02002038static int av7110_fe_dishnetwork_send_legacy_command(struct dvb_frontend* fe, unsigned long cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002039{
2040 struct av7110* av7110 = fe->dvb->priv;
2041
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002042 int ret = av7110_fe_lock_fix(av7110, 0);
2043 if (!ret)
2044 ret = av7110->fe_dishnetwork_send_legacy_command(fe, cmd);
2045 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002046}
2047
Oliver Endriss66190a22006-01-09 15:32:42 -02002048static void dvb_s_recover(struct av7110* av7110)
2049{
2050 av7110_fe_init(av7110->fe);
2051
2052 av7110_fe_set_voltage(av7110->fe, av7110->saved_voltage);
2053 if (av7110->saved_master_cmd.msg_len) {
2054 msleep(20);
2055 av7110_fe_diseqc_send_master_cmd(av7110->fe, &av7110->saved_master_cmd);
2056 }
2057 msleep(20);
2058 av7110_fe_diseqc_send_burst(av7110->fe, av7110->saved_minicmd);
2059 msleep(20);
2060 av7110_fe_set_tone(av7110->fe, av7110->saved_tone);
2061
2062 av7110_fe_set_frontend(av7110->fe, &av7110->saved_fe_params);
2063}
2064
Linus Torvalds1da177e2005-04-16 15:20:36 -07002065static u8 read_pwm(struct av7110* av7110)
2066{
2067 u8 b = 0xff;
2068 u8 pwm;
2069 struct i2c_msg msg[] = { { .addr = 0x50,.flags = 0,.buf = &b,.len = 1 },
2070 { .addr = 0x50,.flags = I2C_M_RD,.buf = &pwm,.len = 1} };
2071
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -08002072 if ((i2c_transfer(&av7110->i2c_adap, msg, 2) != 2) || (pwm == 0xff))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002073 pwm = 0x48;
2074
2075 return pwm;
2076}
2077
2078static int frontend_init(struct av7110 *av7110)
2079{
2080 int ret;
2081
2082 if (av7110->dev->pci->subsystem_vendor == 0x110a) {
2083 switch(av7110->dev->pci->subsystem_device) {
2084 case 0x0000: // Fujitsu/Siemens DVB-Cable (ves1820/Philips CD1516(??))
2085 av7110->fe = ves1820_attach(&philips_cd1516_config,
2086 &av7110->i2c_adap, read_pwm(av7110));
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002087 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002088 av7110->fe->ops.tuner_ops.set_params = philips_cd1516_tuner_set_params;
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002089 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002090 break;
2091 }
2092
2093 } else if (av7110->dev->pci->subsystem_vendor == 0x13c2) {
2094 switch(av7110->dev->pci->subsystem_device) {
2095 case 0x0000: // Hauppauge/TT WinTV DVB-S rev1.X
2096 case 0x0003: // Hauppauge/TT WinTV Nexus-S Rev 2.X
2097 case 0x1002: // Hauppauge/TT WinTV DVB-S rev1.3SE
2098
2099 // try the ALPS BSRV2 first of all
2100 av7110->fe = ves1x93_attach(&alps_bsrv2_config, &av7110->i2c_adap);
2101 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002102 av7110->fe->ops.tuner_ops.set_params = alps_bsrv2_tuner_set_params;
2103 av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
2104 av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
2105 av7110->fe->ops.set_tone = av7110_set_tone;
Oliver Endriss66190a22006-01-09 15:32:42 -02002106 av7110->recover = dvb_s_recover;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002107 break;
2108 }
2109
2110 // try the ALPS BSRU6 now
2111 av7110->fe = stv0299_attach(&alps_bsru6_config, &av7110->i2c_adap);
2112 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002113 av7110->fe->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03002114 av7110->fe->tuner_priv = &av7110->i2c_adap;
2115
Patrick Boettcherdea74862006-05-14 05:01:31 -03002116 av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
2117 av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
2118 av7110->fe->ops.set_tone = av7110_set_tone;
Oliver Endriss66190a22006-01-09 15:32:42 -02002119 av7110->recover = dvb_s_recover;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002120 break;
2121 }
2122
2123 // Try the grundig 29504-451
Michael Krufky50c25ff2006-01-09 15:25:34 -02002124 av7110->fe = tda8083_attach(&grundig_29504_451_config, &av7110->i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002125 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002126 av7110->fe->ops.tuner_ops.set_params = grundig_29504_451_tuner_set_params;
2127 av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
2128 av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
2129 av7110->fe->ops.set_tone = av7110_set_tone;
Oliver Endriss66190a22006-01-09 15:32:42 -02002130 av7110->recover = dvb_s_recover;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002131 break;
2132 }
2133
2134 /* Try DVB-C cards */
2135 switch(av7110->dev->pci->subsystem_device) {
2136 case 0x0000:
2137 /* Siemens DVB-C (full-length card) VES1820/Philips CD1516 */
2138 av7110->fe = ves1820_attach(&philips_cd1516_config, &av7110->i2c_adap,
2139 read_pwm(av7110));
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002140 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002141 av7110->fe->ops.tuner_ops.set_params = philips_cd1516_tuner_set_params;
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002142 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002143 break;
2144 case 0x0003:
Adrian Bunkf3688fc2006-03-29 22:46:12 -03002145 /* Hauppauge DVB-C 2.1 VES1820/ALPS TDBE2 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002146 av7110->fe = ves1820_attach(&alps_tdbe2_config, &av7110->i2c_adap,
2147 read_pwm(av7110));
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002148 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002149 av7110->fe->ops.tuner_ops.set_params = alps_tdbe2_tuner_set_params;
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002150 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002151 break;
2152 }
2153 break;
2154
2155 case 0x0001: // Hauppauge/TT Nexus-T premium rev1.X
2156
2157 // ALPS TDLB7
Michael Krufky50c25ff2006-01-09 15:25:34 -02002158 av7110->fe = sp8870_attach(&alps_tdlb7_config, &av7110->i2c_adap);
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002159 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002160 av7110->fe->ops.tuner_ops.set_params = alps_tdlb7_tuner_set_params;
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002161 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002162 break;
2163
2164 case 0x0002: // Hauppauge/TT DVB-C premium rev2.X
2165
Michael Krufky50c25ff2006-01-09 15:25:34 -02002166 av7110->fe = ves1820_attach(&alps_tdbe2_config, &av7110->i2c_adap, read_pwm(av7110));
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002167 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002168 av7110->fe->ops.tuner_ops.set_params = alps_tdbe2_tuner_set_params;
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002169 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002170 break;
2171
Oliver Endriss8bd63012006-02-07 06:49:11 -02002172 case 0x0004: // Galaxis DVB-S rev1.3
2173 /* ALPS BSRV2 */
2174 av7110->fe = ves1x93_attach(&alps_bsrv2_config, &av7110->i2c_adap);
2175 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002176 av7110->fe->ops.tuner_ops.set_params = alps_bsrv2_tuner_set_params;
2177 av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
2178 av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
2179 av7110->fe->ops.set_tone = av7110_set_tone;
Oliver Endriss8bd63012006-02-07 06:49:11 -02002180 av7110->recover = dvb_s_recover;
2181 }
2182 break;
2183
Linus Torvalds1da177e2005-04-16 15:20:36 -07002184 case 0x0006: /* Fujitsu-Siemens DVB-S rev 1.6 */
2185 /* Grundig 29504-451 */
2186 av7110->fe = tda8083_attach(&grundig_29504_451_config, &av7110->i2c_adap);
2187 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002188 av7110->fe->ops.tuner_ops.set_params = grundig_29504_451_tuner_set_params;
2189 av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
2190 av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
2191 av7110->fe->ops.set_tone = av7110_set_tone;
Oliver Endriss66190a22006-01-09 15:32:42 -02002192 av7110->recover = dvb_s_recover;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002193 }
2194 break;
2195
2196 case 0x0008: // Hauppauge/TT DVB-T
2197
2198 av7110->fe = l64781_attach(&grundig_29504_401_config, &av7110->i2c_adap);
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002199 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002200 av7110->fe->ops.tuner_ops.set_params = grundig_29504_401_tuner_set_params;
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002201 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002202 break;
2203
2204 case 0x000A: // Hauppauge/TT Nexus-CA rev1.X
2205
Andrew de Quinceydc27a162005-09-09 13:03:07 -07002206 av7110->fe = stv0297_attach(&nexusca_stv0297_config, &av7110->i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002207 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002208 av7110->fe->ops.tuner_ops.set_params = nexusca_stv0297_tuner_set_params;
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03002209
Linus Torvalds1da177e2005-04-16 15:20:36 -07002210 /* set TDA9819 into DVB mode */
2211 saa7146_setgpio(av7110->dev, 1, SAA7146_GPIO_OUTLO); // TDA9198 pin9(STD)
2212 saa7146_setgpio(av7110->dev, 3, SAA7146_GPIO_OUTLO); // TDA9198 pin30(VIF)
2213
2214 /* tuner on this needs a slower i2c bus speed */
2215 av7110->dev->i2c_bitrate = SAA7146_I2C_BUS_BIT_RATE_240;
2216 break;
2217 }
Johannes Stezenbach3dfaebd2005-05-16 21:54:19 -07002218 break;
2219
2220 case 0x000E: /* Hauppauge/TT Nexus-S rev 2.3 */
2221 /* ALPS BSBE1 */
2222 av7110->fe = stv0299_attach(&alps_bsbe1_config, &av7110->i2c_adap);
Oliver Endrisseb3daf32006-01-09 15:25:05 -02002223 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002224 av7110->fe->ops.tuner_ops.set_params = alps_bsbe1_tuner_set_params;
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03002225 av7110->fe->tuner_priv = &av7110->i2c_adap;
2226
Andrew de Quinceyd0205422006-04-27 21:45:01 -03002227 if (lnbp21_attach(av7110->fe, &av7110->i2c_adap, 0, 0)) {
Oliver Endrissdb5d91e2006-02-28 10:32:25 -03002228 printk("dvb-ttpci: LNBP21 not found!\n");
Patrick Boettcherdea74862006-05-14 05:01:31 -03002229 if (av7110->fe->ops.release)
2230 av7110->fe->ops.release(av7110->fe);
Oliver Endrissdb5d91e2006-02-28 10:32:25 -03002231 av7110->fe = NULL;
2232 } else {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002233 av7110->fe->ops.dishnetwork_send_legacy_command = NULL;
Oliver Endrissdb5d91e2006-02-28 10:32:25 -03002234 av7110->recover = dvb_s_recover;
2235 }
Oliver Endrisseb3daf32006-01-09 15:25:05 -02002236 }
Johannes Stezenbach3dfaebd2005-05-16 21:54:19 -07002237 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002238 }
2239 }
2240
2241 if (!av7110->fe) {
2242 /* FIXME: propagate the failure code from the lower layers */
2243 ret = -ENOMEM;
2244 printk("dvb-ttpci: A frontend driver was not found for device %04x/%04x subsystem %04x/%04x\n",
2245 av7110->dev->pci->vendor,
2246 av7110->dev->pci->device,
2247 av7110->dev->pci->subsystem_vendor,
2248 av7110->dev->pci->subsystem_device);
2249 } else {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002250 FE_FUNC_OVERRIDE(av7110->fe->ops.init, av7110->fe_init, av7110_fe_init);
2251 FE_FUNC_OVERRIDE(av7110->fe->ops.read_status, av7110->fe_read_status, av7110_fe_read_status);
2252 FE_FUNC_OVERRIDE(av7110->fe->ops.diseqc_reset_overload, av7110->fe_diseqc_reset_overload, av7110_fe_diseqc_reset_overload);
2253 FE_FUNC_OVERRIDE(av7110->fe->ops.diseqc_send_master_cmd, av7110->fe_diseqc_send_master_cmd, av7110_fe_diseqc_send_master_cmd);
2254 FE_FUNC_OVERRIDE(av7110->fe->ops.diseqc_send_burst, av7110->fe_diseqc_send_burst, av7110_fe_diseqc_send_burst);
2255 FE_FUNC_OVERRIDE(av7110->fe->ops.set_tone, av7110->fe_set_tone, av7110_fe_set_tone);
2256 FE_FUNC_OVERRIDE(av7110->fe->ops.set_voltage, av7110->fe_set_voltage, av7110_fe_set_voltage;)
2257 FE_FUNC_OVERRIDE(av7110->fe->ops.dishnetwork_send_legacy_command, av7110->fe_dishnetwork_send_legacy_command, av7110_fe_dishnetwork_send_legacy_command);
2258 FE_FUNC_OVERRIDE(av7110->fe->ops.set_frontend, av7110->fe_set_frontend, av7110_fe_set_frontend);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002259
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07002260 ret = dvb_register_frontend(&av7110->dvb_adapter, av7110->fe);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002261 if (ret < 0) {
2262 printk("av7110: Frontend registration failed!\n");
Patrick Boettcherdea74862006-05-14 05:01:31 -03002263 if (av7110->fe->ops.release)
2264 av7110->fe->ops.release(av7110->fe);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002265 av7110->fe = NULL;
2266 }
2267 }
2268 return ret;
2269}
2270
2271/* Budgetpatch note:
2272 * Original hardware design by Roberto Deza:
2273 * There is a DVB_Wiki at
2274 * http://212.227.36.83/linuxtv/wiki/index.php/Main_Page
2275 * where is described this 'DVB TT Budget Patch', on Card Modding:
2276 * http://212.227.36.83/linuxtv/wiki/index.php/DVB_TT_Budget_Patch
2277 * On the short description there is also a link to a external file,
2278 * with more details:
2279 * http://perso.wanadoo.es/jesussolano/Ttf_tsc1.zip
2280 *
2281 * New software triggering design by Emard that works on
2282 * original Roberto Deza's hardware:
2283 *
2284 * rps1 code for budgetpatch will copy internal HS event to GPIO3 pin.
2285 * GPIO3 is in budget-patch hardware connectd to port B VSYNC
2286 * HS is an internal event of 7146, accessible with RPS
2287 * and temporarily raised high every n lines
2288 * (n in defined in the RPS_THRESH1 counter threshold)
2289 * I think HS is raised high on the beginning of the n-th line
2290 * and remains high until this n-th line that triggered
2291 * it is completely received. When the receiption of n-th line
2292 * ends, HS is lowered.
2293 *
2294 * To transmit data over DMA, 7146 needs changing state at
2295 * port B VSYNC pin. Any changing of port B VSYNC will
2296 * cause some DMA data transfer, with more or less packets loss.
2297 * It depends on the phase and frequency of VSYNC and
2298 * the way of 7146 is instructed to trigger on port B (defined
2299 * in DD1_INIT register, 3rd nibble from the right valid
2300 * numbers are 0-7, see datasheet)
2301 *
2302 * The correct triggering can minimize packet loss,
2303 * dvbtraffic should give this stable bandwidths:
2304 * 22k transponder = 33814 kbit/s
2305 * 27.5k transponder = 38045 kbit/s
2306 * by experiment it is found that the best results
2307 * (stable bandwidths and almost no packet loss)
2308 * are obtained using DD1_INIT triggering number 2
2309 * (Va at rising edge of VS Fa = HS x VS-failing forced toggle)
2310 * and a VSYNC phase that occurs in the middle of DMA transfer
2311 * (about byte 188*512=96256 in the DMA window).
2312 *
2313 * Phase of HS is still not clear to me how to control,
2314 * It just happens to be so. It can be seen if one enables
2315 * RPS_IRQ and print Event Counter 1 in vpeirq(). Every
2316 * time RPS_INTERRUPT is called, the Event Counter 1 will
2317 * increment. That's how the 7146 is programmed to do event
2318 * counting in this budget-patch.c
2319 * I *think* HPS setting has something to do with the phase
2320 * of HS but I cant be 100% sure in that.
2321 *
2322 * hardware debug note: a working budget card (including budget patch)
2323 * with vpeirq() interrupt setup in mode "0x90" (every 64K) will
2324 * generate 3 interrupts per 25-Hz DMA frame of 2*188*512 bytes
2325 * and that means 3*25=75 Hz of interrupt freqency, as seen by
2326 * watch cat /proc/interrupts
2327 *
2328 * If this frequency is 3x lower (and data received in the DMA
2329 * buffer don't start with 0x47, but in the middle of packets,
2330 * whose lengths appear to be like 188 292 188 104 etc.
2331 * this means VSYNC line is not connected in the hardware.
2332 * (check soldering pcb and pins)
2333 * The same behaviour of missing VSYNC can be duplicated on budget
2334 * cards, by seting DD1_INIT trigger mode 7 in 3rd nibble.
2335 */
Johannes Stezenbach1be11e32006-02-27 00:09:20 -03002336static int __devinit av7110_attach(struct saa7146_dev* dev,
2337 struct saa7146_pci_extension_data *pci_ext)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002338{
2339 const int length = TS_WIDTH * TS_HEIGHT;
2340 struct pci_dev *pdev = dev->pci;
2341 struct av7110 *av7110;
2342 int ret, count = 0;
2343
2344 dprintk(4, "dev: %p\n", dev);
2345
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -08002346 /* Set RPS_IRQ to 1 to track rps1 activity.
2347 * Enabling this won't send any interrupt to PC CPU.
2348 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002349#define RPS_IRQ 0
2350
2351 if (budgetpatch == 1) {
2352 budgetpatch = 0;
2353 /* autodetect the presence of budget patch
2354 * this only works if saa7146 has been recently
2355 * reset with with MASK_31 to MC1
2356 *
2357 * will wait for VBI_B event (vertical blank at port B)
2358 * and will reset GPIO3 after VBI_B is detected.
2359 * (GPIO3 should be raised high by CPU to
2360 * test if GPIO3 will generate vertical blank signal
2361 * in budget patch GPIO3 is connected to VSYNC_B
2362 */
2363
2364 /* RESET SAA7146 */
2365 saa7146_write(dev, MC1, MASK_31);
2366 /* autodetection success seems to be time-dependend after reset */
2367
2368 /* Fix VSYNC level */
2369 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
2370 /* set vsync_b triggering */
2371 saa7146_write(dev, DD1_STREAM_B, 0);
2372 /* port B VSYNC at rising edge */
2373 saa7146_write(dev, DD1_INIT, 0x00000200);
2374 saa7146_write(dev, BRS_CTRL, 0x00000000); // VBI
2375 saa7146_write(dev, MC2,
2376 1 * (MASK_08 | MASK_24) | // BRS control
2377 0 * (MASK_09 | MASK_25) | // a
2378 1 * (MASK_10 | MASK_26) | // b
2379 0 * (MASK_06 | MASK_22) | // HPS_CTRL1
2380 0 * (MASK_05 | MASK_21) | // HPS_CTRL2
2381 0 * (MASK_01 | MASK_15) // DEBI
2382 );
2383
2384 /* start writing RPS1 code from beginning */
2385 count = 0;
2386 /* Disable RPS1 */
2387 saa7146_write(dev, MC1, MASK_29);
2388 /* RPS1 timeout disable */
2389 saa7146_write(dev, RPS_TOV1, 0);
2390 WRITE_RPS1(cpu_to_le32(CMD_PAUSE | EVT_VBI_B));
2391 WRITE_RPS1(cpu_to_le32(CMD_WR_REG_MASK | (GPIO_CTRL>>2)));
2392 WRITE_RPS1(cpu_to_le32(GPIO3_MSK));
2393 WRITE_RPS1(cpu_to_le32(SAA7146_GPIO_OUTLO<<24));
2394#if RPS_IRQ
2395 /* issue RPS1 interrupt to increment counter */
2396 WRITE_RPS1(cpu_to_le32(CMD_INTERRUPT));
2397#endif
2398 WRITE_RPS1(cpu_to_le32(CMD_STOP));
2399 /* Jump to begin of RPS program as safety measure (p37) */
2400 WRITE_RPS1(cpu_to_le32(CMD_JUMP));
2401 WRITE_RPS1(cpu_to_le32(dev->d_rps1.dma_handle));
2402
2403#if RPS_IRQ
2404 /* set event counter 1 source as RPS1 interrupt (0x03) (rE4 p53)
2405 * use 0x03 to track RPS1 interrupts - increase by 1 every gpio3 is toggled
2406 * use 0x15 to track VPE interrupts - increase by 1 every vpeirq() is called
2407 */
2408 saa7146_write(dev, EC1SSR, (0x03<<2) | 3 );
2409 /* set event counter 1 treshold to maximum allowed value (rEC p55) */
2410 saa7146_write(dev, ECT1R, 0x3fff );
2411#endif
2412 /* Set RPS1 Address register to point to RPS code (r108 p42) */
2413 saa7146_write(dev, RPS_ADDR1, dev->d_rps1.dma_handle);
2414 /* Enable RPS1, (rFC p33) */
2415 saa7146_write(dev, MC1, (MASK_13 | MASK_29 ));
2416
2417 mdelay(10);
2418 /* now send VSYNC_B to rps1 by rising GPIO3 */
2419 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI);
2420 mdelay(10);
2421 /* if rps1 responded by lowering the GPIO3,
2422 * then we have budgetpatch hardware
2423 */
2424 if ((saa7146_read(dev, GPIO_CTRL) & 0x10000000) == 0) {
2425 budgetpatch = 1;
2426 printk("dvb-ttpci: BUDGET-PATCH DETECTED.\n");
2427 }
2428 /* Disable RPS1 */
2429 saa7146_write(dev, MC1, ( MASK_29 ));
2430#if RPS_IRQ
2431 printk("dvb-ttpci: Event Counter 1 0x%04x\n", saa7146_read(dev, EC1R) & 0x3fff );
2432#endif
2433 }
2434
2435 /* prepare the av7110 device struct */
Panagiotis Issaris74081872006-01-11 19:40:56 -02002436 av7110 = kzalloc(sizeof(struct av7110), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002437 if (!av7110) {
2438 dprintk(1, "out of memory\n");
2439 return -ENOMEM;
2440 }
2441
Linus Torvalds1da177e2005-04-16 15:20:36 -07002442 av7110->card_name = (char*) pci_ext->ext_priv;
2443 av7110->dev = dev;
2444 dev->ext_priv = av7110;
2445
2446 ret = get_firmware(av7110);
2447 if (ret < 0)
2448 goto err_kfree_0;
2449
2450 ret = dvb_register_adapter(&av7110->dvb_adapter, av7110->card_name,
Andrew de Quinceyd09dbf92006-04-10 09:27:37 -03002451 THIS_MODULE, &dev->pci->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002452 if (ret < 0)
2453 goto err_put_firmware_1;
2454
2455 /* the Siemens DVB needs this if you want to have the i2c chips
2456 get recognized before the main driver is fully loaded */
2457 saa7146_write(dev, GPIO_CTRL, 0x500000);
2458
2459#ifdef I2C_ADAP_CLASS_TV_DIGITAL
2460 av7110->i2c_adap.class = I2C_ADAP_CLASS_TV_DIGITAL;
2461#else
2462 av7110->i2c_adap.class = I2C_CLASS_TV_DIGITAL;
2463#endif
2464 strlcpy(av7110->i2c_adap.name, pci_ext->ext_priv, sizeof(av7110->i2c_adap.name));
2465
2466 saa7146_i2c_adapter_prepare(dev, &av7110->i2c_adap, SAA7146_I2C_BUS_BIT_RATE_120); /* 275 kHz */
2467
2468 ret = i2c_add_adapter(&av7110->i2c_adap);
2469 if (ret < 0)
2470 goto err_dvb_unregister_adapter_2;
2471
2472 ttpci_eeprom_parse_mac(&av7110->i2c_adap,
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07002473 av7110->dvb_adapter.proposed_mac);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002474 ret = -ENOMEM;
2475
2476 if (budgetpatch) {
2477 spin_lock_init(&av7110->feedlock1);
2478 av7110->grabbing = saa7146_vmalloc_build_pgtable(pdev, length,
2479 &av7110->pt);
2480 if (!av7110->grabbing)
2481 goto err_i2c_del_3;
2482
2483 saa7146_write(dev, PCI_BT_V1, 0x1c1f101f);
2484 saa7146_write(dev, BCS_CTRL, 0x80400040);
2485 /* set dd1 stream a & b */
2486 saa7146_write(dev, DD1_STREAM_B, 0x00000000);
2487 saa7146_write(dev, DD1_INIT, 0x03000200);
2488 saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
2489 saa7146_write(dev, BRS_CTRL, 0x60000000);
2490 saa7146_write(dev, BASE_ODD3, 0);
2491 saa7146_write(dev, BASE_EVEN3, 0);
2492 saa7146_write(dev, PROT_ADDR3, TS_WIDTH * TS_HEIGHT);
2493 saa7146_write(dev, BASE_PAGE3, av7110->pt.dma | ME1 | 0x90);
2494
2495 saa7146_write(dev, PITCH3, TS_WIDTH);
2496 saa7146_write(dev, NUM_LINE_BYTE3, (TS_HEIGHT << 16) | TS_WIDTH);
2497
2498 /* upload all */
2499 saa7146_write(dev, MC2, 0x077c077c);
2500 saa7146_write(dev, GPIO_CTRL, 0x000000);
2501#if RPS_IRQ
2502 /* set event counter 1 source as RPS1 interrupt (0x03) (rE4 p53)
2503 * use 0x03 to track RPS1 interrupts - increase by 1 every gpio3 is toggled
2504 * use 0x15 to track VPE interrupts - increase by 1 every vpeirq() is called
2505 */
2506 saa7146_write(dev, EC1SSR, (0x03<<2) | 3 );
2507 /* set event counter 1 treshold to maximum allowed value (rEC p55) */
2508 saa7146_write(dev, ECT1R, 0x3fff );
2509#endif
2510 /* Setup BUDGETPATCH MAIN RPS1 "program" (p35) */
2511 count = 0;
2512
2513 /* Wait Source Line Counter Threshold (p36) */
2514 WRITE_RPS1(cpu_to_le32(CMD_PAUSE | EVT_HS));
2515 /* Set GPIO3=1 (p42) */
2516 WRITE_RPS1(cpu_to_le32(CMD_WR_REG_MASK | (GPIO_CTRL>>2)));
2517 WRITE_RPS1(cpu_to_le32(GPIO3_MSK));
2518 WRITE_RPS1(cpu_to_le32(SAA7146_GPIO_OUTHI<<24));
2519#if RPS_IRQ
2520 /* issue RPS1 interrupt */
2521 WRITE_RPS1(cpu_to_le32(CMD_INTERRUPT));
2522#endif
2523 /* Wait reset Source Line Counter Threshold (p36) */
2524 WRITE_RPS1(cpu_to_le32(CMD_PAUSE | RPS_INV | EVT_HS));
2525 /* Set GPIO3=0 (p42) */
2526 WRITE_RPS1(cpu_to_le32(CMD_WR_REG_MASK | (GPIO_CTRL>>2)));
2527 WRITE_RPS1(cpu_to_le32(GPIO3_MSK));
2528 WRITE_RPS1(cpu_to_le32(SAA7146_GPIO_OUTLO<<24));
2529#if RPS_IRQ
2530 /* issue RPS1 interrupt */
2531 WRITE_RPS1(cpu_to_le32(CMD_INTERRUPT));
2532#endif
2533 /* Jump to begin of RPS program (p37) */
2534 WRITE_RPS1(cpu_to_le32(CMD_JUMP));
2535 WRITE_RPS1(cpu_to_le32(dev->d_rps1.dma_handle));
2536
2537 /* Fix VSYNC level */
2538 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
2539 /* Set RPS1 Address register to point to RPS code (r108 p42) */
2540 saa7146_write(dev, RPS_ADDR1, dev->d_rps1.dma_handle);
2541 /* Set Source Line Counter Threshold, using BRS (rCC p43)
2542 * It generates HS event every TS_HEIGHT lines
2543 * this is related to TS_WIDTH set in register
2544 * NUM_LINE_BYTE3. If NUM_LINE_BYTE low 16 bits
2545 * are set to TS_WIDTH bytes (TS_WIDTH=2*188),
2546 * then RPS_THRESH1 should be set to trigger
2547 * every TS_HEIGHT (512) lines.
2548 */
2549 saa7146_write(dev, RPS_THRESH1, (TS_HEIGHT*1) | MASK_12 );
2550
2551 /* Enable RPS1 (rFC p33) */
2552 saa7146_write(dev, MC1, (MASK_13 | MASK_29));
2553
2554 /* end of budgetpatch register initialization */
2555 tasklet_init (&av7110->vpe_tasklet, vpeirq, (unsigned long) av7110);
2556 } else {
2557 saa7146_write(dev, PCI_BT_V1, 0x1c00101f);
2558 saa7146_write(dev, BCS_CTRL, 0x80400040);
2559
2560 /* set dd1 stream a & b */
2561 saa7146_write(dev, DD1_STREAM_B, 0x00000000);
2562 saa7146_write(dev, DD1_INIT, 0x03000000);
2563 saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
2564
2565 /* upload all */
2566 saa7146_write(dev, MC2, 0x077c077c);
2567 saa7146_write(dev, GPIO_CTRL, 0x000000);
2568 }
2569
2570 tasklet_init (&av7110->debi_tasklet, debiirq, (unsigned long) av7110);
2571 tasklet_init (&av7110->gpio_tasklet, gpioirq, (unsigned long) av7110);
2572
Ingo Molnar3593cab2006-02-07 06:49:14 -02002573 mutex_init(&av7110->pid_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002574
2575 /* locks for data transfers from/to AV7110 */
2576 spin_lock_init(&av7110->debilock);
Ingo Molnar3593cab2006-02-07 06:49:14 -02002577 mutex_init(&av7110->dcomlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002578 av7110->debitype = -1;
2579
2580 /* default OSD window */
2581 av7110->osdwin = 1;
Ingo Molnar3593cab2006-02-07 06:49:14 -02002582 mutex_init(&av7110->osd_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002583
C.Y.M2f03ee82006-03-30 04:31:48 -03002584 /* TV standard */
2585 av7110->vidmode = tv_standard == 1 ? VIDEO_MODE_NTSC : VIDEO_MODE_PAL;
2586
Linus Torvalds1da177e2005-04-16 15:20:36 -07002587 /* ARM "watchdog" */
2588 init_waitqueue_head(&av7110->arm_wait);
2589 av7110->arm_thread = NULL;
2590
2591 /* allocate and init buffers */
2592 av7110->debi_virt = pci_alloc_consistent(pdev, 8192, &av7110->debi_bus);
2593 if (!av7110->debi_virt)
2594 goto err_saa71466_vfree_4;
2595
2596
2597 av7110->iobuf = vmalloc(AVOUTLEN+AOUTLEN+BMPLEN+4*IPACKS);
2598 if (!av7110->iobuf)
2599 goto err_pci_free_5;
2600
2601 ret = av7110_av_init(av7110);
2602 if (ret < 0)
2603 goto err_iobuf_vfree_6;
2604
2605 /* init BMP buffer */
2606 av7110->bmpbuf = av7110->iobuf+AVOUTLEN+AOUTLEN;
2607 init_waitqueue_head(&av7110->bmpq);
2608
2609 ret = av7110_ca_init(av7110);
2610 if (ret < 0)
2611 goto err_av7110_av_exit_7;
2612
2613 /* load firmware into AV7110 cards */
2614 ret = av7110_bootarm(av7110);
2615 if (ret < 0)
2616 goto err_av7110_ca_exit_8;
2617
2618 ret = av7110_firmversion(av7110);
2619 if (ret < 0)
2620 goto err_stop_arm_9;
2621
2622 if (FW_VERSION(av7110->arm_app)<0x2501)
2623 printk ("dvb-ttpci: Warning, firmware version 0x%04x is too old. "
2624 "System might be unstable!\n", FW_VERSION(av7110->arm_app));
2625
2626 ret = kernel_thread(arm_thread, (void *) av7110, 0);
2627 if (ret < 0)
2628 goto err_stop_arm_9;
2629
2630 /* set initial volume in mixer struct */
2631 av7110->mixer.volume_left = volume;
2632 av7110->mixer.volume_right = volume;
2633
2634 init_av7110_av(av7110);
2635
2636 ret = av7110_register(av7110);
2637 if (ret < 0)
2638 goto err_arm_thread_stop_10;
2639
2640 /* special case DVB-C: these cards have an analog tuner
2641 plus need some special handling, so we have separate
2642 saa7146_ext_vv data for these... */
2643 ret = av7110_init_v4l(av7110);
2644 if (ret < 0)
2645 goto err_av7110_unregister_11;
2646
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07002647 av7110->dvb_adapter.priv = av7110;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002648 ret = frontend_init(av7110);
2649 if (ret < 0)
2650 goto err_av7110_exit_v4l_12;
2651
2652#if defined(CONFIG_INPUT_EVDEV) || defined(CONFIG_INPUT_EVDEV_MODULE)
Oliver Endriss03388ae2005-09-09 13:03:12 -07002653 av7110_ir_init(av7110);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002654#endif
2655 printk(KERN_INFO "dvb-ttpci: found av7110-%d.\n", av7110_num);
2656 av7110_num++;
2657out:
2658 return ret;
2659
2660err_av7110_exit_v4l_12:
2661 av7110_exit_v4l(av7110);
2662err_av7110_unregister_11:
2663 dvb_unregister(av7110);
2664err_arm_thread_stop_10:
2665 av7110_arm_sync(av7110);
2666err_stop_arm_9:
2667 /* Nothing to do. Rejoice. */
2668err_av7110_ca_exit_8:
2669 av7110_ca_exit(av7110);
2670err_av7110_av_exit_7:
2671 av7110_av_exit(av7110);
2672err_iobuf_vfree_6:
2673 vfree(av7110->iobuf);
2674err_pci_free_5:
2675 pci_free_consistent(pdev, 8192, av7110->debi_virt, av7110->debi_bus);
2676err_saa71466_vfree_4:
2677 if (!av7110->grabbing)
2678 saa7146_pgtable_free(pdev, &av7110->pt);
2679err_i2c_del_3:
2680 i2c_del_adapter(&av7110->i2c_adap);
2681err_dvb_unregister_adapter_2:
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07002682 dvb_unregister_adapter(&av7110->dvb_adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002683err_put_firmware_1:
2684 put_firmware(av7110);
2685err_kfree_0:
2686 kfree(av7110);
2687 goto out;
2688}
2689
Johannes Stezenbach1be11e32006-02-27 00:09:20 -03002690static int __devexit av7110_detach(struct saa7146_dev* saa)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002691{
2692 struct av7110 *av7110 = saa->ext_priv;
2693 dprintk(4, "%p\n", av7110);
2694
Oliver Endriss03388ae2005-09-09 13:03:12 -07002695#if defined(CONFIG_INPUT_EVDEV) || defined(CONFIG_INPUT_EVDEV_MODULE)
2696 av7110_ir_exit(av7110);
2697#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07002698 if (budgetpatch) {
2699 /* Disable RPS1 */
2700 saa7146_write(saa, MC1, MASK_29);
2701 /* VSYNC LOW (inactive) */
2702 saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);
2703 saa7146_write(saa, MC1, MASK_20); /* DMA3 off */
2704 SAA7146_IER_DISABLE(saa, MASK_10);
2705 SAA7146_ISR_CLEAR(saa, MASK_10);
2706 msleep(50);
2707 tasklet_kill(&av7110->vpe_tasklet);
2708 saa7146_pgtable_free(saa->pci, &av7110->pt);
2709 }
2710 av7110_exit_v4l(av7110);
2711
2712 av7110_arm_sync(av7110);
2713
2714 tasklet_kill(&av7110->debi_tasklet);
2715 tasklet_kill(&av7110->gpio_tasklet);
2716
2717 dvb_unregister(av7110);
2718
2719 SAA7146_IER_DISABLE(saa, MASK_19 | MASK_03);
2720 SAA7146_ISR_CLEAR(saa, MASK_19 | MASK_03);
2721
2722 av7110_ca_exit(av7110);
2723 av7110_av_exit(av7110);
2724
2725 vfree(av7110->iobuf);
2726 pci_free_consistent(saa->pci, 8192, av7110->debi_virt,
2727 av7110->debi_bus);
2728
2729 i2c_del_adapter(&av7110->i2c_adap);
2730
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07002731 dvb_unregister_adapter (&av7110->dvb_adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002732
2733 av7110_num--;
2734
2735 put_firmware(av7110);
2736
2737 kfree(av7110);
2738
2739 saa->ext_priv = NULL;
2740
2741 return 0;
2742}
2743
2744
2745static void av7110_irq(struct saa7146_dev* dev, u32 *isr)
2746{
2747 struct av7110 *av7110 = dev->ext_priv;
2748
2749 //print_time("av7110_irq");
2750
2751 /* Note: Don't try to handle the DEBI error irq (MASK_18), in
2752 * intel mode the timeout is asserted all the time...
2753 */
2754
2755 if (*isr & MASK_19) {
2756 //printk("av7110_irq: DEBI\n");
2757 /* Note 1: The DEBI irq is level triggered: We must enable it
2758 * only after we started a DMA xfer, and disable it here
2759 * immediately, or it will be signalled all the time while
2760 * DEBI is idle.
2761 * Note 2: You would think that an irq which is masked is
2762 * not signalled by the hardware. Not so for the SAA7146:
2763 * An irq is signalled as long as the corresponding bit
2764 * in the ISR is set, and disabling irqs just prevents the
2765 * hardware from setting the ISR bit. This means a) that we
2766 * must clear the ISR *after* disabling the irq (which is why
2767 * we must do it here even though saa7146_core did it already),
2768 * and b) that if we were to disable an edge triggered irq
2769 * (like the gpio irqs sadly are) temporarily we would likely
2770 * loose some. This sucks :-(
2771 */
2772 SAA7146_IER_DISABLE(av7110->dev, MASK_19);
2773 SAA7146_ISR_CLEAR(av7110->dev, MASK_19);
2774 tasklet_schedule(&av7110->debi_tasklet);
2775 }
2776
2777 if (*isr & MASK_03) {
2778 //printk("av7110_irq: GPIO\n");
2779 tasklet_schedule(&av7110->gpio_tasklet);
2780 }
2781
2782 if ((*isr & MASK_10) && budgetpatch)
2783 tasklet_schedule(&av7110->vpe_tasklet);
2784}
2785
2786
2787static struct saa7146_extension av7110_extension;
2788
2789#define MAKE_AV7110_INFO(x_var,x_name) \
2790static struct saa7146_pci_extension_data x_var = { \
2791 .ext_priv = x_name, \
2792 .ext = &av7110_extension }
2793
Karl Herz6af4ee12005-09-09 13:03:13 -07002794MAKE_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 -07002795MAKE_AV7110_INFO(ttt_1_X, "Technotrend/Hauppauge WinTV DVB-T rev1.X");
2796MAKE_AV7110_INFO(ttc_1_X, "Technotrend/Hauppauge WinTV Nexus-CA rev1.X");
2797MAKE_AV7110_INFO(ttc_2_X, "Technotrend/Hauppauge WinTV DVB-C rev2.X");
2798MAKE_AV7110_INFO(tts_2_X, "Technotrend/Hauppauge WinTV Nexus-S rev2.X");
Johannes Stezenbach3dfaebd2005-05-16 21:54:19 -07002799MAKE_AV7110_INFO(tts_2_3, "Technotrend/Hauppauge WinTV Nexus-S rev2.3");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002800MAKE_AV7110_INFO(tts_1_3se, "Technotrend/Hauppauge WinTV DVB-S rev1.3 SE");
2801MAKE_AV7110_INFO(ttt, "Technotrend/Hauppauge DVB-T");
2802MAKE_AV7110_INFO(fsc, "Fujitsu Siemens DVB-C");
2803MAKE_AV7110_INFO(fss, "Fujitsu Siemens DVB-S rev1.6");
Oliver Endriss8bd63012006-02-07 06:49:11 -02002804MAKE_AV7110_INFO(gxs_1_3, "Galaxis DVB-S rev1.3");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002805
2806static struct pci_device_id pci_tbl[] = {
Karl Herz6af4ee12005-09-09 13:03:13 -07002807 MAKE_EXTENSION_PCI(fsc, 0x110a, 0x0000),
2808 MAKE_EXTENSION_PCI(tts_1_X_fsc, 0x13c2, 0x0000),
2809 MAKE_EXTENSION_PCI(ttt_1_X, 0x13c2, 0x0001),
2810 MAKE_EXTENSION_PCI(ttc_2_X, 0x13c2, 0x0002),
2811 MAKE_EXTENSION_PCI(tts_2_X, 0x13c2, 0x0003),
Oliver Endriss8bd63012006-02-07 06:49:11 -02002812 MAKE_EXTENSION_PCI(gxs_1_3, 0x13c2, 0x0004),
Karl Herz6af4ee12005-09-09 13:03:13 -07002813 MAKE_EXTENSION_PCI(fss, 0x13c2, 0x0006),
2814 MAKE_EXTENSION_PCI(ttt, 0x13c2, 0x0008),
2815 MAKE_EXTENSION_PCI(ttc_1_X, 0x13c2, 0x000a),
2816 MAKE_EXTENSION_PCI(tts_2_3, 0x13c2, 0x000e),
2817 MAKE_EXTENSION_PCI(tts_1_3se, 0x13c2, 0x1002),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002818
Linus Torvalds1da177e2005-04-16 15:20:36 -07002819/* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0005), UNDEFINED CARD */ // Technisat SkyStar1
2820/* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0009), UNDEFINED CARD */ // TT/Hauppauge WinTV Nexus-CA v????
2821
2822 {
2823 .vendor = 0,
2824 }
2825};
2826
2827MODULE_DEVICE_TABLE(pci, pci_tbl);
2828
2829
2830static struct saa7146_extension av7110_extension = {
2831 .name = "dvb\0",
2832 .flags = SAA7146_I2C_SHORT_DELAY,
2833
2834 .module = THIS_MODULE,
2835 .pci_tbl = &pci_tbl[0],
2836 .attach = av7110_attach,
Johannes Stezenbach1be11e32006-02-27 00:09:20 -03002837 .detach = __devexit_p(av7110_detach),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002838
2839 .irq_mask = MASK_19 | MASK_03 | MASK_10,
2840 .irq_func = av7110_irq,
2841};
2842
2843
2844static int __init av7110_init(void)
2845{
2846 int retval;
2847 retval = saa7146_register_extension(&av7110_extension);
2848 return retval;
2849}
2850
2851
2852static void __exit av7110_exit(void)
2853{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002854 saa7146_unregister_extension(&av7110_extension);
2855}
2856
2857module_init(av7110_init);
2858module_exit(av7110_exit);
2859
2860MODULE_DESCRIPTION("driver for the SAA7146 based AV110 PCI DVB cards by "
2861 "Siemens, Technotrend, Hauppauge");
2862MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, others");
2863MODULE_LICENSE("GPL");