blob: 366c1371ee97dcf3e5eb41e8241fcc495a1aa5cc [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
Linus Torvalds1da177e2005-04-16 15:20:36 -070033#include <linux/module.h>
34#include <linux/kmod.h>
35#include <linux/delay.h>
36#include <linux/fs.h>
37#include <linux/timer.h>
38#include <linux/poll.h>
39#include <linux/byteorder/swabb.h>
40#include <linux/smp_lock.h>
41
42#include <linux/kernel.h>
43#include <linux/moduleparam.h>
44#include <linux/sched.h>
45#include <linux/types.h>
46#include <linux/fcntl.h>
47#include <linux/interrupt.h>
48#include <linux/string.h>
49#include <linux/pci.h>
50#include <linux/vmalloc.h>
51#include <linux/firmware.h>
52#include <linux/crc32.h>
53#include <linux/i2c.h>
54
55#include <asm/system.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070056
57#include <linux/dvb/frontend.h>
58
59#include "dvb_frontend.h"
60
61#include "ttpci-eeprom.h"
62#include "av7110.h"
63#include "av7110_hw.h"
64#include "av7110_av.h"
65#include "av7110_ca.h"
66#include "av7110_ipack.h"
67
Oliver Endrissdb5d91e2006-02-28 10:32:25 -030068#include "bsbe1.h"
69#include "lnbp21.h"
Perceval Anichini265366e2006-03-16 11:22:47 -030070#include "bsru6.h"
Oliver Endrissdb5d91e2006-02-28 10:32:25 -030071
Linus Torvalds1da177e2005-04-16 15:20:36 -070072#define TS_WIDTH 376
73#define TS_HEIGHT 512
74#define TS_BUFLEN (TS_WIDTH*TS_HEIGHT)
75#define TS_MAX_PACKETS (TS_BUFLEN/TS_SIZE)
76
77
78int av7110_debug;
79
80static int vidmode = CVBS_RGB_OUT;
81static int pids_off;
82static int adac = DVB_ADAC_TI;
83static int hw_sections;
84static int rgb_on;
85static int volume = 255;
Mauro Carvalho Chehaba5ed4252006-01-13 14:10:19 -020086static int budgetpatch;
Oliver Endriss4caba422006-03-17 05:29:15 -030087static int wss_cfg_4_3 = 0x4008;
88static int wss_cfg_16_9 = 0x0007;
C.Y.M2f03ee82006-03-30 04:31:48 -030089static int tv_standard;
Linus Torvalds1da177e2005-04-16 15:20:36 -070090
91module_param_named(debug, av7110_debug, int, 0644);
92MODULE_PARM_DESC(debug, "debug level (bitmask, default 0)");
93module_param(vidmode, int, 0444);
94MODULE_PARM_DESC(vidmode,"analog video out: 0 off, 1 CVBS+RGB (default), 2 CVBS+YC, 3 YC");
95module_param(pids_off, int, 0444);
96MODULE_PARM_DESC(pids_off,"clear video/audio/PCR PID filters when demux is closed");
97module_param(adac, int, 0444);
98MODULE_PARM_DESC(adac,"audio DAC type: 0 TI, 1 CRYSTAL, 2 MSP (use if autodetection fails)");
99module_param(hw_sections, int, 0444);
100MODULE_PARM_DESC(hw_sections, "0 use software section filter, 1 use hardware");
101module_param(rgb_on, int, 0444);
102MODULE_PARM_DESC(rgb_on, "For Siemens DVB-C cards only: Enable RGB control"
103 " signal on SCART pin 16 to switch SCART video mode from CVBS to RGB");
104module_param(volume, int, 0444);
105MODULE_PARM_DESC(volume, "initial volume: default 255 (range 0-255)");
106module_param(budgetpatch, int, 0444);
107MODULE_PARM_DESC(budgetpatch, "use budget-patch hardware modification: default 0 (0 no, 1 autodetect, 2 always)");
Oliver Endriss4caba422006-03-17 05:29:15 -0300108module_param(wss_cfg_4_3, int, 0444);
109MODULE_PARM_DESC(wss_cfg_4_3, "WSS 4:3 - default 0x4008 - bit 15: disable, 14: burst mode, 13..0: wss data");
110module_param(wss_cfg_16_9, int, 0444);
111MODULE_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 -0300112module_param(tv_standard, int, 0444);
113MODULE_PARM_DESC(tv_standard, "TV standard: 0 PAL (default), 1 NTSC");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114
115static void restart_feeds(struct av7110 *av7110);
116
Mauro Carvalho Chehaba5ed4252006-01-13 14:10:19 -0200117static int av7110_num;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118
119#define FE_FUNC_OVERRIDE(fe_func, av7110_copy, av7110_func) \
120{\
121 if (fe_func != NULL) { \
122 av7110_copy = fe_func; \
123 fe_func = av7110_func; \
124 } \
125}
126
127
128static void init_av7110_av(struct av7110 *av7110)
129{
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700130 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700131 struct saa7146_dev *dev = av7110->dev;
132
133 /* set internal volume control to maximum */
134 av7110->adac_type = DVB_ADAC_TI;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700135 ret = av7110_set_volume(av7110, av7110->mixer.volume_left, av7110->mixer.volume_right);
Johannes Stezenbach7a2fa902005-07-07 17:58:01 -0700136 if (ret < 0)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700137 printk("dvb-ttpci:cannot set internal volume to maximum:%d\n",ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700138
Oliver Endriss4caba422006-03-17 05:29:15 -0300139 ret = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetWSSConfig, 2, 2, wss_cfg_4_3);
140 if (ret < 0)
141 printk("dvb-ttpci: unable to configure 4:3 wss\n");
142 ret = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetWSSConfig, 2, 3, wss_cfg_16_9);
143 if (ret < 0)
144 printk("dvb-ttpci: unable to configure 16:9 wss\n");
145
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700146 ret = av7710_set_video_mode(av7110, vidmode);
Johannes Stezenbach7a2fa902005-07-07 17:58:01 -0700147 if (ret < 0)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700148 printk("dvb-ttpci:cannot set video mode:%d\n",ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700149
150 /* handle different card types */
151 /* remaining inits according to card and frontend type */
152 av7110->analog_tuner_flags = 0;
153 av7110->current_input = 0;
Tim Kaiser61391e02006-06-25 09:14:07 -0300154 if (dev->pci->subsystem_vendor == 0x13c2 && dev->pci->subsystem_device == 0x000a)
Marco Schluessler1c13b952006-01-09 15:25:06 -0200155 av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, ADSwitch, 1, 0); // SPDIF on
Tim Kaiser61391e02006-06-25 09:14:07 -0300156 if (i2c_writereg(av7110, 0x20, 0x00, 0x00) == 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700157 printk ("dvb-ttpci: Crystal audio DAC @ card %d detected\n",
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -0700158 av7110->dvb_adapter.num);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700159 av7110->adac_type = DVB_ADAC_CRYSTAL;
160 i2c_writereg(av7110, 0x20, 0x01, 0xd2);
161 i2c_writereg(av7110, 0x20, 0x02, 0x49);
162 i2c_writereg(av7110, 0x20, 0x03, 0x00);
163 i2c_writereg(av7110, 0x20, 0x04, 0x00);
164
165 /**
166 * some special handling for the Siemens DVB-C cards...
167 */
168 } else if (0 == av7110_init_analog_module(av7110)) {
169 /* done. */
170 }
171 else if (dev->pci->subsystem_vendor == 0x110a) {
172 printk("dvb-ttpci: DVB-C w/o analog module @ card %d detected\n",
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -0700173 av7110->dvb_adapter.num);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700174 av7110->adac_type = DVB_ADAC_NONE;
175 }
176 else {
177 av7110->adac_type = adac;
178 printk("dvb-ttpci: adac type set to %d @ card %d\n",
Marco Schluessler1c13b952006-01-09 15:25:06 -0200179 av7110->adac_type, av7110->dvb_adapter.num);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700180 }
181
Marco Schluessler1c13b952006-01-09 15:25:06 -0200182 if (av7110->adac_type == DVB_ADAC_NONE || av7110->adac_type == DVB_ADAC_MSP34x0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700183 // switch DVB SCART on
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700184 ret = av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, MainSwitch, 1, 0);
Johannes Stezenbach7a2fa902005-07-07 17:58:01 -0700185 if (ret < 0)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700186 printk("dvb-ttpci:cannot switch on SCART(Main):%d\n",ret);
187 ret = av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, ADSwitch, 1, 1);
Johannes Stezenbach7a2fa902005-07-07 17:58:01 -0700188 if (ret < 0)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700189 printk("dvb-ttpci:cannot switch on SCART(AD):%d\n",ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700190 if (rgb_on &&
Karl Herz6af4ee12005-09-09 13:03:13 -0700191 ((av7110->dev->pci->subsystem_vendor == 0x110a) ||
192 (av7110->dev->pci->subsystem_vendor == 0x13c2)) &&
193 (av7110->dev->pci->subsystem_device == 0x0000)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700194 saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); // RGB on, SCART pin 16
195 //saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); // SCARTpin 8
196 }
197 }
198
Oliver Endriss60edb132005-12-19 08:54:11 -0200199 if (dev->pci->subsystem_vendor == 0x13c2 && dev->pci->subsystem_device == 0x000e)
200 av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, SpdifSwitch, 1, 0); // SPDIF on
201
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700202 ret = av7110_set_volume(av7110, av7110->mixer.volume_left, av7110->mixer.volume_right);
Johannes Stezenbach7a2fa902005-07-07 17:58:01 -0700203 if (ret < 0)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700204 printk("dvb-ttpci:cannot set volume :%d\n",ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700205}
206
207static void recover_arm(struct av7110 *av7110)
208{
209 dprintk(4, "%p\n",av7110);
210
211 av7110_bootarm(av7110);
212 msleep(100);
Oliver Endriss66190a22006-01-09 15:32:42 -0200213
214 init_av7110_av(av7110);
215
216 /* card-specific recovery */
217 if (av7110->recover)
218 av7110->recover(av7110);
219
Linus Torvalds1da177e2005-04-16 15:20:36 -0700220 restart_feeds(av7110);
221 av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, SetIR, 1, av7110->ir_config);
222}
223
Linus Torvalds1da177e2005-04-16 15:20:36 -0700224static void av7110_arm_sync(struct av7110 *av7110)
225{
226 av7110->arm_rmmod = 1;
227 wake_up_interruptible(&av7110->arm_wait);
228
229 while (av7110->arm_thread)
230 msleep(1);
231}
232
233static int arm_thread(void *data)
234{
235 struct av7110 *av7110 = data;
236 u16 newloops = 0;
237 int timeout;
238
239 dprintk(4, "%p\n",av7110);
240
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -0800241 lock_kernel();
242 daemonize("arm_mon");
243 sigfillset(&current->blocked);
244 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700245
246 av7110->arm_thread = current;
247
248 for (;;) {
249 timeout = wait_event_interruptible_timeout(av7110->arm_wait,
250 av7110->arm_rmmod, 5 * HZ);
251 if (-ERESTARTSYS == timeout || av7110->arm_rmmod) {
252 /* got signal or told to quit*/
253 break;
254 }
255
256 if (!av7110->arm_ready)
257 continue;
258
Ingo Molnar3593cab2006-02-07 06:49:14 -0200259 if (mutex_lock_interruptible(&av7110->dcomlock))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700260 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261 newloops = rdebi(av7110, DEBINOSWAP, STATUS_LOOPS, 0, 2);
Ingo Molnar3593cab2006-02-07 06:49:14 -0200262 mutex_unlock(&av7110->dcomlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263
Oliver Endriss66190a22006-01-09 15:32:42 -0200264 if (newloops == av7110->arm_loops || av7110->arm_errors > 3) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700265 printk(KERN_ERR "dvb-ttpci: ARM crashed @ card %d\n",
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -0700266 av7110->dvb_adapter.num);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700267
Oliver Endriss66190a22006-01-09 15:32:42 -0200268 recover_arm(av7110);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269
Ingo Molnar3593cab2006-02-07 06:49:14 -0200270 if (mutex_lock_interruptible(&av7110->dcomlock))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700272 newloops = rdebi(av7110, DEBINOSWAP, STATUS_LOOPS, 0, 2) - 1;
Ingo Molnar3593cab2006-02-07 06:49:14 -0200273 mutex_unlock(&av7110->dcomlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700274 }
275 av7110->arm_loops = newloops;
Oliver Endriss66190a22006-01-09 15:32:42 -0200276 av7110->arm_errors = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700277 }
278
279 av7110->arm_thread = NULL;
280 return 0;
281}
282
283
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284/****************************************************************************
285 * IRQ handling
286 ****************************************************************************/
287
288static int DvbDmxFilterCallback(u8 *buffer1, size_t buffer1_len,
289 u8 *buffer2, size_t buffer2_len,
290 struct dvb_demux_filter *dvbdmxfilter,
291 enum dmx_success success,
292 struct av7110 *av7110)
293{
294 if (!dvbdmxfilter->feed->demux->dmx.frontend)
295 return 0;
296 if (dvbdmxfilter->feed->demux->dmx.frontend->source == DMX_MEMORY_FE)
297 return 0;
298
299 switch (dvbdmxfilter->type) {
300 case DMX_TYPE_SEC:
301 if ((((buffer1[1] << 8) | buffer1[2]) & 0xfff) + 3 != buffer1_len)
302 return 0;
303 if (dvbdmxfilter->doneq) {
304 struct dmx_section_filter *filter = &dvbdmxfilter->filter;
305 int i;
306 u8 xor, neq = 0;
307
308 for (i = 0; i < DVB_DEMUX_MASK_MAX; i++) {
309 xor = filter->filter_value[i] ^ buffer1[i];
310 neq |= dvbdmxfilter->maskandnotmode[i] & xor;
311 }
312 if (!neq)
313 return 0;
314 }
315 return dvbdmxfilter->feed->cb.sec(buffer1, buffer1_len,
316 buffer2, buffer2_len,
317 &dvbdmxfilter->filter,
318 DMX_OK);
319 case DMX_TYPE_TS:
320 if (!(dvbdmxfilter->feed->ts_type & TS_PACKET))
321 return 0;
322 if (dvbdmxfilter->feed->ts_type & TS_PAYLOAD_ONLY)
323 return dvbdmxfilter->feed->cb.ts(buffer1, buffer1_len,
324 buffer2, buffer2_len,
325 &dvbdmxfilter->feed->feed.ts,
326 DMX_OK);
327 else
328 av7110_p2t_write(buffer1, buffer1_len,
329 dvbdmxfilter->feed->pid,
330 &av7110->p2t_filter[dvbdmxfilter->index]);
331 default:
332 return 0;
333 }
334}
335
336
337//#define DEBUG_TIMING
338static inline void print_time(char *s)
339{
340#ifdef DEBUG_TIMING
341 struct timeval tv;
342 do_gettimeofday(&tv);
343 printk("%s: %d.%d\n", s, (int)tv.tv_sec, (int)tv.tv_usec);
344#endif
345}
346
347#define DEBI_READ 0
348#define DEBI_WRITE 1
349static inline void start_debi_dma(struct av7110 *av7110, int dir,
350 unsigned long addr, unsigned int len)
351{
352 dprintk(8, "%c %08lx %u\n", dir == DEBI_READ ? 'R' : 'W', addr, len);
353 if (saa7146_wait_for_debi_done(av7110->dev, 0)) {
354 printk(KERN_ERR "%s: saa7146_wait_for_debi_done timed out\n", __FUNCTION__);
355 return;
356 }
357
358 SAA7146_ISR_CLEAR(av7110->dev, MASK_19); /* for good measure */
359 SAA7146_IER_ENABLE(av7110->dev, MASK_19);
360 if (len < 5)
361 len = 5; /* we want a real DEBI DMA */
362 if (dir == DEBI_WRITE)
363 iwdebi(av7110, DEBISWAB, addr, 0, (len + 3) & ~3);
364 else
365 irdebi(av7110, DEBISWAB, addr, 0, len);
366}
367
368static void debiirq(unsigned long data)
369{
370 struct av7110 *av7110 = (struct av7110 *) data;
371 int type = av7110->debitype;
372 int handle = (type >> 8) & 0x1f;
373 unsigned int xfer = 0;
374
375 print_time("debi");
376 dprintk(4, "type 0x%04x\n", type);
377
378 if (type == -1) {
379 printk("DEBI irq oops @ %ld, psr:0x%08x, ssr:0x%08x\n",
380 jiffies, saa7146_read(av7110->dev, PSR),
381 saa7146_read(av7110->dev, SSR));
382 goto debi_done;
383 }
384 av7110->debitype = -1;
385
386 switch (type & 0xff) {
387
388 case DATA_TS_RECORD:
389 dvb_dmx_swfilter_packets(&av7110->demux,
390 (const u8 *) av7110->debi_virt,
391 av7110->debilen / 188);
392 xfer = RX_BUFF;
393 break;
394
395 case DATA_PES_RECORD:
396 if (av7110->demux.recording)
397 av7110_record_cb(&av7110->p2t[handle],
398 (u8 *) av7110->debi_virt,
399 av7110->debilen);
400 xfer = RX_BUFF;
401 break;
402
403 case DATA_IPMPE:
404 case DATA_FSECTION:
405 case DATA_PIPING:
406 if (av7110->handle2filter[handle])
407 DvbDmxFilterCallback((u8 *)av7110->debi_virt,
408 av7110->debilen, NULL, 0,
409 av7110->handle2filter[handle],
410 DMX_OK, av7110);
411 xfer = RX_BUFF;
412 break;
413
414 case DATA_CI_GET:
415 {
416 u8 *data = av7110->debi_virt;
417
418 if ((data[0] < 2) && data[2] == 0xff) {
419 int flags = 0;
420 if (data[5] > 0)
421 flags |= CA_CI_MODULE_PRESENT;
422 if (data[5] > 5)
423 flags |= CA_CI_MODULE_READY;
424 av7110->ci_slot[data[0]].flags = flags;
425 } else
426 ci_get_data(&av7110->ci_rbuffer,
427 av7110->debi_virt,
428 av7110->debilen);
429 xfer = RX_BUFF;
430 break;
431 }
432
433 case DATA_COMMON_INTERFACE:
434 CI_handle(av7110, (u8 *)av7110->debi_virt, av7110->debilen);
435#if 0
436 {
437 int i;
438
439 printk("av7110%d: ", av7110->num);
440 printk("%02x ", *(u8 *)av7110->debi_virt);
441 printk("%02x ", *(1+(u8 *)av7110->debi_virt));
442 for (i = 2; i < av7110->debilen; i++)
443 printk("%02x ", (*(i+(unsigned char *)av7110->debi_virt)));
444 for (i = 2; i < av7110->debilen; i++)
445 printk("%c", chtrans(*(i+(unsigned char *)av7110->debi_virt)));
446
447 printk("\n");
448 }
449#endif
450 xfer = RX_BUFF;
451 break;
452
453 case DATA_DEBUG_MESSAGE:
454 ((s8*)av7110->debi_virt)[Reserved_SIZE - 1] = 0;
455 printk("%s\n", (s8 *) av7110->debi_virt);
456 xfer = RX_BUFF;
457 break;
458
459 case DATA_CI_PUT:
460 dprintk(4, "debi DATA_CI_PUT\n");
461 case DATA_MPEG_PLAY:
462 dprintk(4, "debi DATA_MPEG_PLAY\n");
463 case DATA_BMP_LOAD:
464 dprintk(4, "debi DATA_BMP_LOAD\n");
465 xfer = TX_BUFF;
466 break;
467 default:
468 break;
469 }
470debi_done:
471 spin_lock(&av7110->debilock);
472 if (xfer)
473 iwdebi(av7110, DEBINOSWAP, xfer, 0, 2);
474 ARM_ClearMailBox(av7110);
475 spin_unlock(&av7110->debilock);
476}
477
478/* irq from av7110 firmware writing the mailbox register in the DPRAM */
479static void gpioirq(unsigned long data)
480{
481 struct av7110 *av7110 = (struct av7110 *) data;
482 u32 rxbuf, txbuf;
483 int len;
484
485 if (av7110->debitype != -1)
486 /* we shouldn't get any irq while a debi xfer is running */
487 printk("dvb-ttpci: GPIO0 irq oops @ %ld, psr:0x%08x, ssr:0x%08x\n",
488 jiffies, saa7146_read(av7110->dev, PSR),
489 saa7146_read(av7110->dev, SSR));
490
491 if (saa7146_wait_for_debi_done(av7110->dev, 0)) {
492 printk(KERN_ERR "%s: saa7146_wait_for_debi_done timed out\n", __FUNCTION__);
493 BUG(); /* maybe we should try resetting the debi? */
494 }
495
496 spin_lock(&av7110->debilock);
497 ARM_ClearIrq(av7110);
498
499 /* see what the av7110 wants */
500 av7110->debitype = irdebi(av7110, DEBINOSWAP, IRQ_STATE, 0, 2);
501 av7110->debilen = irdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
502 rxbuf = irdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
503 txbuf = irdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
504 len = (av7110->debilen + 3) & ~3;
505
506 print_time("gpio");
507 dprintk(8, "GPIO0 irq 0x%04x %d\n", av7110->debitype, av7110->debilen);
508
509 switch (av7110->debitype & 0xff) {
510
511 case DATA_TS_PLAY:
512 case DATA_PES_PLAY:
513 break;
514
515 case DATA_MPEG_VIDEO_EVENT:
516 {
517 u32 h_ar;
518 struct video_event event;
519
520 av7110->video_size.w = irdebi(av7110, DEBINOSWAP, STATUS_MPEG_WIDTH, 0, 2);
521 h_ar = irdebi(av7110, DEBINOSWAP, STATUS_MPEG_HEIGHT_AR, 0, 2);
522
523 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
524 iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
525
526 av7110->video_size.h = h_ar & 0xfff;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527
528 event.type = VIDEO_EVENT_SIZE_CHANGED;
529 event.u.size.w = av7110->video_size.w;
530 event.u.size.h = av7110->video_size.h;
531 switch ((h_ar >> 12) & 0xf)
532 {
533 case 3:
534 av7110->video_size.aspect_ratio = VIDEO_FORMAT_16_9;
535 event.u.size.aspect_ratio = VIDEO_FORMAT_16_9;
536 av7110->videostate.video_format = VIDEO_FORMAT_16_9;
537 break;
538 case 4:
539 av7110->video_size.aspect_ratio = VIDEO_FORMAT_221_1;
540 event.u.size.aspect_ratio = VIDEO_FORMAT_221_1;
541 av7110->videostate.video_format = VIDEO_FORMAT_221_1;
542 break;
543 default:
544 av7110->video_size.aspect_ratio = VIDEO_FORMAT_4_3;
545 event.u.size.aspect_ratio = VIDEO_FORMAT_4_3;
546 av7110->videostate.video_format = VIDEO_FORMAT_4_3;
547 }
Oliver Endriss66190a22006-01-09 15:32:42 -0200548
549 dprintk(8, "GPIO0 irq: DATA_MPEG_VIDEO_EVENT: w/h/ar = %u/%u/%u\n",
550 av7110->video_size.w, av7110->video_size.h,
551 av7110->video_size.aspect_ratio);
552
Linus Torvalds1da177e2005-04-16 15:20:36 -0700553 dvb_video_add_event(av7110, &event);
554 break;
555 }
556
557 case DATA_CI_PUT:
558 {
559 int avail;
560 struct dvb_ringbuffer *cibuf = &av7110->ci_wbuffer;
561
562 avail = dvb_ringbuffer_avail(cibuf);
563 if (avail <= 2) {
564 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
565 iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
566 iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
567 break;
568 }
569 len = DVB_RINGBUFFER_PEEK(cibuf, 0) << 8;
570 len |= DVB_RINGBUFFER_PEEK(cibuf, 1);
571 if (avail < len + 2) {
572 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
573 iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
574 iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
575 break;
576 }
577 DVB_RINGBUFFER_SKIP(cibuf, 2);
578
579 dvb_ringbuffer_read(cibuf, av7110->debi_virt, len, 0);
580
581 iwdebi(av7110, DEBINOSWAP, TX_LEN, len, 2);
582 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, len, 2);
583 dprintk(8, "DMA: CI\n");
584 start_debi_dma(av7110, DEBI_WRITE, DPRAM_BASE + txbuf, len);
585 spin_unlock(&av7110->debilock);
586 wake_up(&cibuf->queue);
587 return;
588 }
589
590 case DATA_MPEG_PLAY:
591 if (!av7110->playing) {
592 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
593 iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
594 iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
595 break;
596 }
597 len = 0;
598 if (av7110->debitype & 0x100) {
599 spin_lock(&av7110->aout.lock);
600 len = av7110_pes_play(av7110->debi_virt, &av7110->aout, 2048);
601 spin_unlock(&av7110->aout.lock);
602 }
603 if (len <= 0 && (av7110->debitype & 0x200)
604 &&av7110->videostate.play_state != VIDEO_FREEZED) {
605 spin_lock(&av7110->avout.lock);
606 len = av7110_pes_play(av7110->debi_virt, &av7110->avout, 2048);
607 spin_unlock(&av7110->avout.lock);
608 }
609 if (len <= 0) {
610 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
611 iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
612 iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
613 break;
614 }
615 dprintk(8, "GPIO0 PES_PLAY len=%04x\n", len);
616 iwdebi(av7110, DEBINOSWAP, TX_LEN, len, 2);
617 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, len, 2);
618 dprintk(8, "DMA: MPEG_PLAY\n");
619 start_debi_dma(av7110, DEBI_WRITE, DPRAM_BASE + txbuf, len);
620 spin_unlock(&av7110->debilock);
621 return;
622
623 case DATA_BMP_LOAD:
624 len = av7110->debilen;
625 dprintk(8, "gpio DATA_BMP_LOAD len %d\n", len);
626 if (!len) {
627 av7110->bmp_state = BMP_LOADED;
628 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
629 iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
630 iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
631 wake_up(&av7110->bmpq);
632 dprintk(8, "gpio DATA_BMP_LOAD done\n");
633 break;
634 }
635 if (len > av7110->bmplen)
636 len = av7110->bmplen;
637 if (len > 2 * 1024)
638 len = 2 * 1024;
639 iwdebi(av7110, DEBINOSWAP, TX_LEN, len, 2);
640 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, len, 2);
641 memcpy(av7110->debi_virt, av7110->bmpbuf+av7110->bmpp, len);
642 av7110->bmpp += len;
643 av7110->bmplen -= len;
644 dprintk(8, "gpio DATA_BMP_LOAD DMA len %d\n", len);
645 start_debi_dma(av7110, DEBI_WRITE, DPRAM_BASE+txbuf, len);
646 spin_unlock(&av7110->debilock);
647 return;
648
649 case DATA_CI_GET:
650 case DATA_COMMON_INTERFACE:
651 case DATA_FSECTION:
652 case DATA_IPMPE:
653 case DATA_PIPING:
654 if (!len || len > 4 * 1024) {
655 iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
656 break;
657 }
658 /* fall through */
659
660 case DATA_TS_RECORD:
661 case DATA_PES_RECORD:
662 dprintk(8, "DMA: TS_REC etc.\n");
663 start_debi_dma(av7110, DEBI_READ, DPRAM_BASE+rxbuf, len);
664 spin_unlock(&av7110->debilock);
665 return;
666
667 case DATA_DEBUG_MESSAGE:
668 if (!len || len > 0xff) {
669 iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
670 break;
671 }
672 start_debi_dma(av7110, DEBI_READ, Reserved, len);
673 spin_unlock(&av7110->debilock);
674 return;
675
676 case DATA_IRCOMMAND:
Oliver Endriss03388ae2005-09-09 13:03:12 -0700677 if (av7110->ir_handler)
678 av7110->ir_handler(av7110,
679 swahw32(irdebi(av7110, DEBINOSWAP, Reserved, 0, 4)));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700680 iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
681 break;
682
683 default:
684 printk("dvb-ttpci: gpioirq unknown type=%d len=%d\n",
685 av7110->debitype, av7110->debilen);
686 break;
687 }
688 av7110->debitype = -1;
689 ARM_ClearMailBox(av7110);
690 spin_unlock(&av7110->debilock);
691}
692
693
694#ifdef CONFIG_DVB_AV7110_OSD
695static int dvb_osd_ioctl(struct inode *inode, struct file *file,
696 unsigned int cmd, void *parg)
697{
698 struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
699 struct av7110 *av7110 = (struct av7110 *) dvbdev->priv;
700
701 dprintk(4, "%p\n", av7110);
702
703 if (cmd == OSD_SEND_CMD)
704 return av7110_osd_cmd(av7110, (osd_cmd_t *) parg);
705 if (cmd == OSD_GET_CAPABILITY)
706 return av7110_osd_capability(av7110, (osd_cap_t *) parg);
707
708 return -EINVAL;
709}
710
711
712static struct file_operations dvb_osd_fops = {
713 .owner = THIS_MODULE,
714 .ioctl = dvb_generic_ioctl,
715 .open = dvb_generic_open,
716 .release = dvb_generic_release,
717};
718
719static struct dvb_device dvbdev_osd = {
720 .priv = NULL,
721 .users = 1,
722 .writers = 1,
723 .fops = &dvb_osd_fops,
724 .kernel_ioctl = dvb_osd_ioctl,
725};
726#endif /* CONFIG_DVB_AV7110_OSD */
727
728
729static inline int SetPIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid,
730 u16 subpid, u16 pcrpid)
731{
Dr. Werner Fink47f36922006-01-09 15:25:07 -0200732 u16 aflags = 0;
733
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734 dprintk(4, "%p\n", av7110);
735
736 if (vpid == 0x1fff || apid == 0x1fff ||
737 ttpid == 0x1fff || subpid == 0x1fff || pcrpid == 0x1fff) {
738 vpid = apid = ttpid = subpid = pcrpid = 0;
739 av7110->pids[DMX_PES_VIDEO] = 0;
740 av7110->pids[DMX_PES_AUDIO] = 0;
741 av7110->pids[DMX_PES_TELETEXT] = 0;
742 av7110->pids[DMX_PES_PCR] = 0;
743 }
744
Dr. Werner Fink47f36922006-01-09 15:25:07 -0200745 if (av7110->audiostate.bypass_mode)
746 aflags |= 0x8000;
747
748 return av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, MultiPID, 6,
749 pcrpid, vpid, apid, ttpid, subpid, aflags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700750}
751
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700752int ChangePIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700753 u16 subpid, u16 pcrpid)
754{
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700755 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700756 dprintk(4, "%p\n", av7110);
757
Ingo Molnar3593cab2006-02-07 06:49:14 -0200758 if (mutex_lock_interruptible(&av7110->pid_mutex))
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700759 return -ERESTARTSYS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700760
761 if (!(vpid & 0x8000))
762 av7110->pids[DMX_PES_VIDEO] = vpid;
763 if (!(apid & 0x8000))
764 av7110->pids[DMX_PES_AUDIO] = apid;
765 if (!(ttpid & 0x8000))
766 av7110->pids[DMX_PES_TELETEXT] = ttpid;
767 if (!(pcrpid & 0x8000))
768 av7110->pids[DMX_PES_PCR] = pcrpid;
769
770 av7110->pids[DMX_PES_SUBTITLE] = 0;
771
772 if (av7110->fe_synced) {
773 pcrpid = av7110->pids[DMX_PES_PCR];
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700774 ret = SetPIDs(av7110, vpid, apid, ttpid, subpid, pcrpid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700775 }
776
Ingo Molnar3593cab2006-02-07 06:49:14 -0200777 mutex_unlock(&av7110->pid_mutex);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700778 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700779}
780
781
782/******************************************************************************
783 * hardware filter functions
784 ******************************************************************************/
785
786static int StartHWFilter(struct dvb_demux_filter *dvbdmxfilter)
787{
788 struct dvb_demux_feed *dvbdmxfeed = dvbdmxfilter->feed;
789 struct av7110 *av7110 = (struct av7110 *) dvbdmxfeed->demux->priv;
790 u16 buf[20];
791 int ret, i;
792 u16 handle;
793// u16 mode = 0x0320;
794 u16 mode = 0xb96a;
795
796 dprintk(4, "%p\n", av7110);
797
798 if (dvbdmxfilter->type == DMX_TYPE_SEC) {
799 if (hw_sections) {
800 buf[4] = (dvbdmxfilter->filter.filter_value[0] << 8) |
801 dvbdmxfilter->maskandmode[0];
802 for (i = 3; i < 18; i++)
803 buf[i + 4 - 2] =
804 (dvbdmxfilter->filter.filter_value[i] << 8) |
805 dvbdmxfilter->maskandmode[i];
806 mode = 4;
807 }
808 } else if ((dvbdmxfeed->ts_type & TS_PACKET) &&
809 !(dvbdmxfeed->ts_type & TS_PAYLOAD_ONLY)) {
810 av7110_p2t_init(&av7110->p2t_filter[dvbdmxfilter->index], dvbdmxfeed);
811 }
812
813 buf[0] = (COMTYPE_PID_FILTER << 8) + AddPIDFilter;
814 buf[1] = 16;
815 buf[2] = dvbdmxfeed->pid;
816 buf[3] = mode;
817
818 ret = av7110_fw_request(av7110, buf, 20, &handle, 1);
819 if (ret != 0 || handle >= 32) {
820 printk("dvb-ttpci: %s error buf %04x %04x %04x %04x "
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700821 "ret %d handle %04x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700822 __FUNCTION__, buf[0], buf[1], buf[2], buf[3],
823 ret, handle);
824 dvbdmxfilter->hw_handle = 0xffff;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700825 if (!ret)
826 ret = -1;
827 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700828 }
829
830 av7110->handle2filter[handle] = dvbdmxfilter;
831 dvbdmxfilter->hw_handle = handle;
832
833 return ret;
834}
835
836static int StopHWFilter(struct dvb_demux_filter *dvbdmxfilter)
837{
838 struct av7110 *av7110 = (struct av7110 *) dvbdmxfilter->feed->demux->priv;
839 u16 buf[3];
840 u16 answ[2];
841 int ret;
842 u16 handle;
843
844 dprintk(4, "%p\n", av7110);
845
846 handle = dvbdmxfilter->hw_handle;
847 if (handle >= 32) {
848 printk("%s tried to stop invalid filter %04x, filter type = %x\n",
849 __FUNCTION__, handle, dvbdmxfilter->type);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700850 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700851 }
852
853 av7110->handle2filter[handle] = NULL;
854
855 buf[0] = (COMTYPE_PID_FILTER << 8) + DelPIDFilter;
856 buf[1] = 1;
857 buf[2] = handle;
858 ret = av7110_fw_request(av7110, buf, 3, answ, 2);
859 if (ret != 0 || answ[1] != handle) {
860 printk("dvb-ttpci: %s error cmd %04x %04x %04x ret %x "
861 "resp %04x %04x pid %d\n",
862 __FUNCTION__, buf[0], buf[1], buf[2], ret,
863 answ[0], answ[1], dvbdmxfilter->feed->pid);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700864 if (!ret)
865 ret = -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700866 }
867 return ret;
868}
869
870
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700871static int dvb_feed_start_pid(struct dvb_demux_feed *dvbdmxfeed)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700872{
873 struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
874 struct av7110 *av7110 = (struct av7110 *) dvbdmx->priv;
875 u16 *pid = dvbdmx->pids, npids[5];
876 int i;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700877 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700878
879 dprintk(4, "%p\n", av7110);
880
881 npids[0] = npids[1] = npids[2] = npids[3] = npids[4] = 0xffff;
882 i = dvbdmxfeed->pes_type;
883 npids[i] = (pid[i]&0x8000) ? 0 : pid[i];
884 if ((i == 2) && npids[i] && (dvbdmxfeed->ts_type & TS_PACKET)) {
885 npids[i] = 0;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700886 ret = ChangePIDs(av7110, npids[1], npids[0], npids[2], npids[3], npids[4]);
887 if (!ret)
888 ret = StartHWFilter(dvbdmxfeed->filter);
889 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700890 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700891 if (dvbdmxfeed->pes_type <= 2 || dvbdmxfeed->pes_type == 4) {
892 ret = ChangePIDs(av7110, npids[1], npids[0], npids[2], npids[3], npids[4]);
893 if (ret)
894 return ret;
895 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700896
897 if (dvbdmxfeed->pes_type < 2 && npids[0])
898 if (av7110->fe_synced)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700899 {
900 ret = av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, Scan, 0);
901 if (ret)
902 return ret;
903 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904
905 if ((dvbdmxfeed->ts_type & TS_PACKET)) {
906 if (dvbdmxfeed->pes_type == 0 && !(dvbdmx->pids[0] & 0x8000))
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700907 ret = av7110_av_start_record(av7110, RP_AUDIO, dvbdmxfeed);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908 if (dvbdmxfeed->pes_type == 1 && !(dvbdmx->pids[1] & 0x8000))
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700909 ret = av7110_av_start_record(av7110, RP_VIDEO, dvbdmxfeed);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700910 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700911 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912}
913
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700914static int dvb_feed_stop_pid(struct dvb_demux_feed *dvbdmxfeed)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700915{
916 struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
917 struct av7110 *av7110 = (struct av7110 *) dvbdmx->priv;
918 u16 *pid = dvbdmx->pids, npids[5];
919 int i;
920
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700921 int ret = 0;
922
Linus Torvalds1da177e2005-04-16 15:20:36 -0700923 dprintk(4, "%p\n", av7110);
924
925 if (dvbdmxfeed->pes_type <= 1) {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700926 ret = av7110_av_stop(av7110, dvbdmxfeed->pes_type ? RP_VIDEO : RP_AUDIO);
927 if (ret)
928 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700929 if (!av7110->rec_mode)
930 dvbdmx->recording = 0;
931 if (!av7110->playing)
932 dvbdmx->playing = 0;
933 }
934 npids[0] = npids[1] = npids[2] = npids[3] = npids[4] = 0xffff;
935 i = dvbdmxfeed->pes_type;
936 switch (i) {
937 case 2: //teletext
938 if (dvbdmxfeed->ts_type & TS_PACKET)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700939 ret = StopHWFilter(dvbdmxfeed->filter);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700940 npids[2] = 0;
941 break;
942 case 0:
943 case 1:
944 case 4:
945 if (!pids_off)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700946 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700947 npids[i] = (pid[i]&0x8000) ? 0 : pid[i];
948 break;
949 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700950 if (!ret)
951 ret = ChangePIDs(av7110, npids[1], npids[0], npids[2], npids[3], npids[4]);
952 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700953}
954
955static int av7110_start_feed(struct dvb_demux_feed *feed)
956{
957 struct dvb_demux *demux = feed->demux;
958 struct av7110 *av7110 = demux->priv;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700959 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700960
961 dprintk(4, "%p\n", av7110);
962
963 if (!demux->dmx.frontend)
964 return -EINVAL;
965
966 if (feed->pid > 0x1fff)
967 return -EINVAL;
968
969 if (feed->type == DMX_TYPE_TS) {
970 if ((feed->ts_type & TS_DECODER) &&
971 (feed->pes_type < DMX_TS_PES_OTHER)) {
972 switch (demux->dmx.frontend->source) {
973 case DMX_MEMORY_FE:
974 if (feed->ts_type & TS_DECODER)
975 if (feed->pes_type < 2 &&
976 !(demux->pids[0] & 0x8000) &&
977 !(demux->pids[1] & 0x8000)) {
978 dvb_ringbuffer_flush_spinlock_wakeup(&av7110->avout);
979 dvb_ringbuffer_flush_spinlock_wakeup(&av7110->aout);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700980 ret = av7110_av_start_play(av7110,RP_AV);
981 if (!ret)
982 demux->playing = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700983 }
984 break;
985 default:
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700986 ret = dvb_feed_start_pid(feed);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700987 break;
988 }
989 } else if ((feed->ts_type & TS_PACKET) &&
990 (demux->dmx.frontend->source != DMX_MEMORY_FE)) {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700991 ret = StartHWFilter(feed->filter);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700992 }
993 }
994
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700995 else if (feed->type == DMX_TYPE_SEC) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700996 int i;
997
998 for (i = 0; i < demux->filternum; i++) {
999 if (demux->filter[i].state != DMX_STATE_READY)
1000 continue;
1001 if (demux->filter[i].type != DMX_TYPE_SEC)
1002 continue;
1003 if (demux->filter[i].filter.parent != &feed->feed.sec)
1004 continue;
1005 demux->filter[i].state = DMX_STATE_GO;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001006 if (demux->dmx.frontend->source != DMX_MEMORY_FE) {
1007 ret = StartHWFilter(&demux->filter[i]);
1008 if (ret)
1009 break;
1010 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001011 }
1012 }
1013
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001014 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001015}
1016
1017
1018static int av7110_stop_feed(struct dvb_demux_feed *feed)
1019{
1020 struct dvb_demux *demux = feed->demux;
1021 struct av7110 *av7110 = demux->priv;
Johannes Stezenbach12ba0502005-07-07 17:58:00 -07001022 int i, rc, ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001023 dprintk(4, "%p\n", av7110);
1024
1025 if (feed->type == DMX_TYPE_TS) {
1026 if (feed->ts_type & TS_DECODER) {
1027 if (feed->pes_type >= DMX_TS_PES_OTHER ||
1028 !demux->pesfilter[feed->pes_type])
1029 return -EINVAL;
1030 demux->pids[feed->pes_type] |= 0x8000;
1031 demux->pesfilter[feed->pes_type] = NULL;
1032 }
1033 if (feed->ts_type & TS_DECODER &&
1034 feed->pes_type < DMX_TS_PES_OTHER) {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001035 ret = dvb_feed_stop_pid(feed);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001036 } else
1037 if ((feed->ts_type & TS_PACKET) &&
1038 (demux->dmx.frontend->source != DMX_MEMORY_FE))
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001039 ret = StopHWFilter(feed->filter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001040 }
1041
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001042 if (!ret && feed->type == DMX_TYPE_SEC) {
Johannes Stezenbach12ba0502005-07-07 17:58:00 -07001043 for (i = 0; i<demux->filternum; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001044 if (demux->filter[i].state == DMX_STATE_GO &&
1045 demux->filter[i].filter.parent == &feed->feed.sec) {
1046 demux->filter[i].state = DMX_STATE_READY;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001047 if (demux->dmx.frontend->source != DMX_MEMORY_FE) {
Johannes Stezenbach12ba0502005-07-07 17:58:00 -07001048 rc = StopHWFilter(&demux->filter[i]);
1049 if (!ret)
1050 ret = rc;
1051 /* keep going, stop as many filters as possible */
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001052 }
Johannes Stezenbach12ba0502005-07-07 17:58:00 -07001053 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001054 }
1055 }
1056
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001057 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058}
1059
1060
1061static void restart_feeds(struct av7110 *av7110)
1062{
1063 struct dvb_demux *dvbdmx = &av7110->demux;
1064 struct dvb_demux_feed *feed;
1065 int mode;
Oliver Endriss66190a22006-01-09 15:32:42 -02001066 int i, j;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067
1068 dprintk(4, "%p\n", av7110);
1069
1070 mode = av7110->playing;
1071 av7110->playing = 0;
1072 av7110->rec_mode = 0;
1073
Oliver Endriss66190a22006-01-09 15:32:42 -02001074 for (i = 0; i < dvbdmx->feednum; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001075 feed = &dvbdmx->feed[i];
Oliver Endriss66190a22006-01-09 15:32:42 -02001076 if (feed->state == DMX_STATE_GO) {
1077 if (feed->type == DMX_TYPE_SEC) {
1078 for (j = 0; j < dvbdmx->filternum; j++) {
1079 if (dvbdmx->filter[j].type != DMX_TYPE_SEC)
1080 continue;
1081 if (dvbdmx->filter[j].filter.parent != &feed->feed.sec)
1082 continue;
1083 if (dvbdmx->filter[j].state == DMX_STATE_GO)
1084 dvbdmx->filter[j].state = DMX_STATE_READY;
1085 }
1086 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001087 av7110_start_feed(feed);
Oliver Endriss66190a22006-01-09 15:32:42 -02001088 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089 }
1090
1091 if (mode)
1092 av7110_av_start_play(av7110, mode);
1093}
1094
1095static int dvb_get_stc(struct dmx_demux *demux, unsigned int num,
1096 uint64_t *stc, unsigned int *base)
1097{
1098 int ret;
1099 u16 fwstc[4];
1100 u16 tag = ((COMTYPE_REQUEST << 8) + ReqSTC);
1101 struct dvb_demux *dvbdemux;
1102 struct av7110 *av7110;
1103
1104 /* pointer casting paranoia... */
Eric Sesterhennae246012006-03-13 13:17:11 -03001105 BUG_ON(!demux);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001106 dvbdemux = (struct dvb_demux *) demux->priv;
Eric Sesterhennae246012006-03-13 13:17:11 -03001107 BUG_ON(!dvbdemux);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001108 av7110 = (struct av7110 *) dvbdemux->priv;
1109
1110 dprintk(4, "%p\n", av7110);
1111
1112 if (num != 0)
1113 return -EINVAL;
1114
1115 ret = av7110_fw_request(av7110, &tag, 0, fwstc, 4);
1116 if (ret) {
1117 printk(KERN_ERR "%s: av7110_fw_request error\n", __FUNCTION__);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001118 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001119 }
1120 dprintk(2, "fwstc = %04hx %04hx %04hx %04hx\n",
1121 fwstc[0], fwstc[1], fwstc[2], fwstc[3]);
1122
1123 *stc = (((uint64_t) ((fwstc[3] & 0x8000) >> 15)) << 32) |
1124 (((uint64_t) fwstc[1]) << 16) | ((uint64_t) fwstc[0]);
1125 *base = 1;
1126
1127 dprintk(4, "stc = %lu\n", (unsigned long)*stc);
1128
1129 return 0;
1130}
1131
1132
1133/******************************************************************************
1134 * SEC device file operations
1135 ******************************************************************************/
1136
1137
1138static int av7110_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
1139{
1140 struct av7110* av7110 = (struct av7110*) fe->dvb->priv;
1141
1142 switch (tone) {
1143 case SEC_TONE_ON:
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001144 return Set22K(av7110, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001145
1146 case SEC_TONE_OFF:
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001147 return Set22K(av7110, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001148
1149 default:
1150 return -EINVAL;
1151 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001152}
1153
1154static int av7110_diseqc_send_master_cmd(struct dvb_frontend* fe,
1155 struct dvb_diseqc_master_cmd* cmd)
1156{
1157 struct av7110* av7110 = fe->dvb->priv;
1158
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001159 return av7110_diseqc_send(av7110, cmd->msg_len, cmd->msg, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001160}
1161
1162static int av7110_diseqc_send_burst(struct dvb_frontend* fe,
1163 fe_sec_mini_cmd_t minicmd)
1164{
1165 struct av7110* av7110 = fe->dvb->priv;
1166
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001167 return av7110_diseqc_send(av7110, 0, NULL, minicmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001168}
1169
1170/* simplified code from budget-core.c */
1171static int stop_ts_capture(struct av7110 *budget)
1172{
1173 dprintk(2, "budget: %p\n", budget);
1174
1175 if (--budget->feeding1)
1176 return budget->feeding1;
1177 saa7146_write(budget->dev, MC1, MASK_20); /* DMA3 off */
1178 SAA7146_IER_DISABLE(budget->dev, MASK_10);
1179 SAA7146_ISR_CLEAR(budget->dev, MASK_10);
1180 return 0;
1181}
1182
1183static int start_ts_capture(struct av7110 *budget)
1184{
1185 dprintk(2, "budget: %p\n", budget);
1186
1187 if (budget->feeding1)
1188 return ++budget->feeding1;
1189 memset(budget->grabbing, 0x00, TS_HEIGHT * TS_WIDTH);
1190 budget->tsf = 0xff;
1191 budget->ttbp = 0;
1192 SAA7146_IER_ENABLE(budget->dev, MASK_10); /* VPE */
1193 saa7146_write(budget->dev, MC1, (MASK_04 | MASK_20)); /* DMA3 on */
1194 return ++budget->feeding1;
1195}
1196
1197static int budget_start_feed(struct dvb_demux_feed *feed)
1198{
1199 struct dvb_demux *demux = feed->demux;
1200 struct av7110 *budget = (struct av7110 *) demux->priv;
1201 int status;
1202
1203 dprintk(2, "av7110: %p\n", budget);
1204
1205 spin_lock(&budget->feedlock1);
1206 feed->pusi_seen = 0; /* have a clean section start */
1207 status = start_ts_capture(budget);
1208 spin_unlock(&budget->feedlock1);
1209 return status;
1210}
1211
1212static int budget_stop_feed(struct dvb_demux_feed *feed)
1213{
1214 struct dvb_demux *demux = feed->demux;
1215 struct av7110 *budget = (struct av7110 *) demux->priv;
1216 int status;
1217
1218 dprintk(2, "budget: %p\n", budget);
1219
1220 spin_lock(&budget->feedlock1);
1221 status = stop_ts_capture(budget);
1222 spin_unlock(&budget->feedlock1);
1223 return status;
1224}
1225
1226static void vpeirq(unsigned long data)
1227{
1228 struct av7110 *budget = (struct av7110 *) data;
1229 u8 *mem = (u8 *) (budget->grabbing);
1230 u32 olddma = budget->ttbp;
1231 u32 newdma = saa7146_read(budget->dev, PCI_VDP3);
1232
1233 if (!budgetpatch) {
1234 printk("av7110.c: vpeirq() called while budgetpatch disabled!"
1235 " check saa7146 IER register\n");
1236 BUG();
1237 }
1238 /* nearest lower position divisible by 188 */
1239 newdma -= newdma % 188;
1240
1241 if (newdma >= TS_BUFLEN)
1242 return;
1243
1244 budget->ttbp = newdma;
1245
1246 if (!budget->feeding1 || (newdma == olddma))
1247 return;
1248
1249#if 0
1250 /* track rps1 activity */
1251 printk("vpeirq: %02x Event Counter 1 0x%04x\n",
1252 mem[olddma],
1253 saa7146_read(budget->dev, EC1R) & 0x3fff);
1254#endif
1255
1256 if (newdma > olddma)
1257 /* no wraparound, dump olddma..newdma */
1258 dvb_dmx_swfilter_packets(&budget->demux1, mem + olddma, (newdma - olddma) / 188);
1259 else {
1260 /* wraparound, dump olddma..buflen and 0..newdma */
1261 dvb_dmx_swfilter_packets(&budget->demux1, mem + olddma, (TS_BUFLEN - olddma) / 188);
1262 dvb_dmx_swfilter_packets(&budget->demux1, mem, newdma / 188);
1263 }
1264}
1265
1266static int av7110_register(struct av7110 *av7110)
1267{
1268 int ret, i;
1269 struct dvb_demux *dvbdemux = &av7110->demux;
1270 struct dvb_demux *dvbdemux1 = &av7110->demux1;
1271
1272 dprintk(4, "%p\n", av7110);
1273
1274 if (av7110->registered)
1275 return -1;
1276
1277 av7110->registered = 1;
1278
1279 dvbdemux->priv = (void *) av7110;
1280
1281 for (i = 0; i < 32; i++)
1282 av7110->handle2filter[i] = NULL;
1283
1284 dvbdemux->filternum = 32;
1285 dvbdemux->feednum = 32;
1286 dvbdemux->start_feed = av7110_start_feed;
1287 dvbdemux->stop_feed = av7110_stop_feed;
1288 dvbdemux->write_to_decoder = av7110_write_to_decoder;
1289 dvbdemux->dmx.capabilities = (DMX_TS_FILTERING | DMX_SECTION_FILTERING |
1290 DMX_MEMORY_BASED_FILTERING);
1291
1292 dvb_dmx_init(&av7110->demux);
1293 av7110->demux.dmx.get_stc = dvb_get_stc;
1294
1295 av7110->dmxdev.filternum = 32;
1296 av7110->dmxdev.demux = &dvbdemux->dmx;
1297 av7110->dmxdev.capabilities = 0;
1298
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001299 dvb_dmxdev_init(&av7110->dmxdev, &av7110->dvb_adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001300
1301 av7110->hw_frontend.source = DMX_FRONTEND_0;
1302
1303 ret = dvbdemux->dmx.add_frontend(&dvbdemux->dmx, &av7110->hw_frontend);
1304
1305 if (ret < 0)
1306 return ret;
1307
1308 av7110->mem_frontend.source = DMX_MEMORY_FE;
1309
1310 ret = dvbdemux->dmx.add_frontend(&dvbdemux->dmx, &av7110->mem_frontend);
1311
1312 if (ret < 0)
1313 return ret;
1314
1315 ret = dvbdemux->dmx.connect_frontend(&dvbdemux->dmx,
1316 &av7110->hw_frontend);
1317 if (ret < 0)
1318 return ret;
1319
1320 av7110_av_register(av7110);
1321 av7110_ca_register(av7110);
1322
1323#ifdef CONFIG_DVB_AV7110_OSD
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001324 dvb_register_device(&av7110->dvb_adapter, &av7110->osd_dev,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001325 &dvbdev_osd, av7110, DVB_DEVICE_OSD);
1326#endif
1327
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001328 dvb_net_init(&av7110->dvb_adapter, &av7110->dvb_net, &dvbdemux->dmx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001329
1330 if (budgetpatch) {
1331 /* initialize software demux1 without its own frontend
1332 * demux1 hardware is connected to frontend0 of demux0
1333 */
1334 dvbdemux1->priv = (void *) av7110;
1335
1336 dvbdemux1->filternum = 256;
1337 dvbdemux1->feednum = 256;
1338 dvbdemux1->start_feed = budget_start_feed;
1339 dvbdemux1->stop_feed = budget_stop_feed;
1340 dvbdemux1->write_to_decoder = NULL;
1341
1342 dvbdemux1->dmx.capabilities = (DMX_TS_FILTERING | DMX_SECTION_FILTERING |
1343 DMX_MEMORY_BASED_FILTERING);
1344
1345 dvb_dmx_init(&av7110->demux1);
1346
1347 av7110->dmxdev1.filternum = 256;
1348 av7110->dmxdev1.demux = &dvbdemux1->dmx;
1349 av7110->dmxdev1.capabilities = 0;
1350
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001351 dvb_dmxdev_init(&av7110->dmxdev1, &av7110->dvb_adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001352
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001353 dvb_net_init(&av7110->dvb_adapter, &av7110->dvb_net1, &dvbdemux1->dmx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001354 printk("dvb-ttpci: additional demux1 for budget-patch registered\n");
1355 }
1356 return 0;
1357}
1358
1359
1360static void dvb_unregister(struct av7110 *av7110)
1361{
1362 struct dvb_demux *dvbdemux = &av7110->demux;
1363 struct dvb_demux *dvbdemux1 = &av7110->demux1;
1364
1365 dprintk(4, "%p\n", av7110);
1366
1367 if (!av7110->registered)
1368 return;
1369
1370 if (budgetpatch) {
1371 dvb_net_release(&av7110->dvb_net1);
1372 dvbdemux->dmx.close(&dvbdemux1->dmx);
1373 dvb_dmxdev_release(&av7110->dmxdev1);
1374 dvb_dmx_release(&av7110->demux1);
1375 }
1376
1377 dvb_net_release(&av7110->dvb_net);
1378
1379 dvbdemux->dmx.close(&dvbdemux->dmx);
1380 dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &av7110->hw_frontend);
1381 dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &av7110->mem_frontend);
1382
1383 dvb_dmxdev_release(&av7110->dmxdev);
1384 dvb_dmx_release(&av7110->demux);
1385
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001386 if (av7110->fe != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001387 dvb_unregister_frontend(av7110->fe);
Andrew de Quinceyf52a8382006-08-08 09:10:09 -03001388 dvb_frontend_detach(av7110->fe);
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001389 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001390 dvb_unregister_device(av7110->osd_dev);
1391 av7110_av_unregister(av7110);
1392 av7110_ca_unregister(av7110);
1393}
1394
1395
1396/****************************************************************************
1397 * I2C client commands
1398 ****************************************************************************/
1399
1400int i2c_writereg(struct av7110 *av7110, u8 id, u8 reg, u8 val)
1401{
1402 u8 msg[2] = { reg, val };
1403 struct i2c_msg msgs;
1404
1405 msgs.flags = 0;
1406 msgs.addr = id / 2;
1407 msgs.len = 2;
1408 msgs.buf = msg;
1409 return i2c_transfer(&av7110->i2c_adap, &msgs, 1);
1410}
1411
1412#if 0
1413u8 i2c_readreg(struct av7110 *av7110, u8 id, u8 reg)
1414{
1415 u8 mm1[] = {0x00};
1416 u8 mm2[] = {0x00};
1417 struct i2c_msg msgs[2];
1418
1419 msgs[0].flags = 0;
1420 msgs[1].flags = I2C_M_RD;
1421 msgs[0].addr = msgs[1].addr = id / 2;
1422 mm1[0] = reg;
1423 msgs[0].len = 1; msgs[1].len = 1;
1424 msgs[0].buf = mm1; msgs[1].buf = mm2;
1425 i2c_transfer(&av7110->i2c_adap, msgs, 2);
1426
1427 return mm2[0];
1428}
1429#endif
1430
1431/****************************************************************************
1432 * INITIALIZATION
1433 ****************************************************************************/
1434
1435
1436static int check_firmware(struct av7110* av7110)
1437{
1438 u32 crc = 0, len = 0;
1439 unsigned char *ptr;
1440
1441 /* check for firmware magic */
1442 ptr = av7110->bin_fw;
1443 if (ptr[0] != 'A' || ptr[1] != 'V' ||
1444 ptr[2] != 'F' || ptr[3] != 'W') {
1445 printk("dvb-ttpci: this is not an av7110 firmware\n");
1446 return -EINVAL;
1447 }
1448 ptr += 4;
1449
1450 /* check dpram file */
1451 crc = ntohl(*(u32*) ptr);
1452 ptr += 4;
1453 len = ntohl(*(u32*) ptr);
1454 ptr += 4;
1455 if (len >= 512) {
Alexey Dobriyanbe787ac2006-03-07 22:20:23 -03001456 printk("dvb-ttpci: dpram file is way too big.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001457 return -EINVAL;
1458 }
1459 if (crc != crc32_le(0, ptr, len)) {
1460 printk("dvb-ttpci: crc32 of dpram file does not match.\n");
1461 return -EINVAL;
1462 }
1463 av7110->bin_dpram = ptr;
1464 av7110->size_dpram = len;
1465 ptr += len;
1466
1467 /* check root file */
1468 crc = ntohl(*(u32*) ptr);
1469 ptr += 4;
1470 len = ntohl(*(u32*) ptr);
1471 ptr += 4;
1472
1473 if (len <= 200000 || len >= 300000 ||
1474 len > ((av7110->bin_fw + av7110->size_fw) - ptr)) {
1475 printk("dvb-ttpci: root file has strange size (%d). aborting.\n", len);
1476 return -EINVAL;
1477 }
1478 if( crc != crc32_le(0, ptr, len)) {
1479 printk("dvb-ttpci: crc32 of root file does not match.\n");
1480 return -EINVAL;
1481 }
1482 av7110->bin_root = ptr;
1483 av7110->size_root = len;
1484 return 0;
1485}
1486
1487#ifdef CONFIG_DVB_AV7110_FIRMWARE_FILE
1488#include "av7110_firm.h"
1489static void put_firmware(struct av7110* av7110)
1490{
1491 av7110->bin_fw = NULL;
1492}
1493
1494static inline int get_firmware(struct av7110* av7110)
1495{
1496 av7110->bin_fw = dvb_ttpci_fw;
1497 av7110->size_fw = sizeof(dvb_ttpci_fw);
1498 return check_firmware(av7110);
1499}
1500#else
1501static void put_firmware(struct av7110* av7110)
1502{
1503 vfree(av7110->bin_fw);
1504}
1505
1506static int get_firmware(struct av7110* av7110)
1507{
1508 int ret;
1509 const struct firmware *fw;
1510
1511 /* request the av7110 firmware, this will block until someone uploads it */
1512 ret = request_firmware(&fw, "dvb-ttpci-01.fw", &av7110->dev->pci->dev);
1513 if (ret) {
1514 if (ret == -ENOENT) {
1515 printk(KERN_ERR "dvb-ttpci: could not load firmware,"
1516 " file not found: dvb-ttpci-01.fw\n");
Ville Skytt\ä12e66f62006-01-09 15:25:38 -02001517 printk(KERN_ERR "dvb-ttpci: usually this should be in "
1518 "/usr/lib/hotplug/firmware or /lib/firmware\n");
1519 printk(KERN_ERR "dvb-ttpci: and can be downloaded from"
Linus Torvalds1da177e2005-04-16 15:20:36 -07001520 " http://www.linuxtv.org/download/dvb/firmware/\n");
1521 } else
1522 printk(KERN_ERR "dvb-ttpci: cannot request firmware"
1523 " (error %i)\n", ret);
1524 return -EINVAL;
1525 }
1526
1527 if (fw->size <= 200000) {
1528 printk("dvb-ttpci: this firmware is way too small.\n");
1529 release_firmware(fw);
1530 return -EINVAL;
1531 }
1532
1533 /* check if the firmware is available */
1534 av7110->bin_fw = (unsigned char *) vmalloc(fw->size);
1535 if (NULL == av7110->bin_fw) {
1536 dprintk(1, "out of memory\n");
1537 release_firmware(fw);
1538 return -ENOMEM;
1539 }
1540
1541 memcpy(av7110->bin_fw, fw->data, fw->size);
1542 av7110->size_fw = fw->size;
1543 if ((ret = check_firmware(av7110)))
1544 vfree(av7110->bin_fw);
1545
1546 release_firmware(fw);
1547 return ret;
1548}
1549#endif
1550
1551
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001552static int alps_bsrv2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001553{
1554 struct av7110* av7110 = (struct av7110*) fe->dvb->priv;
1555 u8 pwr = 0;
1556 u8 buf[4];
1557 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
1558 u32 div = (params->frequency + 479500) / 125;
1559
1560 if (params->frequency > 2000000) pwr = 3;
1561 else if (params->frequency > 1800000) pwr = 2;
1562 else if (params->frequency > 1600000) pwr = 1;
1563 else if (params->frequency > 1200000) pwr = 0;
1564 else if (params->frequency >= 1100000) pwr = 1;
1565 else pwr = 2;
1566
1567 buf[0] = (div >> 8) & 0x7f;
1568 buf[1] = div & 0xff;
1569 buf[2] = ((div & 0x18000) >> 10) | 0x95;
1570 buf[3] = (pwr << 6) | 0x30;
1571
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -08001572 // NOTE: since we're using a prescaler of 2, we set the
Linus Torvalds1da177e2005-04-16 15:20:36 -07001573 // divisor frequency to 62.5kHz and divide by 125 above
1574
Patrick Boettcherdea74862006-05-14 05:01:31 -03001575 if (fe->ops.i2c_gate_ctrl)
1576 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001577 if (i2c_transfer (&av7110->i2c_adap, &msg, 1) != 1)
1578 return -EIO;
1579 return 0;
1580}
1581
1582static struct ves1x93_config alps_bsrv2_config = {
1583 .demod_address = 0x08,
1584 .xin = 90100000UL,
1585 .invert_pwm = 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001586};
1587
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001588static int alps_tdbe2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001589{
1590 struct av7110* av7110 = fe->dvb->priv;
1591 u32 div;
1592 u8 data[4];
1593 struct i2c_msg msg = { .addr = 0x62, .flags = 0, .buf = data, .len = sizeof(data) };
1594
1595 div = (params->frequency + 35937500 + 31250) / 62500;
1596
1597 data[0] = (div >> 8) & 0x7f;
1598 data[1] = div & 0xff;
1599 data[2] = 0x85 | ((div >> 10) & 0x60);
1600 data[3] = (params->frequency < 174000000 ? 0x88 : params->frequency < 470000000 ? 0x84 : 0x81);
1601
Patrick Boettcherdea74862006-05-14 05:01:31 -03001602 if (fe->ops.i2c_gate_ctrl)
1603 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001604 if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
1605 return -EIO;
1606 return 0;
1607}
1608
1609static struct ves1820_config alps_tdbe2_config = {
1610 .demod_address = 0x09,
1611 .xin = 57840000UL,
1612 .invert = 1,
1613 .selagc = VES1820_SELAGC_SIGNAMPERR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001614};
1615
1616
1617
1618
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001619static int grundig_29504_451_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001620{
1621 struct av7110* av7110 = fe->dvb->priv;
1622 u32 div;
1623 u8 data[4];
1624 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
1625
1626 div = params->frequency / 125;
1627 data[0] = (div >> 8) & 0x7f;
1628 data[1] = div & 0xff;
1629 data[2] = 0x8e;
1630 data[3] = 0x00;
1631
Patrick Boettcherdea74862006-05-14 05:01:31 -03001632 if (fe->ops.i2c_gate_ctrl)
1633 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001634 if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
1635 return -EIO;
1636 return 0;
1637}
1638
1639static struct tda8083_config grundig_29504_451_config = {
1640 .demod_address = 0x68,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001641};
1642
1643
1644
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001645static int philips_cd1516_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001646{
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -08001647 struct av7110* av7110 = fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001648 u32 div;
1649 u32 f = params->frequency;
1650 u8 data[4];
1651 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
1652
1653 div = (f + 36125000 + 31250) / 62500;
1654
1655 data[0] = (div >> 8) & 0x7f;
1656 data[1] = div & 0xff;
1657 data[2] = 0x8e;
1658 data[3] = (f < 174000000 ? 0xa1 : f < 470000000 ? 0x92 : 0x34);
1659
Patrick Boettcherdea74862006-05-14 05:01:31 -03001660 if (fe->ops.i2c_gate_ctrl)
1661 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001662 if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
1663 return -EIO;
1664 return 0;
1665}
1666
1667static struct ves1820_config philips_cd1516_config = {
1668 .demod_address = 0x09,
1669 .xin = 57840000UL,
1670 .invert = 1,
1671 .selagc = VES1820_SELAGC_SIGNAMPERR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001672};
1673
1674
1675
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001676static int alps_tdlb7_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001677{
1678 struct av7110* av7110 = fe->dvb->priv;
1679 u32 div, pwr;
1680 u8 data[4];
1681 struct i2c_msg msg = { .addr = 0x60, .flags = 0, .buf = data, .len = sizeof(data) };
1682
1683 div = (params->frequency + 36200000) / 166666;
1684
1685 if (params->frequency <= 782000000)
1686 pwr = 1;
1687 else
1688 pwr = 2;
1689
1690 data[0] = (div >> 8) & 0x7f;
1691 data[1] = div & 0xff;
1692 data[2] = 0x85;
1693 data[3] = pwr << 6;
1694
Patrick Boettcherdea74862006-05-14 05:01:31 -03001695 if (fe->ops.i2c_gate_ctrl)
1696 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001697 if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
1698 return -EIO;
1699 return 0;
1700}
1701
1702static int alps_tdlb7_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name)
1703{
Oliver Endrissd98821e2006-09-14 00:15:13 -03001704#if defined(CONFIG_DVB_SP8870) || defined(CONFIG_DVB_SP8870_MODULE)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001705 struct av7110* av7110 = (struct av7110*) fe->dvb->priv;
1706
1707 return request_firmware(fw, name, &av7110->dev->pci->dev);
Oliver Endrissd98821e2006-09-14 00:15:13 -03001708#else
1709 return -EINVAL;
1710#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001711}
1712
1713static struct sp8870_config alps_tdlb7_config = {
1714
1715 .demod_address = 0x71,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001716 .request_firmware = alps_tdlb7_request_firmware,
1717};
1718
1719
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001720static u8 nexusca_stv0297_inittab[] = {
1721 0x80, 0x01,
1722 0x80, 0x00,
1723 0x81, 0x01,
1724 0x81, 0x00,
1725 0x00, 0x09,
1726 0x01, 0x69,
1727 0x03, 0x00,
1728 0x04, 0x00,
1729 0x07, 0x00,
1730 0x08, 0x00,
1731 0x20, 0x00,
1732 0x21, 0x40,
1733 0x22, 0x00,
1734 0x23, 0x00,
1735 0x24, 0x40,
1736 0x25, 0x88,
1737 0x30, 0xff,
1738 0x31, 0x00,
1739 0x32, 0xff,
1740 0x33, 0x00,
1741 0x34, 0x50,
1742 0x35, 0x7f,
1743 0x36, 0x00,
1744 0x37, 0x20,
1745 0x38, 0x00,
1746 0x40, 0x1c,
1747 0x41, 0xff,
1748 0x42, 0x29,
1749 0x43, 0x00,
1750 0x44, 0xff,
1751 0x45, 0x00,
1752 0x46, 0x00,
1753 0x49, 0x04,
1754 0x4a, 0x00,
1755 0x4b, 0x7b,
1756 0x52, 0x30,
1757 0x55, 0xae,
1758 0x56, 0x47,
1759 0x57, 0xe1,
1760 0x58, 0x3a,
1761 0x5a, 0x1e,
1762 0x5b, 0x34,
1763 0x60, 0x00,
1764 0x63, 0x00,
1765 0x64, 0x00,
1766 0x65, 0x00,
1767 0x66, 0x00,
1768 0x67, 0x00,
1769 0x68, 0x00,
1770 0x69, 0x00,
1771 0x6a, 0x02,
1772 0x6b, 0x00,
1773 0x70, 0xff,
1774 0x71, 0x00,
1775 0x72, 0x00,
1776 0x73, 0x00,
1777 0x74, 0x0c,
1778 0x80, 0x00,
1779 0x81, 0x00,
1780 0x82, 0x00,
1781 0x83, 0x00,
1782 0x84, 0x04,
1783 0x85, 0x80,
1784 0x86, 0x24,
1785 0x87, 0x78,
1786 0x88, 0x10,
1787 0x89, 0x00,
1788 0x90, 0x01,
1789 0x91, 0x01,
1790 0xa0, 0x04,
1791 0xa1, 0x00,
1792 0xa2, 0x00,
1793 0xb0, 0x91,
1794 0xb1, 0x0b,
1795 0xc0, 0x53,
1796 0xc1, 0x70,
1797 0xc2, 0x12,
1798 0xd0, 0x00,
1799 0xd1, 0x00,
1800 0xd2, 0x00,
1801 0xd3, 0x00,
1802 0xd4, 0x00,
1803 0xd5, 0x00,
1804 0xde, 0x00,
1805 0xdf, 0x00,
1806 0x61, 0x49,
1807 0x62, 0x0b,
1808 0x53, 0x08,
1809 0x59, 0x08,
1810 0xff, 0xff,
1811};
Linus Torvalds1da177e2005-04-16 15:20:36 -07001812
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001813static int nexusca_stv0297_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001814{
1815 struct av7110* av7110 = fe->dvb->priv;
1816 u32 div;
1817 u8 data[4];
1818 struct i2c_msg msg = { .addr = 0x63, .flags = 0, .buf = data, .len = sizeof(data) };
1819 struct i2c_msg readmsg = { .addr = 0x63, .flags = I2C_M_RD, .buf = data, .len = 1 };
1820 int i;
1821
1822 div = (params->frequency + 36150000 + 31250) / 62500;
1823
1824 data[0] = (div >> 8) & 0x7f;
1825 data[1] = div & 0xff;
1826 data[2] = 0xce;
1827
1828 if (params->frequency < 45000000)
1829 return -EINVAL;
1830 else if (params->frequency < 137000000)
1831 data[3] = 0x01;
1832 else if (params->frequency < 403000000)
1833 data[3] = 0x02;
1834 else if (params->frequency < 860000000)
1835 data[3] = 0x04;
1836 else
1837 return -EINVAL;
1838
Patrick Boettcherdea74862006-05-14 05:01:31 -03001839 if (fe->ops.i2c_gate_ctrl)
1840 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001841 if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1) {
1842 printk("nexusca: pll transfer failed!\n");
1843 return -EIO;
1844 }
1845
1846 // wait for PLL lock
1847 for(i = 0; i < 20; i++) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001848 if (fe->ops.i2c_gate_ctrl)
1849 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001850 if (i2c_transfer(&av7110->i2c_adap, &readmsg, 1) == 1)
1851 if (data[0] & 0x40) break;
1852 msleep(10);
1853 }
1854
1855 return 0;
1856}
1857
1858static struct stv0297_config nexusca_stv0297_config = {
1859
1860 .demod_address = 0x1C,
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001861 .inittab = nexusca_stv0297_inittab,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001862 .invert = 1,
Thomas Kaiserb8d4c232006-04-27 21:45:20 -03001863 .stop_during_read = 1,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001864};
1865
1866
1867
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001868static int grundig_29504_401_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001869{
1870 struct av7110* av7110 = (struct av7110*) fe->dvb->priv;
1871 u32 div;
1872 u8 cfg, cpump, band_select;
1873 u8 data[4];
1874 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
1875
1876 div = (36125000 + params->frequency) / 166666;
1877
1878 cfg = 0x88;
1879
1880 if (params->frequency < 175000000) cpump = 2;
1881 else if (params->frequency < 390000000) cpump = 1;
1882 else if (params->frequency < 470000000) cpump = 2;
1883 else if (params->frequency < 750000000) cpump = 1;
1884 else cpump = 3;
1885
1886 if (params->frequency < 175000000) band_select = 0x0e;
1887 else if (params->frequency < 470000000) band_select = 0x05;
1888 else band_select = 0x03;
1889
1890 data[0] = (div >> 8) & 0x7f;
1891 data[1] = div & 0xff;
1892 data[2] = ((div >> 10) & 0x60) | cfg;
1893 data[3] = (cpump << 6) | band_select;
1894
Patrick Boettcherdea74862006-05-14 05:01:31 -03001895 if (fe->ops.i2c_gate_ctrl)
1896 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001897 if (i2c_transfer (&av7110->i2c_adap, &msg, 1) != 1) return -EIO;
1898 return 0;
1899}
1900
1901static struct l64781_config grundig_29504_401_config = {
1902 .demod_address = 0x55,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001903};
1904
1905
1906
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001907static int av7110_fe_lock_fix(struct av7110* av7110, fe_status_t status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001908{
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001909 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001910 int synced = (status & FE_HAS_LOCK) ? 1 : 0;
1911
1912 av7110->fe_status = status;
1913
1914 if (av7110->fe_synced == synced)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001915 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001916
Linus Torvalds1da177e2005-04-16 15:20:36 -07001917 if (av7110->playing)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001918 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001919
Ingo Molnar3593cab2006-02-07 06:49:14 -02001920 if (mutex_lock_interruptible(&av7110->pid_mutex))
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001921 return -ERESTARTSYS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001922
Oliver Endriss34612152005-07-07 17:58:02 -07001923 if (synced) {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001924 ret = SetPIDs(av7110, av7110->pids[DMX_PES_VIDEO],
Linus Torvalds1da177e2005-04-16 15:20:36 -07001925 av7110->pids[DMX_PES_AUDIO],
1926 av7110->pids[DMX_PES_TELETEXT], 0,
1927 av7110->pids[DMX_PES_PCR]);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001928 if (!ret)
1929 ret = av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, Scan, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001930 } else {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001931 ret = SetPIDs(av7110, 0, 0, 0, 0, 0);
1932 if (!ret) {
1933 ret = av7110_fw_cmd(av7110, COMTYPE_PID_FILTER, FlushTSQueue, 0);
1934 if (!ret)
1935 ret = av7110_wait_msgstate(av7110, GPMQBusy);
1936 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001937 }
1938
Oliver Endriss34612152005-07-07 17:58:02 -07001939 if (!ret)
1940 av7110->fe_synced = synced;
1941
Ingo Molnar3593cab2006-02-07 06:49:14 -02001942 mutex_unlock(&av7110->pid_mutex);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001943 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001944}
1945
1946static int av7110_fe_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
1947{
1948 struct av7110* av7110 = fe->dvb->priv;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001949
1950 int ret = av7110_fe_lock_fix(av7110, 0);
Oliver Endriss66190a22006-01-09 15:32:42 -02001951 if (!ret) {
1952 av7110->saved_fe_params = *params;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001953 ret = av7110->fe_set_frontend(fe, params);
Oliver Endriss66190a22006-01-09 15:32:42 -02001954 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001955 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001956}
1957
1958static int av7110_fe_init(struct dvb_frontend* fe)
1959{
1960 struct av7110* av7110 = fe->dvb->priv;
1961
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001962 int ret = av7110_fe_lock_fix(av7110, 0);
1963 if (!ret)
1964 ret = av7110->fe_init(fe);
1965 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001966}
1967
1968static int av7110_fe_read_status(struct dvb_frontend* fe, fe_status_t* status)
1969{
1970 struct av7110* av7110 = fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001971
1972 /* call the real implementation */
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001973 int ret = av7110->fe_read_status(fe, status);
1974 if (!ret)
1975 if (((*status ^ av7110->fe_status) & FE_HAS_LOCK) && (*status & FE_HAS_LOCK))
1976 ret = av7110_fe_lock_fix(av7110, *status);
1977 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001978}
1979
1980static int av7110_fe_diseqc_reset_overload(struct dvb_frontend* fe)
1981{
1982 struct av7110* av7110 = fe->dvb->priv;
1983
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001984 int ret = av7110_fe_lock_fix(av7110, 0);
1985 if (!ret)
1986 ret = av7110->fe_diseqc_reset_overload(fe);
1987 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001988}
1989
1990static int av7110_fe_diseqc_send_master_cmd(struct dvb_frontend* fe,
1991 struct dvb_diseqc_master_cmd* cmd)
1992{
1993 struct av7110* av7110 = fe->dvb->priv;
1994
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001995 int ret = av7110_fe_lock_fix(av7110, 0);
Oliver Endriss66190a22006-01-09 15:32:42 -02001996 if (!ret) {
1997 av7110->saved_master_cmd = *cmd;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001998 ret = av7110->fe_diseqc_send_master_cmd(fe, cmd);
Oliver Endriss66190a22006-01-09 15:32:42 -02001999 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002000 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002001}
2002
2003static int av7110_fe_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd)
2004{
2005 struct av7110* av7110 = fe->dvb->priv;
2006
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002007 int ret = av7110_fe_lock_fix(av7110, 0);
Oliver Endriss66190a22006-01-09 15:32:42 -02002008 if (!ret) {
2009 av7110->saved_minicmd = minicmd;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002010 ret = av7110->fe_diseqc_send_burst(fe, minicmd);
Oliver Endriss66190a22006-01-09 15:32:42 -02002011 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002012 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002013}
2014
2015static int av7110_fe_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
2016{
2017 struct av7110* av7110 = fe->dvb->priv;
2018
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002019 int ret = av7110_fe_lock_fix(av7110, 0);
Oliver Endriss66190a22006-01-09 15:32:42 -02002020 if (!ret) {
2021 av7110->saved_tone = tone;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002022 ret = av7110->fe_set_tone(fe, tone);
Oliver Endriss66190a22006-01-09 15:32:42 -02002023 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002024 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002025}
2026
2027static int av7110_fe_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
2028{
2029 struct av7110* av7110 = fe->dvb->priv;
2030
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002031 int ret = av7110_fe_lock_fix(av7110, 0);
Oliver Endriss66190a22006-01-09 15:32:42 -02002032 if (!ret) {
2033 av7110->saved_voltage = voltage;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002034 ret = av7110->fe_set_voltage(fe, voltage);
Oliver Endriss66190a22006-01-09 15:32:42 -02002035 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002036 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002037}
2038
Peter Beutner400b7082006-01-09 15:32:43 -02002039static int av7110_fe_dishnetwork_send_legacy_command(struct dvb_frontend* fe, unsigned long cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002040{
2041 struct av7110* av7110 = fe->dvb->priv;
2042
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002043 int ret = av7110_fe_lock_fix(av7110, 0);
2044 if (!ret)
2045 ret = av7110->fe_dishnetwork_send_legacy_command(fe, cmd);
2046 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002047}
2048
Oliver Endriss66190a22006-01-09 15:32:42 -02002049static void dvb_s_recover(struct av7110* av7110)
2050{
2051 av7110_fe_init(av7110->fe);
2052
2053 av7110_fe_set_voltage(av7110->fe, av7110->saved_voltage);
2054 if (av7110->saved_master_cmd.msg_len) {
2055 msleep(20);
2056 av7110_fe_diseqc_send_master_cmd(av7110->fe, &av7110->saved_master_cmd);
2057 }
2058 msleep(20);
2059 av7110_fe_diseqc_send_burst(av7110->fe, av7110->saved_minicmd);
2060 msleep(20);
2061 av7110_fe_set_tone(av7110->fe, av7110->saved_tone);
2062
2063 av7110_fe_set_frontend(av7110->fe, &av7110->saved_fe_params);
2064}
2065
Linus Torvalds1da177e2005-04-16 15:20:36 -07002066static u8 read_pwm(struct av7110* av7110)
2067{
2068 u8 b = 0xff;
2069 u8 pwm;
2070 struct i2c_msg msg[] = { { .addr = 0x50,.flags = 0,.buf = &b,.len = 1 },
2071 { .addr = 0x50,.flags = I2C_M_RD,.buf = &pwm,.len = 1} };
2072
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -08002073 if ((i2c_transfer(&av7110->i2c_adap, msg, 2) != 2) || (pwm == 0xff))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002074 pwm = 0x48;
2075
2076 return pwm;
2077}
2078
2079static int frontend_init(struct av7110 *av7110)
2080{
2081 int ret;
2082
2083 if (av7110->dev->pci->subsystem_vendor == 0x110a) {
2084 switch(av7110->dev->pci->subsystem_device) {
2085 case 0x0000: // Fujitsu/Siemens DVB-Cable (ves1820/Philips CD1516(??))
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002086 av7110->fe = dvb_attach(ves1820_attach, &philips_cd1516_config,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002087 &av7110->i2c_adap, read_pwm(av7110));
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002088 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002089 av7110->fe->ops.tuner_ops.set_params = philips_cd1516_tuner_set_params;
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002090 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002091 break;
2092 }
2093
2094 } else if (av7110->dev->pci->subsystem_vendor == 0x13c2) {
2095 switch(av7110->dev->pci->subsystem_device) {
2096 case 0x0000: // Hauppauge/TT WinTV DVB-S rev1.X
2097 case 0x0003: // Hauppauge/TT WinTV Nexus-S Rev 2.X
2098 case 0x1002: // Hauppauge/TT WinTV DVB-S rev1.3SE
2099
2100 // try the ALPS BSRV2 first of all
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002101 av7110->fe = dvb_attach(ves1x93_attach, &alps_bsrv2_config, &av7110->i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002102 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002103 av7110->fe->ops.tuner_ops.set_params = alps_bsrv2_tuner_set_params;
2104 av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
2105 av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
2106 av7110->fe->ops.set_tone = av7110_set_tone;
Oliver Endriss66190a22006-01-09 15:32:42 -02002107 av7110->recover = dvb_s_recover;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002108 break;
2109 }
2110
2111 // try the ALPS BSRU6 now
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002112 av7110->fe = dvb_attach(stv0299_attach, &alps_bsru6_config, &av7110->i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002113 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002114 av7110->fe->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03002115 av7110->fe->tuner_priv = &av7110->i2c_adap;
2116
Patrick Boettcherdea74862006-05-14 05:01:31 -03002117 av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
2118 av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
2119 av7110->fe->ops.set_tone = av7110_set_tone;
Oliver Endriss66190a22006-01-09 15:32:42 -02002120 av7110->recover = dvb_s_recover;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002121 break;
2122 }
2123
2124 // Try the grundig 29504-451
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002125 av7110->fe = dvb_attach(tda8083_attach, &grundig_29504_451_config, &av7110->i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002126 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002127 av7110->fe->ops.tuner_ops.set_params = grundig_29504_451_tuner_set_params;
2128 av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
2129 av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
2130 av7110->fe->ops.set_tone = av7110_set_tone;
Oliver Endriss66190a22006-01-09 15:32:42 -02002131 av7110->recover = dvb_s_recover;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002132 break;
2133 }
2134
2135 /* Try DVB-C cards */
2136 switch(av7110->dev->pci->subsystem_device) {
2137 case 0x0000:
2138 /* Siemens DVB-C (full-length card) VES1820/Philips CD1516 */
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002139 av7110->fe = dvb_attach(ves1820_attach, &philips_cd1516_config, &av7110->i2c_adap,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002140 read_pwm(av7110));
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002141 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002142 av7110->fe->ops.tuner_ops.set_params = philips_cd1516_tuner_set_params;
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002143 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002144 break;
2145 case 0x0003:
Adrian Bunkf3688fc2006-03-29 22:46:12 -03002146 /* Hauppauge DVB-C 2.1 VES1820/ALPS TDBE2 */
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002147 av7110->fe = dvb_attach(ves1820_attach, &alps_tdbe2_config, &av7110->i2c_adap,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002148 read_pwm(av7110));
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002149 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002150 av7110->fe->ops.tuner_ops.set_params = alps_tdbe2_tuner_set_params;
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002151 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002152 break;
2153 }
2154 break;
2155
2156 case 0x0001: // Hauppauge/TT Nexus-T premium rev1.X
Oliver Endriss8d90ee52006-08-07 02:04:26 -03002157 // try ALPS TDLB7 first, then Grundig 29504-401
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002158 av7110->fe = dvb_attach(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;
Oliver Endriss8d90ee52006-08-07 02:04:26 -03002161 break;
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002162 }
Oliver Endriss8d90ee52006-08-07 02:04:26 -03002163 /* fall-thru */
2164
2165 case 0x0008: // Hauppauge/TT DVB-T
2166 // Grundig 29504-401
2167 av7110->fe = dvb_attach(l64781_attach, &grundig_29504_401_config, &av7110->i2c_adap);
2168 if (av7110->fe)
2169 av7110->fe->ops.tuner_ops.set_params = grundig_29504_401_tuner_set_params;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002170 break;
2171
2172 case 0x0002: // Hauppauge/TT DVB-C premium rev2.X
2173
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002174 av7110->fe = dvb_attach(ves1820_attach, &alps_tdbe2_config, &av7110->i2c_adap, read_pwm(av7110));
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002175 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002176 av7110->fe->ops.tuner_ops.set_params = alps_tdbe2_tuner_set_params;
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002177 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002178 break;
2179
Oliver Endriss8bd63012006-02-07 06:49:11 -02002180 case 0x0004: // Galaxis DVB-S rev1.3
2181 /* ALPS BSRV2 */
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002182 av7110->fe = dvb_attach(ves1x93_attach, &alps_bsrv2_config, &av7110->i2c_adap);
Oliver Endriss8bd63012006-02-07 06:49:11 -02002183 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002184 av7110->fe->ops.tuner_ops.set_params = alps_bsrv2_tuner_set_params;
2185 av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
2186 av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
2187 av7110->fe->ops.set_tone = av7110_set_tone;
Oliver Endriss8bd63012006-02-07 06:49:11 -02002188 av7110->recover = dvb_s_recover;
2189 }
2190 break;
2191
Linus Torvalds1da177e2005-04-16 15:20:36 -07002192 case 0x0006: /* Fujitsu-Siemens DVB-S rev 1.6 */
2193 /* Grundig 29504-451 */
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002194 av7110->fe = dvb_attach(tda8083_attach, &grundig_29504_451_config, &av7110->i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002195 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002196 av7110->fe->ops.tuner_ops.set_params = grundig_29504_451_tuner_set_params;
2197 av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
2198 av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
2199 av7110->fe->ops.set_tone = av7110_set_tone;
Oliver Endriss66190a22006-01-09 15:32:42 -02002200 av7110->recover = dvb_s_recover;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002201 }
2202 break;
2203
Linus Torvalds1da177e2005-04-16 15:20:36 -07002204 case 0x000A: // Hauppauge/TT Nexus-CA rev1.X
2205
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002206 av7110->fe = dvb_attach(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 */
Marco Schluessler6a857742006-07-10 03:34:16 -03002211 saa7146_setgpio(av7110->dev, 1, SAA7146_GPIO_OUTLO); // TDA9819 pin9(STD)
2212 saa7146_setgpio(av7110->dev, 3, SAA7146_GPIO_OUTLO); // TDA9819 pin30(VIF)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002213
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 */
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002222 av7110->fe = dvb_attach(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 Quincey2bfe0312006-08-08 09:10:08 -03002227 if (dvb_attach(lnbp21_attach, av7110->fe, &av7110->i2c_adap, 0, 0) == NULL) {
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");
Andrew de Quinceyf52a8382006-08-08 09:10:09 -03002263 dvb_frontend_detach(av7110->fe);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002264 av7110->fe = NULL;
2265 }
2266 }
2267 return ret;
2268}
2269
2270/* Budgetpatch note:
2271 * Original hardware design by Roberto Deza:
2272 * There is a DVB_Wiki at
2273 * http://212.227.36.83/linuxtv/wiki/index.php/Main_Page
2274 * where is described this 'DVB TT Budget Patch', on Card Modding:
2275 * http://212.227.36.83/linuxtv/wiki/index.php/DVB_TT_Budget_Patch
2276 * On the short description there is also a link to a external file,
2277 * with more details:
2278 * http://perso.wanadoo.es/jesussolano/Ttf_tsc1.zip
2279 *
2280 * New software triggering design by Emard that works on
2281 * original Roberto Deza's hardware:
2282 *
2283 * rps1 code for budgetpatch will copy internal HS event to GPIO3 pin.
2284 * GPIO3 is in budget-patch hardware connectd to port B VSYNC
2285 * HS is an internal event of 7146, accessible with RPS
2286 * and temporarily raised high every n lines
2287 * (n in defined in the RPS_THRESH1 counter threshold)
2288 * I think HS is raised high on the beginning of the n-th line
2289 * and remains high until this n-th line that triggered
2290 * it is completely received. When the receiption of n-th line
2291 * ends, HS is lowered.
2292 *
2293 * To transmit data over DMA, 7146 needs changing state at
2294 * port B VSYNC pin. Any changing of port B VSYNC will
2295 * cause some DMA data transfer, with more or less packets loss.
2296 * It depends on the phase and frequency of VSYNC and
2297 * the way of 7146 is instructed to trigger on port B (defined
2298 * in DD1_INIT register, 3rd nibble from the right valid
2299 * numbers are 0-7, see datasheet)
2300 *
2301 * The correct triggering can minimize packet loss,
2302 * dvbtraffic should give this stable bandwidths:
2303 * 22k transponder = 33814 kbit/s
2304 * 27.5k transponder = 38045 kbit/s
2305 * by experiment it is found that the best results
2306 * (stable bandwidths and almost no packet loss)
2307 * are obtained using DD1_INIT triggering number 2
2308 * (Va at rising edge of VS Fa = HS x VS-failing forced toggle)
2309 * and a VSYNC phase that occurs in the middle of DMA transfer
2310 * (about byte 188*512=96256 in the DMA window).
2311 *
2312 * Phase of HS is still not clear to me how to control,
2313 * It just happens to be so. It can be seen if one enables
2314 * RPS_IRQ and print Event Counter 1 in vpeirq(). Every
2315 * time RPS_INTERRUPT is called, the Event Counter 1 will
2316 * increment. That's how the 7146 is programmed to do event
2317 * counting in this budget-patch.c
2318 * I *think* HPS setting has something to do with the phase
2319 * of HS but I cant be 100% sure in that.
2320 *
2321 * hardware debug note: a working budget card (including budget patch)
2322 * with vpeirq() interrupt setup in mode "0x90" (every 64K) will
2323 * generate 3 interrupts per 25-Hz DMA frame of 2*188*512 bytes
2324 * and that means 3*25=75 Hz of interrupt freqency, as seen by
2325 * watch cat /proc/interrupts
2326 *
2327 * If this frequency is 3x lower (and data received in the DMA
2328 * buffer don't start with 0x47, but in the middle of packets,
2329 * whose lengths appear to be like 188 292 188 104 etc.
2330 * this means VSYNC line is not connected in the hardware.
2331 * (check soldering pcb and pins)
2332 * The same behaviour of missing VSYNC can be duplicated on budget
2333 * cards, by seting DD1_INIT trigger mode 7 in 3rd nibble.
2334 */
Johannes Stezenbach1be11e32006-02-27 00:09:20 -03002335static int __devinit av7110_attach(struct saa7146_dev* dev,
2336 struct saa7146_pci_extension_data *pci_ext)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002337{
2338 const int length = TS_WIDTH * TS_HEIGHT;
2339 struct pci_dev *pdev = dev->pci;
2340 struct av7110 *av7110;
2341 int ret, count = 0;
2342
2343 dprintk(4, "dev: %p\n", dev);
2344
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -08002345 /* Set RPS_IRQ to 1 to track rps1 activity.
2346 * Enabling this won't send any interrupt to PC CPU.
2347 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002348#define RPS_IRQ 0
2349
2350 if (budgetpatch == 1) {
2351 budgetpatch = 0;
2352 /* autodetect the presence of budget patch
2353 * this only works if saa7146 has been recently
2354 * reset with with MASK_31 to MC1
2355 *
2356 * will wait for VBI_B event (vertical blank at port B)
2357 * and will reset GPIO3 after VBI_B is detected.
2358 * (GPIO3 should be raised high by CPU to
2359 * test if GPIO3 will generate vertical blank signal
2360 * in budget patch GPIO3 is connected to VSYNC_B
2361 */
2362
2363 /* RESET SAA7146 */
2364 saa7146_write(dev, MC1, MASK_31);
2365 /* autodetection success seems to be time-dependend after reset */
2366
2367 /* Fix VSYNC level */
2368 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
2369 /* set vsync_b triggering */
2370 saa7146_write(dev, DD1_STREAM_B, 0);
2371 /* port B VSYNC at rising edge */
2372 saa7146_write(dev, DD1_INIT, 0x00000200);
2373 saa7146_write(dev, BRS_CTRL, 0x00000000); // VBI
2374 saa7146_write(dev, MC2,
2375 1 * (MASK_08 | MASK_24) | // BRS control
2376 0 * (MASK_09 | MASK_25) | // a
2377 1 * (MASK_10 | MASK_26) | // b
2378 0 * (MASK_06 | MASK_22) | // HPS_CTRL1
2379 0 * (MASK_05 | MASK_21) | // HPS_CTRL2
2380 0 * (MASK_01 | MASK_15) // DEBI
2381 );
2382
2383 /* start writing RPS1 code from beginning */
2384 count = 0;
2385 /* Disable RPS1 */
2386 saa7146_write(dev, MC1, MASK_29);
2387 /* RPS1 timeout disable */
2388 saa7146_write(dev, RPS_TOV1, 0);
2389 WRITE_RPS1(cpu_to_le32(CMD_PAUSE | EVT_VBI_B));
2390 WRITE_RPS1(cpu_to_le32(CMD_WR_REG_MASK | (GPIO_CTRL>>2)));
2391 WRITE_RPS1(cpu_to_le32(GPIO3_MSK));
2392 WRITE_RPS1(cpu_to_le32(SAA7146_GPIO_OUTLO<<24));
2393#if RPS_IRQ
2394 /* issue RPS1 interrupt to increment counter */
2395 WRITE_RPS1(cpu_to_le32(CMD_INTERRUPT));
2396#endif
2397 WRITE_RPS1(cpu_to_le32(CMD_STOP));
2398 /* Jump to begin of RPS program as safety measure (p37) */
2399 WRITE_RPS1(cpu_to_le32(CMD_JUMP));
2400 WRITE_RPS1(cpu_to_le32(dev->d_rps1.dma_handle));
2401
2402#if RPS_IRQ
2403 /* set event counter 1 source as RPS1 interrupt (0x03) (rE4 p53)
2404 * use 0x03 to track RPS1 interrupts - increase by 1 every gpio3 is toggled
2405 * use 0x15 to track VPE interrupts - increase by 1 every vpeirq() is called
2406 */
2407 saa7146_write(dev, EC1SSR, (0x03<<2) | 3 );
2408 /* set event counter 1 treshold to maximum allowed value (rEC p55) */
2409 saa7146_write(dev, ECT1R, 0x3fff );
2410#endif
2411 /* Set RPS1 Address register to point to RPS code (r108 p42) */
2412 saa7146_write(dev, RPS_ADDR1, dev->d_rps1.dma_handle);
2413 /* Enable RPS1, (rFC p33) */
2414 saa7146_write(dev, MC1, (MASK_13 | MASK_29 ));
2415
2416 mdelay(10);
2417 /* now send VSYNC_B to rps1 by rising GPIO3 */
2418 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI);
2419 mdelay(10);
2420 /* if rps1 responded by lowering the GPIO3,
2421 * then we have budgetpatch hardware
2422 */
2423 if ((saa7146_read(dev, GPIO_CTRL) & 0x10000000) == 0) {
2424 budgetpatch = 1;
2425 printk("dvb-ttpci: BUDGET-PATCH DETECTED.\n");
2426 }
2427 /* Disable RPS1 */
2428 saa7146_write(dev, MC1, ( MASK_29 ));
2429#if RPS_IRQ
2430 printk("dvb-ttpci: Event Counter 1 0x%04x\n", saa7146_read(dev, EC1R) & 0x3fff );
2431#endif
2432 }
2433
2434 /* prepare the av7110 device struct */
Panagiotis Issaris74081872006-01-11 19:40:56 -02002435 av7110 = kzalloc(sizeof(struct av7110), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002436 if (!av7110) {
2437 dprintk(1, "out of memory\n");
2438 return -ENOMEM;
2439 }
2440
Linus Torvalds1da177e2005-04-16 15:20:36 -07002441 av7110->card_name = (char*) pci_ext->ext_priv;
2442 av7110->dev = dev;
2443 dev->ext_priv = av7110;
2444
2445 ret = get_firmware(av7110);
2446 if (ret < 0)
2447 goto err_kfree_0;
2448
2449 ret = dvb_register_adapter(&av7110->dvb_adapter, av7110->card_name,
Andrew de Quinceyd09dbf92006-04-10 09:27:37 -03002450 THIS_MODULE, &dev->pci->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002451 if (ret < 0)
2452 goto err_put_firmware_1;
2453
2454 /* the Siemens DVB needs this if you want to have the i2c chips
2455 get recognized before the main driver is fully loaded */
2456 saa7146_write(dev, GPIO_CTRL, 0x500000);
2457
2458#ifdef I2C_ADAP_CLASS_TV_DIGITAL
2459 av7110->i2c_adap.class = I2C_ADAP_CLASS_TV_DIGITAL;
2460#else
2461 av7110->i2c_adap.class = I2C_CLASS_TV_DIGITAL;
2462#endif
2463 strlcpy(av7110->i2c_adap.name, pci_ext->ext_priv, sizeof(av7110->i2c_adap.name));
2464
2465 saa7146_i2c_adapter_prepare(dev, &av7110->i2c_adap, SAA7146_I2C_BUS_BIT_RATE_120); /* 275 kHz */
2466
2467 ret = i2c_add_adapter(&av7110->i2c_adap);
2468 if (ret < 0)
2469 goto err_dvb_unregister_adapter_2;
2470
2471 ttpci_eeprom_parse_mac(&av7110->i2c_adap,
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07002472 av7110->dvb_adapter.proposed_mac);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002473 ret = -ENOMEM;
2474
2475 if (budgetpatch) {
2476 spin_lock_init(&av7110->feedlock1);
2477 av7110->grabbing = saa7146_vmalloc_build_pgtable(pdev, length,
2478 &av7110->pt);
2479 if (!av7110->grabbing)
2480 goto err_i2c_del_3;
2481
2482 saa7146_write(dev, PCI_BT_V1, 0x1c1f101f);
2483 saa7146_write(dev, BCS_CTRL, 0x80400040);
2484 /* set dd1 stream a & b */
2485 saa7146_write(dev, DD1_STREAM_B, 0x00000000);
2486 saa7146_write(dev, DD1_INIT, 0x03000200);
2487 saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
2488 saa7146_write(dev, BRS_CTRL, 0x60000000);
2489 saa7146_write(dev, BASE_ODD3, 0);
2490 saa7146_write(dev, BASE_EVEN3, 0);
2491 saa7146_write(dev, PROT_ADDR3, TS_WIDTH * TS_HEIGHT);
2492 saa7146_write(dev, BASE_PAGE3, av7110->pt.dma | ME1 | 0x90);
2493
2494 saa7146_write(dev, PITCH3, TS_WIDTH);
2495 saa7146_write(dev, NUM_LINE_BYTE3, (TS_HEIGHT << 16) | TS_WIDTH);
2496
2497 /* upload all */
2498 saa7146_write(dev, MC2, 0x077c077c);
2499 saa7146_write(dev, GPIO_CTRL, 0x000000);
2500#if RPS_IRQ
2501 /* set event counter 1 source as RPS1 interrupt (0x03) (rE4 p53)
2502 * use 0x03 to track RPS1 interrupts - increase by 1 every gpio3 is toggled
2503 * use 0x15 to track VPE interrupts - increase by 1 every vpeirq() is called
2504 */
2505 saa7146_write(dev, EC1SSR, (0x03<<2) | 3 );
2506 /* set event counter 1 treshold to maximum allowed value (rEC p55) */
2507 saa7146_write(dev, ECT1R, 0x3fff );
2508#endif
2509 /* Setup BUDGETPATCH MAIN RPS1 "program" (p35) */
2510 count = 0;
2511
2512 /* Wait Source Line Counter Threshold (p36) */
2513 WRITE_RPS1(cpu_to_le32(CMD_PAUSE | EVT_HS));
2514 /* Set GPIO3=1 (p42) */
2515 WRITE_RPS1(cpu_to_le32(CMD_WR_REG_MASK | (GPIO_CTRL>>2)));
2516 WRITE_RPS1(cpu_to_le32(GPIO3_MSK));
2517 WRITE_RPS1(cpu_to_le32(SAA7146_GPIO_OUTHI<<24));
2518#if RPS_IRQ
2519 /* issue RPS1 interrupt */
2520 WRITE_RPS1(cpu_to_le32(CMD_INTERRUPT));
2521#endif
2522 /* Wait reset Source Line Counter Threshold (p36) */
2523 WRITE_RPS1(cpu_to_le32(CMD_PAUSE | RPS_INV | EVT_HS));
2524 /* Set GPIO3=0 (p42) */
2525 WRITE_RPS1(cpu_to_le32(CMD_WR_REG_MASK | (GPIO_CTRL>>2)));
2526 WRITE_RPS1(cpu_to_le32(GPIO3_MSK));
2527 WRITE_RPS1(cpu_to_le32(SAA7146_GPIO_OUTLO<<24));
2528#if RPS_IRQ
2529 /* issue RPS1 interrupt */
2530 WRITE_RPS1(cpu_to_le32(CMD_INTERRUPT));
2531#endif
2532 /* Jump to begin of RPS program (p37) */
2533 WRITE_RPS1(cpu_to_le32(CMD_JUMP));
2534 WRITE_RPS1(cpu_to_le32(dev->d_rps1.dma_handle));
2535
2536 /* Fix VSYNC level */
2537 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
2538 /* Set RPS1 Address register to point to RPS code (r108 p42) */
2539 saa7146_write(dev, RPS_ADDR1, dev->d_rps1.dma_handle);
2540 /* Set Source Line Counter Threshold, using BRS (rCC p43)
2541 * It generates HS event every TS_HEIGHT lines
2542 * this is related to TS_WIDTH set in register
2543 * NUM_LINE_BYTE3. If NUM_LINE_BYTE low 16 bits
2544 * are set to TS_WIDTH bytes (TS_WIDTH=2*188),
2545 * then RPS_THRESH1 should be set to trigger
2546 * every TS_HEIGHT (512) lines.
2547 */
2548 saa7146_write(dev, RPS_THRESH1, (TS_HEIGHT*1) | MASK_12 );
2549
2550 /* Enable RPS1 (rFC p33) */
2551 saa7146_write(dev, MC1, (MASK_13 | MASK_29));
2552
2553 /* end of budgetpatch register initialization */
2554 tasklet_init (&av7110->vpe_tasklet, vpeirq, (unsigned long) av7110);
2555 } else {
2556 saa7146_write(dev, PCI_BT_V1, 0x1c00101f);
2557 saa7146_write(dev, BCS_CTRL, 0x80400040);
2558
2559 /* set dd1 stream a & b */
2560 saa7146_write(dev, DD1_STREAM_B, 0x00000000);
2561 saa7146_write(dev, DD1_INIT, 0x03000000);
2562 saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
2563
2564 /* upload all */
2565 saa7146_write(dev, MC2, 0x077c077c);
2566 saa7146_write(dev, GPIO_CTRL, 0x000000);
2567 }
2568
2569 tasklet_init (&av7110->debi_tasklet, debiirq, (unsigned long) av7110);
2570 tasklet_init (&av7110->gpio_tasklet, gpioirq, (unsigned long) av7110);
2571
Ingo Molnar3593cab2006-02-07 06:49:14 -02002572 mutex_init(&av7110->pid_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002573
2574 /* locks for data transfers from/to AV7110 */
2575 spin_lock_init(&av7110->debilock);
Ingo Molnar3593cab2006-02-07 06:49:14 -02002576 mutex_init(&av7110->dcomlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002577 av7110->debitype = -1;
2578
2579 /* default OSD window */
2580 av7110->osdwin = 1;
Ingo Molnar3593cab2006-02-07 06:49:14 -02002581 mutex_init(&av7110->osd_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002582
C.Y.M2f03ee82006-03-30 04:31:48 -03002583 /* TV standard */
2584 av7110->vidmode = tv_standard == 1 ? VIDEO_MODE_NTSC : VIDEO_MODE_PAL;
2585
Linus Torvalds1da177e2005-04-16 15:20:36 -07002586 /* ARM "watchdog" */
2587 init_waitqueue_head(&av7110->arm_wait);
2588 av7110->arm_thread = NULL;
2589
2590 /* allocate and init buffers */
2591 av7110->debi_virt = pci_alloc_consistent(pdev, 8192, &av7110->debi_bus);
2592 if (!av7110->debi_virt)
2593 goto err_saa71466_vfree_4;
2594
2595
2596 av7110->iobuf = vmalloc(AVOUTLEN+AOUTLEN+BMPLEN+4*IPACKS);
2597 if (!av7110->iobuf)
2598 goto err_pci_free_5;
2599
2600 ret = av7110_av_init(av7110);
2601 if (ret < 0)
2602 goto err_iobuf_vfree_6;
2603
2604 /* init BMP buffer */
2605 av7110->bmpbuf = av7110->iobuf+AVOUTLEN+AOUTLEN;
2606 init_waitqueue_head(&av7110->bmpq);
2607
2608 ret = av7110_ca_init(av7110);
2609 if (ret < 0)
2610 goto err_av7110_av_exit_7;
2611
2612 /* load firmware into AV7110 cards */
2613 ret = av7110_bootarm(av7110);
2614 if (ret < 0)
2615 goto err_av7110_ca_exit_8;
2616
2617 ret = av7110_firmversion(av7110);
2618 if (ret < 0)
2619 goto err_stop_arm_9;
2620
2621 if (FW_VERSION(av7110->arm_app)<0x2501)
2622 printk ("dvb-ttpci: Warning, firmware version 0x%04x is too old. "
2623 "System might be unstable!\n", FW_VERSION(av7110->arm_app));
2624
2625 ret = kernel_thread(arm_thread, (void *) av7110, 0);
2626 if (ret < 0)
2627 goto err_stop_arm_9;
2628
2629 /* set initial volume in mixer struct */
2630 av7110->mixer.volume_left = volume;
2631 av7110->mixer.volume_right = volume;
2632
2633 init_av7110_av(av7110);
2634
2635 ret = av7110_register(av7110);
2636 if (ret < 0)
2637 goto err_arm_thread_stop_10;
2638
2639 /* special case DVB-C: these cards have an analog tuner
2640 plus need some special handling, so we have separate
2641 saa7146_ext_vv data for these... */
2642 ret = av7110_init_v4l(av7110);
2643 if (ret < 0)
2644 goto err_av7110_unregister_11;
2645
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07002646 av7110->dvb_adapter.priv = av7110;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002647 ret = frontend_init(av7110);
2648 if (ret < 0)
2649 goto err_av7110_exit_v4l_12;
2650
2651#if defined(CONFIG_INPUT_EVDEV) || defined(CONFIG_INPUT_EVDEV_MODULE)
Oliver Endriss03388ae2005-09-09 13:03:12 -07002652 av7110_ir_init(av7110);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002653#endif
2654 printk(KERN_INFO "dvb-ttpci: found av7110-%d.\n", av7110_num);
2655 av7110_num++;
2656out:
2657 return ret;
2658
2659err_av7110_exit_v4l_12:
2660 av7110_exit_v4l(av7110);
2661err_av7110_unregister_11:
2662 dvb_unregister(av7110);
2663err_arm_thread_stop_10:
2664 av7110_arm_sync(av7110);
2665err_stop_arm_9:
2666 /* Nothing to do. Rejoice. */
2667err_av7110_ca_exit_8:
2668 av7110_ca_exit(av7110);
2669err_av7110_av_exit_7:
2670 av7110_av_exit(av7110);
2671err_iobuf_vfree_6:
2672 vfree(av7110->iobuf);
2673err_pci_free_5:
2674 pci_free_consistent(pdev, 8192, av7110->debi_virt, av7110->debi_bus);
2675err_saa71466_vfree_4:
2676 if (!av7110->grabbing)
2677 saa7146_pgtable_free(pdev, &av7110->pt);
2678err_i2c_del_3:
2679 i2c_del_adapter(&av7110->i2c_adap);
2680err_dvb_unregister_adapter_2:
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07002681 dvb_unregister_adapter(&av7110->dvb_adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002682err_put_firmware_1:
2683 put_firmware(av7110);
2684err_kfree_0:
2685 kfree(av7110);
2686 goto out;
2687}
2688
Johannes Stezenbach1be11e32006-02-27 00:09:20 -03002689static int __devexit av7110_detach(struct saa7146_dev* saa)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002690{
2691 struct av7110 *av7110 = saa->ext_priv;
2692 dprintk(4, "%p\n", av7110);
2693
Oliver Endriss03388ae2005-09-09 13:03:12 -07002694#if defined(CONFIG_INPUT_EVDEV) || defined(CONFIG_INPUT_EVDEV_MODULE)
2695 av7110_ir_exit(av7110);
2696#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07002697 if (budgetpatch) {
2698 /* Disable RPS1 */
2699 saa7146_write(saa, MC1, MASK_29);
2700 /* VSYNC LOW (inactive) */
2701 saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);
2702 saa7146_write(saa, MC1, MASK_20); /* DMA3 off */
2703 SAA7146_IER_DISABLE(saa, MASK_10);
2704 SAA7146_ISR_CLEAR(saa, MASK_10);
2705 msleep(50);
2706 tasklet_kill(&av7110->vpe_tasklet);
2707 saa7146_pgtable_free(saa->pci, &av7110->pt);
2708 }
2709 av7110_exit_v4l(av7110);
2710
2711 av7110_arm_sync(av7110);
2712
2713 tasklet_kill(&av7110->debi_tasklet);
2714 tasklet_kill(&av7110->gpio_tasklet);
2715
2716 dvb_unregister(av7110);
2717
2718 SAA7146_IER_DISABLE(saa, MASK_19 | MASK_03);
2719 SAA7146_ISR_CLEAR(saa, MASK_19 | MASK_03);
2720
2721 av7110_ca_exit(av7110);
2722 av7110_av_exit(av7110);
2723
2724 vfree(av7110->iobuf);
2725 pci_free_consistent(saa->pci, 8192, av7110->debi_virt,
2726 av7110->debi_bus);
2727
2728 i2c_del_adapter(&av7110->i2c_adap);
2729
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07002730 dvb_unregister_adapter (&av7110->dvb_adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002731
2732 av7110_num--;
2733
2734 put_firmware(av7110);
2735
2736 kfree(av7110);
2737
2738 saa->ext_priv = NULL;
2739
2740 return 0;
2741}
2742
2743
2744static void av7110_irq(struct saa7146_dev* dev, u32 *isr)
2745{
2746 struct av7110 *av7110 = dev->ext_priv;
2747
2748 //print_time("av7110_irq");
2749
2750 /* Note: Don't try to handle the DEBI error irq (MASK_18), in
2751 * intel mode the timeout is asserted all the time...
2752 */
2753
2754 if (*isr & MASK_19) {
2755 //printk("av7110_irq: DEBI\n");
2756 /* Note 1: The DEBI irq is level triggered: We must enable it
2757 * only after we started a DMA xfer, and disable it here
2758 * immediately, or it will be signalled all the time while
2759 * DEBI is idle.
2760 * Note 2: You would think that an irq which is masked is
2761 * not signalled by the hardware. Not so for the SAA7146:
2762 * An irq is signalled as long as the corresponding bit
2763 * in the ISR is set, and disabling irqs just prevents the
2764 * hardware from setting the ISR bit. This means a) that we
2765 * must clear the ISR *after* disabling the irq (which is why
2766 * we must do it here even though saa7146_core did it already),
2767 * and b) that if we were to disable an edge triggered irq
2768 * (like the gpio irqs sadly are) temporarily we would likely
2769 * loose some. This sucks :-(
2770 */
2771 SAA7146_IER_DISABLE(av7110->dev, MASK_19);
2772 SAA7146_ISR_CLEAR(av7110->dev, MASK_19);
2773 tasklet_schedule(&av7110->debi_tasklet);
2774 }
2775
2776 if (*isr & MASK_03) {
2777 //printk("av7110_irq: GPIO\n");
2778 tasklet_schedule(&av7110->gpio_tasklet);
2779 }
2780
2781 if ((*isr & MASK_10) && budgetpatch)
2782 tasklet_schedule(&av7110->vpe_tasklet);
2783}
2784
2785
2786static struct saa7146_extension av7110_extension;
2787
2788#define MAKE_AV7110_INFO(x_var,x_name) \
2789static struct saa7146_pci_extension_data x_var = { \
2790 .ext_priv = x_name, \
2791 .ext = &av7110_extension }
2792
Karl Herz6af4ee12005-09-09 13:03:13 -07002793MAKE_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 -07002794MAKE_AV7110_INFO(ttt_1_X, "Technotrend/Hauppauge WinTV DVB-T rev1.X");
2795MAKE_AV7110_INFO(ttc_1_X, "Technotrend/Hauppauge WinTV Nexus-CA rev1.X");
2796MAKE_AV7110_INFO(ttc_2_X, "Technotrend/Hauppauge WinTV DVB-C rev2.X");
2797MAKE_AV7110_INFO(tts_2_X, "Technotrend/Hauppauge WinTV Nexus-S rev2.X");
Johannes Stezenbach3dfaebd2005-05-16 21:54:19 -07002798MAKE_AV7110_INFO(tts_2_3, "Technotrend/Hauppauge WinTV Nexus-S rev2.3");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002799MAKE_AV7110_INFO(tts_1_3se, "Technotrend/Hauppauge WinTV DVB-S rev1.3 SE");
2800MAKE_AV7110_INFO(ttt, "Technotrend/Hauppauge DVB-T");
2801MAKE_AV7110_INFO(fsc, "Fujitsu Siemens DVB-C");
2802MAKE_AV7110_INFO(fss, "Fujitsu Siemens DVB-S rev1.6");
Oliver Endriss8bd63012006-02-07 06:49:11 -02002803MAKE_AV7110_INFO(gxs_1_3, "Galaxis DVB-S rev1.3");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002804
2805static struct pci_device_id pci_tbl[] = {
Karl Herz6af4ee12005-09-09 13:03:13 -07002806 MAKE_EXTENSION_PCI(fsc, 0x110a, 0x0000),
2807 MAKE_EXTENSION_PCI(tts_1_X_fsc, 0x13c2, 0x0000),
2808 MAKE_EXTENSION_PCI(ttt_1_X, 0x13c2, 0x0001),
2809 MAKE_EXTENSION_PCI(ttc_2_X, 0x13c2, 0x0002),
2810 MAKE_EXTENSION_PCI(tts_2_X, 0x13c2, 0x0003),
Oliver Endriss8bd63012006-02-07 06:49:11 -02002811 MAKE_EXTENSION_PCI(gxs_1_3, 0x13c2, 0x0004),
Karl Herz6af4ee12005-09-09 13:03:13 -07002812 MAKE_EXTENSION_PCI(fss, 0x13c2, 0x0006),
2813 MAKE_EXTENSION_PCI(ttt, 0x13c2, 0x0008),
2814 MAKE_EXTENSION_PCI(ttc_1_X, 0x13c2, 0x000a),
2815 MAKE_EXTENSION_PCI(tts_2_3, 0x13c2, 0x000e),
2816 MAKE_EXTENSION_PCI(tts_1_3se, 0x13c2, 0x1002),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002817
Linus Torvalds1da177e2005-04-16 15:20:36 -07002818/* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0005), UNDEFINED CARD */ // Technisat SkyStar1
2819/* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0009), UNDEFINED CARD */ // TT/Hauppauge WinTV Nexus-CA v????
2820
2821 {
2822 .vendor = 0,
2823 }
2824};
2825
2826MODULE_DEVICE_TABLE(pci, pci_tbl);
2827
2828
2829static struct saa7146_extension av7110_extension = {
Dave Jones0e367a12006-08-07 13:18:56 -03002830 .name = "dvb",
Oliver Endriss00c4cc62006-11-01 13:09:51 -03002831 .flags = SAA7146_USE_I2C_IRQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002832
2833 .module = THIS_MODULE,
2834 .pci_tbl = &pci_tbl[0],
2835 .attach = av7110_attach,
Johannes Stezenbach1be11e32006-02-27 00:09:20 -03002836 .detach = __devexit_p(av7110_detach),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002837
2838 .irq_mask = MASK_19 | MASK_03 | MASK_10,
2839 .irq_func = av7110_irq,
2840};
2841
2842
2843static int __init av7110_init(void)
2844{
2845 int retval;
2846 retval = saa7146_register_extension(&av7110_extension);
2847 return retval;
2848}
2849
2850
2851static void __exit av7110_exit(void)
2852{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002853 saa7146_unregister_extension(&av7110_extension);
2854}
2855
2856module_init(av7110_init);
2857module_exit(av7110_exit);
2858
2859MODULE_DESCRIPTION("driver for the SAA7146 based AV110 PCI DVB cards by "
2860 "Siemens, Technotrend, Hauppauge");
2861MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, others");
2862MODULE_LICENSE("GPL");