blob: ef1108c0bf11005167eb6b6b225ac4a890465369 [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);
Oliver Endrissee820a62007-04-27 12:31:21 -0300222
223#if defined(CONFIG_INPUT_EVDEV) || defined(CONFIG_INPUT_EVDEV_MODULE)
224 av7110_check_ir_config(av7110, true);
225#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700226}
227
Linus Torvalds1da177e2005-04-16 15:20:36 -0700228static void av7110_arm_sync(struct av7110 *av7110)
229{
Herbert Poetzl8eec1422007-02-08 14:32:43 -0300230 if (av7110->arm_thread)
231 kthread_stop(av7110->arm_thread);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700232
Herbert Poetzl8eec1422007-02-08 14:32:43 -0300233 av7110->arm_thread = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234}
235
236static int arm_thread(void *data)
237{
238 struct av7110 *av7110 = data;
239 u16 newloops = 0;
240 int timeout;
241
242 dprintk(4, "%p\n",av7110);
243
Linus Torvalds1da177e2005-04-16 15:20:36 -0700244 for (;;) {
245 timeout = wait_event_interruptible_timeout(av7110->arm_wait,
Herbert Poetzl8eec1422007-02-08 14:32:43 -0300246 kthread_should_stop(), 5 * HZ);
247
248 if (-ERESTARTSYS == timeout || kthread_should_stop()) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700249 /* got signal or told to quit*/
250 break;
251 }
252
253 if (!av7110->arm_ready)
254 continue;
255
Oliver Endrissee820a62007-04-27 12:31:21 -0300256#if defined(CONFIG_INPUT_EVDEV) || defined(CONFIG_INPUT_EVDEV_MODULE)
257 av7110_check_ir_config(av7110, false);
258#endif
259
Ingo Molnar3593cab2006-02-07 06:49:14 -0200260 if (mutex_lock_interruptible(&av7110->dcomlock))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700262 newloops = rdebi(av7110, DEBINOSWAP, STATUS_LOOPS, 0, 2);
Ingo Molnar3593cab2006-02-07 06:49:14 -0200263 mutex_unlock(&av7110->dcomlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700264
Oliver Endriss66190a22006-01-09 15:32:42 -0200265 if (newloops == av7110->arm_loops || av7110->arm_errors > 3) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266 printk(KERN_ERR "dvb-ttpci: ARM crashed @ card %d\n",
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -0700267 av7110->dvb_adapter.num);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268
Oliver Endriss66190a22006-01-09 15:32:42 -0200269 recover_arm(av7110);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700270
Ingo Molnar3593cab2006-02-07 06:49:14 -0200271 if (mutex_lock_interruptible(&av7110->dcomlock))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700272 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273 newloops = rdebi(av7110, DEBINOSWAP, STATUS_LOOPS, 0, 2) - 1;
Ingo Molnar3593cab2006-02-07 06:49:14 -0200274 mutex_unlock(&av7110->dcomlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275 }
276 av7110->arm_loops = newloops;
Oliver Endriss66190a22006-01-09 15:32:42 -0200277 av7110->arm_errors = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278 }
279
Linus Torvalds1da177e2005-04-16 15:20:36 -0700280 return 0;
281}
282
283
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284/****************************************************************************
285 * IRQ handling
286 ****************************************************************************/
287
288static int DvbDmxFilterCallback(u8 *buffer1, size_t buffer1_len,
289 u8 *buffer2, size_t buffer2_len,
290 struct dvb_demux_filter *dvbdmxfilter,
291 enum dmx_success success,
292 struct av7110 *av7110)
293{
294 if (!dvbdmxfilter->feed->demux->dmx.frontend)
295 return 0;
296 if (dvbdmxfilter->feed->demux->dmx.frontend->source == DMX_MEMORY_FE)
297 return 0;
298
299 switch (dvbdmxfilter->type) {
300 case DMX_TYPE_SEC:
301 if ((((buffer1[1] << 8) | buffer1[2]) & 0xfff) + 3 != buffer1_len)
302 return 0;
303 if (dvbdmxfilter->doneq) {
304 struct dmx_section_filter *filter = &dvbdmxfilter->filter;
305 int i;
306 u8 xor, neq = 0;
307
308 for (i = 0; i < DVB_DEMUX_MASK_MAX; i++) {
309 xor = filter->filter_value[i] ^ buffer1[i];
310 neq |= dvbdmxfilter->maskandnotmode[i] & xor;
311 }
312 if (!neq)
313 return 0;
314 }
315 return dvbdmxfilter->feed->cb.sec(buffer1, buffer1_len,
316 buffer2, buffer2_len,
317 &dvbdmxfilter->filter,
318 DMX_OK);
319 case DMX_TYPE_TS:
320 if (!(dvbdmxfilter->feed->ts_type & TS_PACKET))
321 return 0;
322 if (dvbdmxfilter->feed->ts_type & TS_PAYLOAD_ONLY)
323 return dvbdmxfilter->feed->cb.ts(buffer1, buffer1_len,
324 buffer2, buffer2_len,
325 &dvbdmxfilter->feed->feed.ts,
326 DMX_OK);
327 else
328 av7110_p2t_write(buffer1, buffer1_len,
329 dvbdmxfilter->feed->pid,
330 &av7110->p2t_filter[dvbdmxfilter->index]);
331 default:
332 return 0;
333 }
334}
335
336
337//#define DEBUG_TIMING
338static inline void print_time(char *s)
339{
340#ifdef DEBUG_TIMING
341 struct timeval tv;
342 do_gettimeofday(&tv);
343 printk("%s: %d.%d\n", s, (int)tv.tv_sec, (int)tv.tv_usec);
344#endif
345}
346
347#define DEBI_READ 0
348#define DEBI_WRITE 1
349static inline void start_debi_dma(struct av7110 *av7110, int dir,
350 unsigned long addr, unsigned int len)
351{
352 dprintk(8, "%c %08lx %u\n", dir == DEBI_READ ? 'R' : 'W', addr, len);
353 if (saa7146_wait_for_debi_done(av7110->dev, 0)) {
354 printk(KERN_ERR "%s: saa7146_wait_for_debi_done timed out\n", __FUNCTION__);
355 return;
356 }
357
358 SAA7146_ISR_CLEAR(av7110->dev, MASK_19); /* for good measure */
359 SAA7146_IER_ENABLE(av7110->dev, MASK_19);
360 if (len < 5)
361 len = 5; /* we want a real DEBI DMA */
362 if (dir == DEBI_WRITE)
363 iwdebi(av7110, DEBISWAB, addr, 0, (len + 3) & ~3);
364 else
365 irdebi(av7110, DEBISWAB, addr, 0, len);
366}
367
368static void debiirq(unsigned long data)
369{
370 struct av7110 *av7110 = (struct av7110 *) data;
371 int type = av7110->debitype;
372 int handle = (type >> 8) & 0x1f;
373 unsigned int xfer = 0;
374
375 print_time("debi");
376 dprintk(4, "type 0x%04x\n", type);
377
378 if (type == -1) {
379 printk("DEBI irq oops @ %ld, psr:0x%08x, ssr:0x%08x\n",
380 jiffies, saa7146_read(av7110->dev, PSR),
381 saa7146_read(av7110->dev, SSR));
382 goto debi_done;
383 }
384 av7110->debitype = -1;
385
386 switch (type & 0xff) {
387
388 case DATA_TS_RECORD:
389 dvb_dmx_swfilter_packets(&av7110->demux,
390 (const u8 *) av7110->debi_virt,
391 av7110->debilen / 188);
392 xfer = RX_BUFF;
393 break;
394
395 case DATA_PES_RECORD:
396 if (av7110->demux.recording)
397 av7110_record_cb(&av7110->p2t[handle],
398 (u8 *) av7110->debi_virt,
399 av7110->debilen);
400 xfer = RX_BUFF;
401 break;
402
403 case DATA_IPMPE:
404 case DATA_FSECTION:
405 case DATA_PIPING:
406 if (av7110->handle2filter[handle])
407 DvbDmxFilterCallback((u8 *)av7110->debi_virt,
408 av7110->debilen, NULL, 0,
409 av7110->handle2filter[handle],
410 DMX_OK, av7110);
411 xfer = RX_BUFF;
412 break;
413
414 case DATA_CI_GET:
415 {
416 u8 *data = av7110->debi_virt;
417
418 if ((data[0] < 2) && data[2] == 0xff) {
419 int flags = 0;
420 if (data[5] > 0)
421 flags |= CA_CI_MODULE_PRESENT;
422 if (data[5] > 5)
423 flags |= CA_CI_MODULE_READY;
424 av7110->ci_slot[data[0]].flags = flags;
425 } else
426 ci_get_data(&av7110->ci_rbuffer,
427 av7110->debi_virt,
428 av7110->debilen);
429 xfer = RX_BUFF;
430 break;
431 }
432
433 case DATA_COMMON_INTERFACE:
434 CI_handle(av7110, (u8 *)av7110->debi_virt, av7110->debilen);
435#if 0
436 {
437 int i;
438
439 printk("av7110%d: ", av7110->num);
440 printk("%02x ", *(u8 *)av7110->debi_virt);
441 printk("%02x ", *(1+(u8 *)av7110->debi_virt));
442 for (i = 2; i < av7110->debilen; i++)
443 printk("%02x ", (*(i+(unsigned char *)av7110->debi_virt)));
444 for (i = 2; i < av7110->debilen; i++)
445 printk("%c", chtrans(*(i+(unsigned char *)av7110->debi_virt)));
446
447 printk("\n");
448 }
449#endif
450 xfer = RX_BUFF;
451 break;
452
453 case DATA_DEBUG_MESSAGE:
454 ((s8*)av7110->debi_virt)[Reserved_SIZE - 1] = 0;
455 printk("%s\n", (s8 *) av7110->debi_virt);
456 xfer = RX_BUFF;
457 break;
458
459 case DATA_CI_PUT:
460 dprintk(4, "debi DATA_CI_PUT\n");
461 case DATA_MPEG_PLAY:
462 dprintk(4, "debi DATA_MPEG_PLAY\n");
463 case DATA_BMP_LOAD:
464 dprintk(4, "debi DATA_BMP_LOAD\n");
465 xfer = TX_BUFF;
466 break;
467 default:
468 break;
469 }
470debi_done:
471 spin_lock(&av7110->debilock);
472 if (xfer)
473 iwdebi(av7110, DEBINOSWAP, xfer, 0, 2);
474 ARM_ClearMailBox(av7110);
475 spin_unlock(&av7110->debilock);
476}
477
478/* irq from av7110 firmware writing the mailbox register in the DPRAM */
479static void gpioirq(unsigned long data)
480{
481 struct av7110 *av7110 = (struct av7110 *) data;
482 u32 rxbuf, txbuf;
483 int len;
484
485 if (av7110->debitype != -1)
486 /* we shouldn't get any irq while a debi xfer is running */
487 printk("dvb-ttpci: GPIO0 irq oops @ %ld, psr:0x%08x, ssr:0x%08x\n",
488 jiffies, saa7146_read(av7110->dev, PSR),
489 saa7146_read(av7110->dev, SSR));
490
491 if (saa7146_wait_for_debi_done(av7110->dev, 0)) {
492 printk(KERN_ERR "%s: saa7146_wait_for_debi_done timed out\n", __FUNCTION__);
493 BUG(); /* maybe we should try resetting the debi? */
494 }
495
496 spin_lock(&av7110->debilock);
497 ARM_ClearIrq(av7110);
498
499 /* see what the av7110 wants */
500 av7110->debitype = irdebi(av7110, DEBINOSWAP, IRQ_STATE, 0, 2);
501 av7110->debilen = irdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
502 rxbuf = irdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
503 txbuf = irdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
504 len = (av7110->debilen + 3) & ~3;
505
506 print_time("gpio");
507 dprintk(8, "GPIO0 irq 0x%04x %d\n", av7110->debitype, av7110->debilen);
508
509 switch (av7110->debitype & 0xff) {
510
511 case DATA_TS_PLAY:
512 case DATA_PES_PLAY:
513 break;
514
515 case DATA_MPEG_VIDEO_EVENT:
516 {
517 u32 h_ar;
518 struct video_event event;
519
520 av7110->video_size.w = irdebi(av7110, DEBINOSWAP, STATUS_MPEG_WIDTH, 0, 2);
521 h_ar = irdebi(av7110, DEBINOSWAP, STATUS_MPEG_HEIGHT_AR, 0, 2);
522
523 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
524 iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
525
526 av7110->video_size.h = h_ar & 0xfff;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527
528 event.type = VIDEO_EVENT_SIZE_CHANGED;
529 event.u.size.w = av7110->video_size.w;
530 event.u.size.h = av7110->video_size.h;
531 switch ((h_ar >> 12) & 0xf)
532 {
533 case 3:
534 av7110->video_size.aspect_ratio = VIDEO_FORMAT_16_9;
535 event.u.size.aspect_ratio = VIDEO_FORMAT_16_9;
536 av7110->videostate.video_format = VIDEO_FORMAT_16_9;
537 break;
538 case 4:
539 av7110->video_size.aspect_ratio = VIDEO_FORMAT_221_1;
540 event.u.size.aspect_ratio = VIDEO_FORMAT_221_1;
541 av7110->videostate.video_format = VIDEO_FORMAT_221_1;
542 break;
543 default:
544 av7110->video_size.aspect_ratio = VIDEO_FORMAT_4_3;
545 event.u.size.aspect_ratio = VIDEO_FORMAT_4_3;
546 av7110->videostate.video_format = VIDEO_FORMAT_4_3;
547 }
Oliver Endriss66190a22006-01-09 15:32:42 -0200548
549 dprintk(8, "GPIO0 irq: DATA_MPEG_VIDEO_EVENT: w/h/ar = %u/%u/%u\n",
550 av7110->video_size.w, av7110->video_size.h,
551 av7110->video_size.aspect_ratio);
552
Linus Torvalds1da177e2005-04-16 15:20:36 -0700553 dvb_video_add_event(av7110, &event);
554 break;
555 }
556
557 case DATA_CI_PUT:
558 {
559 int avail;
560 struct dvb_ringbuffer *cibuf = &av7110->ci_wbuffer;
561
562 avail = dvb_ringbuffer_avail(cibuf);
563 if (avail <= 2) {
564 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
565 iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
566 iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
567 break;
568 }
569 len = DVB_RINGBUFFER_PEEK(cibuf, 0) << 8;
570 len |= DVB_RINGBUFFER_PEEK(cibuf, 1);
571 if (avail < len + 2) {
572 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
573 iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
574 iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
575 break;
576 }
577 DVB_RINGBUFFER_SKIP(cibuf, 2);
578
579 dvb_ringbuffer_read(cibuf, av7110->debi_virt, len, 0);
580
581 iwdebi(av7110, DEBINOSWAP, TX_LEN, len, 2);
582 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, len, 2);
583 dprintk(8, "DMA: CI\n");
584 start_debi_dma(av7110, DEBI_WRITE, DPRAM_BASE + txbuf, len);
585 spin_unlock(&av7110->debilock);
586 wake_up(&cibuf->queue);
587 return;
588 }
589
590 case DATA_MPEG_PLAY:
591 if (!av7110->playing) {
592 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
593 iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
594 iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
595 break;
596 }
597 len = 0;
598 if (av7110->debitype & 0x100) {
599 spin_lock(&av7110->aout.lock);
600 len = av7110_pes_play(av7110->debi_virt, &av7110->aout, 2048);
601 spin_unlock(&av7110->aout.lock);
602 }
603 if (len <= 0 && (av7110->debitype & 0x200)
604 &&av7110->videostate.play_state != VIDEO_FREEZED) {
605 spin_lock(&av7110->avout.lock);
606 len = av7110_pes_play(av7110->debi_virt, &av7110->avout, 2048);
607 spin_unlock(&av7110->avout.lock);
608 }
609 if (len <= 0) {
610 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
611 iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
612 iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
613 break;
614 }
615 dprintk(8, "GPIO0 PES_PLAY len=%04x\n", len);
616 iwdebi(av7110, DEBINOSWAP, TX_LEN, len, 2);
617 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, len, 2);
618 dprintk(8, "DMA: MPEG_PLAY\n");
619 start_debi_dma(av7110, DEBI_WRITE, DPRAM_BASE + txbuf, len);
620 spin_unlock(&av7110->debilock);
621 return;
622
623 case DATA_BMP_LOAD:
624 len = av7110->debilen;
625 dprintk(8, "gpio DATA_BMP_LOAD len %d\n", len);
626 if (!len) {
627 av7110->bmp_state = BMP_LOADED;
628 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
629 iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
630 iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
631 wake_up(&av7110->bmpq);
632 dprintk(8, "gpio DATA_BMP_LOAD done\n");
633 break;
634 }
635 if (len > av7110->bmplen)
636 len = av7110->bmplen;
637 if (len > 2 * 1024)
638 len = 2 * 1024;
639 iwdebi(av7110, DEBINOSWAP, TX_LEN, len, 2);
640 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, len, 2);
641 memcpy(av7110->debi_virt, av7110->bmpbuf+av7110->bmpp, len);
642 av7110->bmpp += len;
643 av7110->bmplen -= len;
644 dprintk(8, "gpio DATA_BMP_LOAD DMA len %d\n", len);
645 start_debi_dma(av7110, DEBI_WRITE, DPRAM_BASE+txbuf, len);
646 spin_unlock(&av7110->debilock);
647 return;
648
649 case DATA_CI_GET:
650 case DATA_COMMON_INTERFACE:
651 case DATA_FSECTION:
652 case DATA_IPMPE:
653 case DATA_PIPING:
654 if (!len || len > 4 * 1024) {
655 iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
656 break;
657 }
658 /* fall through */
659
660 case DATA_TS_RECORD:
661 case DATA_PES_RECORD:
662 dprintk(8, "DMA: TS_REC etc.\n");
663 start_debi_dma(av7110, DEBI_READ, DPRAM_BASE+rxbuf, len);
664 spin_unlock(&av7110->debilock);
665 return;
666
667 case DATA_DEBUG_MESSAGE:
668 if (!len || len > 0xff) {
669 iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
670 break;
671 }
672 start_debi_dma(av7110, DEBI_READ, Reserved, len);
673 spin_unlock(&av7110->debilock);
674 return;
675
676 case DATA_IRCOMMAND:
Oliver Endrissee820a62007-04-27 12:31:21 -0300677 if (av7110->ir.ir_handler)
678 av7110->ir.ir_handler(av7110,
Oliver Endriss03388ae2005-09-09 13:03:12 -0700679 swahw32(irdebi(av7110, DEBINOSWAP, Reserved, 0, 4)));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700680 iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
681 break;
682
683 default:
684 printk("dvb-ttpci: gpioirq unknown type=%d len=%d\n",
685 av7110->debitype, av7110->debilen);
686 break;
687 }
688 av7110->debitype = -1;
689 ARM_ClearMailBox(av7110);
690 spin_unlock(&av7110->debilock);
691}
692
693
694#ifdef CONFIG_DVB_AV7110_OSD
695static int dvb_osd_ioctl(struct inode *inode, struct file *file,
696 unsigned int cmd, void *parg)
697{
Tobias Klauserd9bdf772006-12-26 07:33:48 -0300698 struct dvb_device *dvbdev = file->private_data;
699 struct av7110 *av7110 = dvbdev->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700700
701 dprintk(4, "%p\n", av7110);
702
703 if (cmd == OSD_SEND_CMD)
704 return av7110_osd_cmd(av7110, (osd_cmd_t *) parg);
705 if (cmd == OSD_GET_CAPABILITY)
706 return av7110_osd_capability(av7110, (osd_cap_t *) parg);
707
708 return -EINVAL;
709}
710
711
712static struct file_operations dvb_osd_fops = {
713 .owner = THIS_MODULE,
714 .ioctl = dvb_generic_ioctl,
715 .open = dvb_generic_open,
716 .release = dvb_generic_release,
717};
718
719static struct dvb_device dvbdev_osd = {
720 .priv = NULL,
721 .users = 1,
722 .writers = 1,
723 .fops = &dvb_osd_fops,
724 .kernel_ioctl = dvb_osd_ioctl,
725};
726#endif /* CONFIG_DVB_AV7110_OSD */
727
728
729static inline int SetPIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid,
730 u16 subpid, u16 pcrpid)
731{
Dr. Werner Fink47f36922006-01-09 15:25:07 -0200732 u16 aflags = 0;
733
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734 dprintk(4, "%p\n", av7110);
735
736 if (vpid == 0x1fff || apid == 0x1fff ||
737 ttpid == 0x1fff || subpid == 0x1fff || pcrpid == 0x1fff) {
738 vpid = apid = ttpid = subpid = pcrpid = 0;
739 av7110->pids[DMX_PES_VIDEO] = 0;
740 av7110->pids[DMX_PES_AUDIO] = 0;
741 av7110->pids[DMX_PES_TELETEXT] = 0;
742 av7110->pids[DMX_PES_PCR] = 0;
743 }
744
Dr. Werner Fink47f36922006-01-09 15:25:07 -0200745 if (av7110->audiostate.bypass_mode)
746 aflags |= 0x8000;
747
748 return av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, MultiPID, 6,
749 pcrpid, vpid, apid, ttpid, subpid, aflags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700750}
751
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700752int ChangePIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700753 u16 subpid, u16 pcrpid)
754{
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700755 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700756 dprintk(4, "%p\n", av7110);
757
Ingo Molnar3593cab2006-02-07 06:49:14 -0200758 if (mutex_lock_interruptible(&av7110->pid_mutex))
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700759 return -ERESTARTSYS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700760
761 if (!(vpid & 0x8000))
762 av7110->pids[DMX_PES_VIDEO] = vpid;
763 if (!(apid & 0x8000))
764 av7110->pids[DMX_PES_AUDIO] = apid;
765 if (!(ttpid & 0x8000))
766 av7110->pids[DMX_PES_TELETEXT] = ttpid;
767 if (!(pcrpid & 0x8000))
768 av7110->pids[DMX_PES_PCR] = pcrpid;
769
770 av7110->pids[DMX_PES_SUBTITLE] = 0;
771
772 if (av7110->fe_synced) {
773 pcrpid = av7110->pids[DMX_PES_PCR];
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700774 ret = SetPIDs(av7110, vpid, apid, ttpid, subpid, pcrpid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700775 }
776
Ingo Molnar3593cab2006-02-07 06:49:14 -0200777 mutex_unlock(&av7110->pid_mutex);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700778 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700779}
780
781
782/******************************************************************************
783 * hardware filter functions
784 ******************************************************************************/
785
786static int StartHWFilter(struct dvb_demux_filter *dvbdmxfilter)
787{
788 struct dvb_demux_feed *dvbdmxfeed = dvbdmxfilter->feed;
Tobias Klauserd9bdf772006-12-26 07:33:48 -0300789 struct av7110 *av7110 = dvbdmxfeed->demux->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790 u16 buf[20];
791 int ret, i;
792 u16 handle;
793// u16 mode = 0x0320;
794 u16 mode = 0xb96a;
795
796 dprintk(4, "%p\n", av7110);
797
798 if (dvbdmxfilter->type == DMX_TYPE_SEC) {
799 if (hw_sections) {
800 buf[4] = (dvbdmxfilter->filter.filter_value[0] << 8) |
801 dvbdmxfilter->maskandmode[0];
802 for (i = 3; i < 18; i++)
803 buf[i + 4 - 2] =
804 (dvbdmxfilter->filter.filter_value[i] << 8) |
805 dvbdmxfilter->maskandmode[i];
806 mode = 4;
807 }
808 } else if ((dvbdmxfeed->ts_type & TS_PACKET) &&
809 !(dvbdmxfeed->ts_type & TS_PAYLOAD_ONLY)) {
810 av7110_p2t_init(&av7110->p2t_filter[dvbdmxfilter->index], dvbdmxfeed);
811 }
812
813 buf[0] = (COMTYPE_PID_FILTER << 8) + AddPIDFilter;
814 buf[1] = 16;
815 buf[2] = dvbdmxfeed->pid;
816 buf[3] = mode;
817
818 ret = av7110_fw_request(av7110, buf, 20, &handle, 1);
819 if (ret != 0 || handle >= 32) {
820 printk("dvb-ttpci: %s error buf %04x %04x %04x %04x "
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700821 "ret %d handle %04x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700822 __FUNCTION__, buf[0], buf[1], buf[2], buf[3],
823 ret, handle);
824 dvbdmxfilter->hw_handle = 0xffff;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700825 if (!ret)
826 ret = -1;
827 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700828 }
829
830 av7110->handle2filter[handle] = dvbdmxfilter;
831 dvbdmxfilter->hw_handle = handle;
832
833 return ret;
834}
835
836static int StopHWFilter(struct dvb_demux_filter *dvbdmxfilter)
837{
Tobias Klauserd9bdf772006-12-26 07:33:48 -0300838 struct av7110 *av7110 = dvbdmxfilter->feed->demux->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700839 u16 buf[3];
840 u16 answ[2];
841 int ret;
842 u16 handle;
843
844 dprintk(4, "%p\n", av7110);
845
846 handle = dvbdmxfilter->hw_handle;
847 if (handle >= 32) {
848 printk("%s tried to stop invalid filter %04x, filter type = %x\n",
849 __FUNCTION__, handle, dvbdmxfilter->type);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700850 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700851 }
852
853 av7110->handle2filter[handle] = NULL;
854
855 buf[0] = (COMTYPE_PID_FILTER << 8) + DelPIDFilter;
856 buf[1] = 1;
857 buf[2] = handle;
858 ret = av7110_fw_request(av7110, buf, 3, answ, 2);
859 if (ret != 0 || answ[1] != handle) {
860 printk("dvb-ttpci: %s error cmd %04x %04x %04x ret %x "
861 "resp %04x %04x pid %d\n",
862 __FUNCTION__, buf[0], buf[1], buf[2], ret,
863 answ[0], answ[1], dvbdmxfilter->feed->pid);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700864 if (!ret)
865 ret = -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700866 }
867 return ret;
868}
869
870
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700871static int dvb_feed_start_pid(struct dvb_demux_feed *dvbdmxfeed)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700872{
873 struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
Tobias Klauserd9bdf772006-12-26 07:33:48 -0300874 struct av7110 *av7110 = dvbdmx->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700875 u16 *pid = dvbdmx->pids, npids[5];
876 int i;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700877 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700878
879 dprintk(4, "%p\n", av7110);
880
881 npids[0] = npids[1] = npids[2] = npids[3] = npids[4] = 0xffff;
882 i = dvbdmxfeed->pes_type;
883 npids[i] = (pid[i]&0x8000) ? 0 : pid[i];
884 if ((i == 2) && npids[i] && (dvbdmxfeed->ts_type & TS_PACKET)) {
885 npids[i] = 0;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700886 ret = ChangePIDs(av7110, npids[1], npids[0], npids[2], npids[3], npids[4]);
887 if (!ret)
888 ret = StartHWFilter(dvbdmxfeed->filter);
889 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700890 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700891 if (dvbdmxfeed->pes_type <= 2 || dvbdmxfeed->pes_type == 4) {
892 ret = ChangePIDs(av7110, npids[1], npids[0], npids[2], npids[3], npids[4]);
893 if (ret)
894 return ret;
895 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700896
897 if (dvbdmxfeed->pes_type < 2 && npids[0])
898 if (av7110->fe_synced)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700899 {
900 ret = av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, Scan, 0);
901 if (ret)
902 return ret;
903 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904
905 if ((dvbdmxfeed->ts_type & TS_PACKET)) {
906 if (dvbdmxfeed->pes_type == 0 && !(dvbdmx->pids[0] & 0x8000))
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700907 ret = av7110_av_start_record(av7110, RP_AUDIO, dvbdmxfeed);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908 if (dvbdmxfeed->pes_type == 1 && !(dvbdmx->pids[1] & 0x8000))
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700909 ret = av7110_av_start_record(av7110, RP_VIDEO, dvbdmxfeed);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700910 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700911 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912}
913
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700914static int dvb_feed_stop_pid(struct dvb_demux_feed *dvbdmxfeed)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700915{
916 struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
Tobias Klauserd9bdf772006-12-26 07:33:48 -0300917 struct av7110 *av7110 = dvbdmx->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918 u16 *pid = dvbdmx->pids, npids[5];
919 int i;
920
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700921 int ret = 0;
922
Linus Torvalds1da177e2005-04-16 15:20:36 -0700923 dprintk(4, "%p\n", av7110);
924
925 if (dvbdmxfeed->pes_type <= 1) {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700926 ret = av7110_av_stop(av7110, dvbdmxfeed->pes_type ? RP_VIDEO : RP_AUDIO);
927 if (ret)
928 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700929 if (!av7110->rec_mode)
930 dvbdmx->recording = 0;
931 if (!av7110->playing)
932 dvbdmx->playing = 0;
933 }
934 npids[0] = npids[1] = npids[2] = npids[3] = npids[4] = 0xffff;
935 i = dvbdmxfeed->pes_type;
936 switch (i) {
937 case 2: //teletext
938 if (dvbdmxfeed->ts_type & TS_PACKET)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700939 ret = StopHWFilter(dvbdmxfeed->filter);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700940 npids[2] = 0;
941 break;
942 case 0:
943 case 1:
944 case 4:
945 if (!pids_off)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700946 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700947 npids[i] = (pid[i]&0x8000) ? 0 : pid[i];
948 break;
949 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700950 if (!ret)
951 ret = ChangePIDs(av7110, npids[1], npids[0], npids[2], npids[3], npids[4]);
952 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700953}
954
955static int av7110_start_feed(struct dvb_demux_feed *feed)
956{
957 struct dvb_demux *demux = feed->demux;
958 struct av7110 *av7110 = demux->priv;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700959 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700960
961 dprintk(4, "%p\n", av7110);
962
963 if (!demux->dmx.frontend)
964 return -EINVAL;
965
966 if (feed->pid > 0x1fff)
967 return -EINVAL;
968
969 if (feed->type == DMX_TYPE_TS) {
970 if ((feed->ts_type & TS_DECODER) &&
971 (feed->pes_type < DMX_TS_PES_OTHER)) {
972 switch (demux->dmx.frontend->source) {
973 case DMX_MEMORY_FE:
974 if (feed->ts_type & TS_DECODER)
975 if (feed->pes_type < 2 &&
976 !(demux->pids[0] & 0x8000) &&
977 !(demux->pids[1] & 0x8000)) {
978 dvb_ringbuffer_flush_spinlock_wakeup(&av7110->avout);
979 dvb_ringbuffer_flush_spinlock_wakeup(&av7110->aout);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700980 ret = av7110_av_start_play(av7110,RP_AV);
981 if (!ret)
982 demux->playing = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700983 }
984 break;
985 default:
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700986 ret = dvb_feed_start_pid(feed);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700987 break;
988 }
989 } else if ((feed->ts_type & TS_PACKET) &&
990 (demux->dmx.frontend->source != DMX_MEMORY_FE)) {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700991 ret = StartHWFilter(feed->filter);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700992 }
993 }
994
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700995 else if (feed->type == DMX_TYPE_SEC) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700996 int i;
997
998 for (i = 0; i < demux->filternum; i++) {
999 if (demux->filter[i].state != DMX_STATE_READY)
1000 continue;
1001 if (demux->filter[i].type != DMX_TYPE_SEC)
1002 continue;
1003 if (demux->filter[i].filter.parent != &feed->feed.sec)
1004 continue;
1005 demux->filter[i].state = DMX_STATE_GO;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001006 if (demux->dmx.frontend->source != DMX_MEMORY_FE) {
1007 ret = StartHWFilter(&demux->filter[i]);
1008 if (ret)
1009 break;
1010 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001011 }
1012 }
1013
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001014 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001015}
1016
1017
1018static int av7110_stop_feed(struct dvb_demux_feed *feed)
1019{
1020 struct dvb_demux *demux = feed->demux;
1021 struct av7110 *av7110 = demux->priv;
Johannes Stezenbach12ba0502005-07-07 17:58:00 -07001022 int i, rc, ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001023 dprintk(4, "%p\n", av7110);
1024
1025 if (feed->type == DMX_TYPE_TS) {
1026 if (feed->ts_type & TS_DECODER) {
1027 if (feed->pes_type >= DMX_TS_PES_OTHER ||
1028 !demux->pesfilter[feed->pes_type])
1029 return -EINVAL;
1030 demux->pids[feed->pes_type] |= 0x8000;
1031 demux->pesfilter[feed->pes_type] = NULL;
1032 }
1033 if (feed->ts_type & TS_DECODER &&
1034 feed->pes_type < DMX_TS_PES_OTHER) {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001035 ret = dvb_feed_stop_pid(feed);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001036 } else
1037 if ((feed->ts_type & TS_PACKET) &&
1038 (demux->dmx.frontend->source != DMX_MEMORY_FE))
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001039 ret = StopHWFilter(feed->filter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001040 }
1041
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001042 if (!ret && feed->type == DMX_TYPE_SEC) {
Johannes Stezenbach12ba0502005-07-07 17:58:00 -07001043 for (i = 0; i<demux->filternum; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001044 if (demux->filter[i].state == DMX_STATE_GO &&
1045 demux->filter[i].filter.parent == &feed->feed.sec) {
1046 demux->filter[i].state = DMX_STATE_READY;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001047 if (demux->dmx.frontend->source != DMX_MEMORY_FE) {
Johannes Stezenbach12ba0502005-07-07 17:58:00 -07001048 rc = StopHWFilter(&demux->filter[i]);
1049 if (!ret)
1050 ret = rc;
1051 /* keep going, stop as many filters as possible */
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001052 }
Johannes Stezenbach12ba0502005-07-07 17:58:00 -07001053 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001054 }
1055 }
1056
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001057 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058}
1059
1060
1061static void restart_feeds(struct av7110 *av7110)
1062{
1063 struct dvb_demux *dvbdmx = &av7110->demux;
1064 struct dvb_demux_feed *feed;
1065 int mode;
Oliver Endriss66190a22006-01-09 15:32:42 -02001066 int i, j;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067
1068 dprintk(4, "%p\n", av7110);
1069
1070 mode = av7110->playing;
1071 av7110->playing = 0;
1072 av7110->rec_mode = 0;
1073
Oliver Endriss66190a22006-01-09 15:32:42 -02001074 for (i = 0; i < dvbdmx->feednum; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001075 feed = &dvbdmx->feed[i];
Oliver Endriss66190a22006-01-09 15:32:42 -02001076 if (feed->state == DMX_STATE_GO) {
1077 if (feed->type == DMX_TYPE_SEC) {
1078 for (j = 0; j < dvbdmx->filternum; j++) {
1079 if (dvbdmx->filter[j].type != DMX_TYPE_SEC)
1080 continue;
1081 if (dvbdmx->filter[j].filter.parent != &feed->feed.sec)
1082 continue;
1083 if (dvbdmx->filter[j].state == DMX_STATE_GO)
1084 dvbdmx->filter[j].state = DMX_STATE_READY;
1085 }
1086 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001087 av7110_start_feed(feed);
Oliver Endriss66190a22006-01-09 15:32:42 -02001088 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089 }
1090
1091 if (mode)
1092 av7110_av_start_play(av7110, mode);
1093}
1094
1095static int dvb_get_stc(struct dmx_demux *demux, unsigned int num,
1096 uint64_t *stc, unsigned int *base)
1097{
1098 int ret;
1099 u16 fwstc[4];
1100 u16 tag = ((COMTYPE_REQUEST << 8) + ReqSTC);
1101 struct dvb_demux *dvbdemux;
1102 struct av7110 *av7110;
1103
1104 /* pointer casting paranoia... */
Eric Sesterhennae246012006-03-13 13:17:11 -03001105 BUG_ON(!demux);
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001106 dvbdemux = demux->priv;
Eric Sesterhennae246012006-03-13 13:17:11 -03001107 BUG_ON(!dvbdemux);
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001108 av7110 = dvbdemux->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109
1110 dprintk(4, "%p\n", av7110);
1111
1112 if (num != 0)
1113 return -EINVAL;
1114
1115 ret = av7110_fw_request(av7110, &tag, 0, fwstc, 4);
1116 if (ret) {
1117 printk(KERN_ERR "%s: av7110_fw_request error\n", __FUNCTION__);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001118 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001119 }
1120 dprintk(2, "fwstc = %04hx %04hx %04hx %04hx\n",
1121 fwstc[0], fwstc[1], fwstc[2], fwstc[3]);
1122
1123 *stc = (((uint64_t) ((fwstc[3] & 0x8000) >> 15)) << 32) |
1124 (((uint64_t) fwstc[1]) << 16) | ((uint64_t) fwstc[0]);
1125 *base = 1;
1126
1127 dprintk(4, "stc = %lu\n", (unsigned long)*stc);
1128
1129 return 0;
1130}
1131
1132
1133/******************************************************************************
1134 * SEC device file operations
1135 ******************************************************************************/
1136
1137
1138static int av7110_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
1139{
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001140 struct av7110* av7110 = fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001141
1142 switch (tone) {
1143 case SEC_TONE_ON:
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001144 return Set22K(av7110, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001145
1146 case SEC_TONE_OFF:
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001147 return Set22K(av7110, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001148
1149 default:
1150 return -EINVAL;
1151 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001152}
1153
1154static int av7110_diseqc_send_master_cmd(struct dvb_frontend* fe,
1155 struct dvb_diseqc_master_cmd* cmd)
1156{
1157 struct av7110* av7110 = fe->dvb->priv;
1158
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001159 return av7110_diseqc_send(av7110, cmd->msg_len, cmd->msg, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001160}
1161
1162static int av7110_diseqc_send_burst(struct dvb_frontend* fe,
1163 fe_sec_mini_cmd_t minicmd)
1164{
1165 struct av7110* av7110 = fe->dvb->priv;
1166
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001167 return av7110_diseqc_send(av7110, 0, NULL, minicmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001168}
1169
1170/* simplified code from budget-core.c */
1171static int stop_ts_capture(struct av7110 *budget)
1172{
1173 dprintk(2, "budget: %p\n", budget);
1174
1175 if (--budget->feeding1)
1176 return budget->feeding1;
1177 saa7146_write(budget->dev, MC1, MASK_20); /* DMA3 off */
1178 SAA7146_IER_DISABLE(budget->dev, MASK_10);
1179 SAA7146_ISR_CLEAR(budget->dev, MASK_10);
1180 return 0;
1181}
1182
1183static int start_ts_capture(struct av7110 *budget)
1184{
1185 dprintk(2, "budget: %p\n", budget);
1186
1187 if (budget->feeding1)
1188 return ++budget->feeding1;
1189 memset(budget->grabbing, 0x00, TS_HEIGHT * TS_WIDTH);
1190 budget->tsf = 0xff;
1191 budget->ttbp = 0;
1192 SAA7146_IER_ENABLE(budget->dev, MASK_10); /* VPE */
1193 saa7146_write(budget->dev, MC1, (MASK_04 | MASK_20)); /* DMA3 on */
1194 return ++budget->feeding1;
1195}
1196
1197static int budget_start_feed(struct dvb_demux_feed *feed)
1198{
1199 struct dvb_demux *demux = feed->demux;
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001200 struct av7110 *budget = demux->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001201 int status;
1202
1203 dprintk(2, "av7110: %p\n", budget);
1204
1205 spin_lock(&budget->feedlock1);
1206 feed->pusi_seen = 0; /* have a clean section start */
1207 status = start_ts_capture(budget);
1208 spin_unlock(&budget->feedlock1);
1209 return status;
1210}
1211
1212static int budget_stop_feed(struct dvb_demux_feed *feed)
1213{
1214 struct dvb_demux *demux = feed->demux;
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001215 struct av7110 *budget = demux->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001216 int status;
1217
1218 dprintk(2, "budget: %p\n", budget);
1219
1220 spin_lock(&budget->feedlock1);
1221 status = stop_ts_capture(budget);
1222 spin_unlock(&budget->feedlock1);
1223 return status;
1224}
1225
1226static void vpeirq(unsigned long data)
1227{
1228 struct av7110 *budget = (struct av7110 *) data;
1229 u8 *mem = (u8 *) (budget->grabbing);
1230 u32 olddma = budget->ttbp;
1231 u32 newdma = saa7146_read(budget->dev, PCI_VDP3);
1232
1233 if (!budgetpatch) {
1234 printk("av7110.c: vpeirq() called while budgetpatch disabled!"
1235 " check saa7146 IER register\n");
1236 BUG();
1237 }
1238 /* nearest lower position divisible by 188 */
1239 newdma -= newdma % 188;
1240
1241 if (newdma >= TS_BUFLEN)
1242 return;
1243
1244 budget->ttbp = newdma;
1245
1246 if (!budget->feeding1 || (newdma == olddma))
1247 return;
1248
Jon Burgess87c30192007-05-03 12:23:44 -03001249 /* Ensure streamed PCI data is synced to CPU */
1250 pci_dma_sync_sg_for_cpu(budget->dev->pci, budget->pt.slist, budget->pt.nents, PCI_DMA_FROMDEVICE);
1251
Linus Torvalds1da177e2005-04-16 15:20:36 -07001252#if 0
1253 /* track rps1 activity */
1254 printk("vpeirq: %02x Event Counter 1 0x%04x\n",
1255 mem[olddma],
1256 saa7146_read(budget->dev, EC1R) & 0x3fff);
1257#endif
1258
1259 if (newdma > olddma)
1260 /* no wraparound, dump olddma..newdma */
1261 dvb_dmx_swfilter_packets(&budget->demux1, mem + olddma, (newdma - olddma) / 188);
1262 else {
1263 /* wraparound, dump olddma..buflen and 0..newdma */
1264 dvb_dmx_swfilter_packets(&budget->demux1, mem + olddma, (TS_BUFLEN - olddma) / 188);
1265 dvb_dmx_swfilter_packets(&budget->demux1, mem, newdma / 188);
1266 }
1267}
1268
1269static int av7110_register(struct av7110 *av7110)
1270{
1271 int ret, i;
1272 struct dvb_demux *dvbdemux = &av7110->demux;
1273 struct dvb_demux *dvbdemux1 = &av7110->demux1;
1274
1275 dprintk(4, "%p\n", av7110);
1276
1277 if (av7110->registered)
1278 return -1;
1279
1280 av7110->registered = 1;
1281
1282 dvbdemux->priv = (void *) av7110;
1283
1284 for (i = 0; i < 32; i++)
1285 av7110->handle2filter[i] = NULL;
1286
1287 dvbdemux->filternum = 32;
1288 dvbdemux->feednum = 32;
1289 dvbdemux->start_feed = av7110_start_feed;
1290 dvbdemux->stop_feed = av7110_stop_feed;
1291 dvbdemux->write_to_decoder = av7110_write_to_decoder;
1292 dvbdemux->dmx.capabilities = (DMX_TS_FILTERING | DMX_SECTION_FILTERING |
1293 DMX_MEMORY_BASED_FILTERING);
1294
1295 dvb_dmx_init(&av7110->demux);
1296 av7110->demux.dmx.get_stc = dvb_get_stc;
1297
1298 av7110->dmxdev.filternum = 32;
1299 av7110->dmxdev.demux = &dvbdemux->dmx;
1300 av7110->dmxdev.capabilities = 0;
1301
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001302 dvb_dmxdev_init(&av7110->dmxdev, &av7110->dvb_adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001303
1304 av7110->hw_frontend.source = DMX_FRONTEND_0;
1305
1306 ret = dvbdemux->dmx.add_frontend(&dvbdemux->dmx, &av7110->hw_frontend);
1307
1308 if (ret < 0)
1309 return ret;
1310
1311 av7110->mem_frontend.source = DMX_MEMORY_FE;
1312
1313 ret = dvbdemux->dmx.add_frontend(&dvbdemux->dmx, &av7110->mem_frontend);
1314
1315 if (ret < 0)
1316 return ret;
1317
1318 ret = dvbdemux->dmx.connect_frontend(&dvbdemux->dmx,
1319 &av7110->hw_frontend);
1320 if (ret < 0)
1321 return ret;
1322
1323 av7110_av_register(av7110);
1324 av7110_ca_register(av7110);
1325
1326#ifdef CONFIG_DVB_AV7110_OSD
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001327 dvb_register_device(&av7110->dvb_adapter, &av7110->osd_dev,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001328 &dvbdev_osd, av7110, DVB_DEVICE_OSD);
1329#endif
1330
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001331 dvb_net_init(&av7110->dvb_adapter, &av7110->dvb_net, &dvbdemux->dmx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001332
1333 if (budgetpatch) {
1334 /* initialize software demux1 without its own frontend
1335 * demux1 hardware is connected to frontend0 of demux0
1336 */
1337 dvbdemux1->priv = (void *) av7110;
1338
1339 dvbdemux1->filternum = 256;
1340 dvbdemux1->feednum = 256;
1341 dvbdemux1->start_feed = budget_start_feed;
1342 dvbdemux1->stop_feed = budget_stop_feed;
1343 dvbdemux1->write_to_decoder = NULL;
1344
1345 dvbdemux1->dmx.capabilities = (DMX_TS_FILTERING | DMX_SECTION_FILTERING |
1346 DMX_MEMORY_BASED_FILTERING);
1347
1348 dvb_dmx_init(&av7110->demux1);
1349
1350 av7110->dmxdev1.filternum = 256;
1351 av7110->dmxdev1.demux = &dvbdemux1->dmx;
1352 av7110->dmxdev1.capabilities = 0;
1353
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001354 dvb_dmxdev_init(&av7110->dmxdev1, &av7110->dvb_adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001355
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001356 dvb_net_init(&av7110->dvb_adapter, &av7110->dvb_net1, &dvbdemux1->dmx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001357 printk("dvb-ttpci: additional demux1 for budget-patch registered\n");
1358 }
1359 return 0;
1360}
1361
1362
1363static void dvb_unregister(struct av7110 *av7110)
1364{
1365 struct dvb_demux *dvbdemux = &av7110->demux;
1366 struct dvb_demux *dvbdemux1 = &av7110->demux1;
1367
1368 dprintk(4, "%p\n", av7110);
1369
1370 if (!av7110->registered)
1371 return;
1372
1373 if (budgetpatch) {
1374 dvb_net_release(&av7110->dvb_net1);
1375 dvbdemux->dmx.close(&dvbdemux1->dmx);
1376 dvb_dmxdev_release(&av7110->dmxdev1);
1377 dvb_dmx_release(&av7110->demux1);
1378 }
1379
1380 dvb_net_release(&av7110->dvb_net);
1381
1382 dvbdemux->dmx.close(&dvbdemux->dmx);
1383 dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &av7110->hw_frontend);
1384 dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &av7110->mem_frontend);
1385
1386 dvb_dmxdev_release(&av7110->dmxdev);
1387 dvb_dmx_release(&av7110->demux);
1388
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001389 if (av7110->fe != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001390 dvb_unregister_frontend(av7110->fe);
Andrew de Quinceyf52a8382006-08-08 09:10:09 -03001391 dvb_frontend_detach(av7110->fe);
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001392 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001393 dvb_unregister_device(av7110->osd_dev);
1394 av7110_av_unregister(av7110);
1395 av7110_ca_unregister(av7110);
1396}
1397
1398
1399/****************************************************************************
1400 * I2C client commands
1401 ****************************************************************************/
1402
1403int i2c_writereg(struct av7110 *av7110, u8 id, u8 reg, u8 val)
1404{
1405 u8 msg[2] = { reg, val };
1406 struct i2c_msg msgs;
1407
1408 msgs.flags = 0;
1409 msgs.addr = id / 2;
1410 msgs.len = 2;
1411 msgs.buf = msg;
1412 return i2c_transfer(&av7110->i2c_adap, &msgs, 1);
1413}
1414
1415#if 0
1416u8 i2c_readreg(struct av7110 *av7110, u8 id, u8 reg)
1417{
1418 u8 mm1[] = {0x00};
1419 u8 mm2[] = {0x00};
1420 struct i2c_msg msgs[2];
1421
1422 msgs[0].flags = 0;
1423 msgs[1].flags = I2C_M_RD;
1424 msgs[0].addr = msgs[1].addr = id / 2;
1425 mm1[0] = reg;
1426 msgs[0].len = 1; msgs[1].len = 1;
1427 msgs[0].buf = mm1; msgs[1].buf = mm2;
1428 i2c_transfer(&av7110->i2c_adap, msgs, 2);
1429
1430 return mm2[0];
1431}
1432#endif
1433
1434/****************************************************************************
1435 * INITIALIZATION
1436 ****************************************************************************/
1437
1438
1439static int check_firmware(struct av7110* av7110)
1440{
1441 u32 crc = 0, len = 0;
1442 unsigned char *ptr;
1443
1444 /* check for firmware magic */
1445 ptr = av7110->bin_fw;
1446 if (ptr[0] != 'A' || ptr[1] != 'V' ||
1447 ptr[2] != 'F' || ptr[3] != 'W') {
1448 printk("dvb-ttpci: this is not an av7110 firmware\n");
1449 return -EINVAL;
1450 }
1451 ptr += 4;
1452
1453 /* check dpram file */
1454 crc = ntohl(*(u32*) ptr);
1455 ptr += 4;
1456 len = ntohl(*(u32*) ptr);
1457 ptr += 4;
1458 if (len >= 512) {
Alexey Dobriyanbe787ac2006-03-07 22:20:23 -03001459 printk("dvb-ttpci: dpram file is way too big.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001460 return -EINVAL;
1461 }
1462 if (crc != crc32_le(0, ptr, len)) {
1463 printk("dvb-ttpci: crc32 of dpram file does not match.\n");
1464 return -EINVAL;
1465 }
1466 av7110->bin_dpram = ptr;
1467 av7110->size_dpram = len;
1468 ptr += len;
1469
1470 /* check root file */
1471 crc = ntohl(*(u32*) ptr);
1472 ptr += 4;
1473 len = ntohl(*(u32*) ptr);
1474 ptr += 4;
1475
1476 if (len <= 200000 || len >= 300000 ||
1477 len > ((av7110->bin_fw + av7110->size_fw) - ptr)) {
1478 printk("dvb-ttpci: root file has strange size (%d). aborting.\n", len);
1479 return -EINVAL;
1480 }
1481 if( crc != crc32_le(0, ptr, len)) {
1482 printk("dvb-ttpci: crc32 of root file does not match.\n");
1483 return -EINVAL;
1484 }
1485 av7110->bin_root = ptr;
1486 av7110->size_root = len;
1487 return 0;
1488}
1489
1490#ifdef CONFIG_DVB_AV7110_FIRMWARE_FILE
1491#include "av7110_firm.h"
1492static void put_firmware(struct av7110* av7110)
1493{
1494 av7110->bin_fw = NULL;
1495}
1496
1497static inline int get_firmware(struct av7110* av7110)
1498{
1499 av7110->bin_fw = dvb_ttpci_fw;
1500 av7110->size_fw = sizeof(dvb_ttpci_fw);
1501 return check_firmware(av7110);
1502}
1503#else
1504static void put_firmware(struct av7110* av7110)
1505{
1506 vfree(av7110->bin_fw);
1507}
1508
1509static int get_firmware(struct av7110* av7110)
1510{
1511 int ret;
1512 const struct firmware *fw;
1513
1514 /* request the av7110 firmware, this will block until someone uploads it */
1515 ret = request_firmware(&fw, "dvb-ttpci-01.fw", &av7110->dev->pci->dev);
1516 if (ret) {
1517 if (ret == -ENOENT) {
1518 printk(KERN_ERR "dvb-ttpci: could not load firmware,"
1519 " file not found: dvb-ttpci-01.fw\n");
Ville Skytt\ä12e66f62006-01-09 15:25:38 -02001520 printk(KERN_ERR "dvb-ttpci: usually this should be in "
1521 "/usr/lib/hotplug/firmware or /lib/firmware\n");
1522 printk(KERN_ERR "dvb-ttpci: and can be downloaded from"
Linus Torvalds1da177e2005-04-16 15:20:36 -07001523 " http://www.linuxtv.org/download/dvb/firmware/\n");
1524 } else
1525 printk(KERN_ERR "dvb-ttpci: cannot request firmware"
1526 " (error %i)\n", ret);
1527 return -EINVAL;
1528 }
1529
1530 if (fw->size <= 200000) {
1531 printk("dvb-ttpci: this firmware is way too small.\n");
1532 release_firmware(fw);
1533 return -EINVAL;
1534 }
1535
1536 /* check if the firmware is available */
1537 av7110->bin_fw = (unsigned char *) vmalloc(fw->size);
1538 if (NULL == av7110->bin_fw) {
1539 dprintk(1, "out of memory\n");
1540 release_firmware(fw);
1541 return -ENOMEM;
1542 }
1543
1544 memcpy(av7110->bin_fw, fw->data, fw->size);
1545 av7110->size_fw = fw->size;
1546 if ((ret = check_firmware(av7110)))
1547 vfree(av7110->bin_fw);
1548
1549 release_firmware(fw);
1550 return ret;
1551}
1552#endif
1553
1554
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001555static int alps_bsrv2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001556{
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001557 struct av7110* av7110 = fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001558 u8 pwr = 0;
1559 u8 buf[4];
1560 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
1561 u32 div = (params->frequency + 479500) / 125;
1562
1563 if (params->frequency > 2000000) pwr = 3;
1564 else if (params->frequency > 1800000) pwr = 2;
1565 else if (params->frequency > 1600000) pwr = 1;
1566 else if (params->frequency > 1200000) pwr = 0;
1567 else if (params->frequency >= 1100000) pwr = 1;
1568 else pwr = 2;
1569
1570 buf[0] = (div >> 8) & 0x7f;
1571 buf[1] = div & 0xff;
1572 buf[2] = ((div & 0x18000) >> 10) | 0x95;
1573 buf[3] = (pwr << 6) | 0x30;
1574
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -08001575 // NOTE: since we're using a prescaler of 2, we set the
Linus Torvalds1da177e2005-04-16 15:20:36 -07001576 // divisor frequency to 62.5kHz and divide by 125 above
1577
Patrick Boettcherdea74862006-05-14 05:01:31 -03001578 if (fe->ops.i2c_gate_ctrl)
1579 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001580 if (i2c_transfer (&av7110->i2c_adap, &msg, 1) != 1)
1581 return -EIO;
1582 return 0;
1583}
1584
1585static struct ves1x93_config alps_bsrv2_config = {
1586 .demod_address = 0x08,
1587 .xin = 90100000UL,
1588 .invert_pwm = 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001589};
1590
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001591static int alps_tdbe2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001592{
1593 struct av7110* av7110 = fe->dvb->priv;
1594 u32 div;
1595 u8 data[4];
1596 struct i2c_msg msg = { .addr = 0x62, .flags = 0, .buf = data, .len = sizeof(data) };
1597
1598 div = (params->frequency + 35937500 + 31250) / 62500;
1599
1600 data[0] = (div >> 8) & 0x7f;
1601 data[1] = div & 0xff;
1602 data[2] = 0x85 | ((div >> 10) & 0x60);
1603 data[3] = (params->frequency < 174000000 ? 0x88 : params->frequency < 470000000 ? 0x84 : 0x81);
1604
Patrick Boettcherdea74862006-05-14 05:01:31 -03001605 if (fe->ops.i2c_gate_ctrl)
1606 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001607 if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
1608 return -EIO;
1609 return 0;
1610}
1611
1612static struct ves1820_config alps_tdbe2_config = {
1613 .demod_address = 0x09,
1614 .xin = 57840000UL,
1615 .invert = 1,
1616 .selagc = VES1820_SELAGC_SIGNAMPERR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001617};
1618
1619
1620
1621
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001622static int grundig_29504_451_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001623{
1624 struct av7110* av7110 = fe->dvb->priv;
1625 u32 div;
1626 u8 data[4];
1627 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
1628
1629 div = params->frequency / 125;
1630 data[0] = (div >> 8) & 0x7f;
1631 data[1] = div & 0xff;
1632 data[2] = 0x8e;
1633 data[3] = 0x00;
1634
Patrick Boettcherdea74862006-05-14 05:01:31 -03001635 if (fe->ops.i2c_gate_ctrl)
1636 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001637 if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
1638 return -EIO;
1639 return 0;
1640}
1641
1642static struct tda8083_config grundig_29504_451_config = {
1643 .demod_address = 0x68,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001644};
1645
1646
1647
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001648static int philips_cd1516_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001649{
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -08001650 struct av7110* av7110 = fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001651 u32 div;
1652 u32 f = params->frequency;
1653 u8 data[4];
1654 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
1655
1656 div = (f + 36125000 + 31250) / 62500;
1657
1658 data[0] = (div >> 8) & 0x7f;
1659 data[1] = div & 0xff;
1660 data[2] = 0x8e;
1661 data[3] = (f < 174000000 ? 0xa1 : f < 470000000 ? 0x92 : 0x34);
1662
Patrick Boettcherdea74862006-05-14 05:01:31 -03001663 if (fe->ops.i2c_gate_ctrl)
1664 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001665 if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
1666 return -EIO;
1667 return 0;
1668}
1669
1670static struct ves1820_config philips_cd1516_config = {
1671 .demod_address = 0x09,
1672 .xin = 57840000UL,
1673 .invert = 1,
1674 .selagc = VES1820_SELAGC_SIGNAMPERR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001675};
1676
1677
1678
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001679static int alps_tdlb7_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001680{
1681 struct av7110* av7110 = fe->dvb->priv;
1682 u32 div, pwr;
1683 u8 data[4];
1684 struct i2c_msg msg = { .addr = 0x60, .flags = 0, .buf = data, .len = sizeof(data) };
1685
1686 div = (params->frequency + 36200000) / 166666;
1687
1688 if (params->frequency <= 782000000)
1689 pwr = 1;
1690 else
1691 pwr = 2;
1692
1693 data[0] = (div >> 8) & 0x7f;
1694 data[1] = div & 0xff;
1695 data[2] = 0x85;
1696 data[3] = pwr << 6;
1697
Patrick Boettcherdea74862006-05-14 05:01:31 -03001698 if (fe->ops.i2c_gate_ctrl)
1699 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001700 if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
1701 return -EIO;
1702 return 0;
1703}
1704
1705static int alps_tdlb7_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name)
1706{
Oliver Endrissd98821e2006-09-14 00:15:13 -03001707#if defined(CONFIG_DVB_SP8870) || defined(CONFIG_DVB_SP8870_MODULE)
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001708 struct av7110* av7110 = fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001709
1710 return request_firmware(fw, name, &av7110->dev->pci->dev);
Oliver Endrissd98821e2006-09-14 00:15:13 -03001711#else
1712 return -EINVAL;
1713#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001714}
1715
1716static struct sp8870_config alps_tdlb7_config = {
1717
1718 .demod_address = 0x71,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001719 .request_firmware = alps_tdlb7_request_firmware,
1720};
1721
1722
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001723static u8 nexusca_stv0297_inittab[] = {
1724 0x80, 0x01,
1725 0x80, 0x00,
1726 0x81, 0x01,
1727 0x81, 0x00,
1728 0x00, 0x09,
1729 0x01, 0x69,
1730 0x03, 0x00,
1731 0x04, 0x00,
1732 0x07, 0x00,
1733 0x08, 0x00,
1734 0x20, 0x00,
1735 0x21, 0x40,
1736 0x22, 0x00,
1737 0x23, 0x00,
1738 0x24, 0x40,
1739 0x25, 0x88,
1740 0x30, 0xff,
1741 0x31, 0x00,
1742 0x32, 0xff,
1743 0x33, 0x00,
1744 0x34, 0x50,
1745 0x35, 0x7f,
1746 0x36, 0x00,
1747 0x37, 0x20,
1748 0x38, 0x00,
1749 0x40, 0x1c,
1750 0x41, 0xff,
1751 0x42, 0x29,
1752 0x43, 0x00,
1753 0x44, 0xff,
1754 0x45, 0x00,
1755 0x46, 0x00,
1756 0x49, 0x04,
1757 0x4a, 0x00,
1758 0x4b, 0x7b,
1759 0x52, 0x30,
1760 0x55, 0xae,
1761 0x56, 0x47,
1762 0x57, 0xe1,
1763 0x58, 0x3a,
1764 0x5a, 0x1e,
1765 0x5b, 0x34,
1766 0x60, 0x00,
1767 0x63, 0x00,
1768 0x64, 0x00,
1769 0x65, 0x00,
1770 0x66, 0x00,
1771 0x67, 0x00,
1772 0x68, 0x00,
1773 0x69, 0x00,
1774 0x6a, 0x02,
1775 0x6b, 0x00,
1776 0x70, 0xff,
1777 0x71, 0x00,
1778 0x72, 0x00,
1779 0x73, 0x00,
1780 0x74, 0x0c,
1781 0x80, 0x00,
1782 0x81, 0x00,
1783 0x82, 0x00,
1784 0x83, 0x00,
1785 0x84, 0x04,
1786 0x85, 0x80,
1787 0x86, 0x24,
1788 0x87, 0x78,
1789 0x88, 0x10,
1790 0x89, 0x00,
1791 0x90, 0x01,
1792 0x91, 0x01,
1793 0xa0, 0x04,
1794 0xa1, 0x00,
1795 0xa2, 0x00,
1796 0xb0, 0x91,
1797 0xb1, 0x0b,
1798 0xc0, 0x53,
1799 0xc1, 0x70,
1800 0xc2, 0x12,
1801 0xd0, 0x00,
1802 0xd1, 0x00,
1803 0xd2, 0x00,
1804 0xd3, 0x00,
1805 0xd4, 0x00,
1806 0xd5, 0x00,
1807 0xde, 0x00,
1808 0xdf, 0x00,
1809 0x61, 0x49,
1810 0x62, 0x0b,
1811 0x53, 0x08,
1812 0x59, 0x08,
1813 0xff, 0xff,
1814};
Linus Torvalds1da177e2005-04-16 15:20:36 -07001815
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001816static int nexusca_stv0297_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001817{
1818 struct av7110* av7110 = fe->dvb->priv;
1819 u32 div;
1820 u8 data[4];
1821 struct i2c_msg msg = { .addr = 0x63, .flags = 0, .buf = data, .len = sizeof(data) };
1822 struct i2c_msg readmsg = { .addr = 0x63, .flags = I2C_M_RD, .buf = data, .len = 1 };
1823 int i;
1824
1825 div = (params->frequency + 36150000 + 31250) / 62500;
1826
1827 data[0] = (div >> 8) & 0x7f;
1828 data[1] = div & 0xff;
1829 data[2] = 0xce;
1830
1831 if (params->frequency < 45000000)
1832 return -EINVAL;
1833 else if (params->frequency < 137000000)
1834 data[3] = 0x01;
1835 else if (params->frequency < 403000000)
1836 data[3] = 0x02;
1837 else if (params->frequency < 860000000)
1838 data[3] = 0x04;
1839 else
1840 return -EINVAL;
1841
Patrick Boettcherdea74862006-05-14 05:01:31 -03001842 if (fe->ops.i2c_gate_ctrl)
1843 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001844 if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1) {
1845 printk("nexusca: pll transfer failed!\n");
1846 return -EIO;
1847 }
1848
1849 // wait for PLL lock
1850 for(i = 0; i < 20; i++) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001851 if (fe->ops.i2c_gate_ctrl)
1852 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001853 if (i2c_transfer(&av7110->i2c_adap, &readmsg, 1) == 1)
1854 if (data[0] & 0x40) break;
1855 msleep(10);
1856 }
1857
1858 return 0;
1859}
1860
1861static struct stv0297_config nexusca_stv0297_config = {
1862
1863 .demod_address = 0x1C,
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001864 .inittab = nexusca_stv0297_inittab,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001865 .invert = 1,
Thomas Kaiserb8d4c232006-04-27 21:45:20 -03001866 .stop_during_read = 1,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001867};
1868
1869
1870
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001871static int grundig_29504_401_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001872{
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001873 struct av7110* av7110 = fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001874 u32 div;
1875 u8 cfg, cpump, band_select;
1876 u8 data[4];
1877 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
1878
1879 div = (36125000 + params->frequency) / 166666;
1880
1881 cfg = 0x88;
1882
1883 if (params->frequency < 175000000) cpump = 2;
1884 else if (params->frequency < 390000000) cpump = 1;
1885 else if (params->frequency < 470000000) cpump = 2;
1886 else if (params->frequency < 750000000) cpump = 1;
1887 else cpump = 3;
1888
1889 if (params->frequency < 175000000) band_select = 0x0e;
1890 else if (params->frequency < 470000000) band_select = 0x05;
1891 else band_select = 0x03;
1892
1893 data[0] = (div >> 8) & 0x7f;
1894 data[1] = div & 0xff;
1895 data[2] = ((div >> 10) & 0x60) | cfg;
1896 data[3] = (cpump << 6) | band_select;
1897
Patrick Boettcherdea74862006-05-14 05:01:31 -03001898 if (fe->ops.i2c_gate_ctrl)
1899 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001900 if (i2c_transfer (&av7110->i2c_adap, &msg, 1) != 1) return -EIO;
1901 return 0;
1902}
1903
1904static struct l64781_config grundig_29504_401_config = {
1905 .demod_address = 0x55,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001906};
1907
1908
1909
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001910static int av7110_fe_lock_fix(struct av7110* av7110, fe_status_t status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001911{
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001912 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001913 int synced = (status & FE_HAS_LOCK) ? 1 : 0;
1914
1915 av7110->fe_status = status;
1916
1917 if (av7110->fe_synced == synced)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001918 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001919
Oliver Endriss14500d42007-03-03 14:45:48 -03001920 if (av7110->playing) {
1921 av7110->fe_synced = synced;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001922 return 0;
Oliver Endriss14500d42007-03-03 14:45:48 -03001923 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001924
Ingo Molnar3593cab2006-02-07 06:49:14 -02001925 if (mutex_lock_interruptible(&av7110->pid_mutex))
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001926 return -ERESTARTSYS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001927
Oliver Endriss34612152005-07-07 17:58:02 -07001928 if (synced) {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001929 ret = SetPIDs(av7110, av7110->pids[DMX_PES_VIDEO],
Linus Torvalds1da177e2005-04-16 15:20:36 -07001930 av7110->pids[DMX_PES_AUDIO],
1931 av7110->pids[DMX_PES_TELETEXT], 0,
1932 av7110->pids[DMX_PES_PCR]);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001933 if (!ret)
1934 ret = av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, Scan, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001935 } else {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001936 ret = SetPIDs(av7110, 0, 0, 0, 0, 0);
1937 if (!ret) {
1938 ret = av7110_fw_cmd(av7110, COMTYPE_PID_FILTER, FlushTSQueue, 0);
1939 if (!ret)
1940 ret = av7110_wait_msgstate(av7110, GPMQBusy);
1941 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001942 }
1943
Oliver Endriss34612152005-07-07 17:58:02 -07001944 if (!ret)
1945 av7110->fe_synced = synced;
1946
Ingo Molnar3593cab2006-02-07 06:49:14 -02001947 mutex_unlock(&av7110->pid_mutex);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001948 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001949}
1950
1951static int av7110_fe_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
1952{
1953 struct av7110* av7110 = fe->dvb->priv;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001954
1955 int ret = av7110_fe_lock_fix(av7110, 0);
Oliver Endriss66190a22006-01-09 15:32:42 -02001956 if (!ret) {
1957 av7110->saved_fe_params = *params;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001958 ret = av7110->fe_set_frontend(fe, params);
Oliver Endriss66190a22006-01-09 15:32:42 -02001959 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001960 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001961}
1962
1963static int av7110_fe_init(struct dvb_frontend* fe)
1964{
1965 struct av7110* av7110 = fe->dvb->priv;
1966
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001967 int ret = av7110_fe_lock_fix(av7110, 0);
1968 if (!ret)
1969 ret = av7110->fe_init(fe);
1970 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001971}
1972
1973static int av7110_fe_read_status(struct dvb_frontend* fe, fe_status_t* status)
1974{
1975 struct av7110* av7110 = fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001976
1977 /* call the real implementation */
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001978 int ret = av7110->fe_read_status(fe, status);
1979 if (!ret)
1980 if (((*status ^ av7110->fe_status) & FE_HAS_LOCK) && (*status & FE_HAS_LOCK))
1981 ret = av7110_fe_lock_fix(av7110, *status);
1982 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001983}
1984
1985static int av7110_fe_diseqc_reset_overload(struct dvb_frontend* fe)
1986{
1987 struct av7110* av7110 = fe->dvb->priv;
1988
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001989 int ret = av7110_fe_lock_fix(av7110, 0);
1990 if (!ret)
1991 ret = av7110->fe_diseqc_reset_overload(fe);
1992 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001993}
1994
1995static int av7110_fe_diseqc_send_master_cmd(struct dvb_frontend* fe,
1996 struct dvb_diseqc_master_cmd* cmd)
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_master_cmd = *cmd;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002003 ret = av7110->fe_diseqc_send_master_cmd(fe, cmd);
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_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd)
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_minicmd = minicmd;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002015 ret = av7110->fe_diseqc_send_burst(fe, minicmd);
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_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
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_tone = tone;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002027 ret = av7110->fe_set_tone(fe, tone);
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
2032static int av7110_fe_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
2033{
2034 struct av7110* av7110 = fe->dvb->priv;
2035
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002036 int ret = av7110_fe_lock_fix(av7110, 0);
Oliver Endriss66190a22006-01-09 15:32:42 -02002037 if (!ret) {
2038 av7110->saved_voltage = voltage;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002039 ret = av7110->fe_set_voltage(fe, voltage);
Oliver Endriss66190a22006-01-09 15:32:42 -02002040 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002041 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002042}
2043
Peter Beutner400b7082006-01-09 15:32:43 -02002044static int av7110_fe_dishnetwork_send_legacy_command(struct dvb_frontend* fe, unsigned long cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002045{
2046 struct av7110* av7110 = fe->dvb->priv;
2047
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002048 int ret = av7110_fe_lock_fix(av7110, 0);
2049 if (!ret)
2050 ret = av7110->fe_dishnetwork_send_legacy_command(fe, cmd);
2051 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002052}
2053
Oliver Endriss66190a22006-01-09 15:32:42 -02002054static void dvb_s_recover(struct av7110* av7110)
2055{
2056 av7110_fe_init(av7110->fe);
2057
2058 av7110_fe_set_voltage(av7110->fe, av7110->saved_voltage);
2059 if (av7110->saved_master_cmd.msg_len) {
2060 msleep(20);
2061 av7110_fe_diseqc_send_master_cmd(av7110->fe, &av7110->saved_master_cmd);
2062 }
2063 msleep(20);
2064 av7110_fe_diseqc_send_burst(av7110->fe, av7110->saved_minicmd);
2065 msleep(20);
2066 av7110_fe_set_tone(av7110->fe, av7110->saved_tone);
2067
2068 av7110_fe_set_frontend(av7110->fe, &av7110->saved_fe_params);
2069}
2070
Linus Torvalds1da177e2005-04-16 15:20:36 -07002071static u8 read_pwm(struct av7110* av7110)
2072{
2073 u8 b = 0xff;
2074 u8 pwm;
2075 struct i2c_msg msg[] = { { .addr = 0x50,.flags = 0,.buf = &b,.len = 1 },
2076 { .addr = 0x50,.flags = I2C_M_RD,.buf = &pwm,.len = 1} };
2077
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -08002078 if ((i2c_transfer(&av7110->i2c_adap, msg, 2) != 2) || (pwm == 0xff))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002079 pwm = 0x48;
2080
2081 return pwm;
2082}
2083
2084static int frontend_init(struct av7110 *av7110)
2085{
2086 int ret;
2087
2088 if (av7110->dev->pci->subsystem_vendor == 0x110a) {
2089 switch(av7110->dev->pci->subsystem_device) {
2090 case 0x0000: // Fujitsu/Siemens DVB-Cable (ves1820/Philips CD1516(??))
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002091 av7110->fe = dvb_attach(ves1820_attach, &philips_cd1516_config,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002092 &av7110->i2c_adap, read_pwm(av7110));
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002093 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002094 av7110->fe->ops.tuner_ops.set_params = philips_cd1516_tuner_set_params;
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002095 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002096 break;
2097 }
2098
2099 } else if (av7110->dev->pci->subsystem_vendor == 0x13c2) {
2100 switch(av7110->dev->pci->subsystem_device) {
2101 case 0x0000: // Hauppauge/TT WinTV DVB-S rev1.X
2102 case 0x0003: // Hauppauge/TT WinTV Nexus-S Rev 2.X
2103 case 0x1002: // Hauppauge/TT WinTV DVB-S rev1.3SE
2104
2105 // try the ALPS BSRV2 first of all
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002106 av7110->fe = dvb_attach(ves1x93_attach, &alps_bsrv2_config, &av7110->i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002107 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002108 av7110->fe->ops.tuner_ops.set_params = alps_bsrv2_tuner_set_params;
2109 av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
2110 av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
2111 av7110->fe->ops.set_tone = av7110_set_tone;
Oliver Endriss66190a22006-01-09 15:32:42 -02002112 av7110->recover = dvb_s_recover;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002113 break;
2114 }
2115
2116 // try the ALPS BSRU6 now
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002117 av7110->fe = dvb_attach(stv0299_attach, &alps_bsru6_config, &av7110->i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002118 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002119 av7110->fe->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03002120 av7110->fe->tuner_priv = &av7110->i2c_adap;
2121
Patrick Boettcherdea74862006-05-14 05:01:31 -03002122 av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
2123 av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
2124 av7110->fe->ops.set_tone = av7110_set_tone;
Oliver Endriss66190a22006-01-09 15:32:42 -02002125 av7110->recover = dvb_s_recover;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002126 break;
2127 }
2128
2129 // Try the grundig 29504-451
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002130 av7110->fe = dvb_attach(tda8083_attach, &grundig_29504_451_config, &av7110->i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002131 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002132 av7110->fe->ops.tuner_ops.set_params = grundig_29504_451_tuner_set_params;
2133 av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
2134 av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
2135 av7110->fe->ops.set_tone = av7110_set_tone;
Oliver Endriss66190a22006-01-09 15:32:42 -02002136 av7110->recover = dvb_s_recover;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002137 break;
2138 }
2139
2140 /* Try DVB-C cards */
2141 switch(av7110->dev->pci->subsystem_device) {
2142 case 0x0000:
2143 /* Siemens DVB-C (full-length card) VES1820/Philips CD1516 */
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002144 av7110->fe = dvb_attach(ves1820_attach, &philips_cd1516_config, &av7110->i2c_adap,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002145 read_pwm(av7110));
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002146 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002147 av7110->fe->ops.tuner_ops.set_params = philips_cd1516_tuner_set_params;
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002148 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002149 break;
2150 case 0x0003:
Adrian Bunkf3688fc2006-03-29 22:46:12 -03002151 /* Hauppauge DVB-C 2.1 VES1820/ALPS TDBE2 */
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002152 av7110->fe = dvb_attach(ves1820_attach, &alps_tdbe2_config, &av7110->i2c_adap,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002153 read_pwm(av7110));
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002154 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002155 av7110->fe->ops.tuner_ops.set_params = alps_tdbe2_tuner_set_params;
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002156 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002157 break;
2158 }
2159 break;
2160
2161 case 0x0001: // Hauppauge/TT Nexus-T premium rev1.X
Oliver Endriss8d90ee52006-08-07 02:04:26 -03002162 // try ALPS TDLB7 first, then Grundig 29504-401
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002163 av7110->fe = dvb_attach(sp8870_attach, &alps_tdlb7_config, &av7110->i2c_adap);
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002164 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002165 av7110->fe->ops.tuner_ops.set_params = alps_tdlb7_tuner_set_params;
Oliver Endriss8d90ee52006-08-07 02:04:26 -03002166 break;
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002167 }
Oliver Endriss8d90ee52006-08-07 02:04:26 -03002168 /* fall-thru */
2169
2170 case 0x0008: // Hauppauge/TT DVB-T
2171 // Grundig 29504-401
2172 av7110->fe = dvb_attach(l64781_attach, &grundig_29504_401_config, &av7110->i2c_adap);
2173 if (av7110->fe)
2174 av7110->fe->ops.tuner_ops.set_params = grundig_29504_401_tuner_set_params;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002175 break;
2176
2177 case 0x0002: // Hauppauge/TT DVB-C premium rev2.X
2178
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002179 av7110->fe = dvb_attach(ves1820_attach, &alps_tdbe2_config, &av7110->i2c_adap, read_pwm(av7110));
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002180 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002181 av7110->fe->ops.tuner_ops.set_params = alps_tdbe2_tuner_set_params;
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002182 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002183 break;
2184
Oliver Endriss8bd63012006-02-07 06:49:11 -02002185 case 0x0004: // Galaxis DVB-S rev1.3
2186 /* ALPS BSRV2 */
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002187 av7110->fe = dvb_attach(ves1x93_attach, &alps_bsrv2_config, &av7110->i2c_adap);
Oliver Endriss8bd63012006-02-07 06:49:11 -02002188 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002189 av7110->fe->ops.tuner_ops.set_params = alps_bsrv2_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 Endriss8bd63012006-02-07 06:49:11 -02002193 av7110->recover = dvb_s_recover;
2194 }
2195 break;
2196
Linus Torvalds1da177e2005-04-16 15:20:36 -07002197 case 0x0006: /* Fujitsu-Siemens DVB-S rev 1.6 */
2198 /* Grundig 29504-451 */
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002199 av7110->fe = dvb_attach(tda8083_attach, &grundig_29504_451_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 = grundig_29504_451_tuner_set_params;
2202 av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
2203 av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
2204 av7110->fe->ops.set_tone = av7110_set_tone;
Oliver Endriss66190a22006-01-09 15:32:42 -02002205 av7110->recover = dvb_s_recover;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002206 }
2207 break;
2208
Linus Torvalds1da177e2005-04-16 15:20:36 -07002209 case 0x000A: // Hauppauge/TT Nexus-CA rev1.X
2210
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002211 av7110->fe = dvb_attach(stv0297_attach, &nexusca_stv0297_config, &av7110->i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002212 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002213 av7110->fe->ops.tuner_ops.set_params = nexusca_stv0297_tuner_set_params;
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03002214
Linus Torvalds1da177e2005-04-16 15:20:36 -07002215 /* set TDA9819 into DVB mode */
Marco Schluessler6a857742006-07-10 03:34:16 -03002216 saa7146_setgpio(av7110->dev, 1, SAA7146_GPIO_OUTLO); // TDA9819 pin9(STD)
2217 saa7146_setgpio(av7110->dev, 3, SAA7146_GPIO_OUTLO); // TDA9819 pin30(VIF)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002218
2219 /* tuner on this needs a slower i2c bus speed */
2220 av7110->dev->i2c_bitrate = SAA7146_I2C_BUS_BIT_RATE_240;
2221 break;
2222 }
Johannes Stezenbach3dfaebd2005-05-16 21:54:19 -07002223 break;
2224
2225 case 0x000E: /* Hauppauge/TT Nexus-S rev 2.3 */
2226 /* ALPS BSBE1 */
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002227 av7110->fe = dvb_attach(stv0299_attach, &alps_bsbe1_config, &av7110->i2c_adap);
Oliver Endrisseb3daf32006-01-09 15:25:05 -02002228 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002229 av7110->fe->ops.tuner_ops.set_params = alps_bsbe1_tuner_set_params;
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03002230 av7110->fe->tuner_priv = &av7110->i2c_adap;
2231
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002232 if (dvb_attach(lnbp21_attach, av7110->fe, &av7110->i2c_adap, 0, 0) == NULL) {
Oliver Endrissdb5d91e2006-02-28 10:32:25 -03002233 printk("dvb-ttpci: LNBP21 not found!\n");
Patrick Boettcherdea74862006-05-14 05:01:31 -03002234 if (av7110->fe->ops.release)
2235 av7110->fe->ops.release(av7110->fe);
Oliver Endrissdb5d91e2006-02-28 10:32:25 -03002236 av7110->fe = NULL;
2237 } else {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002238 av7110->fe->ops.dishnetwork_send_legacy_command = NULL;
Oliver Endrissdb5d91e2006-02-28 10:32:25 -03002239 av7110->recover = dvb_s_recover;
2240 }
Oliver Endrisseb3daf32006-01-09 15:25:05 -02002241 }
Johannes Stezenbach3dfaebd2005-05-16 21:54:19 -07002242 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002243 }
2244 }
2245
2246 if (!av7110->fe) {
2247 /* FIXME: propagate the failure code from the lower layers */
2248 ret = -ENOMEM;
2249 printk("dvb-ttpci: A frontend driver was not found for device %04x/%04x subsystem %04x/%04x\n",
2250 av7110->dev->pci->vendor,
2251 av7110->dev->pci->device,
2252 av7110->dev->pci->subsystem_vendor,
2253 av7110->dev->pci->subsystem_device);
2254 } else {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002255 FE_FUNC_OVERRIDE(av7110->fe->ops.init, av7110->fe_init, av7110_fe_init);
2256 FE_FUNC_OVERRIDE(av7110->fe->ops.read_status, av7110->fe_read_status, av7110_fe_read_status);
2257 FE_FUNC_OVERRIDE(av7110->fe->ops.diseqc_reset_overload, av7110->fe_diseqc_reset_overload, av7110_fe_diseqc_reset_overload);
2258 FE_FUNC_OVERRIDE(av7110->fe->ops.diseqc_send_master_cmd, av7110->fe_diseqc_send_master_cmd, av7110_fe_diseqc_send_master_cmd);
2259 FE_FUNC_OVERRIDE(av7110->fe->ops.diseqc_send_burst, av7110->fe_diseqc_send_burst, av7110_fe_diseqc_send_burst);
2260 FE_FUNC_OVERRIDE(av7110->fe->ops.set_tone, av7110->fe_set_tone, av7110_fe_set_tone);
2261 FE_FUNC_OVERRIDE(av7110->fe->ops.set_voltage, av7110->fe_set_voltage, av7110_fe_set_voltage;)
2262 FE_FUNC_OVERRIDE(av7110->fe->ops.dishnetwork_send_legacy_command, av7110->fe_dishnetwork_send_legacy_command, av7110_fe_dishnetwork_send_legacy_command);
2263 FE_FUNC_OVERRIDE(av7110->fe->ops.set_frontend, av7110->fe_set_frontend, av7110_fe_set_frontend);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002264
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07002265 ret = dvb_register_frontend(&av7110->dvb_adapter, av7110->fe);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002266 if (ret < 0) {
2267 printk("av7110: Frontend registration failed!\n");
Andrew de Quinceyf52a8382006-08-08 09:10:09 -03002268 dvb_frontend_detach(av7110->fe);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002269 av7110->fe = NULL;
2270 }
2271 }
2272 return ret;
2273}
2274
2275/* Budgetpatch note:
2276 * Original hardware design by Roberto Deza:
2277 * There is a DVB_Wiki at
2278 * http://212.227.36.83/linuxtv/wiki/index.php/Main_Page
2279 * where is described this 'DVB TT Budget Patch', on Card Modding:
2280 * http://212.227.36.83/linuxtv/wiki/index.php/DVB_TT_Budget_Patch
2281 * On the short description there is also a link to a external file,
2282 * with more details:
2283 * http://perso.wanadoo.es/jesussolano/Ttf_tsc1.zip
2284 *
2285 * New software triggering design by Emard that works on
2286 * original Roberto Deza's hardware:
2287 *
2288 * rps1 code for budgetpatch will copy internal HS event to GPIO3 pin.
2289 * GPIO3 is in budget-patch hardware connectd to port B VSYNC
2290 * HS is an internal event of 7146, accessible with RPS
2291 * and temporarily raised high every n lines
2292 * (n in defined in the RPS_THRESH1 counter threshold)
2293 * I think HS is raised high on the beginning of the n-th line
2294 * and remains high until this n-th line that triggered
2295 * it is completely received. When the receiption of n-th line
2296 * ends, HS is lowered.
2297 *
2298 * To transmit data over DMA, 7146 needs changing state at
2299 * port B VSYNC pin. Any changing of port B VSYNC will
2300 * cause some DMA data transfer, with more or less packets loss.
2301 * It depends on the phase and frequency of VSYNC and
2302 * the way of 7146 is instructed to trigger on port B (defined
2303 * in DD1_INIT register, 3rd nibble from the right valid
2304 * numbers are 0-7, see datasheet)
2305 *
2306 * The correct triggering can minimize packet loss,
2307 * dvbtraffic should give this stable bandwidths:
2308 * 22k transponder = 33814 kbit/s
2309 * 27.5k transponder = 38045 kbit/s
2310 * by experiment it is found that the best results
2311 * (stable bandwidths and almost no packet loss)
2312 * are obtained using DD1_INIT triggering number 2
2313 * (Va at rising edge of VS Fa = HS x VS-failing forced toggle)
2314 * and a VSYNC phase that occurs in the middle of DMA transfer
2315 * (about byte 188*512=96256 in the DMA window).
2316 *
2317 * Phase of HS is still not clear to me how to control,
2318 * It just happens to be so. It can be seen if one enables
2319 * RPS_IRQ and print Event Counter 1 in vpeirq(). Every
2320 * time RPS_INTERRUPT is called, the Event Counter 1 will
2321 * increment. That's how the 7146 is programmed to do event
2322 * counting in this budget-patch.c
2323 * I *think* HPS setting has something to do with the phase
2324 * of HS but I cant be 100% sure in that.
2325 *
2326 * hardware debug note: a working budget card (including budget patch)
2327 * with vpeirq() interrupt setup in mode "0x90" (every 64K) will
2328 * generate 3 interrupts per 25-Hz DMA frame of 2*188*512 bytes
2329 * and that means 3*25=75 Hz of interrupt freqency, as seen by
2330 * watch cat /proc/interrupts
2331 *
2332 * If this frequency is 3x lower (and data received in the DMA
2333 * buffer don't start with 0x47, but in the middle of packets,
2334 * whose lengths appear to be like 188 292 188 104 etc.
2335 * this means VSYNC line is not connected in the hardware.
2336 * (check soldering pcb and pins)
2337 * The same behaviour of missing VSYNC can be duplicated on budget
2338 * cards, by seting DD1_INIT trigger mode 7 in 3rd nibble.
2339 */
Johannes Stezenbach1be11e32006-02-27 00:09:20 -03002340static int __devinit av7110_attach(struct saa7146_dev* dev,
2341 struct saa7146_pci_extension_data *pci_ext)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002342{
2343 const int length = TS_WIDTH * TS_HEIGHT;
2344 struct pci_dev *pdev = dev->pci;
2345 struct av7110 *av7110;
Herbert Poetzl8eec1422007-02-08 14:32:43 -03002346 struct task_struct *thread;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002347 int ret, count = 0;
2348
2349 dprintk(4, "dev: %p\n", dev);
2350
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -08002351 /* Set RPS_IRQ to 1 to track rps1 activity.
2352 * Enabling this won't send any interrupt to PC CPU.
2353 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002354#define RPS_IRQ 0
2355
2356 if (budgetpatch == 1) {
2357 budgetpatch = 0;
2358 /* autodetect the presence of budget patch
2359 * this only works if saa7146 has been recently
2360 * reset with with MASK_31 to MC1
2361 *
2362 * will wait for VBI_B event (vertical blank at port B)
2363 * and will reset GPIO3 after VBI_B is detected.
2364 * (GPIO3 should be raised high by CPU to
2365 * test if GPIO3 will generate vertical blank signal
2366 * in budget patch GPIO3 is connected to VSYNC_B
2367 */
2368
2369 /* RESET SAA7146 */
2370 saa7146_write(dev, MC1, MASK_31);
2371 /* autodetection success seems to be time-dependend after reset */
2372
2373 /* Fix VSYNC level */
2374 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
2375 /* set vsync_b triggering */
2376 saa7146_write(dev, DD1_STREAM_B, 0);
2377 /* port B VSYNC at rising edge */
2378 saa7146_write(dev, DD1_INIT, 0x00000200);
2379 saa7146_write(dev, BRS_CTRL, 0x00000000); // VBI
2380 saa7146_write(dev, MC2,
2381 1 * (MASK_08 | MASK_24) | // BRS control
2382 0 * (MASK_09 | MASK_25) | // a
2383 1 * (MASK_10 | MASK_26) | // b
2384 0 * (MASK_06 | MASK_22) | // HPS_CTRL1
2385 0 * (MASK_05 | MASK_21) | // HPS_CTRL2
2386 0 * (MASK_01 | MASK_15) // DEBI
2387 );
2388
2389 /* start writing RPS1 code from beginning */
2390 count = 0;
2391 /* Disable RPS1 */
2392 saa7146_write(dev, MC1, MASK_29);
2393 /* RPS1 timeout disable */
2394 saa7146_write(dev, RPS_TOV1, 0);
2395 WRITE_RPS1(cpu_to_le32(CMD_PAUSE | EVT_VBI_B));
2396 WRITE_RPS1(cpu_to_le32(CMD_WR_REG_MASK | (GPIO_CTRL>>2)));
2397 WRITE_RPS1(cpu_to_le32(GPIO3_MSK));
2398 WRITE_RPS1(cpu_to_le32(SAA7146_GPIO_OUTLO<<24));
2399#if RPS_IRQ
2400 /* issue RPS1 interrupt to increment counter */
2401 WRITE_RPS1(cpu_to_le32(CMD_INTERRUPT));
2402#endif
2403 WRITE_RPS1(cpu_to_le32(CMD_STOP));
2404 /* Jump to begin of RPS program as safety measure (p37) */
2405 WRITE_RPS1(cpu_to_le32(CMD_JUMP));
2406 WRITE_RPS1(cpu_to_le32(dev->d_rps1.dma_handle));
2407
2408#if RPS_IRQ
2409 /* set event counter 1 source as RPS1 interrupt (0x03) (rE4 p53)
2410 * use 0x03 to track RPS1 interrupts - increase by 1 every gpio3 is toggled
2411 * use 0x15 to track VPE interrupts - increase by 1 every vpeirq() is called
2412 */
2413 saa7146_write(dev, EC1SSR, (0x03<<2) | 3 );
2414 /* set event counter 1 treshold to maximum allowed value (rEC p55) */
2415 saa7146_write(dev, ECT1R, 0x3fff );
2416#endif
2417 /* Set RPS1 Address register to point to RPS code (r108 p42) */
2418 saa7146_write(dev, RPS_ADDR1, dev->d_rps1.dma_handle);
2419 /* Enable RPS1, (rFC p33) */
2420 saa7146_write(dev, MC1, (MASK_13 | MASK_29 ));
2421
2422 mdelay(10);
2423 /* now send VSYNC_B to rps1 by rising GPIO3 */
2424 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI);
2425 mdelay(10);
2426 /* if rps1 responded by lowering the GPIO3,
2427 * then we have budgetpatch hardware
2428 */
2429 if ((saa7146_read(dev, GPIO_CTRL) & 0x10000000) == 0) {
2430 budgetpatch = 1;
2431 printk("dvb-ttpci: BUDGET-PATCH DETECTED.\n");
2432 }
2433 /* Disable RPS1 */
2434 saa7146_write(dev, MC1, ( MASK_29 ));
2435#if RPS_IRQ
2436 printk("dvb-ttpci: Event Counter 1 0x%04x\n", saa7146_read(dev, EC1R) & 0x3fff );
2437#endif
2438 }
2439
2440 /* prepare the av7110 device struct */
Panagiotis Issaris74081872006-01-11 19:40:56 -02002441 av7110 = kzalloc(sizeof(struct av7110), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002442 if (!av7110) {
2443 dprintk(1, "out of memory\n");
2444 return -ENOMEM;
2445 }
2446
Linus Torvalds1da177e2005-04-16 15:20:36 -07002447 av7110->card_name = (char*) pci_ext->ext_priv;
2448 av7110->dev = dev;
2449 dev->ext_priv = av7110;
2450
2451 ret = get_firmware(av7110);
2452 if (ret < 0)
2453 goto err_kfree_0;
2454
2455 ret = dvb_register_adapter(&av7110->dvb_adapter, av7110->card_name,
Andrew de Quinceyd09dbf92006-04-10 09:27:37 -03002456 THIS_MODULE, &dev->pci->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002457 if (ret < 0)
2458 goto err_put_firmware_1;
2459
2460 /* the Siemens DVB needs this if you want to have the i2c chips
2461 get recognized before the main driver is fully loaded */
2462 saa7146_write(dev, GPIO_CTRL, 0x500000);
2463
2464#ifdef I2C_ADAP_CLASS_TV_DIGITAL
2465 av7110->i2c_adap.class = I2C_ADAP_CLASS_TV_DIGITAL;
2466#else
2467 av7110->i2c_adap.class = I2C_CLASS_TV_DIGITAL;
2468#endif
2469 strlcpy(av7110->i2c_adap.name, pci_ext->ext_priv, sizeof(av7110->i2c_adap.name));
2470
2471 saa7146_i2c_adapter_prepare(dev, &av7110->i2c_adap, SAA7146_I2C_BUS_BIT_RATE_120); /* 275 kHz */
2472
2473 ret = i2c_add_adapter(&av7110->i2c_adap);
2474 if (ret < 0)
2475 goto err_dvb_unregister_adapter_2;
2476
2477 ttpci_eeprom_parse_mac(&av7110->i2c_adap,
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07002478 av7110->dvb_adapter.proposed_mac);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002479 ret = -ENOMEM;
2480
2481 if (budgetpatch) {
2482 spin_lock_init(&av7110->feedlock1);
2483 av7110->grabbing = saa7146_vmalloc_build_pgtable(pdev, length,
2484 &av7110->pt);
2485 if (!av7110->grabbing)
2486 goto err_i2c_del_3;
2487
2488 saa7146_write(dev, PCI_BT_V1, 0x1c1f101f);
2489 saa7146_write(dev, BCS_CTRL, 0x80400040);
2490 /* set dd1 stream a & b */
2491 saa7146_write(dev, DD1_STREAM_B, 0x00000000);
2492 saa7146_write(dev, DD1_INIT, 0x03000200);
2493 saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
2494 saa7146_write(dev, BRS_CTRL, 0x60000000);
2495 saa7146_write(dev, BASE_ODD3, 0);
2496 saa7146_write(dev, BASE_EVEN3, 0);
2497 saa7146_write(dev, PROT_ADDR3, TS_WIDTH * TS_HEIGHT);
2498 saa7146_write(dev, BASE_PAGE3, av7110->pt.dma | ME1 | 0x90);
2499
2500 saa7146_write(dev, PITCH3, TS_WIDTH);
2501 saa7146_write(dev, NUM_LINE_BYTE3, (TS_HEIGHT << 16) | TS_WIDTH);
2502
2503 /* upload all */
2504 saa7146_write(dev, MC2, 0x077c077c);
2505 saa7146_write(dev, GPIO_CTRL, 0x000000);
2506#if RPS_IRQ
2507 /* set event counter 1 source as RPS1 interrupt (0x03) (rE4 p53)
2508 * use 0x03 to track RPS1 interrupts - increase by 1 every gpio3 is toggled
2509 * use 0x15 to track VPE interrupts - increase by 1 every vpeirq() is called
2510 */
2511 saa7146_write(dev, EC1SSR, (0x03<<2) | 3 );
2512 /* set event counter 1 treshold to maximum allowed value (rEC p55) */
2513 saa7146_write(dev, ECT1R, 0x3fff );
2514#endif
2515 /* Setup BUDGETPATCH MAIN RPS1 "program" (p35) */
2516 count = 0;
2517
2518 /* Wait Source Line Counter Threshold (p36) */
2519 WRITE_RPS1(cpu_to_le32(CMD_PAUSE | EVT_HS));
2520 /* Set GPIO3=1 (p42) */
2521 WRITE_RPS1(cpu_to_le32(CMD_WR_REG_MASK | (GPIO_CTRL>>2)));
2522 WRITE_RPS1(cpu_to_le32(GPIO3_MSK));
2523 WRITE_RPS1(cpu_to_le32(SAA7146_GPIO_OUTHI<<24));
2524#if RPS_IRQ
2525 /* issue RPS1 interrupt */
2526 WRITE_RPS1(cpu_to_le32(CMD_INTERRUPT));
2527#endif
2528 /* Wait reset Source Line Counter Threshold (p36) */
2529 WRITE_RPS1(cpu_to_le32(CMD_PAUSE | RPS_INV | EVT_HS));
2530 /* Set GPIO3=0 (p42) */
2531 WRITE_RPS1(cpu_to_le32(CMD_WR_REG_MASK | (GPIO_CTRL>>2)));
2532 WRITE_RPS1(cpu_to_le32(GPIO3_MSK));
2533 WRITE_RPS1(cpu_to_le32(SAA7146_GPIO_OUTLO<<24));
2534#if RPS_IRQ
2535 /* issue RPS1 interrupt */
2536 WRITE_RPS1(cpu_to_le32(CMD_INTERRUPT));
2537#endif
2538 /* Jump to begin of RPS program (p37) */
2539 WRITE_RPS1(cpu_to_le32(CMD_JUMP));
2540 WRITE_RPS1(cpu_to_le32(dev->d_rps1.dma_handle));
2541
2542 /* Fix VSYNC level */
2543 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
2544 /* Set RPS1 Address register to point to RPS code (r108 p42) */
2545 saa7146_write(dev, RPS_ADDR1, dev->d_rps1.dma_handle);
2546 /* Set Source Line Counter Threshold, using BRS (rCC p43)
2547 * It generates HS event every TS_HEIGHT lines
2548 * this is related to TS_WIDTH set in register
2549 * NUM_LINE_BYTE3. If NUM_LINE_BYTE low 16 bits
2550 * are set to TS_WIDTH bytes (TS_WIDTH=2*188),
2551 * then RPS_THRESH1 should be set to trigger
2552 * every TS_HEIGHT (512) lines.
2553 */
2554 saa7146_write(dev, RPS_THRESH1, (TS_HEIGHT*1) | MASK_12 );
2555
2556 /* Enable RPS1 (rFC p33) */
2557 saa7146_write(dev, MC1, (MASK_13 | MASK_29));
2558
2559 /* end of budgetpatch register initialization */
2560 tasklet_init (&av7110->vpe_tasklet, vpeirq, (unsigned long) av7110);
2561 } else {
2562 saa7146_write(dev, PCI_BT_V1, 0x1c00101f);
2563 saa7146_write(dev, BCS_CTRL, 0x80400040);
2564
2565 /* set dd1 stream a & b */
2566 saa7146_write(dev, DD1_STREAM_B, 0x00000000);
2567 saa7146_write(dev, DD1_INIT, 0x03000000);
2568 saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
2569
2570 /* upload all */
2571 saa7146_write(dev, MC2, 0x077c077c);
2572 saa7146_write(dev, GPIO_CTRL, 0x000000);
2573 }
2574
2575 tasklet_init (&av7110->debi_tasklet, debiirq, (unsigned long) av7110);
2576 tasklet_init (&av7110->gpio_tasklet, gpioirq, (unsigned long) av7110);
2577
Ingo Molnar3593cab2006-02-07 06:49:14 -02002578 mutex_init(&av7110->pid_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002579
2580 /* locks for data transfers from/to AV7110 */
2581 spin_lock_init(&av7110->debilock);
Ingo Molnar3593cab2006-02-07 06:49:14 -02002582 mutex_init(&av7110->dcomlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002583 av7110->debitype = -1;
2584
2585 /* default OSD window */
2586 av7110->osdwin = 1;
Ingo Molnar3593cab2006-02-07 06:49:14 -02002587 mutex_init(&av7110->osd_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002588
C.Y.M2f03ee82006-03-30 04:31:48 -03002589 /* TV standard */
2590 av7110->vidmode = tv_standard == 1 ? VIDEO_MODE_NTSC : VIDEO_MODE_PAL;
2591
Linus Torvalds1da177e2005-04-16 15:20:36 -07002592 /* ARM "watchdog" */
2593 init_waitqueue_head(&av7110->arm_wait);
2594 av7110->arm_thread = NULL;
2595
2596 /* allocate and init buffers */
2597 av7110->debi_virt = pci_alloc_consistent(pdev, 8192, &av7110->debi_bus);
2598 if (!av7110->debi_virt)
2599 goto err_saa71466_vfree_4;
2600
2601
2602 av7110->iobuf = vmalloc(AVOUTLEN+AOUTLEN+BMPLEN+4*IPACKS);
2603 if (!av7110->iobuf)
2604 goto err_pci_free_5;
2605
2606 ret = av7110_av_init(av7110);
2607 if (ret < 0)
2608 goto err_iobuf_vfree_6;
2609
2610 /* init BMP buffer */
2611 av7110->bmpbuf = av7110->iobuf+AVOUTLEN+AOUTLEN;
2612 init_waitqueue_head(&av7110->bmpq);
2613
2614 ret = av7110_ca_init(av7110);
2615 if (ret < 0)
2616 goto err_av7110_av_exit_7;
2617
2618 /* load firmware into AV7110 cards */
2619 ret = av7110_bootarm(av7110);
2620 if (ret < 0)
2621 goto err_av7110_ca_exit_8;
2622
2623 ret = av7110_firmversion(av7110);
2624 if (ret < 0)
2625 goto err_stop_arm_9;
2626
2627 if (FW_VERSION(av7110->arm_app)<0x2501)
2628 printk ("dvb-ttpci: Warning, firmware version 0x%04x is too old. "
2629 "System might be unstable!\n", FW_VERSION(av7110->arm_app));
2630
Herbert Poetzl8eec1422007-02-08 14:32:43 -03002631 thread = kthread_run(arm_thread, (void *) av7110, "arm_mon");
2632 if (IS_ERR(thread)) {
2633 ret = PTR_ERR(thread);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002634 goto err_stop_arm_9;
Herbert Poetzl8eec1422007-02-08 14:32:43 -03002635 }
2636 av7110->arm_thread = thread;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002637
2638 /* set initial volume in mixer struct */
2639 av7110->mixer.volume_left = volume;
2640 av7110->mixer.volume_right = volume;
2641
2642 init_av7110_av(av7110);
2643
2644 ret = av7110_register(av7110);
2645 if (ret < 0)
2646 goto err_arm_thread_stop_10;
2647
2648 /* special case DVB-C: these cards have an analog tuner
2649 plus need some special handling, so we have separate
2650 saa7146_ext_vv data for these... */
2651 ret = av7110_init_v4l(av7110);
2652 if (ret < 0)
2653 goto err_av7110_unregister_11;
2654
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07002655 av7110->dvb_adapter.priv = av7110;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002656 ret = frontend_init(av7110);
2657 if (ret < 0)
2658 goto err_av7110_exit_v4l_12;
2659
2660#if defined(CONFIG_INPUT_EVDEV) || defined(CONFIG_INPUT_EVDEV_MODULE)
Oliver Endriss03388ae2005-09-09 13:03:12 -07002661 av7110_ir_init(av7110);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002662#endif
2663 printk(KERN_INFO "dvb-ttpci: found av7110-%d.\n", av7110_num);
2664 av7110_num++;
2665out:
2666 return ret;
2667
2668err_av7110_exit_v4l_12:
2669 av7110_exit_v4l(av7110);
2670err_av7110_unregister_11:
2671 dvb_unregister(av7110);
2672err_arm_thread_stop_10:
2673 av7110_arm_sync(av7110);
2674err_stop_arm_9:
2675 /* Nothing to do. Rejoice. */
2676err_av7110_ca_exit_8:
2677 av7110_ca_exit(av7110);
2678err_av7110_av_exit_7:
2679 av7110_av_exit(av7110);
2680err_iobuf_vfree_6:
2681 vfree(av7110->iobuf);
2682err_pci_free_5:
2683 pci_free_consistent(pdev, 8192, av7110->debi_virt, av7110->debi_bus);
2684err_saa71466_vfree_4:
Jon Burgess87c30192007-05-03 12:23:44 -03002685 if (av7110->grabbing)
2686 saa7146_vfree_destroy_pgtable(pdev, av7110->grabbing, &av7110->pt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002687err_i2c_del_3:
2688 i2c_del_adapter(&av7110->i2c_adap);
2689err_dvb_unregister_adapter_2:
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07002690 dvb_unregister_adapter(&av7110->dvb_adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002691err_put_firmware_1:
2692 put_firmware(av7110);
2693err_kfree_0:
2694 kfree(av7110);
2695 goto out;
2696}
2697
Johannes Stezenbach1be11e32006-02-27 00:09:20 -03002698static int __devexit av7110_detach(struct saa7146_dev* saa)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002699{
2700 struct av7110 *av7110 = saa->ext_priv;
2701 dprintk(4, "%p\n", av7110);
2702
Oliver Endriss03388ae2005-09-09 13:03:12 -07002703#if defined(CONFIG_INPUT_EVDEV) || defined(CONFIG_INPUT_EVDEV_MODULE)
2704 av7110_ir_exit(av7110);
2705#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07002706 if (budgetpatch) {
2707 /* Disable RPS1 */
2708 saa7146_write(saa, MC1, MASK_29);
2709 /* VSYNC LOW (inactive) */
2710 saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);
2711 saa7146_write(saa, MC1, MASK_20); /* DMA3 off */
2712 SAA7146_IER_DISABLE(saa, MASK_10);
2713 SAA7146_ISR_CLEAR(saa, MASK_10);
2714 msleep(50);
2715 tasklet_kill(&av7110->vpe_tasklet);
Jon Burgess87c30192007-05-03 12:23:44 -03002716 saa7146_vfree_destroy_pgtable(saa->pci, av7110->grabbing, &av7110->pt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002717 }
2718 av7110_exit_v4l(av7110);
2719
2720 av7110_arm_sync(av7110);
2721
2722 tasklet_kill(&av7110->debi_tasklet);
2723 tasklet_kill(&av7110->gpio_tasklet);
2724
2725 dvb_unregister(av7110);
2726
2727 SAA7146_IER_DISABLE(saa, MASK_19 | MASK_03);
2728 SAA7146_ISR_CLEAR(saa, MASK_19 | MASK_03);
2729
2730 av7110_ca_exit(av7110);
2731 av7110_av_exit(av7110);
2732
2733 vfree(av7110->iobuf);
2734 pci_free_consistent(saa->pci, 8192, av7110->debi_virt,
2735 av7110->debi_bus);
2736
2737 i2c_del_adapter(&av7110->i2c_adap);
2738
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07002739 dvb_unregister_adapter (&av7110->dvb_adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002740
2741 av7110_num--;
2742
2743 put_firmware(av7110);
2744
2745 kfree(av7110);
2746
2747 saa->ext_priv = NULL;
2748
2749 return 0;
2750}
2751
2752
2753static void av7110_irq(struct saa7146_dev* dev, u32 *isr)
2754{
2755 struct av7110 *av7110 = dev->ext_priv;
2756
2757 //print_time("av7110_irq");
2758
2759 /* Note: Don't try to handle the DEBI error irq (MASK_18), in
2760 * intel mode the timeout is asserted all the time...
2761 */
2762
2763 if (*isr & MASK_19) {
2764 //printk("av7110_irq: DEBI\n");
2765 /* Note 1: The DEBI irq is level triggered: We must enable it
2766 * only after we started a DMA xfer, and disable it here
2767 * immediately, or it will be signalled all the time while
2768 * DEBI is idle.
2769 * Note 2: You would think that an irq which is masked is
2770 * not signalled by the hardware. Not so for the SAA7146:
2771 * An irq is signalled as long as the corresponding bit
2772 * in the ISR is set, and disabling irqs just prevents the
2773 * hardware from setting the ISR bit. This means a) that we
2774 * must clear the ISR *after* disabling the irq (which is why
2775 * we must do it here even though saa7146_core did it already),
2776 * and b) that if we were to disable an edge triggered irq
2777 * (like the gpio irqs sadly are) temporarily we would likely
2778 * loose some. This sucks :-(
2779 */
2780 SAA7146_IER_DISABLE(av7110->dev, MASK_19);
2781 SAA7146_ISR_CLEAR(av7110->dev, MASK_19);
2782 tasklet_schedule(&av7110->debi_tasklet);
2783 }
2784
2785 if (*isr & MASK_03) {
2786 //printk("av7110_irq: GPIO\n");
2787 tasklet_schedule(&av7110->gpio_tasklet);
2788 }
2789
2790 if ((*isr & MASK_10) && budgetpatch)
2791 tasklet_schedule(&av7110->vpe_tasklet);
2792}
2793
2794
2795static struct saa7146_extension av7110_extension;
2796
2797#define MAKE_AV7110_INFO(x_var,x_name) \
2798static struct saa7146_pci_extension_data x_var = { \
2799 .ext_priv = x_name, \
2800 .ext = &av7110_extension }
2801
Karl Herz6af4ee12005-09-09 13:03:13 -07002802MAKE_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 -07002803MAKE_AV7110_INFO(ttt_1_X, "Technotrend/Hauppauge WinTV DVB-T rev1.X");
2804MAKE_AV7110_INFO(ttc_1_X, "Technotrend/Hauppauge WinTV Nexus-CA rev1.X");
2805MAKE_AV7110_INFO(ttc_2_X, "Technotrend/Hauppauge WinTV DVB-C rev2.X");
2806MAKE_AV7110_INFO(tts_2_X, "Technotrend/Hauppauge WinTV Nexus-S rev2.X");
Johannes Stezenbach3dfaebd2005-05-16 21:54:19 -07002807MAKE_AV7110_INFO(tts_2_3, "Technotrend/Hauppauge WinTV Nexus-S rev2.3");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002808MAKE_AV7110_INFO(tts_1_3se, "Technotrend/Hauppauge WinTV DVB-S rev1.3 SE");
2809MAKE_AV7110_INFO(ttt, "Technotrend/Hauppauge DVB-T");
2810MAKE_AV7110_INFO(fsc, "Fujitsu Siemens DVB-C");
2811MAKE_AV7110_INFO(fss, "Fujitsu Siemens DVB-S rev1.6");
Oliver Endriss8bd63012006-02-07 06:49:11 -02002812MAKE_AV7110_INFO(gxs_1_3, "Galaxis DVB-S rev1.3");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002813
2814static struct pci_device_id pci_tbl[] = {
Karl Herz6af4ee12005-09-09 13:03:13 -07002815 MAKE_EXTENSION_PCI(fsc, 0x110a, 0x0000),
2816 MAKE_EXTENSION_PCI(tts_1_X_fsc, 0x13c2, 0x0000),
2817 MAKE_EXTENSION_PCI(ttt_1_X, 0x13c2, 0x0001),
2818 MAKE_EXTENSION_PCI(ttc_2_X, 0x13c2, 0x0002),
2819 MAKE_EXTENSION_PCI(tts_2_X, 0x13c2, 0x0003),
Oliver Endriss8bd63012006-02-07 06:49:11 -02002820 MAKE_EXTENSION_PCI(gxs_1_3, 0x13c2, 0x0004),
Karl Herz6af4ee12005-09-09 13:03:13 -07002821 MAKE_EXTENSION_PCI(fss, 0x13c2, 0x0006),
2822 MAKE_EXTENSION_PCI(ttt, 0x13c2, 0x0008),
2823 MAKE_EXTENSION_PCI(ttc_1_X, 0x13c2, 0x000a),
2824 MAKE_EXTENSION_PCI(tts_2_3, 0x13c2, 0x000e),
2825 MAKE_EXTENSION_PCI(tts_1_3se, 0x13c2, 0x1002),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002826
Linus Torvalds1da177e2005-04-16 15:20:36 -07002827/* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0005), UNDEFINED CARD */ // Technisat SkyStar1
2828/* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0009), UNDEFINED CARD */ // TT/Hauppauge WinTV Nexus-CA v????
2829
2830 {
2831 .vendor = 0,
2832 }
2833};
2834
2835MODULE_DEVICE_TABLE(pci, pci_tbl);
2836
2837
2838static struct saa7146_extension av7110_extension = {
Dave Jones0e367a12006-08-07 13:18:56 -03002839 .name = "dvb",
Oliver Endriss00c4cc62006-11-01 13:09:51 -03002840 .flags = SAA7146_USE_I2C_IRQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002841
2842 .module = THIS_MODULE,
2843 .pci_tbl = &pci_tbl[0],
2844 .attach = av7110_attach,
Johannes Stezenbach1be11e32006-02-27 00:09:20 -03002845 .detach = __devexit_p(av7110_detach),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002846
2847 .irq_mask = MASK_19 | MASK_03 | MASK_10,
2848 .irq_func = av7110_irq,
2849};
2850
2851
2852static int __init av7110_init(void)
2853{
2854 int retval;
2855 retval = saa7146_register_extension(&av7110_extension);
2856 return retval;
2857}
2858
2859
2860static void __exit av7110_exit(void)
2861{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002862 saa7146_unregister_extension(&av7110_extension);
2863}
2864
2865module_init(av7110_init);
2866module_exit(av7110_exit);
2867
2868MODULE_DESCRIPTION("driver for the SAA7146 based AV110 PCI DVB cards by "
2869 "Siemens, Technotrend, Hauppauge");
2870MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, others");
2871MODULE_LICENSE("GPL");