blob: 29ed532ba966932e9d1c687e13057cfef63c393c [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>
Herbert Poetzl8eec1422007-02-08 14:32:43 -030054#include <linux/kthread.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070055
56#include <asm/system.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070057
58#include <linux/dvb/frontend.h>
59
60#include "dvb_frontend.h"
61
62#include "ttpci-eeprom.h"
63#include "av7110.h"
64#include "av7110_hw.h"
65#include "av7110_av.h"
66#include "av7110_ca.h"
67#include "av7110_ipack.h"
68
Oliver Endrissdb5d91e2006-02-28 10:32:25 -030069#include "bsbe1.h"
70#include "lnbp21.h"
Perceval Anichini265366e2006-03-16 11:22:47 -030071#include "bsru6.h"
Oliver Endrissdb5d91e2006-02-28 10:32:25 -030072
Linus Torvalds1da177e2005-04-16 15:20:36 -070073#define TS_WIDTH 376
74#define TS_HEIGHT 512
75#define TS_BUFLEN (TS_WIDTH*TS_HEIGHT)
76#define TS_MAX_PACKETS (TS_BUFLEN/TS_SIZE)
77
78
79int av7110_debug;
80
81static int vidmode = CVBS_RGB_OUT;
82static int pids_off;
83static int adac = DVB_ADAC_TI;
84static int hw_sections;
85static int rgb_on;
86static int volume = 255;
Mauro Carvalho Chehaba5ed4252006-01-13 14:10:19 -020087static int budgetpatch;
Oliver Endriss4caba422006-03-17 05:29:15 -030088static int wss_cfg_4_3 = 0x4008;
89static int wss_cfg_16_9 = 0x0007;
C.Y.M2f03ee82006-03-30 04:31:48 -030090static int tv_standard;
Linus Torvalds1da177e2005-04-16 15:20:36 -070091
92module_param_named(debug, av7110_debug, int, 0644);
93MODULE_PARM_DESC(debug, "debug level (bitmask, default 0)");
94module_param(vidmode, int, 0444);
95MODULE_PARM_DESC(vidmode,"analog video out: 0 off, 1 CVBS+RGB (default), 2 CVBS+YC, 3 YC");
96module_param(pids_off, int, 0444);
97MODULE_PARM_DESC(pids_off,"clear video/audio/PCR PID filters when demux is closed");
98module_param(adac, int, 0444);
99MODULE_PARM_DESC(adac,"audio DAC type: 0 TI, 1 CRYSTAL, 2 MSP (use if autodetection fails)");
100module_param(hw_sections, int, 0444);
101MODULE_PARM_DESC(hw_sections, "0 use software section filter, 1 use hardware");
102module_param(rgb_on, int, 0444);
103MODULE_PARM_DESC(rgb_on, "For Siemens DVB-C cards only: Enable RGB control"
104 " signal on SCART pin 16 to switch SCART video mode from CVBS to RGB");
105module_param(volume, int, 0444);
106MODULE_PARM_DESC(volume, "initial volume: default 255 (range 0-255)");
107module_param(budgetpatch, int, 0444);
108MODULE_PARM_DESC(budgetpatch, "use budget-patch hardware modification: default 0 (0 no, 1 autodetect, 2 always)");
Oliver Endriss4caba422006-03-17 05:29:15 -0300109module_param(wss_cfg_4_3, int, 0444);
110MODULE_PARM_DESC(wss_cfg_4_3, "WSS 4:3 - default 0x4008 - bit 15: disable, 14: burst mode, 13..0: wss data");
111module_param(wss_cfg_16_9, int, 0444);
112MODULE_PARM_DESC(wss_cfg_16_9, "WSS 16:9 - default 0x0007 - bit 15: disable, 14: burst mode, 13..0: wss data");
C.Y.M2f03ee82006-03-30 04:31:48 -0300113module_param(tv_standard, int, 0444);
114MODULE_PARM_DESC(tv_standard, "TV standard: 0 PAL (default), 1 NTSC");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700115
116static void restart_feeds(struct av7110 *av7110);
117
Mauro Carvalho Chehaba5ed4252006-01-13 14:10:19 -0200118static int av7110_num;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700119
120#define FE_FUNC_OVERRIDE(fe_func, av7110_copy, av7110_func) \
121{\
122 if (fe_func != NULL) { \
123 av7110_copy = fe_func; \
124 fe_func = av7110_func; \
125 } \
126}
127
128
129static void init_av7110_av(struct av7110 *av7110)
130{
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700131 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700132 struct saa7146_dev *dev = av7110->dev;
133
134 /* set internal volume control to maximum */
135 av7110->adac_type = DVB_ADAC_TI;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700136 ret = av7110_set_volume(av7110, av7110->mixer.volume_left, av7110->mixer.volume_right);
Johannes Stezenbach7a2fa902005-07-07 17:58:01 -0700137 if (ret < 0)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700138 printk("dvb-ttpci:cannot set internal volume to maximum:%d\n",ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139
Oliver Endriss4caba422006-03-17 05:29:15 -0300140 ret = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetWSSConfig, 2, 2, wss_cfg_4_3);
141 if (ret < 0)
142 printk("dvb-ttpci: unable to configure 4:3 wss\n");
143 ret = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetWSSConfig, 2, 3, wss_cfg_16_9);
144 if (ret < 0)
145 printk("dvb-ttpci: unable to configure 16:9 wss\n");
146
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700147 ret = av7710_set_video_mode(av7110, vidmode);
Johannes Stezenbach7a2fa902005-07-07 17:58:01 -0700148 if (ret < 0)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700149 printk("dvb-ttpci:cannot set video mode:%d\n",ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700150
151 /* handle different card types */
152 /* remaining inits according to card and frontend type */
153 av7110->analog_tuner_flags = 0;
154 av7110->current_input = 0;
Tim Kaiser61391e02006-06-25 09:14:07 -0300155 if (dev->pci->subsystem_vendor == 0x13c2 && dev->pci->subsystem_device == 0x000a)
Marco Schluessler1c13b952006-01-09 15:25:06 -0200156 av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, ADSwitch, 1, 0); // SPDIF on
Tim Kaiser61391e02006-06-25 09:14:07 -0300157 if (i2c_writereg(av7110, 0x20, 0x00, 0x00) == 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700158 printk ("dvb-ttpci: Crystal audio DAC @ card %d detected\n",
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -0700159 av7110->dvb_adapter.num);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700160 av7110->adac_type = DVB_ADAC_CRYSTAL;
161 i2c_writereg(av7110, 0x20, 0x01, 0xd2);
162 i2c_writereg(av7110, 0x20, 0x02, 0x49);
163 i2c_writereg(av7110, 0x20, 0x03, 0x00);
164 i2c_writereg(av7110, 0x20, 0x04, 0x00);
165
166 /**
167 * some special handling for the Siemens DVB-C cards...
168 */
169 } else if (0 == av7110_init_analog_module(av7110)) {
170 /* done. */
171 }
172 else if (dev->pci->subsystem_vendor == 0x110a) {
173 printk("dvb-ttpci: DVB-C w/o analog module @ card %d detected\n",
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -0700174 av7110->dvb_adapter.num);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700175 av7110->adac_type = DVB_ADAC_NONE;
176 }
177 else {
178 av7110->adac_type = adac;
179 printk("dvb-ttpci: adac type set to %d @ card %d\n",
Marco Schluessler1c13b952006-01-09 15:25:06 -0200180 av7110->adac_type, av7110->dvb_adapter.num);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700181 }
182
Marco Schluessler1c13b952006-01-09 15:25:06 -0200183 if (av7110->adac_type == DVB_ADAC_NONE || av7110->adac_type == DVB_ADAC_MSP34x0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700184 // switch DVB SCART on
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700185 ret = av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, MainSwitch, 1, 0);
Johannes Stezenbach7a2fa902005-07-07 17:58:01 -0700186 if (ret < 0)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700187 printk("dvb-ttpci:cannot switch on SCART(Main):%d\n",ret);
188 ret = av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, ADSwitch, 1, 1);
Johannes Stezenbach7a2fa902005-07-07 17:58:01 -0700189 if (ret < 0)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700190 printk("dvb-ttpci:cannot switch on SCART(AD):%d\n",ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700191 if (rgb_on &&
Karl Herz6af4ee12005-09-09 13:03:13 -0700192 ((av7110->dev->pci->subsystem_vendor == 0x110a) ||
193 (av7110->dev->pci->subsystem_vendor == 0x13c2)) &&
194 (av7110->dev->pci->subsystem_device == 0x0000)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700195 saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); // RGB on, SCART pin 16
196 //saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); // SCARTpin 8
197 }
198 }
199
Oliver Endriss60edb132005-12-19 08:54:11 -0200200 if (dev->pci->subsystem_vendor == 0x13c2 && dev->pci->subsystem_device == 0x000e)
201 av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, SpdifSwitch, 1, 0); // SPDIF on
202
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700203 ret = av7110_set_volume(av7110, av7110->mixer.volume_left, av7110->mixer.volume_right);
Johannes Stezenbach7a2fa902005-07-07 17:58:01 -0700204 if (ret < 0)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700205 printk("dvb-ttpci:cannot set volume :%d\n",ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700206}
207
208static void recover_arm(struct av7110 *av7110)
209{
210 dprintk(4, "%p\n",av7110);
211
212 av7110_bootarm(av7110);
213 msleep(100);
Oliver Endriss66190a22006-01-09 15:32:42 -0200214
215 init_av7110_av(av7110);
216
217 /* card-specific recovery */
218 if (av7110->recover)
219 av7110->recover(av7110);
220
Linus Torvalds1da177e2005-04-16 15:20:36 -0700221 restart_feeds(av7110);
222 av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, SetIR, 1, av7110->ir_config);
223}
224
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225static void av7110_arm_sync(struct av7110 *av7110)
226{
Herbert Poetzl8eec1422007-02-08 14:32:43 -0300227 if (av7110->arm_thread)
228 kthread_stop(av7110->arm_thread);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700229
Herbert Poetzl8eec1422007-02-08 14:32:43 -0300230 av7110->arm_thread = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700231}
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
Linus Torvalds1da177e2005-04-16 15:20:36 -0700241 for (;;) {
242 timeout = wait_event_interruptible_timeout(av7110->arm_wait,
Herbert Poetzl8eec1422007-02-08 14:32:43 -0300243 kthread_should_stop(), 5 * HZ);
244
245 if (-ERESTARTSYS == timeout || kthread_should_stop()) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700246 /* got signal or told to quit*/
247 break;
248 }
249
250 if (!av7110->arm_ready)
251 continue;
252
Ingo Molnar3593cab2006-02-07 06:49:14 -0200253 if (mutex_lock_interruptible(&av7110->dcomlock))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255 newloops = rdebi(av7110, DEBINOSWAP, STATUS_LOOPS, 0, 2);
Ingo Molnar3593cab2006-02-07 06:49:14 -0200256 mutex_unlock(&av7110->dcomlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257
Oliver Endriss66190a22006-01-09 15:32:42 -0200258 if (newloops == av7110->arm_loops || av7110->arm_errors > 3) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700259 printk(KERN_ERR "dvb-ttpci: ARM crashed @ card %d\n",
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -0700260 av7110->dvb_adapter.num);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261
Oliver Endriss66190a22006-01-09 15:32:42 -0200262 recover_arm(av7110);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263
Ingo Molnar3593cab2006-02-07 06:49:14 -0200264 if (mutex_lock_interruptible(&av7110->dcomlock))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700265 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266 newloops = rdebi(av7110, DEBINOSWAP, STATUS_LOOPS, 0, 2) - 1;
Ingo Molnar3593cab2006-02-07 06:49:14 -0200267 mutex_unlock(&av7110->dcomlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268 }
269 av7110->arm_loops = newloops;
Oliver Endriss66190a22006-01-09 15:32:42 -0200270 av7110->arm_errors = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271 }
272
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273 return 0;
274}
275
276
Linus Torvalds1da177e2005-04-16 15:20:36 -0700277/****************************************************************************
278 * IRQ handling
279 ****************************************************************************/
280
281static int DvbDmxFilterCallback(u8 *buffer1, size_t buffer1_len,
282 u8 *buffer2, size_t buffer2_len,
283 struct dvb_demux_filter *dvbdmxfilter,
284 enum dmx_success success,
285 struct av7110 *av7110)
286{
287 if (!dvbdmxfilter->feed->demux->dmx.frontend)
288 return 0;
289 if (dvbdmxfilter->feed->demux->dmx.frontend->source == DMX_MEMORY_FE)
290 return 0;
291
292 switch (dvbdmxfilter->type) {
293 case DMX_TYPE_SEC:
294 if ((((buffer1[1] << 8) | buffer1[2]) & 0xfff) + 3 != buffer1_len)
295 return 0;
296 if (dvbdmxfilter->doneq) {
297 struct dmx_section_filter *filter = &dvbdmxfilter->filter;
298 int i;
299 u8 xor, neq = 0;
300
301 for (i = 0; i < DVB_DEMUX_MASK_MAX; i++) {
302 xor = filter->filter_value[i] ^ buffer1[i];
303 neq |= dvbdmxfilter->maskandnotmode[i] & xor;
304 }
305 if (!neq)
306 return 0;
307 }
308 return dvbdmxfilter->feed->cb.sec(buffer1, buffer1_len,
309 buffer2, buffer2_len,
310 &dvbdmxfilter->filter,
311 DMX_OK);
312 case DMX_TYPE_TS:
313 if (!(dvbdmxfilter->feed->ts_type & TS_PACKET))
314 return 0;
315 if (dvbdmxfilter->feed->ts_type & TS_PAYLOAD_ONLY)
316 return dvbdmxfilter->feed->cb.ts(buffer1, buffer1_len,
317 buffer2, buffer2_len,
318 &dvbdmxfilter->feed->feed.ts,
319 DMX_OK);
320 else
321 av7110_p2t_write(buffer1, buffer1_len,
322 dvbdmxfilter->feed->pid,
323 &av7110->p2t_filter[dvbdmxfilter->index]);
324 default:
325 return 0;
326 }
327}
328
329
330//#define DEBUG_TIMING
331static inline void print_time(char *s)
332{
333#ifdef DEBUG_TIMING
334 struct timeval tv;
335 do_gettimeofday(&tv);
336 printk("%s: %d.%d\n", s, (int)tv.tv_sec, (int)tv.tv_usec);
337#endif
338}
339
340#define DEBI_READ 0
341#define DEBI_WRITE 1
342static inline void start_debi_dma(struct av7110 *av7110, int dir,
343 unsigned long addr, unsigned int len)
344{
345 dprintk(8, "%c %08lx %u\n", dir == DEBI_READ ? 'R' : 'W', addr, len);
346 if (saa7146_wait_for_debi_done(av7110->dev, 0)) {
347 printk(KERN_ERR "%s: saa7146_wait_for_debi_done timed out\n", __FUNCTION__);
348 return;
349 }
350
351 SAA7146_ISR_CLEAR(av7110->dev, MASK_19); /* for good measure */
352 SAA7146_IER_ENABLE(av7110->dev, MASK_19);
353 if (len < 5)
354 len = 5; /* we want a real DEBI DMA */
355 if (dir == DEBI_WRITE)
356 iwdebi(av7110, DEBISWAB, addr, 0, (len + 3) & ~3);
357 else
358 irdebi(av7110, DEBISWAB, addr, 0, len);
359}
360
361static void debiirq(unsigned long data)
362{
363 struct av7110 *av7110 = (struct av7110 *) data;
364 int type = av7110->debitype;
365 int handle = (type >> 8) & 0x1f;
366 unsigned int xfer = 0;
367
368 print_time("debi");
369 dprintk(4, "type 0x%04x\n", type);
370
371 if (type == -1) {
372 printk("DEBI irq oops @ %ld, psr:0x%08x, ssr:0x%08x\n",
373 jiffies, saa7146_read(av7110->dev, PSR),
374 saa7146_read(av7110->dev, SSR));
375 goto debi_done;
376 }
377 av7110->debitype = -1;
378
379 switch (type & 0xff) {
380
381 case DATA_TS_RECORD:
382 dvb_dmx_swfilter_packets(&av7110->demux,
383 (const u8 *) av7110->debi_virt,
384 av7110->debilen / 188);
385 xfer = RX_BUFF;
386 break;
387
388 case DATA_PES_RECORD:
389 if (av7110->demux.recording)
390 av7110_record_cb(&av7110->p2t[handle],
391 (u8 *) av7110->debi_virt,
392 av7110->debilen);
393 xfer = RX_BUFF;
394 break;
395
396 case DATA_IPMPE:
397 case DATA_FSECTION:
398 case DATA_PIPING:
399 if (av7110->handle2filter[handle])
400 DvbDmxFilterCallback((u8 *)av7110->debi_virt,
401 av7110->debilen, NULL, 0,
402 av7110->handle2filter[handle],
403 DMX_OK, av7110);
404 xfer = RX_BUFF;
405 break;
406
407 case DATA_CI_GET:
408 {
409 u8 *data = av7110->debi_virt;
410
411 if ((data[0] < 2) && data[2] == 0xff) {
412 int flags = 0;
413 if (data[5] > 0)
414 flags |= CA_CI_MODULE_PRESENT;
415 if (data[5] > 5)
416 flags |= CA_CI_MODULE_READY;
417 av7110->ci_slot[data[0]].flags = flags;
418 } else
419 ci_get_data(&av7110->ci_rbuffer,
420 av7110->debi_virt,
421 av7110->debilen);
422 xfer = RX_BUFF;
423 break;
424 }
425
426 case DATA_COMMON_INTERFACE:
427 CI_handle(av7110, (u8 *)av7110->debi_virt, av7110->debilen);
428#if 0
429 {
430 int i;
431
432 printk("av7110%d: ", av7110->num);
433 printk("%02x ", *(u8 *)av7110->debi_virt);
434 printk("%02x ", *(1+(u8 *)av7110->debi_virt));
435 for (i = 2; i < av7110->debilen; i++)
436 printk("%02x ", (*(i+(unsigned char *)av7110->debi_virt)));
437 for (i = 2; i < av7110->debilen; i++)
438 printk("%c", chtrans(*(i+(unsigned char *)av7110->debi_virt)));
439
440 printk("\n");
441 }
442#endif
443 xfer = RX_BUFF;
444 break;
445
446 case DATA_DEBUG_MESSAGE:
447 ((s8*)av7110->debi_virt)[Reserved_SIZE - 1] = 0;
448 printk("%s\n", (s8 *) av7110->debi_virt);
449 xfer = RX_BUFF;
450 break;
451
452 case DATA_CI_PUT:
453 dprintk(4, "debi DATA_CI_PUT\n");
454 case DATA_MPEG_PLAY:
455 dprintk(4, "debi DATA_MPEG_PLAY\n");
456 case DATA_BMP_LOAD:
457 dprintk(4, "debi DATA_BMP_LOAD\n");
458 xfer = TX_BUFF;
459 break;
460 default:
461 break;
462 }
463debi_done:
464 spin_lock(&av7110->debilock);
465 if (xfer)
466 iwdebi(av7110, DEBINOSWAP, xfer, 0, 2);
467 ARM_ClearMailBox(av7110);
468 spin_unlock(&av7110->debilock);
469}
470
471/* irq from av7110 firmware writing the mailbox register in the DPRAM */
472static void gpioirq(unsigned long data)
473{
474 struct av7110 *av7110 = (struct av7110 *) data;
475 u32 rxbuf, txbuf;
476 int len;
477
478 if (av7110->debitype != -1)
479 /* we shouldn't get any irq while a debi xfer is running */
480 printk("dvb-ttpci: GPIO0 irq oops @ %ld, psr:0x%08x, ssr:0x%08x\n",
481 jiffies, saa7146_read(av7110->dev, PSR),
482 saa7146_read(av7110->dev, SSR));
483
484 if (saa7146_wait_for_debi_done(av7110->dev, 0)) {
485 printk(KERN_ERR "%s: saa7146_wait_for_debi_done timed out\n", __FUNCTION__);
486 BUG(); /* maybe we should try resetting the debi? */
487 }
488
489 spin_lock(&av7110->debilock);
490 ARM_ClearIrq(av7110);
491
492 /* see what the av7110 wants */
493 av7110->debitype = irdebi(av7110, DEBINOSWAP, IRQ_STATE, 0, 2);
494 av7110->debilen = irdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
495 rxbuf = irdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
496 txbuf = irdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
497 len = (av7110->debilen + 3) & ~3;
498
499 print_time("gpio");
500 dprintk(8, "GPIO0 irq 0x%04x %d\n", av7110->debitype, av7110->debilen);
501
502 switch (av7110->debitype & 0xff) {
503
504 case DATA_TS_PLAY:
505 case DATA_PES_PLAY:
506 break;
507
508 case DATA_MPEG_VIDEO_EVENT:
509 {
510 u32 h_ar;
511 struct video_event event;
512
513 av7110->video_size.w = irdebi(av7110, DEBINOSWAP, STATUS_MPEG_WIDTH, 0, 2);
514 h_ar = irdebi(av7110, DEBINOSWAP, STATUS_MPEG_HEIGHT_AR, 0, 2);
515
516 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
517 iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
518
519 av7110->video_size.h = h_ar & 0xfff;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700520
521 event.type = VIDEO_EVENT_SIZE_CHANGED;
522 event.u.size.w = av7110->video_size.w;
523 event.u.size.h = av7110->video_size.h;
524 switch ((h_ar >> 12) & 0xf)
525 {
526 case 3:
527 av7110->video_size.aspect_ratio = VIDEO_FORMAT_16_9;
528 event.u.size.aspect_ratio = VIDEO_FORMAT_16_9;
529 av7110->videostate.video_format = VIDEO_FORMAT_16_9;
530 break;
531 case 4:
532 av7110->video_size.aspect_ratio = VIDEO_FORMAT_221_1;
533 event.u.size.aspect_ratio = VIDEO_FORMAT_221_1;
534 av7110->videostate.video_format = VIDEO_FORMAT_221_1;
535 break;
536 default:
537 av7110->video_size.aspect_ratio = VIDEO_FORMAT_4_3;
538 event.u.size.aspect_ratio = VIDEO_FORMAT_4_3;
539 av7110->videostate.video_format = VIDEO_FORMAT_4_3;
540 }
Oliver Endriss66190a22006-01-09 15:32:42 -0200541
542 dprintk(8, "GPIO0 irq: DATA_MPEG_VIDEO_EVENT: w/h/ar = %u/%u/%u\n",
543 av7110->video_size.w, av7110->video_size.h,
544 av7110->video_size.aspect_ratio);
545
Linus Torvalds1da177e2005-04-16 15:20:36 -0700546 dvb_video_add_event(av7110, &event);
547 break;
548 }
549
550 case DATA_CI_PUT:
551 {
552 int avail;
553 struct dvb_ringbuffer *cibuf = &av7110->ci_wbuffer;
554
555 avail = dvb_ringbuffer_avail(cibuf);
556 if (avail <= 2) {
557 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
558 iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
559 iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
560 break;
561 }
562 len = DVB_RINGBUFFER_PEEK(cibuf, 0) << 8;
563 len |= DVB_RINGBUFFER_PEEK(cibuf, 1);
564 if (avail < len + 2) {
565 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
566 iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
567 iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
568 break;
569 }
570 DVB_RINGBUFFER_SKIP(cibuf, 2);
571
572 dvb_ringbuffer_read(cibuf, av7110->debi_virt, len, 0);
573
574 iwdebi(av7110, DEBINOSWAP, TX_LEN, len, 2);
575 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, len, 2);
576 dprintk(8, "DMA: CI\n");
577 start_debi_dma(av7110, DEBI_WRITE, DPRAM_BASE + txbuf, len);
578 spin_unlock(&av7110->debilock);
579 wake_up(&cibuf->queue);
580 return;
581 }
582
583 case DATA_MPEG_PLAY:
584 if (!av7110->playing) {
585 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
586 iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
587 iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
588 break;
589 }
590 len = 0;
591 if (av7110->debitype & 0x100) {
592 spin_lock(&av7110->aout.lock);
593 len = av7110_pes_play(av7110->debi_virt, &av7110->aout, 2048);
594 spin_unlock(&av7110->aout.lock);
595 }
596 if (len <= 0 && (av7110->debitype & 0x200)
597 &&av7110->videostate.play_state != VIDEO_FREEZED) {
598 spin_lock(&av7110->avout.lock);
599 len = av7110_pes_play(av7110->debi_virt, &av7110->avout, 2048);
600 spin_unlock(&av7110->avout.lock);
601 }
602 if (len <= 0) {
603 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
604 iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
605 iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
606 break;
607 }
608 dprintk(8, "GPIO0 PES_PLAY len=%04x\n", len);
609 iwdebi(av7110, DEBINOSWAP, TX_LEN, len, 2);
610 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, len, 2);
611 dprintk(8, "DMA: MPEG_PLAY\n");
612 start_debi_dma(av7110, DEBI_WRITE, DPRAM_BASE + txbuf, len);
613 spin_unlock(&av7110->debilock);
614 return;
615
616 case DATA_BMP_LOAD:
617 len = av7110->debilen;
618 dprintk(8, "gpio DATA_BMP_LOAD len %d\n", len);
619 if (!len) {
620 av7110->bmp_state = BMP_LOADED;
621 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
622 iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
623 iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
624 wake_up(&av7110->bmpq);
625 dprintk(8, "gpio DATA_BMP_LOAD done\n");
626 break;
627 }
628 if (len > av7110->bmplen)
629 len = av7110->bmplen;
630 if (len > 2 * 1024)
631 len = 2 * 1024;
632 iwdebi(av7110, DEBINOSWAP, TX_LEN, len, 2);
633 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, len, 2);
634 memcpy(av7110->debi_virt, av7110->bmpbuf+av7110->bmpp, len);
635 av7110->bmpp += len;
636 av7110->bmplen -= len;
637 dprintk(8, "gpio DATA_BMP_LOAD DMA len %d\n", len);
638 start_debi_dma(av7110, DEBI_WRITE, DPRAM_BASE+txbuf, len);
639 spin_unlock(&av7110->debilock);
640 return;
641
642 case DATA_CI_GET:
643 case DATA_COMMON_INTERFACE:
644 case DATA_FSECTION:
645 case DATA_IPMPE:
646 case DATA_PIPING:
647 if (!len || len > 4 * 1024) {
648 iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
649 break;
650 }
651 /* fall through */
652
653 case DATA_TS_RECORD:
654 case DATA_PES_RECORD:
655 dprintk(8, "DMA: TS_REC etc.\n");
656 start_debi_dma(av7110, DEBI_READ, DPRAM_BASE+rxbuf, len);
657 spin_unlock(&av7110->debilock);
658 return;
659
660 case DATA_DEBUG_MESSAGE:
661 if (!len || len > 0xff) {
662 iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
663 break;
664 }
665 start_debi_dma(av7110, DEBI_READ, Reserved, len);
666 spin_unlock(&av7110->debilock);
667 return;
668
669 case DATA_IRCOMMAND:
Oliver Endriss03388ae2005-09-09 13:03:12 -0700670 if (av7110->ir_handler)
671 av7110->ir_handler(av7110,
672 swahw32(irdebi(av7110, DEBINOSWAP, Reserved, 0, 4)));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700673 iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
674 break;
675
676 default:
677 printk("dvb-ttpci: gpioirq unknown type=%d len=%d\n",
678 av7110->debitype, av7110->debilen);
679 break;
680 }
681 av7110->debitype = -1;
682 ARM_ClearMailBox(av7110);
683 spin_unlock(&av7110->debilock);
684}
685
686
687#ifdef CONFIG_DVB_AV7110_OSD
688static int dvb_osd_ioctl(struct inode *inode, struct file *file,
689 unsigned int cmd, void *parg)
690{
Tobias Klauserd9bdf772006-12-26 07:33:48 -0300691 struct dvb_device *dvbdev = file->private_data;
692 struct av7110 *av7110 = dvbdev->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700693
694 dprintk(4, "%p\n", av7110);
695
696 if (cmd == OSD_SEND_CMD)
697 return av7110_osd_cmd(av7110, (osd_cmd_t *) parg);
698 if (cmd == OSD_GET_CAPABILITY)
699 return av7110_osd_capability(av7110, (osd_cap_t *) parg);
700
701 return -EINVAL;
702}
703
704
705static struct file_operations dvb_osd_fops = {
706 .owner = THIS_MODULE,
707 .ioctl = dvb_generic_ioctl,
708 .open = dvb_generic_open,
709 .release = dvb_generic_release,
710};
711
712static struct dvb_device dvbdev_osd = {
713 .priv = NULL,
714 .users = 1,
715 .writers = 1,
716 .fops = &dvb_osd_fops,
717 .kernel_ioctl = dvb_osd_ioctl,
718};
719#endif /* CONFIG_DVB_AV7110_OSD */
720
721
722static inline int SetPIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid,
723 u16 subpid, u16 pcrpid)
724{
Dr. Werner Fink47f36922006-01-09 15:25:07 -0200725 u16 aflags = 0;
726
Linus Torvalds1da177e2005-04-16 15:20:36 -0700727 dprintk(4, "%p\n", av7110);
728
729 if (vpid == 0x1fff || apid == 0x1fff ||
730 ttpid == 0x1fff || subpid == 0x1fff || pcrpid == 0x1fff) {
731 vpid = apid = ttpid = subpid = pcrpid = 0;
732 av7110->pids[DMX_PES_VIDEO] = 0;
733 av7110->pids[DMX_PES_AUDIO] = 0;
734 av7110->pids[DMX_PES_TELETEXT] = 0;
735 av7110->pids[DMX_PES_PCR] = 0;
736 }
737
Dr. Werner Fink47f36922006-01-09 15:25:07 -0200738 if (av7110->audiostate.bypass_mode)
739 aflags |= 0x8000;
740
741 return av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, MultiPID, 6,
742 pcrpid, vpid, apid, ttpid, subpid, aflags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743}
744
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700745int ChangePIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700746 u16 subpid, u16 pcrpid)
747{
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700748 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749 dprintk(4, "%p\n", av7110);
750
Ingo Molnar3593cab2006-02-07 06:49:14 -0200751 if (mutex_lock_interruptible(&av7110->pid_mutex))
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700752 return -ERESTARTSYS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700753
754 if (!(vpid & 0x8000))
755 av7110->pids[DMX_PES_VIDEO] = vpid;
756 if (!(apid & 0x8000))
757 av7110->pids[DMX_PES_AUDIO] = apid;
758 if (!(ttpid & 0x8000))
759 av7110->pids[DMX_PES_TELETEXT] = ttpid;
760 if (!(pcrpid & 0x8000))
761 av7110->pids[DMX_PES_PCR] = pcrpid;
762
763 av7110->pids[DMX_PES_SUBTITLE] = 0;
764
765 if (av7110->fe_synced) {
766 pcrpid = av7110->pids[DMX_PES_PCR];
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700767 ret = SetPIDs(av7110, vpid, apid, ttpid, subpid, pcrpid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700768 }
769
Ingo Molnar3593cab2006-02-07 06:49:14 -0200770 mutex_unlock(&av7110->pid_mutex);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700771 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772}
773
774
775/******************************************************************************
776 * hardware filter functions
777 ******************************************************************************/
778
779static int StartHWFilter(struct dvb_demux_filter *dvbdmxfilter)
780{
781 struct dvb_demux_feed *dvbdmxfeed = dvbdmxfilter->feed;
Tobias Klauserd9bdf772006-12-26 07:33:48 -0300782 struct av7110 *av7110 = dvbdmxfeed->demux->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700783 u16 buf[20];
784 int ret, i;
785 u16 handle;
786// u16 mode = 0x0320;
787 u16 mode = 0xb96a;
788
789 dprintk(4, "%p\n", av7110);
790
791 if (dvbdmxfilter->type == DMX_TYPE_SEC) {
792 if (hw_sections) {
793 buf[4] = (dvbdmxfilter->filter.filter_value[0] << 8) |
794 dvbdmxfilter->maskandmode[0];
795 for (i = 3; i < 18; i++)
796 buf[i + 4 - 2] =
797 (dvbdmxfilter->filter.filter_value[i] << 8) |
798 dvbdmxfilter->maskandmode[i];
799 mode = 4;
800 }
801 } else if ((dvbdmxfeed->ts_type & TS_PACKET) &&
802 !(dvbdmxfeed->ts_type & TS_PAYLOAD_ONLY)) {
803 av7110_p2t_init(&av7110->p2t_filter[dvbdmxfilter->index], dvbdmxfeed);
804 }
805
806 buf[0] = (COMTYPE_PID_FILTER << 8) + AddPIDFilter;
807 buf[1] = 16;
808 buf[2] = dvbdmxfeed->pid;
809 buf[3] = mode;
810
811 ret = av7110_fw_request(av7110, buf, 20, &handle, 1);
812 if (ret != 0 || handle >= 32) {
813 printk("dvb-ttpci: %s error buf %04x %04x %04x %04x "
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700814 "ret %d handle %04x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700815 __FUNCTION__, buf[0], buf[1], buf[2], buf[3],
816 ret, handle);
817 dvbdmxfilter->hw_handle = 0xffff;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700818 if (!ret)
819 ret = -1;
820 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821 }
822
823 av7110->handle2filter[handle] = dvbdmxfilter;
824 dvbdmxfilter->hw_handle = handle;
825
826 return ret;
827}
828
829static int StopHWFilter(struct dvb_demux_filter *dvbdmxfilter)
830{
Tobias Klauserd9bdf772006-12-26 07:33:48 -0300831 struct av7110 *av7110 = dvbdmxfilter->feed->demux->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700832 u16 buf[3];
833 u16 answ[2];
834 int ret;
835 u16 handle;
836
837 dprintk(4, "%p\n", av7110);
838
839 handle = dvbdmxfilter->hw_handle;
840 if (handle >= 32) {
841 printk("%s tried to stop invalid filter %04x, filter type = %x\n",
842 __FUNCTION__, handle, dvbdmxfilter->type);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700843 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700844 }
845
846 av7110->handle2filter[handle] = NULL;
847
848 buf[0] = (COMTYPE_PID_FILTER << 8) + DelPIDFilter;
849 buf[1] = 1;
850 buf[2] = handle;
851 ret = av7110_fw_request(av7110, buf, 3, answ, 2);
852 if (ret != 0 || answ[1] != handle) {
853 printk("dvb-ttpci: %s error cmd %04x %04x %04x ret %x "
854 "resp %04x %04x pid %d\n",
855 __FUNCTION__, buf[0], buf[1], buf[2], ret,
856 answ[0], answ[1], dvbdmxfilter->feed->pid);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700857 if (!ret)
858 ret = -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700859 }
860 return ret;
861}
862
863
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700864static int dvb_feed_start_pid(struct dvb_demux_feed *dvbdmxfeed)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700865{
866 struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
Tobias Klauserd9bdf772006-12-26 07:33:48 -0300867 struct av7110 *av7110 = dvbdmx->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700868 u16 *pid = dvbdmx->pids, npids[5];
869 int i;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700870 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700871
872 dprintk(4, "%p\n", av7110);
873
874 npids[0] = npids[1] = npids[2] = npids[3] = npids[4] = 0xffff;
875 i = dvbdmxfeed->pes_type;
876 npids[i] = (pid[i]&0x8000) ? 0 : pid[i];
877 if ((i == 2) && npids[i] && (dvbdmxfeed->ts_type & TS_PACKET)) {
878 npids[i] = 0;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700879 ret = ChangePIDs(av7110, npids[1], npids[0], npids[2], npids[3], npids[4]);
880 if (!ret)
881 ret = StartHWFilter(dvbdmxfeed->filter);
882 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700883 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700884 if (dvbdmxfeed->pes_type <= 2 || dvbdmxfeed->pes_type == 4) {
885 ret = ChangePIDs(av7110, npids[1], npids[0], npids[2], npids[3], npids[4]);
886 if (ret)
887 return ret;
888 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700889
890 if (dvbdmxfeed->pes_type < 2 && npids[0])
891 if (av7110->fe_synced)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700892 {
893 ret = av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, Scan, 0);
894 if (ret)
895 return ret;
896 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700897
898 if ((dvbdmxfeed->ts_type & TS_PACKET)) {
899 if (dvbdmxfeed->pes_type == 0 && !(dvbdmx->pids[0] & 0x8000))
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700900 ret = av7110_av_start_record(av7110, RP_AUDIO, dvbdmxfeed);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901 if (dvbdmxfeed->pes_type == 1 && !(dvbdmx->pids[1] & 0x8000))
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700902 ret = av7110_av_start_record(av7110, RP_VIDEO, dvbdmxfeed);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700903 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700904 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905}
906
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700907static int dvb_feed_stop_pid(struct dvb_demux_feed *dvbdmxfeed)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908{
909 struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
Tobias Klauserd9bdf772006-12-26 07:33:48 -0300910 struct av7110 *av7110 = dvbdmx->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700911 u16 *pid = dvbdmx->pids, npids[5];
912 int i;
913
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700914 int ret = 0;
915
Linus Torvalds1da177e2005-04-16 15:20:36 -0700916 dprintk(4, "%p\n", av7110);
917
918 if (dvbdmxfeed->pes_type <= 1) {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700919 ret = av7110_av_stop(av7110, dvbdmxfeed->pes_type ? RP_VIDEO : RP_AUDIO);
920 if (ret)
921 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700922 if (!av7110->rec_mode)
923 dvbdmx->recording = 0;
924 if (!av7110->playing)
925 dvbdmx->playing = 0;
926 }
927 npids[0] = npids[1] = npids[2] = npids[3] = npids[4] = 0xffff;
928 i = dvbdmxfeed->pes_type;
929 switch (i) {
930 case 2: //teletext
931 if (dvbdmxfeed->ts_type & TS_PACKET)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700932 ret = StopHWFilter(dvbdmxfeed->filter);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700933 npids[2] = 0;
934 break;
935 case 0:
936 case 1:
937 case 4:
938 if (!pids_off)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700939 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700940 npids[i] = (pid[i]&0x8000) ? 0 : pid[i];
941 break;
942 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700943 if (!ret)
944 ret = ChangePIDs(av7110, npids[1], npids[0], npids[2], npids[3], npids[4]);
945 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700946}
947
948static int av7110_start_feed(struct dvb_demux_feed *feed)
949{
950 struct dvb_demux *demux = feed->demux;
951 struct av7110 *av7110 = demux->priv;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700952 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700953
954 dprintk(4, "%p\n", av7110);
955
956 if (!demux->dmx.frontend)
957 return -EINVAL;
958
959 if (feed->pid > 0x1fff)
960 return -EINVAL;
961
962 if (feed->type == DMX_TYPE_TS) {
963 if ((feed->ts_type & TS_DECODER) &&
964 (feed->pes_type < DMX_TS_PES_OTHER)) {
965 switch (demux->dmx.frontend->source) {
966 case DMX_MEMORY_FE:
967 if (feed->ts_type & TS_DECODER)
968 if (feed->pes_type < 2 &&
969 !(demux->pids[0] & 0x8000) &&
970 !(demux->pids[1] & 0x8000)) {
971 dvb_ringbuffer_flush_spinlock_wakeup(&av7110->avout);
972 dvb_ringbuffer_flush_spinlock_wakeup(&av7110->aout);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700973 ret = av7110_av_start_play(av7110,RP_AV);
974 if (!ret)
975 demux->playing = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700976 }
977 break;
978 default:
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700979 ret = dvb_feed_start_pid(feed);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700980 break;
981 }
982 } else if ((feed->ts_type & TS_PACKET) &&
983 (demux->dmx.frontend->source != DMX_MEMORY_FE)) {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700984 ret = StartHWFilter(feed->filter);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700985 }
986 }
987
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700988 else if (feed->type == DMX_TYPE_SEC) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989 int i;
990
991 for (i = 0; i < demux->filternum; i++) {
992 if (demux->filter[i].state != DMX_STATE_READY)
993 continue;
994 if (demux->filter[i].type != DMX_TYPE_SEC)
995 continue;
996 if (demux->filter[i].filter.parent != &feed->feed.sec)
997 continue;
998 demux->filter[i].state = DMX_STATE_GO;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700999 if (demux->dmx.frontend->source != DMX_MEMORY_FE) {
1000 ret = StartHWFilter(&demux->filter[i]);
1001 if (ret)
1002 break;
1003 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001004 }
1005 }
1006
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001007 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001008}
1009
1010
1011static int av7110_stop_feed(struct dvb_demux_feed *feed)
1012{
1013 struct dvb_demux *demux = feed->demux;
1014 struct av7110 *av7110 = demux->priv;
Johannes Stezenbach12ba0502005-07-07 17:58:00 -07001015 int i, rc, ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001016 dprintk(4, "%p\n", av7110);
1017
1018 if (feed->type == DMX_TYPE_TS) {
1019 if (feed->ts_type & TS_DECODER) {
1020 if (feed->pes_type >= DMX_TS_PES_OTHER ||
1021 !demux->pesfilter[feed->pes_type])
1022 return -EINVAL;
1023 demux->pids[feed->pes_type] |= 0x8000;
1024 demux->pesfilter[feed->pes_type] = NULL;
1025 }
1026 if (feed->ts_type & TS_DECODER &&
1027 feed->pes_type < DMX_TS_PES_OTHER) {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001028 ret = dvb_feed_stop_pid(feed);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029 } else
1030 if ((feed->ts_type & TS_PACKET) &&
1031 (demux->dmx.frontend->source != DMX_MEMORY_FE))
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001032 ret = StopHWFilter(feed->filter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033 }
1034
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001035 if (!ret && feed->type == DMX_TYPE_SEC) {
Johannes Stezenbach12ba0502005-07-07 17:58:00 -07001036 for (i = 0; i<demux->filternum; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001037 if (demux->filter[i].state == DMX_STATE_GO &&
1038 demux->filter[i].filter.parent == &feed->feed.sec) {
1039 demux->filter[i].state = DMX_STATE_READY;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001040 if (demux->dmx.frontend->source != DMX_MEMORY_FE) {
Johannes Stezenbach12ba0502005-07-07 17:58:00 -07001041 rc = StopHWFilter(&demux->filter[i]);
1042 if (!ret)
1043 ret = rc;
1044 /* keep going, stop as many filters as possible */
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001045 }
Johannes Stezenbach12ba0502005-07-07 17:58:00 -07001046 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001047 }
1048 }
1049
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001050 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051}
1052
1053
1054static void restart_feeds(struct av7110 *av7110)
1055{
1056 struct dvb_demux *dvbdmx = &av7110->demux;
1057 struct dvb_demux_feed *feed;
1058 int mode;
Oliver Endriss66190a22006-01-09 15:32:42 -02001059 int i, j;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001060
1061 dprintk(4, "%p\n", av7110);
1062
1063 mode = av7110->playing;
1064 av7110->playing = 0;
1065 av7110->rec_mode = 0;
1066
Oliver Endriss66190a22006-01-09 15:32:42 -02001067 for (i = 0; i < dvbdmx->feednum; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068 feed = &dvbdmx->feed[i];
Oliver Endriss66190a22006-01-09 15:32:42 -02001069 if (feed->state == DMX_STATE_GO) {
1070 if (feed->type == DMX_TYPE_SEC) {
1071 for (j = 0; j < dvbdmx->filternum; j++) {
1072 if (dvbdmx->filter[j].type != DMX_TYPE_SEC)
1073 continue;
1074 if (dvbdmx->filter[j].filter.parent != &feed->feed.sec)
1075 continue;
1076 if (dvbdmx->filter[j].state == DMX_STATE_GO)
1077 dvbdmx->filter[j].state = DMX_STATE_READY;
1078 }
1079 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001080 av7110_start_feed(feed);
Oliver Endriss66190a22006-01-09 15:32:42 -02001081 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001082 }
1083
1084 if (mode)
1085 av7110_av_start_play(av7110, mode);
1086}
1087
1088static int dvb_get_stc(struct dmx_demux *demux, unsigned int num,
1089 uint64_t *stc, unsigned int *base)
1090{
1091 int ret;
1092 u16 fwstc[4];
1093 u16 tag = ((COMTYPE_REQUEST << 8) + ReqSTC);
1094 struct dvb_demux *dvbdemux;
1095 struct av7110 *av7110;
1096
1097 /* pointer casting paranoia... */
Eric Sesterhennae246012006-03-13 13:17:11 -03001098 BUG_ON(!demux);
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001099 dvbdemux = demux->priv;
Eric Sesterhennae246012006-03-13 13:17:11 -03001100 BUG_ON(!dvbdemux);
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001101 av7110 = dvbdemux->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001102
1103 dprintk(4, "%p\n", av7110);
1104
1105 if (num != 0)
1106 return -EINVAL;
1107
1108 ret = av7110_fw_request(av7110, &tag, 0, fwstc, 4);
1109 if (ret) {
1110 printk(KERN_ERR "%s: av7110_fw_request error\n", __FUNCTION__);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001111 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001112 }
1113 dprintk(2, "fwstc = %04hx %04hx %04hx %04hx\n",
1114 fwstc[0], fwstc[1], fwstc[2], fwstc[3]);
1115
1116 *stc = (((uint64_t) ((fwstc[3] & 0x8000) >> 15)) << 32) |
1117 (((uint64_t) fwstc[1]) << 16) | ((uint64_t) fwstc[0]);
1118 *base = 1;
1119
1120 dprintk(4, "stc = %lu\n", (unsigned long)*stc);
1121
1122 return 0;
1123}
1124
1125
1126/******************************************************************************
1127 * SEC device file operations
1128 ******************************************************************************/
1129
1130
1131static int av7110_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
1132{
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001133 struct av7110* av7110 = fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001134
1135 switch (tone) {
1136 case SEC_TONE_ON:
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001137 return Set22K(av7110, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001138
1139 case SEC_TONE_OFF:
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001140 return Set22K(av7110, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001141
1142 default:
1143 return -EINVAL;
1144 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001145}
1146
1147static int av7110_diseqc_send_master_cmd(struct dvb_frontend* fe,
1148 struct dvb_diseqc_master_cmd* cmd)
1149{
1150 struct av7110* av7110 = fe->dvb->priv;
1151
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001152 return av7110_diseqc_send(av7110, cmd->msg_len, cmd->msg, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001153}
1154
1155static int av7110_diseqc_send_burst(struct dvb_frontend* fe,
1156 fe_sec_mini_cmd_t minicmd)
1157{
1158 struct av7110* av7110 = fe->dvb->priv;
1159
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001160 return av7110_diseqc_send(av7110, 0, NULL, minicmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001161}
1162
1163/* simplified code from budget-core.c */
1164static int stop_ts_capture(struct av7110 *budget)
1165{
1166 dprintk(2, "budget: %p\n", budget);
1167
1168 if (--budget->feeding1)
1169 return budget->feeding1;
1170 saa7146_write(budget->dev, MC1, MASK_20); /* DMA3 off */
1171 SAA7146_IER_DISABLE(budget->dev, MASK_10);
1172 SAA7146_ISR_CLEAR(budget->dev, MASK_10);
1173 return 0;
1174}
1175
1176static int start_ts_capture(struct av7110 *budget)
1177{
1178 dprintk(2, "budget: %p\n", budget);
1179
1180 if (budget->feeding1)
1181 return ++budget->feeding1;
1182 memset(budget->grabbing, 0x00, TS_HEIGHT * TS_WIDTH);
1183 budget->tsf = 0xff;
1184 budget->ttbp = 0;
1185 SAA7146_IER_ENABLE(budget->dev, MASK_10); /* VPE */
1186 saa7146_write(budget->dev, MC1, (MASK_04 | MASK_20)); /* DMA3 on */
1187 return ++budget->feeding1;
1188}
1189
1190static int budget_start_feed(struct dvb_demux_feed *feed)
1191{
1192 struct dvb_demux *demux = feed->demux;
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001193 struct av7110 *budget = demux->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001194 int status;
1195
1196 dprintk(2, "av7110: %p\n", budget);
1197
1198 spin_lock(&budget->feedlock1);
1199 feed->pusi_seen = 0; /* have a clean section start */
1200 status = start_ts_capture(budget);
1201 spin_unlock(&budget->feedlock1);
1202 return status;
1203}
1204
1205static int budget_stop_feed(struct dvb_demux_feed *feed)
1206{
1207 struct dvb_demux *demux = feed->demux;
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001208 struct av7110 *budget = demux->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001209 int status;
1210
1211 dprintk(2, "budget: %p\n", budget);
1212
1213 spin_lock(&budget->feedlock1);
1214 status = stop_ts_capture(budget);
1215 spin_unlock(&budget->feedlock1);
1216 return status;
1217}
1218
1219static void vpeirq(unsigned long data)
1220{
1221 struct av7110 *budget = (struct av7110 *) data;
1222 u8 *mem = (u8 *) (budget->grabbing);
1223 u32 olddma = budget->ttbp;
1224 u32 newdma = saa7146_read(budget->dev, PCI_VDP3);
1225
1226 if (!budgetpatch) {
1227 printk("av7110.c: vpeirq() called while budgetpatch disabled!"
1228 " check saa7146 IER register\n");
1229 BUG();
1230 }
1231 /* nearest lower position divisible by 188 */
1232 newdma -= newdma % 188;
1233
1234 if (newdma >= TS_BUFLEN)
1235 return;
1236
1237 budget->ttbp = newdma;
1238
1239 if (!budget->feeding1 || (newdma == olddma))
1240 return;
1241
1242#if 0
1243 /* track rps1 activity */
1244 printk("vpeirq: %02x Event Counter 1 0x%04x\n",
1245 mem[olddma],
1246 saa7146_read(budget->dev, EC1R) & 0x3fff);
1247#endif
1248
1249 if (newdma > olddma)
1250 /* no wraparound, dump olddma..newdma */
1251 dvb_dmx_swfilter_packets(&budget->demux1, mem + olddma, (newdma - olddma) / 188);
1252 else {
1253 /* wraparound, dump olddma..buflen and 0..newdma */
1254 dvb_dmx_swfilter_packets(&budget->demux1, mem + olddma, (TS_BUFLEN - olddma) / 188);
1255 dvb_dmx_swfilter_packets(&budget->demux1, mem, newdma / 188);
1256 }
1257}
1258
1259static int av7110_register(struct av7110 *av7110)
1260{
1261 int ret, i;
1262 struct dvb_demux *dvbdemux = &av7110->demux;
1263 struct dvb_demux *dvbdemux1 = &av7110->demux1;
1264
1265 dprintk(4, "%p\n", av7110);
1266
1267 if (av7110->registered)
1268 return -1;
1269
1270 av7110->registered = 1;
1271
1272 dvbdemux->priv = (void *) av7110;
1273
1274 for (i = 0; i < 32; i++)
1275 av7110->handle2filter[i] = NULL;
1276
1277 dvbdemux->filternum = 32;
1278 dvbdemux->feednum = 32;
1279 dvbdemux->start_feed = av7110_start_feed;
1280 dvbdemux->stop_feed = av7110_stop_feed;
1281 dvbdemux->write_to_decoder = av7110_write_to_decoder;
1282 dvbdemux->dmx.capabilities = (DMX_TS_FILTERING | DMX_SECTION_FILTERING |
1283 DMX_MEMORY_BASED_FILTERING);
1284
1285 dvb_dmx_init(&av7110->demux);
1286 av7110->demux.dmx.get_stc = dvb_get_stc;
1287
1288 av7110->dmxdev.filternum = 32;
1289 av7110->dmxdev.demux = &dvbdemux->dmx;
1290 av7110->dmxdev.capabilities = 0;
1291
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001292 dvb_dmxdev_init(&av7110->dmxdev, &av7110->dvb_adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001293
1294 av7110->hw_frontend.source = DMX_FRONTEND_0;
1295
1296 ret = dvbdemux->dmx.add_frontend(&dvbdemux->dmx, &av7110->hw_frontend);
1297
1298 if (ret < 0)
1299 return ret;
1300
1301 av7110->mem_frontend.source = DMX_MEMORY_FE;
1302
1303 ret = dvbdemux->dmx.add_frontend(&dvbdemux->dmx, &av7110->mem_frontend);
1304
1305 if (ret < 0)
1306 return ret;
1307
1308 ret = dvbdemux->dmx.connect_frontend(&dvbdemux->dmx,
1309 &av7110->hw_frontend);
1310 if (ret < 0)
1311 return ret;
1312
1313 av7110_av_register(av7110);
1314 av7110_ca_register(av7110);
1315
1316#ifdef CONFIG_DVB_AV7110_OSD
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001317 dvb_register_device(&av7110->dvb_adapter, &av7110->osd_dev,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001318 &dvbdev_osd, av7110, DVB_DEVICE_OSD);
1319#endif
1320
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001321 dvb_net_init(&av7110->dvb_adapter, &av7110->dvb_net, &dvbdemux->dmx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001322
1323 if (budgetpatch) {
1324 /* initialize software demux1 without its own frontend
1325 * demux1 hardware is connected to frontend0 of demux0
1326 */
1327 dvbdemux1->priv = (void *) av7110;
1328
1329 dvbdemux1->filternum = 256;
1330 dvbdemux1->feednum = 256;
1331 dvbdemux1->start_feed = budget_start_feed;
1332 dvbdemux1->stop_feed = budget_stop_feed;
1333 dvbdemux1->write_to_decoder = NULL;
1334
1335 dvbdemux1->dmx.capabilities = (DMX_TS_FILTERING | DMX_SECTION_FILTERING |
1336 DMX_MEMORY_BASED_FILTERING);
1337
1338 dvb_dmx_init(&av7110->demux1);
1339
1340 av7110->dmxdev1.filternum = 256;
1341 av7110->dmxdev1.demux = &dvbdemux1->dmx;
1342 av7110->dmxdev1.capabilities = 0;
1343
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001344 dvb_dmxdev_init(&av7110->dmxdev1, &av7110->dvb_adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001345
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001346 dvb_net_init(&av7110->dvb_adapter, &av7110->dvb_net1, &dvbdemux1->dmx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001347 printk("dvb-ttpci: additional demux1 for budget-patch registered\n");
1348 }
1349 return 0;
1350}
1351
1352
1353static void dvb_unregister(struct av7110 *av7110)
1354{
1355 struct dvb_demux *dvbdemux = &av7110->demux;
1356 struct dvb_demux *dvbdemux1 = &av7110->demux1;
1357
1358 dprintk(4, "%p\n", av7110);
1359
1360 if (!av7110->registered)
1361 return;
1362
1363 if (budgetpatch) {
1364 dvb_net_release(&av7110->dvb_net1);
1365 dvbdemux->dmx.close(&dvbdemux1->dmx);
1366 dvb_dmxdev_release(&av7110->dmxdev1);
1367 dvb_dmx_release(&av7110->demux1);
1368 }
1369
1370 dvb_net_release(&av7110->dvb_net);
1371
1372 dvbdemux->dmx.close(&dvbdemux->dmx);
1373 dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &av7110->hw_frontend);
1374 dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &av7110->mem_frontend);
1375
1376 dvb_dmxdev_release(&av7110->dmxdev);
1377 dvb_dmx_release(&av7110->demux);
1378
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001379 if (av7110->fe != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001380 dvb_unregister_frontend(av7110->fe);
Andrew de Quinceyf52a8382006-08-08 09:10:09 -03001381 dvb_frontend_detach(av7110->fe);
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001382 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001383 dvb_unregister_device(av7110->osd_dev);
1384 av7110_av_unregister(av7110);
1385 av7110_ca_unregister(av7110);
1386}
1387
1388
1389/****************************************************************************
1390 * I2C client commands
1391 ****************************************************************************/
1392
1393int i2c_writereg(struct av7110 *av7110, u8 id, u8 reg, u8 val)
1394{
1395 u8 msg[2] = { reg, val };
1396 struct i2c_msg msgs;
1397
1398 msgs.flags = 0;
1399 msgs.addr = id / 2;
1400 msgs.len = 2;
1401 msgs.buf = msg;
1402 return i2c_transfer(&av7110->i2c_adap, &msgs, 1);
1403}
1404
1405#if 0
1406u8 i2c_readreg(struct av7110 *av7110, u8 id, u8 reg)
1407{
1408 u8 mm1[] = {0x00};
1409 u8 mm2[] = {0x00};
1410 struct i2c_msg msgs[2];
1411
1412 msgs[0].flags = 0;
1413 msgs[1].flags = I2C_M_RD;
1414 msgs[0].addr = msgs[1].addr = id / 2;
1415 mm1[0] = reg;
1416 msgs[0].len = 1; msgs[1].len = 1;
1417 msgs[0].buf = mm1; msgs[1].buf = mm2;
1418 i2c_transfer(&av7110->i2c_adap, msgs, 2);
1419
1420 return mm2[0];
1421}
1422#endif
1423
1424/****************************************************************************
1425 * INITIALIZATION
1426 ****************************************************************************/
1427
1428
1429static int check_firmware(struct av7110* av7110)
1430{
1431 u32 crc = 0, len = 0;
1432 unsigned char *ptr;
1433
1434 /* check for firmware magic */
1435 ptr = av7110->bin_fw;
1436 if (ptr[0] != 'A' || ptr[1] != 'V' ||
1437 ptr[2] != 'F' || ptr[3] != 'W') {
1438 printk("dvb-ttpci: this is not an av7110 firmware\n");
1439 return -EINVAL;
1440 }
1441 ptr += 4;
1442
1443 /* check dpram file */
1444 crc = ntohl(*(u32*) ptr);
1445 ptr += 4;
1446 len = ntohl(*(u32*) ptr);
1447 ptr += 4;
1448 if (len >= 512) {
Alexey Dobriyanbe787ac2006-03-07 22:20:23 -03001449 printk("dvb-ttpci: dpram file is way too big.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001450 return -EINVAL;
1451 }
1452 if (crc != crc32_le(0, ptr, len)) {
1453 printk("dvb-ttpci: crc32 of dpram file does not match.\n");
1454 return -EINVAL;
1455 }
1456 av7110->bin_dpram = ptr;
1457 av7110->size_dpram = len;
1458 ptr += len;
1459
1460 /* check root file */
1461 crc = ntohl(*(u32*) ptr);
1462 ptr += 4;
1463 len = ntohl(*(u32*) ptr);
1464 ptr += 4;
1465
1466 if (len <= 200000 || len >= 300000 ||
1467 len > ((av7110->bin_fw + av7110->size_fw) - ptr)) {
1468 printk("dvb-ttpci: root file has strange size (%d). aborting.\n", len);
1469 return -EINVAL;
1470 }
1471 if( crc != crc32_le(0, ptr, len)) {
1472 printk("dvb-ttpci: crc32 of root file does not match.\n");
1473 return -EINVAL;
1474 }
1475 av7110->bin_root = ptr;
1476 av7110->size_root = len;
1477 return 0;
1478}
1479
1480#ifdef CONFIG_DVB_AV7110_FIRMWARE_FILE
1481#include "av7110_firm.h"
1482static void put_firmware(struct av7110* av7110)
1483{
1484 av7110->bin_fw = NULL;
1485}
1486
1487static inline int get_firmware(struct av7110* av7110)
1488{
1489 av7110->bin_fw = dvb_ttpci_fw;
1490 av7110->size_fw = sizeof(dvb_ttpci_fw);
1491 return check_firmware(av7110);
1492}
1493#else
1494static void put_firmware(struct av7110* av7110)
1495{
1496 vfree(av7110->bin_fw);
1497}
1498
1499static int get_firmware(struct av7110* av7110)
1500{
1501 int ret;
1502 const struct firmware *fw;
1503
1504 /* request the av7110 firmware, this will block until someone uploads it */
1505 ret = request_firmware(&fw, "dvb-ttpci-01.fw", &av7110->dev->pci->dev);
1506 if (ret) {
1507 if (ret == -ENOENT) {
1508 printk(KERN_ERR "dvb-ttpci: could not load firmware,"
1509 " file not found: dvb-ttpci-01.fw\n");
Ville Skytt\ä12e66f62006-01-09 15:25:38 -02001510 printk(KERN_ERR "dvb-ttpci: usually this should be in "
1511 "/usr/lib/hotplug/firmware or /lib/firmware\n");
1512 printk(KERN_ERR "dvb-ttpci: and can be downloaded from"
Linus Torvalds1da177e2005-04-16 15:20:36 -07001513 " http://www.linuxtv.org/download/dvb/firmware/\n");
1514 } else
1515 printk(KERN_ERR "dvb-ttpci: cannot request firmware"
1516 " (error %i)\n", ret);
1517 return -EINVAL;
1518 }
1519
1520 if (fw->size <= 200000) {
1521 printk("dvb-ttpci: this firmware is way too small.\n");
1522 release_firmware(fw);
1523 return -EINVAL;
1524 }
1525
1526 /* check if the firmware is available */
1527 av7110->bin_fw = (unsigned char *) vmalloc(fw->size);
1528 if (NULL == av7110->bin_fw) {
1529 dprintk(1, "out of memory\n");
1530 release_firmware(fw);
1531 return -ENOMEM;
1532 }
1533
1534 memcpy(av7110->bin_fw, fw->data, fw->size);
1535 av7110->size_fw = fw->size;
1536 if ((ret = check_firmware(av7110)))
1537 vfree(av7110->bin_fw);
1538
1539 release_firmware(fw);
1540 return ret;
1541}
1542#endif
1543
1544
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001545static int alps_bsrv2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001546{
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001547 struct av7110* av7110 = fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001548 u8 pwr = 0;
1549 u8 buf[4];
1550 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
1551 u32 div = (params->frequency + 479500) / 125;
1552
1553 if (params->frequency > 2000000) pwr = 3;
1554 else if (params->frequency > 1800000) pwr = 2;
1555 else if (params->frequency > 1600000) pwr = 1;
1556 else if (params->frequency > 1200000) pwr = 0;
1557 else if (params->frequency >= 1100000) pwr = 1;
1558 else pwr = 2;
1559
1560 buf[0] = (div >> 8) & 0x7f;
1561 buf[1] = div & 0xff;
1562 buf[2] = ((div & 0x18000) >> 10) | 0x95;
1563 buf[3] = (pwr << 6) | 0x30;
1564
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -08001565 // NOTE: since we're using a prescaler of 2, we set the
Linus Torvalds1da177e2005-04-16 15:20:36 -07001566 // divisor frequency to 62.5kHz and divide by 125 above
1567
Patrick Boettcherdea74862006-05-14 05:01:31 -03001568 if (fe->ops.i2c_gate_ctrl)
1569 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001570 if (i2c_transfer (&av7110->i2c_adap, &msg, 1) != 1)
1571 return -EIO;
1572 return 0;
1573}
1574
1575static struct ves1x93_config alps_bsrv2_config = {
1576 .demod_address = 0x08,
1577 .xin = 90100000UL,
1578 .invert_pwm = 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001579};
1580
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001581static int alps_tdbe2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001582{
1583 struct av7110* av7110 = fe->dvb->priv;
1584 u32 div;
1585 u8 data[4];
1586 struct i2c_msg msg = { .addr = 0x62, .flags = 0, .buf = data, .len = sizeof(data) };
1587
1588 div = (params->frequency + 35937500 + 31250) / 62500;
1589
1590 data[0] = (div >> 8) & 0x7f;
1591 data[1] = div & 0xff;
1592 data[2] = 0x85 | ((div >> 10) & 0x60);
1593 data[3] = (params->frequency < 174000000 ? 0x88 : params->frequency < 470000000 ? 0x84 : 0x81);
1594
Patrick Boettcherdea74862006-05-14 05:01:31 -03001595 if (fe->ops.i2c_gate_ctrl)
1596 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001597 if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
1598 return -EIO;
1599 return 0;
1600}
1601
1602static struct ves1820_config alps_tdbe2_config = {
1603 .demod_address = 0x09,
1604 .xin = 57840000UL,
1605 .invert = 1,
1606 .selagc = VES1820_SELAGC_SIGNAMPERR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001607};
1608
1609
1610
1611
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001612static int grundig_29504_451_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001613{
1614 struct av7110* av7110 = fe->dvb->priv;
1615 u32 div;
1616 u8 data[4];
1617 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
1618
1619 div = params->frequency / 125;
1620 data[0] = (div >> 8) & 0x7f;
1621 data[1] = div & 0xff;
1622 data[2] = 0x8e;
1623 data[3] = 0x00;
1624
Patrick Boettcherdea74862006-05-14 05:01:31 -03001625 if (fe->ops.i2c_gate_ctrl)
1626 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001627 if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
1628 return -EIO;
1629 return 0;
1630}
1631
1632static struct tda8083_config grundig_29504_451_config = {
1633 .demod_address = 0x68,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001634};
1635
1636
1637
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001638static int philips_cd1516_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001639{
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -08001640 struct av7110* av7110 = fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001641 u32 div;
1642 u32 f = params->frequency;
1643 u8 data[4];
1644 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
1645
1646 div = (f + 36125000 + 31250) / 62500;
1647
1648 data[0] = (div >> 8) & 0x7f;
1649 data[1] = div & 0xff;
1650 data[2] = 0x8e;
1651 data[3] = (f < 174000000 ? 0xa1 : f < 470000000 ? 0x92 : 0x34);
1652
Patrick Boettcherdea74862006-05-14 05:01:31 -03001653 if (fe->ops.i2c_gate_ctrl)
1654 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001655 if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
1656 return -EIO;
1657 return 0;
1658}
1659
1660static struct ves1820_config philips_cd1516_config = {
1661 .demod_address = 0x09,
1662 .xin = 57840000UL,
1663 .invert = 1,
1664 .selagc = VES1820_SELAGC_SIGNAMPERR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001665};
1666
1667
1668
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001669static int alps_tdlb7_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001670{
1671 struct av7110* av7110 = fe->dvb->priv;
1672 u32 div, pwr;
1673 u8 data[4];
1674 struct i2c_msg msg = { .addr = 0x60, .flags = 0, .buf = data, .len = sizeof(data) };
1675
1676 div = (params->frequency + 36200000) / 166666;
1677
1678 if (params->frequency <= 782000000)
1679 pwr = 1;
1680 else
1681 pwr = 2;
1682
1683 data[0] = (div >> 8) & 0x7f;
1684 data[1] = div & 0xff;
1685 data[2] = 0x85;
1686 data[3] = pwr << 6;
1687
Patrick Boettcherdea74862006-05-14 05:01:31 -03001688 if (fe->ops.i2c_gate_ctrl)
1689 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001690 if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
1691 return -EIO;
1692 return 0;
1693}
1694
1695static int alps_tdlb7_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name)
1696{
Oliver Endrissd98821e2006-09-14 00:15:13 -03001697#if defined(CONFIG_DVB_SP8870) || defined(CONFIG_DVB_SP8870_MODULE)
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001698 struct av7110* av7110 = fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001699
1700 return request_firmware(fw, name, &av7110->dev->pci->dev);
Oliver Endrissd98821e2006-09-14 00:15:13 -03001701#else
1702 return -EINVAL;
1703#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001704}
1705
1706static struct sp8870_config alps_tdlb7_config = {
1707
1708 .demod_address = 0x71,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001709 .request_firmware = alps_tdlb7_request_firmware,
1710};
1711
1712
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001713static u8 nexusca_stv0297_inittab[] = {
1714 0x80, 0x01,
1715 0x80, 0x00,
1716 0x81, 0x01,
1717 0x81, 0x00,
1718 0x00, 0x09,
1719 0x01, 0x69,
1720 0x03, 0x00,
1721 0x04, 0x00,
1722 0x07, 0x00,
1723 0x08, 0x00,
1724 0x20, 0x00,
1725 0x21, 0x40,
1726 0x22, 0x00,
1727 0x23, 0x00,
1728 0x24, 0x40,
1729 0x25, 0x88,
1730 0x30, 0xff,
1731 0x31, 0x00,
1732 0x32, 0xff,
1733 0x33, 0x00,
1734 0x34, 0x50,
1735 0x35, 0x7f,
1736 0x36, 0x00,
1737 0x37, 0x20,
1738 0x38, 0x00,
1739 0x40, 0x1c,
1740 0x41, 0xff,
1741 0x42, 0x29,
1742 0x43, 0x00,
1743 0x44, 0xff,
1744 0x45, 0x00,
1745 0x46, 0x00,
1746 0x49, 0x04,
1747 0x4a, 0x00,
1748 0x4b, 0x7b,
1749 0x52, 0x30,
1750 0x55, 0xae,
1751 0x56, 0x47,
1752 0x57, 0xe1,
1753 0x58, 0x3a,
1754 0x5a, 0x1e,
1755 0x5b, 0x34,
1756 0x60, 0x00,
1757 0x63, 0x00,
1758 0x64, 0x00,
1759 0x65, 0x00,
1760 0x66, 0x00,
1761 0x67, 0x00,
1762 0x68, 0x00,
1763 0x69, 0x00,
1764 0x6a, 0x02,
1765 0x6b, 0x00,
1766 0x70, 0xff,
1767 0x71, 0x00,
1768 0x72, 0x00,
1769 0x73, 0x00,
1770 0x74, 0x0c,
1771 0x80, 0x00,
1772 0x81, 0x00,
1773 0x82, 0x00,
1774 0x83, 0x00,
1775 0x84, 0x04,
1776 0x85, 0x80,
1777 0x86, 0x24,
1778 0x87, 0x78,
1779 0x88, 0x10,
1780 0x89, 0x00,
1781 0x90, 0x01,
1782 0x91, 0x01,
1783 0xa0, 0x04,
1784 0xa1, 0x00,
1785 0xa2, 0x00,
1786 0xb0, 0x91,
1787 0xb1, 0x0b,
1788 0xc0, 0x53,
1789 0xc1, 0x70,
1790 0xc2, 0x12,
1791 0xd0, 0x00,
1792 0xd1, 0x00,
1793 0xd2, 0x00,
1794 0xd3, 0x00,
1795 0xd4, 0x00,
1796 0xd5, 0x00,
1797 0xde, 0x00,
1798 0xdf, 0x00,
1799 0x61, 0x49,
1800 0x62, 0x0b,
1801 0x53, 0x08,
1802 0x59, 0x08,
1803 0xff, 0xff,
1804};
Linus Torvalds1da177e2005-04-16 15:20:36 -07001805
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001806static int nexusca_stv0297_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001807{
1808 struct av7110* av7110 = fe->dvb->priv;
1809 u32 div;
1810 u8 data[4];
1811 struct i2c_msg msg = { .addr = 0x63, .flags = 0, .buf = data, .len = sizeof(data) };
1812 struct i2c_msg readmsg = { .addr = 0x63, .flags = I2C_M_RD, .buf = data, .len = 1 };
1813 int i;
1814
1815 div = (params->frequency + 36150000 + 31250) / 62500;
1816
1817 data[0] = (div >> 8) & 0x7f;
1818 data[1] = div & 0xff;
1819 data[2] = 0xce;
1820
1821 if (params->frequency < 45000000)
1822 return -EINVAL;
1823 else if (params->frequency < 137000000)
1824 data[3] = 0x01;
1825 else if (params->frequency < 403000000)
1826 data[3] = 0x02;
1827 else if (params->frequency < 860000000)
1828 data[3] = 0x04;
1829 else
1830 return -EINVAL;
1831
Patrick Boettcherdea74862006-05-14 05:01:31 -03001832 if (fe->ops.i2c_gate_ctrl)
1833 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001834 if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1) {
1835 printk("nexusca: pll transfer failed!\n");
1836 return -EIO;
1837 }
1838
1839 // wait for PLL lock
1840 for(i = 0; i < 20; i++) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001841 if (fe->ops.i2c_gate_ctrl)
1842 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001843 if (i2c_transfer(&av7110->i2c_adap, &readmsg, 1) == 1)
1844 if (data[0] & 0x40) break;
1845 msleep(10);
1846 }
1847
1848 return 0;
1849}
1850
1851static struct stv0297_config nexusca_stv0297_config = {
1852
1853 .demod_address = 0x1C,
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001854 .inittab = nexusca_stv0297_inittab,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001855 .invert = 1,
Thomas Kaiserb8d4c232006-04-27 21:45:20 -03001856 .stop_during_read = 1,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001857};
1858
1859
1860
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001861static int grundig_29504_401_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001862{
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001863 struct av7110* av7110 = fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001864 u32 div;
1865 u8 cfg, cpump, band_select;
1866 u8 data[4];
1867 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
1868
1869 div = (36125000 + params->frequency) / 166666;
1870
1871 cfg = 0x88;
1872
1873 if (params->frequency < 175000000) cpump = 2;
1874 else if (params->frequency < 390000000) cpump = 1;
1875 else if (params->frequency < 470000000) cpump = 2;
1876 else if (params->frequency < 750000000) cpump = 1;
1877 else cpump = 3;
1878
1879 if (params->frequency < 175000000) band_select = 0x0e;
1880 else if (params->frequency < 470000000) band_select = 0x05;
1881 else band_select = 0x03;
1882
1883 data[0] = (div >> 8) & 0x7f;
1884 data[1] = div & 0xff;
1885 data[2] = ((div >> 10) & 0x60) | cfg;
1886 data[3] = (cpump << 6) | band_select;
1887
Patrick Boettcherdea74862006-05-14 05:01:31 -03001888 if (fe->ops.i2c_gate_ctrl)
1889 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001890 if (i2c_transfer (&av7110->i2c_adap, &msg, 1) != 1) return -EIO;
1891 return 0;
1892}
1893
1894static struct l64781_config grundig_29504_401_config = {
1895 .demod_address = 0x55,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001896};
1897
1898
1899
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001900static int av7110_fe_lock_fix(struct av7110* av7110, fe_status_t status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001901{
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001902 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001903 int synced = (status & FE_HAS_LOCK) ? 1 : 0;
1904
1905 av7110->fe_status = status;
1906
1907 if (av7110->fe_synced == synced)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001908 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001909
Linus Torvalds1da177e2005-04-16 15:20:36 -07001910 if (av7110->playing)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001911 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001912
Ingo Molnar3593cab2006-02-07 06:49:14 -02001913 if (mutex_lock_interruptible(&av7110->pid_mutex))
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001914 return -ERESTARTSYS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001915
Oliver Endriss34612152005-07-07 17:58:02 -07001916 if (synced) {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001917 ret = SetPIDs(av7110, av7110->pids[DMX_PES_VIDEO],
Linus Torvalds1da177e2005-04-16 15:20:36 -07001918 av7110->pids[DMX_PES_AUDIO],
1919 av7110->pids[DMX_PES_TELETEXT], 0,
1920 av7110->pids[DMX_PES_PCR]);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001921 if (!ret)
1922 ret = av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, Scan, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001923 } else {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001924 ret = SetPIDs(av7110, 0, 0, 0, 0, 0);
1925 if (!ret) {
1926 ret = av7110_fw_cmd(av7110, COMTYPE_PID_FILTER, FlushTSQueue, 0);
1927 if (!ret)
1928 ret = av7110_wait_msgstate(av7110, GPMQBusy);
1929 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001930 }
1931
Oliver Endriss34612152005-07-07 17:58:02 -07001932 if (!ret)
1933 av7110->fe_synced = synced;
1934
Ingo Molnar3593cab2006-02-07 06:49:14 -02001935 mutex_unlock(&av7110->pid_mutex);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001936 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001937}
1938
1939static int av7110_fe_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
1940{
1941 struct av7110* av7110 = fe->dvb->priv;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001942
1943 int ret = av7110_fe_lock_fix(av7110, 0);
Oliver Endriss66190a22006-01-09 15:32:42 -02001944 if (!ret) {
1945 av7110->saved_fe_params = *params;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001946 ret = av7110->fe_set_frontend(fe, params);
Oliver Endriss66190a22006-01-09 15:32:42 -02001947 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001948 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001949}
1950
1951static int av7110_fe_init(struct dvb_frontend* fe)
1952{
1953 struct av7110* av7110 = fe->dvb->priv;
1954
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001955 int ret = av7110_fe_lock_fix(av7110, 0);
1956 if (!ret)
1957 ret = av7110->fe_init(fe);
1958 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001959}
1960
1961static int av7110_fe_read_status(struct dvb_frontend* fe, fe_status_t* status)
1962{
1963 struct av7110* av7110 = fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001964
1965 /* call the real implementation */
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001966 int ret = av7110->fe_read_status(fe, status);
1967 if (!ret)
1968 if (((*status ^ av7110->fe_status) & FE_HAS_LOCK) && (*status & FE_HAS_LOCK))
1969 ret = av7110_fe_lock_fix(av7110, *status);
1970 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001971}
1972
1973static int av7110_fe_diseqc_reset_overload(struct dvb_frontend* fe)
1974{
1975 struct av7110* av7110 = fe->dvb->priv;
1976
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001977 int ret = av7110_fe_lock_fix(av7110, 0);
1978 if (!ret)
1979 ret = av7110->fe_diseqc_reset_overload(fe);
1980 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001981}
1982
1983static int av7110_fe_diseqc_send_master_cmd(struct dvb_frontend* fe,
1984 struct dvb_diseqc_master_cmd* cmd)
1985{
1986 struct av7110* av7110 = fe->dvb->priv;
1987
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001988 int ret = av7110_fe_lock_fix(av7110, 0);
Oliver Endriss66190a22006-01-09 15:32:42 -02001989 if (!ret) {
1990 av7110->saved_master_cmd = *cmd;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001991 ret = av7110->fe_diseqc_send_master_cmd(fe, cmd);
Oliver Endriss66190a22006-01-09 15:32:42 -02001992 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001993 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001994}
1995
1996static int av7110_fe_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd)
1997{
1998 struct av7110* av7110 = fe->dvb->priv;
1999
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002000 int ret = av7110_fe_lock_fix(av7110, 0);
Oliver Endriss66190a22006-01-09 15:32:42 -02002001 if (!ret) {
2002 av7110->saved_minicmd = minicmd;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002003 ret = av7110->fe_diseqc_send_burst(fe, minicmd);
Oliver Endriss66190a22006-01-09 15:32:42 -02002004 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002005 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002006}
2007
2008static int av7110_fe_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
2009{
2010 struct av7110* av7110 = fe->dvb->priv;
2011
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002012 int ret = av7110_fe_lock_fix(av7110, 0);
Oliver Endriss66190a22006-01-09 15:32:42 -02002013 if (!ret) {
2014 av7110->saved_tone = tone;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002015 ret = av7110->fe_set_tone(fe, tone);
Oliver Endriss66190a22006-01-09 15:32:42 -02002016 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002017 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002018}
2019
2020static int av7110_fe_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
2021{
2022 struct av7110* av7110 = fe->dvb->priv;
2023
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002024 int ret = av7110_fe_lock_fix(av7110, 0);
Oliver Endriss66190a22006-01-09 15:32:42 -02002025 if (!ret) {
2026 av7110->saved_voltage = voltage;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002027 ret = av7110->fe_set_voltage(fe, voltage);
Oliver Endriss66190a22006-01-09 15:32:42 -02002028 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002029 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002030}
2031
Peter Beutner400b7082006-01-09 15:32:43 -02002032static int av7110_fe_dishnetwork_send_legacy_command(struct dvb_frontend* fe, unsigned long cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002033{
2034 struct av7110* av7110 = fe->dvb->priv;
2035
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002036 int ret = av7110_fe_lock_fix(av7110, 0);
2037 if (!ret)
2038 ret = av7110->fe_dishnetwork_send_legacy_command(fe, cmd);
2039 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002040}
2041
Oliver Endriss66190a22006-01-09 15:32:42 -02002042static void dvb_s_recover(struct av7110* av7110)
2043{
2044 av7110_fe_init(av7110->fe);
2045
2046 av7110_fe_set_voltage(av7110->fe, av7110->saved_voltage);
2047 if (av7110->saved_master_cmd.msg_len) {
2048 msleep(20);
2049 av7110_fe_diseqc_send_master_cmd(av7110->fe, &av7110->saved_master_cmd);
2050 }
2051 msleep(20);
2052 av7110_fe_diseqc_send_burst(av7110->fe, av7110->saved_minicmd);
2053 msleep(20);
2054 av7110_fe_set_tone(av7110->fe, av7110->saved_tone);
2055
2056 av7110_fe_set_frontend(av7110->fe, &av7110->saved_fe_params);
2057}
2058
Linus Torvalds1da177e2005-04-16 15:20:36 -07002059static u8 read_pwm(struct av7110* av7110)
2060{
2061 u8 b = 0xff;
2062 u8 pwm;
2063 struct i2c_msg msg[] = { { .addr = 0x50,.flags = 0,.buf = &b,.len = 1 },
2064 { .addr = 0x50,.flags = I2C_M_RD,.buf = &pwm,.len = 1} };
2065
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -08002066 if ((i2c_transfer(&av7110->i2c_adap, msg, 2) != 2) || (pwm == 0xff))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002067 pwm = 0x48;
2068
2069 return pwm;
2070}
2071
2072static int frontend_init(struct av7110 *av7110)
2073{
2074 int ret;
2075
2076 if (av7110->dev->pci->subsystem_vendor == 0x110a) {
2077 switch(av7110->dev->pci->subsystem_device) {
2078 case 0x0000: // Fujitsu/Siemens DVB-Cable (ves1820/Philips CD1516(??))
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002079 av7110->fe = dvb_attach(ves1820_attach, &philips_cd1516_config,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002080 &av7110->i2c_adap, read_pwm(av7110));
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002081 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002082 av7110->fe->ops.tuner_ops.set_params = philips_cd1516_tuner_set_params;
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002083 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002084 break;
2085 }
2086
2087 } else if (av7110->dev->pci->subsystem_vendor == 0x13c2) {
2088 switch(av7110->dev->pci->subsystem_device) {
2089 case 0x0000: // Hauppauge/TT WinTV DVB-S rev1.X
2090 case 0x0003: // Hauppauge/TT WinTV Nexus-S Rev 2.X
2091 case 0x1002: // Hauppauge/TT WinTV DVB-S rev1.3SE
2092
2093 // try the ALPS BSRV2 first of all
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002094 av7110->fe = dvb_attach(ves1x93_attach, &alps_bsrv2_config, &av7110->i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002095 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002096 av7110->fe->ops.tuner_ops.set_params = alps_bsrv2_tuner_set_params;
2097 av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
2098 av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
2099 av7110->fe->ops.set_tone = av7110_set_tone;
Oliver Endriss66190a22006-01-09 15:32:42 -02002100 av7110->recover = dvb_s_recover;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002101 break;
2102 }
2103
2104 // try the ALPS BSRU6 now
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002105 av7110->fe = dvb_attach(stv0299_attach, &alps_bsru6_config, &av7110->i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002106 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002107 av7110->fe->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03002108 av7110->fe->tuner_priv = &av7110->i2c_adap;
2109
Patrick Boettcherdea74862006-05-14 05:01:31 -03002110 av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
2111 av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
2112 av7110->fe->ops.set_tone = av7110_set_tone;
Oliver Endriss66190a22006-01-09 15:32:42 -02002113 av7110->recover = dvb_s_recover;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002114 break;
2115 }
2116
2117 // Try the grundig 29504-451
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002118 av7110->fe = dvb_attach(tda8083_attach, &grundig_29504_451_config, &av7110->i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002119 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002120 av7110->fe->ops.tuner_ops.set_params = grundig_29504_451_tuner_set_params;
2121 av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
2122 av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
2123 av7110->fe->ops.set_tone = av7110_set_tone;
Oliver Endriss66190a22006-01-09 15:32:42 -02002124 av7110->recover = dvb_s_recover;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002125 break;
2126 }
2127
2128 /* Try DVB-C cards */
2129 switch(av7110->dev->pci->subsystem_device) {
2130 case 0x0000:
2131 /* Siemens DVB-C (full-length card) VES1820/Philips CD1516 */
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002132 av7110->fe = dvb_attach(ves1820_attach, &philips_cd1516_config, &av7110->i2c_adap,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002133 read_pwm(av7110));
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002134 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002135 av7110->fe->ops.tuner_ops.set_params = philips_cd1516_tuner_set_params;
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002136 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002137 break;
2138 case 0x0003:
Adrian Bunkf3688fc2006-03-29 22:46:12 -03002139 /* Hauppauge DVB-C 2.1 VES1820/ALPS TDBE2 */
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002140 av7110->fe = dvb_attach(ves1820_attach, &alps_tdbe2_config, &av7110->i2c_adap,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002141 read_pwm(av7110));
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002142 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002143 av7110->fe->ops.tuner_ops.set_params = alps_tdbe2_tuner_set_params;
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002144 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002145 break;
2146 }
2147 break;
2148
2149 case 0x0001: // Hauppauge/TT Nexus-T premium rev1.X
Oliver Endriss8d90ee52006-08-07 02:04:26 -03002150 // try ALPS TDLB7 first, then Grundig 29504-401
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002151 av7110->fe = dvb_attach(sp8870_attach, &alps_tdlb7_config, &av7110->i2c_adap);
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002152 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002153 av7110->fe->ops.tuner_ops.set_params = alps_tdlb7_tuner_set_params;
Oliver Endriss8d90ee52006-08-07 02:04:26 -03002154 break;
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002155 }
Oliver Endriss8d90ee52006-08-07 02:04:26 -03002156 /* fall-thru */
2157
2158 case 0x0008: // Hauppauge/TT DVB-T
2159 // Grundig 29504-401
2160 av7110->fe = dvb_attach(l64781_attach, &grundig_29504_401_config, &av7110->i2c_adap);
2161 if (av7110->fe)
2162 av7110->fe->ops.tuner_ops.set_params = grundig_29504_401_tuner_set_params;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002163 break;
2164
2165 case 0x0002: // Hauppauge/TT DVB-C premium rev2.X
2166
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002167 av7110->fe = dvb_attach(ves1820_attach, &alps_tdbe2_config, &av7110->i2c_adap, read_pwm(av7110));
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002168 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002169 av7110->fe->ops.tuner_ops.set_params = alps_tdbe2_tuner_set_params;
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002170 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002171 break;
2172
Oliver Endriss8bd63012006-02-07 06:49:11 -02002173 case 0x0004: // Galaxis DVB-S rev1.3
2174 /* ALPS BSRV2 */
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002175 av7110->fe = dvb_attach(ves1x93_attach, &alps_bsrv2_config, &av7110->i2c_adap);
Oliver Endriss8bd63012006-02-07 06:49:11 -02002176 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002177 av7110->fe->ops.tuner_ops.set_params = alps_bsrv2_tuner_set_params;
2178 av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
2179 av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
2180 av7110->fe->ops.set_tone = av7110_set_tone;
Oliver Endriss8bd63012006-02-07 06:49:11 -02002181 av7110->recover = dvb_s_recover;
2182 }
2183 break;
2184
Linus Torvalds1da177e2005-04-16 15:20:36 -07002185 case 0x0006: /* Fujitsu-Siemens DVB-S rev 1.6 */
2186 /* Grundig 29504-451 */
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002187 av7110->fe = dvb_attach(tda8083_attach, &grundig_29504_451_config, &av7110->i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002188 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002189 av7110->fe->ops.tuner_ops.set_params = grundig_29504_451_tuner_set_params;
2190 av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
2191 av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
2192 av7110->fe->ops.set_tone = av7110_set_tone;
Oliver Endriss66190a22006-01-09 15:32:42 -02002193 av7110->recover = dvb_s_recover;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002194 }
2195 break;
2196
Linus Torvalds1da177e2005-04-16 15:20:36 -07002197 case 0x000A: // Hauppauge/TT Nexus-CA rev1.X
2198
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002199 av7110->fe = dvb_attach(stv0297_attach, &nexusca_stv0297_config, &av7110->i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002200 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002201 av7110->fe->ops.tuner_ops.set_params = nexusca_stv0297_tuner_set_params;
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03002202
Linus Torvalds1da177e2005-04-16 15:20:36 -07002203 /* set TDA9819 into DVB mode */
Marco Schluessler6a857742006-07-10 03:34:16 -03002204 saa7146_setgpio(av7110->dev, 1, SAA7146_GPIO_OUTLO); // TDA9819 pin9(STD)
2205 saa7146_setgpio(av7110->dev, 3, SAA7146_GPIO_OUTLO); // TDA9819 pin30(VIF)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002206
2207 /* tuner on this needs a slower i2c bus speed */
2208 av7110->dev->i2c_bitrate = SAA7146_I2C_BUS_BIT_RATE_240;
2209 break;
2210 }
Johannes Stezenbach3dfaebd2005-05-16 21:54:19 -07002211 break;
2212
2213 case 0x000E: /* Hauppauge/TT Nexus-S rev 2.3 */
2214 /* ALPS BSBE1 */
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002215 av7110->fe = dvb_attach(stv0299_attach, &alps_bsbe1_config, &av7110->i2c_adap);
Oliver Endrisseb3daf32006-01-09 15:25:05 -02002216 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002217 av7110->fe->ops.tuner_ops.set_params = alps_bsbe1_tuner_set_params;
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03002218 av7110->fe->tuner_priv = &av7110->i2c_adap;
2219
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002220 if (dvb_attach(lnbp21_attach, av7110->fe, &av7110->i2c_adap, 0, 0) == NULL) {
Oliver Endrissdb5d91e2006-02-28 10:32:25 -03002221 printk("dvb-ttpci: LNBP21 not found!\n");
Patrick Boettcherdea74862006-05-14 05:01:31 -03002222 if (av7110->fe->ops.release)
2223 av7110->fe->ops.release(av7110->fe);
Oliver Endrissdb5d91e2006-02-28 10:32:25 -03002224 av7110->fe = NULL;
2225 } else {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002226 av7110->fe->ops.dishnetwork_send_legacy_command = NULL;
Oliver Endrissdb5d91e2006-02-28 10:32:25 -03002227 av7110->recover = dvb_s_recover;
2228 }
Oliver Endrisseb3daf32006-01-09 15:25:05 -02002229 }
Johannes Stezenbach3dfaebd2005-05-16 21:54:19 -07002230 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002231 }
2232 }
2233
2234 if (!av7110->fe) {
2235 /* FIXME: propagate the failure code from the lower layers */
2236 ret = -ENOMEM;
2237 printk("dvb-ttpci: A frontend driver was not found for device %04x/%04x subsystem %04x/%04x\n",
2238 av7110->dev->pci->vendor,
2239 av7110->dev->pci->device,
2240 av7110->dev->pci->subsystem_vendor,
2241 av7110->dev->pci->subsystem_device);
2242 } else {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002243 FE_FUNC_OVERRIDE(av7110->fe->ops.init, av7110->fe_init, av7110_fe_init);
2244 FE_FUNC_OVERRIDE(av7110->fe->ops.read_status, av7110->fe_read_status, av7110_fe_read_status);
2245 FE_FUNC_OVERRIDE(av7110->fe->ops.diseqc_reset_overload, av7110->fe_diseqc_reset_overload, av7110_fe_diseqc_reset_overload);
2246 FE_FUNC_OVERRIDE(av7110->fe->ops.diseqc_send_master_cmd, av7110->fe_diseqc_send_master_cmd, av7110_fe_diseqc_send_master_cmd);
2247 FE_FUNC_OVERRIDE(av7110->fe->ops.diseqc_send_burst, av7110->fe_diseqc_send_burst, av7110_fe_diseqc_send_burst);
2248 FE_FUNC_OVERRIDE(av7110->fe->ops.set_tone, av7110->fe_set_tone, av7110_fe_set_tone);
2249 FE_FUNC_OVERRIDE(av7110->fe->ops.set_voltage, av7110->fe_set_voltage, av7110_fe_set_voltage;)
2250 FE_FUNC_OVERRIDE(av7110->fe->ops.dishnetwork_send_legacy_command, av7110->fe_dishnetwork_send_legacy_command, av7110_fe_dishnetwork_send_legacy_command);
2251 FE_FUNC_OVERRIDE(av7110->fe->ops.set_frontend, av7110->fe_set_frontend, av7110_fe_set_frontend);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002252
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07002253 ret = dvb_register_frontend(&av7110->dvb_adapter, av7110->fe);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002254 if (ret < 0) {
2255 printk("av7110: Frontend registration failed!\n");
Andrew de Quinceyf52a8382006-08-08 09:10:09 -03002256 dvb_frontend_detach(av7110->fe);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002257 av7110->fe = NULL;
2258 }
2259 }
2260 return ret;
2261}
2262
2263/* Budgetpatch note:
2264 * Original hardware design by Roberto Deza:
2265 * There is a DVB_Wiki at
2266 * http://212.227.36.83/linuxtv/wiki/index.php/Main_Page
2267 * where is described this 'DVB TT Budget Patch', on Card Modding:
2268 * http://212.227.36.83/linuxtv/wiki/index.php/DVB_TT_Budget_Patch
2269 * On the short description there is also a link to a external file,
2270 * with more details:
2271 * http://perso.wanadoo.es/jesussolano/Ttf_tsc1.zip
2272 *
2273 * New software triggering design by Emard that works on
2274 * original Roberto Deza's hardware:
2275 *
2276 * rps1 code for budgetpatch will copy internal HS event to GPIO3 pin.
2277 * GPIO3 is in budget-patch hardware connectd to port B VSYNC
2278 * HS is an internal event of 7146, accessible with RPS
2279 * and temporarily raised high every n lines
2280 * (n in defined in the RPS_THRESH1 counter threshold)
2281 * I think HS is raised high on the beginning of the n-th line
2282 * and remains high until this n-th line that triggered
2283 * it is completely received. When the receiption of n-th line
2284 * ends, HS is lowered.
2285 *
2286 * To transmit data over DMA, 7146 needs changing state at
2287 * port B VSYNC pin. Any changing of port B VSYNC will
2288 * cause some DMA data transfer, with more or less packets loss.
2289 * It depends on the phase and frequency of VSYNC and
2290 * the way of 7146 is instructed to trigger on port B (defined
2291 * in DD1_INIT register, 3rd nibble from the right valid
2292 * numbers are 0-7, see datasheet)
2293 *
2294 * The correct triggering can minimize packet loss,
2295 * dvbtraffic should give this stable bandwidths:
2296 * 22k transponder = 33814 kbit/s
2297 * 27.5k transponder = 38045 kbit/s
2298 * by experiment it is found that the best results
2299 * (stable bandwidths and almost no packet loss)
2300 * are obtained using DD1_INIT triggering number 2
2301 * (Va at rising edge of VS Fa = HS x VS-failing forced toggle)
2302 * and a VSYNC phase that occurs in the middle of DMA transfer
2303 * (about byte 188*512=96256 in the DMA window).
2304 *
2305 * Phase of HS is still not clear to me how to control,
2306 * It just happens to be so. It can be seen if one enables
2307 * RPS_IRQ and print Event Counter 1 in vpeirq(). Every
2308 * time RPS_INTERRUPT is called, the Event Counter 1 will
2309 * increment. That's how the 7146 is programmed to do event
2310 * counting in this budget-patch.c
2311 * I *think* HPS setting has something to do with the phase
2312 * of HS but I cant be 100% sure in that.
2313 *
2314 * hardware debug note: a working budget card (including budget patch)
2315 * with vpeirq() interrupt setup in mode "0x90" (every 64K) will
2316 * generate 3 interrupts per 25-Hz DMA frame of 2*188*512 bytes
2317 * and that means 3*25=75 Hz of interrupt freqency, as seen by
2318 * watch cat /proc/interrupts
2319 *
2320 * If this frequency is 3x lower (and data received in the DMA
2321 * buffer don't start with 0x47, but in the middle of packets,
2322 * whose lengths appear to be like 188 292 188 104 etc.
2323 * this means VSYNC line is not connected in the hardware.
2324 * (check soldering pcb and pins)
2325 * The same behaviour of missing VSYNC can be duplicated on budget
2326 * cards, by seting DD1_INIT trigger mode 7 in 3rd nibble.
2327 */
Johannes Stezenbach1be11e32006-02-27 00:09:20 -03002328static int __devinit av7110_attach(struct saa7146_dev* dev,
2329 struct saa7146_pci_extension_data *pci_ext)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002330{
2331 const int length = TS_WIDTH * TS_HEIGHT;
2332 struct pci_dev *pdev = dev->pci;
2333 struct av7110 *av7110;
Herbert Poetzl8eec1422007-02-08 14:32:43 -03002334 struct task_struct *thread;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002335 int ret, count = 0;
2336
2337 dprintk(4, "dev: %p\n", dev);
2338
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -08002339 /* Set RPS_IRQ to 1 to track rps1 activity.
2340 * Enabling this won't send any interrupt to PC CPU.
2341 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002342#define RPS_IRQ 0
2343
2344 if (budgetpatch == 1) {
2345 budgetpatch = 0;
2346 /* autodetect the presence of budget patch
2347 * this only works if saa7146 has been recently
2348 * reset with with MASK_31 to MC1
2349 *
2350 * will wait for VBI_B event (vertical blank at port B)
2351 * and will reset GPIO3 after VBI_B is detected.
2352 * (GPIO3 should be raised high by CPU to
2353 * test if GPIO3 will generate vertical blank signal
2354 * in budget patch GPIO3 is connected to VSYNC_B
2355 */
2356
2357 /* RESET SAA7146 */
2358 saa7146_write(dev, MC1, MASK_31);
2359 /* autodetection success seems to be time-dependend after reset */
2360
2361 /* Fix VSYNC level */
2362 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
2363 /* set vsync_b triggering */
2364 saa7146_write(dev, DD1_STREAM_B, 0);
2365 /* port B VSYNC at rising edge */
2366 saa7146_write(dev, DD1_INIT, 0x00000200);
2367 saa7146_write(dev, BRS_CTRL, 0x00000000); // VBI
2368 saa7146_write(dev, MC2,
2369 1 * (MASK_08 | MASK_24) | // BRS control
2370 0 * (MASK_09 | MASK_25) | // a
2371 1 * (MASK_10 | MASK_26) | // b
2372 0 * (MASK_06 | MASK_22) | // HPS_CTRL1
2373 0 * (MASK_05 | MASK_21) | // HPS_CTRL2
2374 0 * (MASK_01 | MASK_15) // DEBI
2375 );
2376
2377 /* start writing RPS1 code from beginning */
2378 count = 0;
2379 /* Disable RPS1 */
2380 saa7146_write(dev, MC1, MASK_29);
2381 /* RPS1 timeout disable */
2382 saa7146_write(dev, RPS_TOV1, 0);
2383 WRITE_RPS1(cpu_to_le32(CMD_PAUSE | EVT_VBI_B));
2384 WRITE_RPS1(cpu_to_le32(CMD_WR_REG_MASK | (GPIO_CTRL>>2)));
2385 WRITE_RPS1(cpu_to_le32(GPIO3_MSK));
2386 WRITE_RPS1(cpu_to_le32(SAA7146_GPIO_OUTLO<<24));
2387#if RPS_IRQ
2388 /* issue RPS1 interrupt to increment counter */
2389 WRITE_RPS1(cpu_to_le32(CMD_INTERRUPT));
2390#endif
2391 WRITE_RPS1(cpu_to_le32(CMD_STOP));
2392 /* Jump to begin of RPS program as safety measure (p37) */
2393 WRITE_RPS1(cpu_to_le32(CMD_JUMP));
2394 WRITE_RPS1(cpu_to_le32(dev->d_rps1.dma_handle));
2395
2396#if RPS_IRQ
2397 /* set event counter 1 source as RPS1 interrupt (0x03) (rE4 p53)
2398 * use 0x03 to track RPS1 interrupts - increase by 1 every gpio3 is toggled
2399 * use 0x15 to track VPE interrupts - increase by 1 every vpeirq() is called
2400 */
2401 saa7146_write(dev, EC1SSR, (0x03<<2) | 3 );
2402 /* set event counter 1 treshold to maximum allowed value (rEC p55) */
2403 saa7146_write(dev, ECT1R, 0x3fff );
2404#endif
2405 /* Set RPS1 Address register to point to RPS code (r108 p42) */
2406 saa7146_write(dev, RPS_ADDR1, dev->d_rps1.dma_handle);
2407 /* Enable RPS1, (rFC p33) */
2408 saa7146_write(dev, MC1, (MASK_13 | MASK_29 ));
2409
2410 mdelay(10);
2411 /* now send VSYNC_B to rps1 by rising GPIO3 */
2412 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI);
2413 mdelay(10);
2414 /* if rps1 responded by lowering the GPIO3,
2415 * then we have budgetpatch hardware
2416 */
2417 if ((saa7146_read(dev, GPIO_CTRL) & 0x10000000) == 0) {
2418 budgetpatch = 1;
2419 printk("dvb-ttpci: BUDGET-PATCH DETECTED.\n");
2420 }
2421 /* Disable RPS1 */
2422 saa7146_write(dev, MC1, ( MASK_29 ));
2423#if RPS_IRQ
2424 printk("dvb-ttpci: Event Counter 1 0x%04x\n", saa7146_read(dev, EC1R) & 0x3fff );
2425#endif
2426 }
2427
2428 /* prepare the av7110 device struct */
Panagiotis Issaris74081872006-01-11 19:40:56 -02002429 av7110 = kzalloc(sizeof(struct av7110), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002430 if (!av7110) {
2431 dprintk(1, "out of memory\n");
2432 return -ENOMEM;
2433 }
2434
Linus Torvalds1da177e2005-04-16 15:20:36 -07002435 av7110->card_name = (char*) pci_ext->ext_priv;
2436 av7110->dev = dev;
2437 dev->ext_priv = av7110;
2438
2439 ret = get_firmware(av7110);
2440 if (ret < 0)
2441 goto err_kfree_0;
2442
2443 ret = dvb_register_adapter(&av7110->dvb_adapter, av7110->card_name,
Andrew de Quinceyd09dbf92006-04-10 09:27:37 -03002444 THIS_MODULE, &dev->pci->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002445 if (ret < 0)
2446 goto err_put_firmware_1;
2447
2448 /* the Siemens DVB needs this if you want to have the i2c chips
2449 get recognized before the main driver is fully loaded */
2450 saa7146_write(dev, GPIO_CTRL, 0x500000);
2451
2452#ifdef I2C_ADAP_CLASS_TV_DIGITAL
2453 av7110->i2c_adap.class = I2C_ADAP_CLASS_TV_DIGITAL;
2454#else
2455 av7110->i2c_adap.class = I2C_CLASS_TV_DIGITAL;
2456#endif
2457 strlcpy(av7110->i2c_adap.name, pci_ext->ext_priv, sizeof(av7110->i2c_adap.name));
2458
2459 saa7146_i2c_adapter_prepare(dev, &av7110->i2c_adap, SAA7146_I2C_BUS_BIT_RATE_120); /* 275 kHz */
2460
2461 ret = i2c_add_adapter(&av7110->i2c_adap);
2462 if (ret < 0)
2463 goto err_dvb_unregister_adapter_2;
2464
2465 ttpci_eeprom_parse_mac(&av7110->i2c_adap,
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07002466 av7110->dvb_adapter.proposed_mac);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002467 ret = -ENOMEM;
2468
2469 if (budgetpatch) {
2470 spin_lock_init(&av7110->feedlock1);
2471 av7110->grabbing = saa7146_vmalloc_build_pgtable(pdev, length,
2472 &av7110->pt);
2473 if (!av7110->grabbing)
2474 goto err_i2c_del_3;
2475
2476 saa7146_write(dev, PCI_BT_V1, 0x1c1f101f);
2477 saa7146_write(dev, BCS_CTRL, 0x80400040);
2478 /* set dd1 stream a & b */
2479 saa7146_write(dev, DD1_STREAM_B, 0x00000000);
2480 saa7146_write(dev, DD1_INIT, 0x03000200);
2481 saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
2482 saa7146_write(dev, BRS_CTRL, 0x60000000);
2483 saa7146_write(dev, BASE_ODD3, 0);
2484 saa7146_write(dev, BASE_EVEN3, 0);
2485 saa7146_write(dev, PROT_ADDR3, TS_WIDTH * TS_HEIGHT);
2486 saa7146_write(dev, BASE_PAGE3, av7110->pt.dma | ME1 | 0x90);
2487
2488 saa7146_write(dev, PITCH3, TS_WIDTH);
2489 saa7146_write(dev, NUM_LINE_BYTE3, (TS_HEIGHT << 16) | TS_WIDTH);
2490
2491 /* upload all */
2492 saa7146_write(dev, MC2, 0x077c077c);
2493 saa7146_write(dev, GPIO_CTRL, 0x000000);
2494#if RPS_IRQ
2495 /* set event counter 1 source as RPS1 interrupt (0x03) (rE4 p53)
2496 * use 0x03 to track RPS1 interrupts - increase by 1 every gpio3 is toggled
2497 * use 0x15 to track VPE interrupts - increase by 1 every vpeirq() is called
2498 */
2499 saa7146_write(dev, EC1SSR, (0x03<<2) | 3 );
2500 /* set event counter 1 treshold to maximum allowed value (rEC p55) */
2501 saa7146_write(dev, ECT1R, 0x3fff );
2502#endif
2503 /* Setup BUDGETPATCH MAIN RPS1 "program" (p35) */
2504 count = 0;
2505
2506 /* Wait Source Line Counter Threshold (p36) */
2507 WRITE_RPS1(cpu_to_le32(CMD_PAUSE | EVT_HS));
2508 /* Set GPIO3=1 (p42) */
2509 WRITE_RPS1(cpu_to_le32(CMD_WR_REG_MASK | (GPIO_CTRL>>2)));
2510 WRITE_RPS1(cpu_to_le32(GPIO3_MSK));
2511 WRITE_RPS1(cpu_to_le32(SAA7146_GPIO_OUTHI<<24));
2512#if RPS_IRQ
2513 /* issue RPS1 interrupt */
2514 WRITE_RPS1(cpu_to_le32(CMD_INTERRUPT));
2515#endif
2516 /* Wait reset Source Line Counter Threshold (p36) */
2517 WRITE_RPS1(cpu_to_le32(CMD_PAUSE | RPS_INV | EVT_HS));
2518 /* Set GPIO3=0 (p42) */
2519 WRITE_RPS1(cpu_to_le32(CMD_WR_REG_MASK | (GPIO_CTRL>>2)));
2520 WRITE_RPS1(cpu_to_le32(GPIO3_MSK));
2521 WRITE_RPS1(cpu_to_le32(SAA7146_GPIO_OUTLO<<24));
2522#if RPS_IRQ
2523 /* issue RPS1 interrupt */
2524 WRITE_RPS1(cpu_to_le32(CMD_INTERRUPT));
2525#endif
2526 /* Jump to begin of RPS program (p37) */
2527 WRITE_RPS1(cpu_to_le32(CMD_JUMP));
2528 WRITE_RPS1(cpu_to_le32(dev->d_rps1.dma_handle));
2529
2530 /* Fix VSYNC level */
2531 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
2532 /* Set RPS1 Address register to point to RPS code (r108 p42) */
2533 saa7146_write(dev, RPS_ADDR1, dev->d_rps1.dma_handle);
2534 /* Set Source Line Counter Threshold, using BRS (rCC p43)
2535 * It generates HS event every TS_HEIGHT lines
2536 * this is related to TS_WIDTH set in register
2537 * NUM_LINE_BYTE3. If NUM_LINE_BYTE low 16 bits
2538 * are set to TS_WIDTH bytes (TS_WIDTH=2*188),
2539 * then RPS_THRESH1 should be set to trigger
2540 * every TS_HEIGHT (512) lines.
2541 */
2542 saa7146_write(dev, RPS_THRESH1, (TS_HEIGHT*1) | MASK_12 );
2543
2544 /* Enable RPS1 (rFC p33) */
2545 saa7146_write(dev, MC1, (MASK_13 | MASK_29));
2546
2547 /* end of budgetpatch register initialization */
2548 tasklet_init (&av7110->vpe_tasklet, vpeirq, (unsigned long) av7110);
2549 } else {
2550 saa7146_write(dev, PCI_BT_V1, 0x1c00101f);
2551 saa7146_write(dev, BCS_CTRL, 0x80400040);
2552
2553 /* set dd1 stream a & b */
2554 saa7146_write(dev, DD1_STREAM_B, 0x00000000);
2555 saa7146_write(dev, DD1_INIT, 0x03000000);
2556 saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
2557
2558 /* upload all */
2559 saa7146_write(dev, MC2, 0x077c077c);
2560 saa7146_write(dev, GPIO_CTRL, 0x000000);
2561 }
2562
2563 tasklet_init (&av7110->debi_tasklet, debiirq, (unsigned long) av7110);
2564 tasklet_init (&av7110->gpio_tasklet, gpioirq, (unsigned long) av7110);
2565
Ingo Molnar3593cab2006-02-07 06:49:14 -02002566 mutex_init(&av7110->pid_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002567
2568 /* locks for data transfers from/to AV7110 */
2569 spin_lock_init(&av7110->debilock);
Ingo Molnar3593cab2006-02-07 06:49:14 -02002570 mutex_init(&av7110->dcomlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002571 av7110->debitype = -1;
2572
2573 /* default OSD window */
2574 av7110->osdwin = 1;
Ingo Molnar3593cab2006-02-07 06:49:14 -02002575 mutex_init(&av7110->osd_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002576
C.Y.M2f03ee82006-03-30 04:31:48 -03002577 /* TV standard */
2578 av7110->vidmode = tv_standard == 1 ? VIDEO_MODE_NTSC : VIDEO_MODE_PAL;
2579
Linus Torvalds1da177e2005-04-16 15:20:36 -07002580 /* ARM "watchdog" */
2581 init_waitqueue_head(&av7110->arm_wait);
2582 av7110->arm_thread = NULL;
2583
2584 /* allocate and init buffers */
2585 av7110->debi_virt = pci_alloc_consistent(pdev, 8192, &av7110->debi_bus);
2586 if (!av7110->debi_virt)
2587 goto err_saa71466_vfree_4;
2588
2589
2590 av7110->iobuf = vmalloc(AVOUTLEN+AOUTLEN+BMPLEN+4*IPACKS);
2591 if (!av7110->iobuf)
2592 goto err_pci_free_5;
2593
2594 ret = av7110_av_init(av7110);
2595 if (ret < 0)
2596 goto err_iobuf_vfree_6;
2597
2598 /* init BMP buffer */
2599 av7110->bmpbuf = av7110->iobuf+AVOUTLEN+AOUTLEN;
2600 init_waitqueue_head(&av7110->bmpq);
2601
2602 ret = av7110_ca_init(av7110);
2603 if (ret < 0)
2604 goto err_av7110_av_exit_7;
2605
2606 /* load firmware into AV7110 cards */
2607 ret = av7110_bootarm(av7110);
2608 if (ret < 0)
2609 goto err_av7110_ca_exit_8;
2610
2611 ret = av7110_firmversion(av7110);
2612 if (ret < 0)
2613 goto err_stop_arm_9;
2614
2615 if (FW_VERSION(av7110->arm_app)<0x2501)
2616 printk ("dvb-ttpci: Warning, firmware version 0x%04x is too old. "
2617 "System might be unstable!\n", FW_VERSION(av7110->arm_app));
2618
Herbert Poetzl8eec1422007-02-08 14:32:43 -03002619 thread = kthread_run(arm_thread, (void *) av7110, "arm_mon");
2620 if (IS_ERR(thread)) {
2621 ret = PTR_ERR(thread);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002622 goto err_stop_arm_9;
Herbert Poetzl8eec1422007-02-08 14:32:43 -03002623 }
2624 av7110->arm_thread = thread;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002625
2626 /* set initial volume in mixer struct */
2627 av7110->mixer.volume_left = volume;
2628 av7110->mixer.volume_right = volume;
2629
2630 init_av7110_av(av7110);
2631
2632 ret = av7110_register(av7110);
2633 if (ret < 0)
2634 goto err_arm_thread_stop_10;
2635
2636 /* special case DVB-C: these cards have an analog tuner
2637 plus need some special handling, so we have separate
2638 saa7146_ext_vv data for these... */
2639 ret = av7110_init_v4l(av7110);
2640 if (ret < 0)
2641 goto err_av7110_unregister_11;
2642
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07002643 av7110->dvb_adapter.priv = av7110;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002644 ret = frontend_init(av7110);
2645 if (ret < 0)
2646 goto err_av7110_exit_v4l_12;
2647
2648#if defined(CONFIG_INPUT_EVDEV) || defined(CONFIG_INPUT_EVDEV_MODULE)
Oliver Endriss03388ae2005-09-09 13:03:12 -07002649 av7110_ir_init(av7110);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002650#endif
2651 printk(KERN_INFO "dvb-ttpci: found av7110-%d.\n", av7110_num);
2652 av7110_num++;
2653out:
2654 return ret;
2655
2656err_av7110_exit_v4l_12:
2657 av7110_exit_v4l(av7110);
2658err_av7110_unregister_11:
2659 dvb_unregister(av7110);
2660err_arm_thread_stop_10:
2661 av7110_arm_sync(av7110);
2662err_stop_arm_9:
2663 /* Nothing to do. Rejoice. */
2664err_av7110_ca_exit_8:
2665 av7110_ca_exit(av7110);
2666err_av7110_av_exit_7:
2667 av7110_av_exit(av7110);
2668err_iobuf_vfree_6:
2669 vfree(av7110->iobuf);
2670err_pci_free_5:
2671 pci_free_consistent(pdev, 8192, av7110->debi_virt, av7110->debi_bus);
2672err_saa71466_vfree_4:
2673 if (!av7110->grabbing)
2674 saa7146_pgtable_free(pdev, &av7110->pt);
2675err_i2c_del_3:
2676 i2c_del_adapter(&av7110->i2c_adap);
2677err_dvb_unregister_adapter_2:
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07002678 dvb_unregister_adapter(&av7110->dvb_adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002679err_put_firmware_1:
2680 put_firmware(av7110);
2681err_kfree_0:
2682 kfree(av7110);
2683 goto out;
2684}
2685
Johannes Stezenbach1be11e32006-02-27 00:09:20 -03002686static int __devexit av7110_detach(struct saa7146_dev* saa)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002687{
2688 struct av7110 *av7110 = saa->ext_priv;
2689 dprintk(4, "%p\n", av7110);
2690
Oliver Endriss03388ae2005-09-09 13:03:12 -07002691#if defined(CONFIG_INPUT_EVDEV) || defined(CONFIG_INPUT_EVDEV_MODULE)
2692 av7110_ir_exit(av7110);
2693#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07002694 if (budgetpatch) {
2695 /* Disable RPS1 */
2696 saa7146_write(saa, MC1, MASK_29);
2697 /* VSYNC LOW (inactive) */
2698 saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);
2699 saa7146_write(saa, MC1, MASK_20); /* DMA3 off */
2700 SAA7146_IER_DISABLE(saa, MASK_10);
2701 SAA7146_ISR_CLEAR(saa, MASK_10);
2702 msleep(50);
2703 tasklet_kill(&av7110->vpe_tasklet);
2704 saa7146_pgtable_free(saa->pci, &av7110->pt);
2705 }
2706 av7110_exit_v4l(av7110);
2707
2708 av7110_arm_sync(av7110);
2709
2710 tasklet_kill(&av7110->debi_tasklet);
2711 tasklet_kill(&av7110->gpio_tasklet);
2712
2713 dvb_unregister(av7110);
2714
2715 SAA7146_IER_DISABLE(saa, MASK_19 | MASK_03);
2716 SAA7146_ISR_CLEAR(saa, MASK_19 | MASK_03);
2717
2718 av7110_ca_exit(av7110);
2719 av7110_av_exit(av7110);
2720
2721 vfree(av7110->iobuf);
2722 pci_free_consistent(saa->pci, 8192, av7110->debi_virt,
2723 av7110->debi_bus);
2724
2725 i2c_del_adapter(&av7110->i2c_adap);
2726
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07002727 dvb_unregister_adapter (&av7110->dvb_adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002728
2729 av7110_num--;
2730
2731 put_firmware(av7110);
2732
2733 kfree(av7110);
2734
2735 saa->ext_priv = NULL;
2736
2737 return 0;
2738}
2739
2740
2741static void av7110_irq(struct saa7146_dev* dev, u32 *isr)
2742{
2743 struct av7110 *av7110 = dev->ext_priv;
2744
2745 //print_time("av7110_irq");
2746
2747 /* Note: Don't try to handle the DEBI error irq (MASK_18), in
2748 * intel mode the timeout is asserted all the time...
2749 */
2750
2751 if (*isr & MASK_19) {
2752 //printk("av7110_irq: DEBI\n");
2753 /* Note 1: The DEBI irq is level triggered: We must enable it
2754 * only after we started a DMA xfer, and disable it here
2755 * immediately, or it will be signalled all the time while
2756 * DEBI is idle.
2757 * Note 2: You would think that an irq which is masked is
2758 * not signalled by the hardware. Not so for the SAA7146:
2759 * An irq is signalled as long as the corresponding bit
2760 * in the ISR is set, and disabling irqs just prevents the
2761 * hardware from setting the ISR bit. This means a) that we
2762 * must clear the ISR *after* disabling the irq (which is why
2763 * we must do it here even though saa7146_core did it already),
2764 * and b) that if we were to disable an edge triggered irq
2765 * (like the gpio irqs sadly are) temporarily we would likely
2766 * loose some. This sucks :-(
2767 */
2768 SAA7146_IER_DISABLE(av7110->dev, MASK_19);
2769 SAA7146_ISR_CLEAR(av7110->dev, MASK_19);
2770 tasklet_schedule(&av7110->debi_tasklet);
2771 }
2772
2773 if (*isr & MASK_03) {
2774 //printk("av7110_irq: GPIO\n");
2775 tasklet_schedule(&av7110->gpio_tasklet);
2776 }
2777
2778 if ((*isr & MASK_10) && budgetpatch)
2779 tasklet_schedule(&av7110->vpe_tasklet);
2780}
2781
2782
2783static struct saa7146_extension av7110_extension;
2784
2785#define MAKE_AV7110_INFO(x_var,x_name) \
2786static struct saa7146_pci_extension_data x_var = { \
2787 .ext_priv = x_name, \
2788 .ext = &av7110_extension }
2789
Karl Herz6af4ee12005-09-09 13:03:13 -07002790MAKE_AV7110_INFO(tts_1_X_fsc,"Technotrend/Hauppauge WinTV DVB-S rev1.X or Fujitsu Siemens DVB-C");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002791MAKE_AV7110_INFO(ttt_1_X, "Technotrend/Hauppauge WinTV DVB-T rev1.X");
2792MAKE_AV7110_INFO(ttc_1_X, "Technotrend/Hauppauge WinTV Nexus-CA rev1.X");
2793MAKE_AV7110_INFO(ttc_2_X, "Technotrend/Hauppauge WinTV DVB-C rev2.X");
2794MAKE_AV7110_INFO(tts_2_X, "Technotrend/Hauppauge WinTV Nexus-S rev2.X");
Johannes Stezenbach3dfaebd2005-05-16 21:54:19 -07002795MAKE_AV7110_INFO(tts_2_3, "Technotrend/Hauppauge WinTV Nexus-S rev2.3");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002796MAKE_AV7110_INFO(tts_1_3se, "Technotrend/Hauppauge WinTV DVB-S rev1.3 SE");
2797MAKE_AV7110_INFO(ttt, "Technotrend/Hauppauge DVB-T");
2798MAKE_AV7110_INFO(fsc, "Fujitsu Siemens DVB-C");
2799MAKE_AV7110_INFO(fss, "Fujitsu Siemens DVB-S rev1.6");
Oliver Endriss8bd63012006-02-07 06:49:11 -02002800MAKE_AV7110_INFO(gxs_1_3, "Galaxis DVB-S rev1.3");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002801
2802static struct pci_device_id pci_tbl[] = {
Karl Herz6af4ee12005-09-09 13:03:13 -07002803 MAKE_EXTENSION_PCI(fsc, 0x110a, 0x0000),
2804 MAKE_EXTENSION_PCI(tts_1_X_fsc, 0x13c2, 0x0000),
2805 MAKE_EXTENSION_PCI(ttt_1_X, 0x13c2, 0x0001),
2806 MAKE_EXTENSION_PCI(ttc_2_X, 0x13c2, 0x0002),
2807 MAKE_EXTENSION_PCI(tts_2_X, 0x13c2, 0x0003),
Oliver Endriss8bd63012006-02-07 06:49:11 -02002808 MAKE_EXTENSION_PCI(gxs_1_3, 0x13c2, 0x0004),
Karl Herz6af4ee12005-09-09 13:03:13 -07002809 MAKE_EXTENSION_PCI(fss, 0x13c2, 0x0006),
2810 MAKE_EXTENSION_PCI(ttt, 0x13c2, 0x0008),
2811 MAKE_EXTENSION_PCI(ttc_1_X, 0x13c2, 0x000a),
2812 MAKE_EXTENSION_PCI(tts_2_3, 0x13c2, 0x000e),
2813 MAKE_EXTENSION_PCI(tts_1_3se, 0x13c2, 0x1002),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002814
Linus Torvalds1da177e2005-04-16 15:20:36 -07002815/* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0005), UNDEFINED CARD */ // Technisat SkyStar1
2816/* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0009), UNDEFINED CARD */ // TT/Hauppauge WinTV Nexus-CA v????
2817
2818 {
2819 .vendor = 0,
2820 }
2821};
2822
2823MODULE_DEVICE_TABLE(pci, pci_tbl);
2824
2825
2826static struct saa7146_extension av7110_extension = {
Dave Jones0e367a12006-08-07 13:18:56 -03002827 .name = "dvb",
Oliver Endriss00c4cc62006-11-01 13:09:51 -03002828 .flags = SAA7146_USE_I2C_IRQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002829
2830 .module = THIS_MODULE,
2831 .pci_tbl = &pci_tbl[0],
2832 .attach = av7110_attach,
Johannes Stezenbach1be11e32006-02-27 00:09:20 -03002833 .detach = __devexit_p(av7110_detach),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002834
2835 .irq_mask = MASK_19 | MASK_03 | MASK_10,
2836 .irq_func = av7110_irq,
2837};
2838
2839
2840static int __init av7110_init(void)
2841{
2842 int retval;
2843 retval = saa7146_register_extension(&av7110_extension);
2844 return retval;
2845}
2846
2847
2848static void __exit av7110_exit(void)
2849{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002850 saa7146_unregister_extension(&av7110_extension);
2851}
2852
2853module_init(av7110_init);
2854module_exit(av7110_exit);
2855
2856MODULE_DESCRIPTION("driver for the SAA7146 based AV110 PCI DVB cards by "
2857 "Siemens, Technotrend, Hauppauge");
2858MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, others");
2859MODULE_LICENSE("GPL");