blob: 2cee9e3bd29f8c33cb4b73e1c1f7d156cf7b3d8d [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 Endrissdefd574e2007-07-12 23:08:07 -0300140 ret = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetMonitorType,
141 1, (u16) av7110->display_ar);
142 if (ret < 0)
143 printk("dvb-ttpci: unable to set aspect ratio\n");
144 ret = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetPanScanType,
145 1, av7110->display_panscan);
146 if (ret < 0)
147 printk("dvb-ttpci: unable to set pan scan\n");
148
Oliver Endriss4caba422006-03-17 05:29:15 -0300149 ret = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetWSSConfig, 2, 2, wss_cfg_4_3);
150 if (ret < 0)
151 printk("dvb-ttpci: unable to configure 4:3 wss\n");
152 ret = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetWSSConfig, 2, 3, wss_cfg_16_9);
153 if (ret < 0)
154 printk("dvb-ttpci: unable to configure 16:9 wss\n");
155
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700156 ret = av7710_set_video_mode(av7110, vidmode);
Johannes Stezenbach7a2fa902005-07-07 17:58:01 -0700157 if (ret < 0)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700158 printk("dvb-ttpci:cannot set video mode:%d\n",ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700159
160 /* handle different card types */
161 /* remaining inits according to card and frontend type */
162 av7110->analog_tuner_flags = 0;
163 av7110->current_input = 0;
Tim Kaiser61391e02006-06-25 09:14:07 -0300164 if (dev->pci->subsystem_vendor == 0x13c2 && dev->pci->subsystem_device == 0x000a)
Marco Schluessler1c13b952006-01-09 15:25:06 -0200165 av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, ADSwitch, 1, 0); // SPDIF on
Tim Kaiser61391e02006-06-25 09:14:07 -0300166 if (i2c_writereg(av7110, 0x20, 0x00, 0x00) == 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700167 printk ("dvb-ttpci: Crystal audio DAC @ card %d detected\n",
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -0700168 av7110->dvb_adapter.num);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700169 av7110->adac_type = DVB_ADAC_CRYSTAL;
170 i2c_writereg(av7110, 0x20, 0x01, 0xd2);
171 i2c_writereg(av7110, 0x20, 0x02, 0x49);
172 i2c_writereg(av7110, 0x20, 0x03, 0x00);
173 i2c_writereg(av7110, 0x20, 0x04, 0x00);
174
175 /**
176 * some special handling for the Siemens DVB-C cards...
177 */
178 } else if (0 == av7110_init_analog_module(av7110)) {
179 /* done. */
180 }
181 else if (dev->pci->subsystem_vendor == 0x110a) {
182 printk("dvb-ttpci: DVB-C w/o analog module @ card %d detected\n",
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -0700183 av7110->dvb_adapter.num);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700184 av7110->adac_type = DVB_ADAC_NONE;
185 }
186 else {
187 av7110->adac_type = adac;
188 printk("dvb-ttpci: adac type set to %d @ card %d\n",
Marco Schluessler1c13b952006-01-09 15:25:06 -0200189 av7110->adac_type, av7110->dvb_adapter.num);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700190 }
191
Marco Schluessler1c13b952006-01-09 15:25:06 -0200192 if (av7110->adac_type == DVB_ADAC_NONE || av7110->adac_type == DVB_ADAC_MSP34x0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700193 // switch DVB SCART on
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700194 ret = av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, MainSwitch, 1, 0);
Johannes Stezenbach7a2fa902005-07-07 17:58:01 -0700195 if (ret < 0)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700196 printk("dvb-ttpci:cannot switch on SCART(Main):%d\n",ret);
197 ret = av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, ADSwitch, 1, 1);
Johannes Stezenbach7a2fa902005-07-07 17:58:01 -0700198 if (ret < 0)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700199 printk("dvb-ttpci:cannot switch on SCART(AD):%d\n",ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200 if (rgb_on &&
Karl Herz6af4ee12005-09-09 13:03:13 -0700201 ((av7110->dev->pci->subsystem_vendor == 0x110a) ||
202 (av7110->dev->pci->subsystem_vendor == 0x13c2)) &&
203 (av7110->dev->pci->subsystem_device == 0x0000)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700204 saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); // RGB on, SCART pin 16
205 //saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); // SCARTpin 8
206 }
207 }
208
Oliver Endriss60edb132005-12-19 08:54:11 -0200209 if (dev->pci->subsystem_vendor == 0x13c2 && dev->pci->subsystem_device == 0x000e)
210 av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, SpdifSwitch, 1, 0); // SPDIF on
211
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700212 ret = av7110_set_volume(av7110, av7110->mixer.volume_left, av7110->mixer.volume_right);
Johannes Stezenbach7a2fa902005-07-07 17:58:01 -0700213 if (ret < 0)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700214 printk("dvb-ttpci:cannot set volume :%d\n",ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215}
216
217static void recover_arm(struct av7110 *av7110)
218{
219 dprintk(4, "%p\n",av7110);
220
221 av7110_bootarm(av7110);
222 msleep(100);
Oliver Endriss66190a22006-01-09 15:32:42 -0200223
224 init_av7110_av(av7110);
225
226 /* card-specific recovery */
227 if (av7110->recover)
228 av7110->recover(av7110);
229
Linus Torvalds1da177e2005-04-16 15:20:36 -0700230 restart_feeds(av7110);
Oliver Endrissee820a62007-04-27 12:31:21 -0300231
232#if defined(CONFIG_INPUT_EVDEV) || defined(CONFIG_INPUT_EVDEV_MODULE)
233 av7110_check_ir_config(av7110, true);
234#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700235}
236
Linus Torvalds1da177e2005-04-16 15:20:36 -0700237static void av7110_arm_sync(struct av7110 *av7110)
238{
Herbert Poetzl8eec1422007-02-08 14:32:43 -0300239 if (av7110->arm_thread)
240 kthread_stop(av7110->arm_thread);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700241
Herbert Poetzl8eec1422007-02-08 14:32:43 -0300242 av7110->arm_thread = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700243}
244
245static int arm_thread(void *data)
246{
247 struct av7110 *av7110 = data;
248 u16 newloops = 0;
249 int timeout;
250
251 dprintk(4, "%p\n",av7110);
252
Linus Torvalds1da177e2005-04-16 15:20:36 -0700253 for (;;) {
254 timeout = wait_event_interruptible_timeout(av7110->arm_wait,
Herbert Poetzl8eec1422007-02-08 14:32:43 -0300255 kthread_should_stop(), 5 * HZ);
256
257 if (-ERESTARTSYS == timeout || kthread_should_stop()) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258 /* got signal or told to quit*/
259 break;
260 }
261
262 if (!av7110->arm_ready)
263 continue;
264
Oliver Endrissee820a62007-04-27 12:31:21 -0300265#if defined(CONFIG_INPUT_EVDEV) || defined(CONFIG_INPUT_EVDEV_MODULE)
266 av7110_check_ir_config(av7110, false);
267#endif
268
Ingo Molnar3593cab2006-02-07 06:49:14 -0200269 if (mutex_lock_interruptible(&av7110->dcomlock))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700270 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271 newloops = rdebi(av7110, DEBINOSWAP, STATUS_LOOPS, 0, 2);
Ingo Molnar3593cab2006-02-07 06:49:14 -0200272 mutex_unlock(&av7110->dcomlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273
Oliver Endriss66190a22006-01-09 15:32:42 -0200274 if (newloops == av7110->arm_loops || av7110->arm_errors > 3) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275 printk(KERN_ERR "dvb-ttpci: ARM crashed @ card %d\n",
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -0700276 av7110->dvb_adapter.num);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700277
Oliver Endriss66190a22006-01-09 15:32:42 -0200278 recover_arm(av7110);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279
Ingo Molnar3593cab2006-02-07 06:49:14 -0200280 if (mutex_lock_interruptible(&av7110->dcomlock))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700281 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700282 newloops = rdebi(av7110, DEBINOSWAP, STATUS_LOOPS, 0, 2) - 1;
Ingo Molnar3593cab2006-02-07 06:49:14 -0200283 mutex_unlock(&av7110->dcomlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284 }
285 av7110->arm_loops = newloops;
Oliver Endriss66190a22006-01-09 15:32:42 -0200286 av7110->arm_errors = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287 }
288
Linus Torvalds1da177e2005-04-16 15:20:36 -0700289 return 0;
290}
291
292
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293/****************************************************************************
294 * IRQ handling
295 ****************************************************************************/
296
297static int DvbDmxFilterCallback(u8 *buffer1, size_t buffer1_len,
298 u8 *buffer2, size_t buffer2_len,
299 struct dvb_demux_filter *dvbdmxfilter,
300 enum dmx_success success,
301 struct av7110 *av7110)
302{
303 if (!dvbdmxfilter->feed->demux->dmx.frontend)
304 return 0;
305 if (dvbdmxfilter->feed->demux->dmx.frontend->source == DMX_MEMORY_FE)
306 return 0;
307
308 switch (dvbdmxfilter->type) {
309 case DMX_TYPE_SEC:
310 if ((((buffer1[1] << 8) | buffer1[2]) & 0xfff) + 3 != buffer1_len)
311 return 0;
312 if (dvbdmxfilter->doneq) {
313 struct dmx_section_filter *filter = &dvbdmxfilter->filter;
314 int i;
315 u8 xor, neq = 0;
316
317 for (i = 0; i < DVB_DEMUX_MASK_MAX; i++) {
318 xor = filter->filter_value[i] ^ buffer1[i];
319 neq |= dvbdmxfilter->maskandnotmode[i] & xor;
320 }
321 if (!neq)
322 return 0;
323 }
324 return dvbdmxfilter->feed->cb.sec(buffer1, buffer1_len,
325 buffer2, buffer2_len,
326 &dvbdmxfilter->filter,
327 DMX_OK);
328 case DMX_TYPE_TS:
329 if (!(dvbdmxfilter->feed->ts_type & TS_PACKET))
330 return 0;
331 if (dvbdmxfilter->feed->ts_type & TS_PAYLOAD_ONLY)
332 return dvbdmxfilter->feed->cb.ts(buffer1, buffer1_len,
333 buffer2, buffer2_len,
334 &dvbdmxfilter->feed->feed.ts,
335 DMX_OK);
336 else
337 av7110_p2t_write(buffer1, buffer1_len,
338 dvbdmxfilter->feed->pid,
339 &av7110->p2t_filter[dvbdmxfilter->index]);
340 default:
341 return 0;
342 }
343}
344
345
346//#define DEBUG_TIMING
347static inline void print_time(char *s)
348{
349#ifdef DEBUG_TIMING
350 struct timeval tv;
351 do_gettimeofday(&tv);
352 printk("%s: %d.%d\n", s, (int)tv.tv_sec, (int)tv.tv_usec);
353#endif
354}
355
356#define DEBI_READ 0
357#define DEBI_WRITE 1
358static inline void start_debi_dma(struct av7110 *av7110, int dir,
359 unsigned long addr, unsigned int len)
360{
361 dprintk(8, "%c %08lx %u\n", dir == DEBI_READ ? 'R' : 'W', addr, len);
362 if (saa7146_wait_for_debi_done(av7110->dev, 0)) {
363 printk(KERN_ERR "%s: saa7146_wait_for_debi_done timed out\n", __FUNCTION__);
364 return;
365 }
366
367 SAA7146_ISR_CLEAR(av7110->dev, MASK_19); /* for good measure */
368 SAA7146_IER_ENABLE(av7110->dev, MASK_19);
369 if (len < 5)
370 len = 5; /* we want a real DEBI DMA */
371 if (dir == DEBI_WRITE)
372 iwdebi(av7110, DEBISWAB, addr, 0, (len + 3) & ~3);
373 else
374 irdebi(av7110, DEBISWAB, addr, 0, len);
375}
376
377static void debiirq(unsigned long data)
378{
379 struct av7110 *av7110 = (struct av7110 *) data;
380 int type = av7110->debitype;
381 int handle = (type >> 8) & 0x1f;
382 unsigned int xfer = 0;
383
384 print_time("debi");
385 dprintk(4, "type 0x%04x\n", type);
386
387 if (type == -1) {
388 printk("DEBI irq oops @ %ld, psr:0x%08x, ssr:0x%08x\n",
389 jiffies, saa7146_read(av7110->dev, PSR),
390 saa7146_read(av7110->dev, SSR));
391 goto debi_done;
392 }
393 av7110->debitype = -1;
394
395 switch (type & 0xff) {
396
397 case DATA_TS_RECORD:
398 dvb_dmx_swfilter_packets(&av7110->demux,
399 (const u8 *) av7110->debi_virt,
400 av7110->debilen / 188);
401 xfer = RX_BUFF;
402 break;
403
404 case DATA_PES_RECORD:
405 if (av7110->demux.recording)
406 av7110_record_cb(&av7110->p2t[handle],
407 (u8 *) av7110->debi_virt,
408 av7110->debilen);
409 xfer = RX_BUFF;
410 break;
411
412 case DATA_IPMPE:
413 case DATA_FSECTION:
414 case DATA_PIPING:
415 if (av7110->handle2filter[handle])
416 DvbDmxFilterCallback((u8 *)av7110->debi_virt,
417 av7110->debilen, NULL, 0,
418 av7110->handle2filter[handle],
419 DMX_OK, av7110);
420 xfer = RX_BUFF;
421 break;
422
423 case DATA_CI_GET:
424 {
425 u8 *data = av7110->debi_virt;
426
427 if ((data[0] < 2) && data[2] == 0xff) {
428 int flags = 0;
429 if (data[5] > 0)
430 flags |= CA_CI_MODULE_PRESENT;
431 if (data[5] > 5)
432 flags |= CA_CI_MODULE_READY;
433 av7110->ci_slot[data[0]].flags = flags;
434 } else
435 ci_get_data(&av7110->ci_rbuffer,
436 av7110->debi_virt,
437 av7110->debilen);
438 xfer = RX_BUFF;
439 break;
440 }
441
442 case DATA_COMMON_INTERFACE:
443 CI_handle(av7110, (u8 *)av7110->debi_virt, av7110->debilen);
444#if 0
445 {
446 int i;
447
448 printk("av7110%d: ", av7110->num);
449 printk("%02x ", *(u8 *)av7110->debi_virt);
450 printk("%02x ", *(1+(u8 *)av7110->debi_virt));
451 for (i = 2; i < av7110->debilen; i++)
452 printk("%02x ", (*(i+(unsigned char *)av7110->debi_virt)));
453 for (i = 2; i < av7110->debilen; i++)
454 printk("%c", chtrans(*(i+(unsigned char *)av7110->debi_virt)));
455
456 printk("\n");
457 }
458#endif
459 xfer = RX_BUFF;
460 break;
461
462 case DATA_DEBUG_MESSAGE:
463 ((s8*)av7110->debi_virt)[Reserved_SIZE - 1] = 0;
464 printk("%s\n", (s8 *) av7110->debi_virt);
465 xfer = RX_BUFF;
466 break;
467
468 case DATA_CI_PUT:
469 dprintk(4, "debi DATA_CI_PUT\n");
470 case DATA_MPEG_PLAY:
471 dprintk(4, "debi DATA_MPEG_PLAY\n");
472 case DATA_BMP_LOAD:
473 dprintk(4, "debi DATA_BMP_LOAD\n");
474 xfer = TX_BUFF;
475 break;
476 default:
477 break;
478 }
479debi_done:
480 spin_lock(&av7110->debilock);
481 if (xfer)
482 iwdebi(av7110, DEBINOSWAP, xfer, 0, 2);
483 ARM_ClearMailBox(av7110);
484 spin_unlock(&av7110->debilock);
485}
486
487/* irq from av7110 firmware writing the mailbox register in the DPRAM */
488static void gpioirq(unsigned long data)
489{
490 struct av7110 *av7110 = (struct av7110 *) data;
491 u32 rxbuf, txbuf;
492 int len;
493
494 if (av7110->debitype != -1)
495 /* we shouldn't get any irq while a debi xfer is running */
496 printk("dvb-ttpci: GPIO0 irq oops @ %ld, psr:0x%08x, ssr:0x%08x\n",
497 jiffies, saa7146_read(av7110->dev, PSR),
498 saa7146_read(av7110->dev, SSR));
499
500 if (saa7146_wait_for_debi_done(av7110->dev, 0)) {
501 printk(KERN_ERR "%s: saa7146_wait_for_debi_done timed out\n", __FUNCTION__);
502 BUG(); /* maybe we should try resetting the debi? */
503 }
504
505 spin_lock(&av7110->debilock);
506 ARM_ClearIrq(av7110);
507
508 /* see what the av7110 wants */
509 av7110->debitype = irdebi(av7110, DEBINOSWAP, IRQ_STATE, 0, 2);
510 av7110->debilen = irdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
511 rxbuf = irdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
512 txbuf = irdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
513 len = (av7110->debilen + 3) & ~3;
514
515 print_time("gpio");
516 dprintk(8, "GPIO0 irq 0x%04x %d\n", av7110->debitype, av7110->debilen);
517
518 switch (av7110->debitype & 0xff) {
519
520 case DATA_TS_PLAY:
521 case DATA_PES_PLAY:
522 break;
523
524 case DATA_MPEG_VIDEO_EVENT:
525 {
526 u32 h_ar;
527 struct video_event event;
528
529 av7110->video_size.w = irdebi(av7110, DEBINOSWAP, STATUS_MPEG_WIDTH, 0, 2);
530 h_ar = irdebi(av7110, DEBINOSWAP, STATUS_MPEG_HEIGHT_AR, 0, 2);
531
532 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
533 iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
534
535 av7110->video_size.h = h_ar & 0xfff;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700536
537 event.type = VIDEO_EVENT_SIZE_CHANGED;
538 event.u.size.w = av7110->video_size.w;
539 event.u.size.h = av7110->video_size.h;
540 switch ((h_ar >> 12) & 0xf)
541 {
542 case 3:
543 av7110->video_size.aspect_ratio = VIDEO_FORMAT_16_9;
544 event.u.size.aspect_ratio = VIDEO_FORMAT_16_9;
545 av7110->videostate.video_format = VIDEO_FORMAT_16_9;
546 break;
547 case 4:
548 av7110->video_size.aspect_ratio = VIDEO_FORMAT_221_1;
549 event.u.size.aspect_ratio = VIDEO_FORMAT_221_1;
550 av7110->videostate.video_format = VIDEO_FORMAT_221_1;
551 break;
552 default:
553 av7110->video_size.aspect_ratio = VIDEO_FORMAT_4_3;
554 event.u.size.aspect_ratio = VIDEO_FORMAT_4_3;
555 av7110->videostate.video_format = VIDEO_FORMAT_4_3;
556 }
Oliver Endriss66190a22006-01-09 15:32:42 -0200557
558 dprintk(8, "GPIO0 irq: DATA_MPEG_VIDEO_EVENT: w/h/ar = %u/%u/%u\n",
559 av7110->video_size.w, av7110->video_size.h,
560 av7110->video_size.aspect_ratio);
561
Linus Torvalds1da177e2005-04-16 15:20:36 -0700562 dvb_video_add_event(av7110, &event);
563 break;
564 }
565
566 case DATA_CI_PUT:
567 {
568 int avail;
569 struct dvb_ringbuffer *cibuf = &av7110->ci_wbuffer;
570
571 avail = dvb_ringbuffer_avail(cibuf);
572 if (avail <= 2) {
573 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
574 iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
575 iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
576 break;
577 }
578 len = DVB_RINGBUFFER_PEEK(cibuf, 0) << 8;
579 len |= DVB_RINGBUFFER_PEEK(cibuf, 1);
580 if (avail < len + 2) {
581 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
582 iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
583 iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
584 break;
585 }
586 DVB_RINGBUFFER_SKIP(cibuf, 2);
587
588 dvb_ringbuffer_read(cibuf, av7110->debi_virt, len, 0);
589
590 iwdebi(av7110, DEBINOSWAP, TX_LEN, len, 2);
591 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, len, 2);
592 dprintk(8, "DMA: CI\n");
593 start_debi_dma(av7110, DEBI_WRITE, DPRAM_BASE + txbuf, len);
594 spin_unlock(&av7110->debilock);
595 wake_up(&cibuf->queue);
596 return;
597 }
598
599 case DATA_MPEG_PLAY:
600 if (!av7110->playing) {
601 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
602 iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
603 iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
604 break;
605 }
606 len = 0;
607 if (av7110->debitype & 0x100) {
608 spin_lock(&av7110->aout.lock);
609 len = av7110_pes_play(av7110->debi_virt, &av7110->aout, 2048);
610 spin_unlock(&av7110->aout.lock);
611 }
612 if (len <= 0 && (av7110->debitype & 0x200)
613 &&av7110->videostate.play_state != VIDEO_FREEZED) {
614 spin_lock(&av7110->avout.lock);
615 len = av7110_pes_play(av7110->debi_virt, &av7110->avout, 2048);
616 spin_unlock(&av7110->avout.lock);
617 }
618 if (len <= 0) {
619 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
620 iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
621 iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
622 break;
623 }
624 dprintk(8, "GPIO0 PES_PLAY len=%04x\n", len);
625 iwdebi(av7110, DEBINOSWAP, TX_LEN, len, 2);
626 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, len, 2);
627 dprintk(8, "DMA: MPEG_PLAY\n");
628 start_debi_dma(av7110, DEBI_WRITE, DPRAM_BASE + txbuf, len);
629 spin_unlock(&av7110->debilock);
630 return;
631
632 case DATA_BMP_LOAD:
633 len = av7110->debilen;
634 dprintk(8, "gpio DATA_BMP_LOAD len %d\n", len);
635 if (!len) {
636 av7110->bmp_state = BMP_LOADED;
637 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
638 iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
639 iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
640 wake_up(&av7110->bmpq);
641 dprintk(8, "gpio DATA_BMP_LOAD done\n");
642 break;
643 }
644 if (len > av7110->bmplen)
645 len = av7110->bmplen;
646 if (len > 2 * 1024)
647 len = 2 * 1024;
648 iwdebi(av7110, DEBINOSWAP, TX_LEN, len, 2);
649 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, len, 2);
650 memcpy(av7110->debi_virt, av7110->bmpbuf+av7110->bmpp, len);
651 av7110->bmpp += len;
652 av7110->bmplen -= len;
653 dprintk(8, "gpio DATA_BMP_LOAD DMA len %d\n", len);
654 start_debi_dma(av7110, DEBI_WRITE, DPRAM_BASE+txbuf, len);
655 spin_unlock(&av7110->debilock);
656 return;
657
658 case DATA_CI_GET:
659 case DATA_COMMON_INTERFACE:
660 case DATA_FSECTION:
661 case DATA_IPMPE:
662 case DATA_PIPING:
663 if (!len || len > 4 * 1024) {
664 iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
665 break;
666 }
667 /* fall through */
668
669 case DATA_TS_RECORD:
670 case DATA_PES_RECORD:
671 dprintk(8, "DMA: TS_REC etc.\n");
672 start_debi_dma(av7110, DEBI_READ, DPRAM_BASE+rxbuf, len);
673 spin_unlock(&av7110->debilock);
674 return;
675
676 case DATA_DEBUG_MESSAGE:
677 if (!len || len > 0xff) {
678 iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
679 break;
680 }
681 start_debi_dma(av7110, DEBI_READ, Reserved, len);
682 spin_unlock(&av7110->debilock);
683 return;
684
685 case DATA_IRCOMMAND:
Oliver Endrissee820a62007-04-27 12:31:21 -0300686 if (av7110->ir.ir_handler)
687 av7110->ir.ir_handler(av7110,
Oliver Endriss03388ae2005-09-09 13:03:12 -0700688 swahw32(irdebi(av7110, DEBINOSWAP, Reserved, 0, 4)));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700689 iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
690 break;
691
692 default:
693 printk("dvb-ttpci: gpioirq unknown type=%d len=%d\n",
694 av7110->debitype, av7110->debilen);
695 break;
696 }
697 av7110->debitype = -1;
698 ARM_ClearMailBox(av7110);
699 spin_unlock(&av7110->debilock);
700}
701
702
703#ifdef CONFIG_DVB_AV7110_OSD
704static int dvb_osd_ioctl(struct inode *inode, struct file *file,
705 unsigned int cmd, void *parg)
706{
Tobias Klauserd9bdf772006-12-26 07:33:48 -0300707 struct dvb_device *dvbdev = file->private_data;
708 struct av7110 *av7110 = dvbdev->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700709
710 dprintk(4, "%p\n", av7110);
711
712 if (cmd == OSD_SEND_CMD)
713 return av7110_osd_cmd(av7110, (osd_cmd_t *) parg);
714 if (cmd == OSD_GET_CAPABILITY)
715 return av7110_osd_capability(av7110, (osd_cap_t *) parg);
716
717 return -EINVAL;
718}
719
720
721static struct file_operations dvb_osd_fops = {
722 .owner = THIS_MODULE,
723 .ioctl = dvb_generic_ioctl,
724 .open = dvb_generic_open,
725 .release = dvb_generic_release,
726};
727
728static struct dvb_device dvbdev_osd = {
729 .priv = NULL,
730 .users = 1,
731 .writers = 1,
732 .fops = &dvb_osd_fops,
733 .kernel_ioctl = dvb_osd_ioctl,
734};
735#endif /* CONFIG_DVB_AV7110_OSD */
736
737
738static inline int SetPIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid,
739 u16 subpid, u16 pcrpid)
740{
Dr. Werner Fink47f36922006-01-09 15:25:07 -0200741 u16 aflags = 0;
742
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743 dprintk(4, "%p\n", av7110);
744
745 if (vpid == 0x1fff || apid == 0x1fff ||
746 ttpid == 0x1fff || subpid == 0x1fff || pcrpid == 0x1fff) {
747 vpid = apid = ttpid = subpid = pcrpid = 0;
748 av7110->pids[DMX_PES_VIDEO] = 0;
749 av7110->pids[DMX_PES_AUDIO] = 0;
750 av7110->pids[DMX_PES_TELETEXT] = 0;
751 av7110->pids[DMX_PES_PCR] = 0;
752 }
753
Dr. Werner Fink47f36922006-01-09 15:25:07 -0200754 if (av7110->audiostate.bypass_mode)
755 aflags |= 0x8000;
756
757 return av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, MultiPID, 6,
758 pcrpid, vpid, apid, ttpid, subpid, aflags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700759}
760
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700761int ChangePIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700762 u16 subpid, u16 pcrpid)
763{
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700764 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700765 dprintk(4, "%p\n", av7110);
766
Ingo Molnar3593cab2006-02-07 06:49:14 -0200767 if (mutex_lock_interruptible(&av7110->pid_mutex))
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700768 return -ERESTARTSYS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700769
770 if (!(vpid & 0x8000))
771 av7110->pids[DMX_PES_VIDEO] = vpid;
772 if (!(apid & 0x8000))
773 av7110->pids[DMX_PES_AUDIO] = apid;
774 if (!(ttpid & 0x8000))
775 av7110->pids[DMX_PES_TELETEXT] = ttpid;
776 if (!(pcrpid & 0x8000))
777 av7110->pids[DMX_PES_PCR] = pcrpid;
778
779 av7110->pids[DMX_PES_SUBTITLE] = 0;
780
781 if (av7110->fe_synced) {
782 pcrpid = av7110->pids[DMX_PES_PCR];
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700783 ret = SetPIDs(av7110, vpid, apid, ttpid, subpid, pcrpid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700784 }
785
Ingo Molnar3593cab2006-02-07 06:49:14 -0200786 mutex_unlock(&av7110->pid_mutex);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700787 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700788}
789
790
791/******************************************************************************
792 * hardware filter functions
793 ******************************************************************************/
794
795static int StartHWFilter(struct dvb_demux_filter *dvbdmxfilter)
796{
797 struct dvb_demux_feed *dvbdmxfeed = dvbdmxfilter->feed;
Tobias Klauserd9bdf772006-12-26 07:33:48 -0300798 struct av7110 *av7110 = dvbdmxfeed->demux->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799 u16 buf[20];
800 int ret, i;
801 u16 handle;
802// u16 mode = 0x0320;
803 u16 mode = 0xb96a;
804
805 dprintk(4, "%p\n", av7110);
806
807 if (dvbdmxfilter->type == DMX_TYPE_SEC) {
808 if (hw_sections) {
809 buf[4] = (dvbdmxfilter->filter.filter_value[0] << 8) |
810 dvbdmxfilter->maskandmode[0];
811 for (i = 3; i < 18; i++)
812 buf[i + 4 - 2] =
813 (dvbdmxfilter->filter.filter_value[i] << 8) |
814 dvbdmxfilter->maskandmode[i];
815 mode = 4;
816 }
817 } else if ((dvbdmxfeed->ts_type & TS_PACKET) &&
818 !(dvbdmxfeed->ts_type & TS_PAYLOAD_ONLY)) {
819 av7110_p2t_init(&av7110->p2t_filter[dvbdmxfilter->index], dvbdmxfeed);
820 }
821
822 buf[0] = (COMTYPE_PID_FILTER << 8) + AddPIDFilter;
823 buf[1] = 16;
824 buf[2] = dvbdmxfeed->pid;
825 buf[3] = mode;
826
827 ret = av7110_fw_request(av7110, buf, 20, &handle, 1);
828 if (ret != 0 || handle >= 32) {
829 printk("dvb-ttpci: %s error buf %04x %04x %04x %04x "
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700830 "ret %d handle %04x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700831 __FUNCTION__, buf[0], buf[1], buf[2], buf[3],
832 ret, handle);
833 dvbdmxfilter->hw_handle = 0xffff;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700834 if (!ret)
835 ret = -1;
836 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700837 }
838
839 av7110->handle2filter[handle] = dvbdmxfilter;
840 dvbdmxfilter->hw_handle = handle;
841
842 return ret;
843}
844
845static int StopHWFilter(struct dvb_demux_filter *dvbdmxfilter)
846{
Tobias Klauserd9bdf772006-12-26 07:33:48 -0300847 struct av7110 *av7110 = dvbdmxfilter->feed->demux->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700848 u16 buf[3];
849 u16 answ[2];
850 int ret;
851 u16 handle;
852
853 dprintk(4, "%p\n", av7110);
854
855 handle = dvbdmxfilter->hw_handle;
856 if (handle >= 32) {
857 printk("%s tried to stop invalid filter %04x, filter type = %x\n",
858 __FUNCTION__, handle, dvbdmxfilter->type);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700859 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700860 }
861
862 av7110->handle2filter[handle] = NULL;
863
864 buf[0] = (COMTYPE_PID_FILTER << 8) + DelPIDFilter;
865 buf[1] = 1;
866 buf[2] = handle;
867 ret = av7110_fw_request(av7110, buf, 3, answ, 2);
868 if (ret != 0 || answ[1] != handle) {
869 printk("dvb-ttpci: %s error cmd %04x %04x %04x ret %x "
870 "resp %04x %04x pid %d\n",
871 __FUNCTION__, buf[0], buf[1], buf[2], ret,
872 answ[0], answ[1], dvbdmxfilter->feed->pid);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700873 if (!ret)
874 ret = -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700875 }
876 return ret;
877}
878
879
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700880static int dvb_feed_start_pid(struct dvb_demux_feed *dvbdmxfeed)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700881{
882 struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
Tobias Klauserd9bdf772006-12-26 07:33:48 -0300883 struct av7110 *av7110 = dvbdmx->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700884 u16 *pid = dvbdmx->pids, npids[5];
885 int i;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700886 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700887
888 dprintk(4, "%p\n", av7110);
889
890 npids[0] = npids[1] = npids[2] = npids[3] = npids[4] = 0xffff;
891 i = dvbdmxfeed->pes_type;
892 npids[i] = (pid[i]&0x8000) ? 0 : pid[i];
893 if ((i == 2) && npids[i] && (dvbdmxfeed->ts_type & TS_PACKET)) {
894 npids[i] = 0;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700895 ret = ChangePIDs(av7110, npids[1], npids[0], npids[2], npids[3], npids[4]);
896 if (!ret)
897 ret = StartHWFilter(dvbdmxfeed->filter);
898 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700899 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700900 if (dvbdmxfeed->pes_type <= 2 || dvbdmxfeed->pes_type == 4) {
901 ret = ChangePIDs(av7110, npids[1], npids[0], npids[2], npids[3], npids[4]);
902 if (ret)
903 return ret;
904 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905
906 if (dvbdmxfeed->pes_type < 2 && npids[0])
907 if (av7110->fe_synced)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700908 {
909 ret = av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, Scan, 0);
910 if (ret)
911 return ret;
912 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913
914 if ((dvbdmxfeed->ts_type & TS_PACKET)) {
915 if (dvbdmxfeed->pes_type == 0 && !(dvbdmx->pids[0] & 0x8000))
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700916 ret = av7110_av_start_record(av7110, RP_AUDIO, dvbdmxfeed);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700917 if (dvbdmxfeed->pes_type == 1 && !(dvbdmx->pids[1] & 0x8000))
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700918 ret = av7110_av_start_record(av7110, RP_VIDEO, dvbdmxfeed);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700920 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700921}
922
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700923static int dvb_feed_stop_pid(struct dvb_demux_feed *dvbdmxfeed)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924{
925 struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
Tobias Klauserd9bdf772006-12-26 07:33:48 -0300926 struct av7110 *av7110 = dvbdmx->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700927 u16 *pid = dvbdmx->pids, npids[5];
928 int i;
929
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700930 int ret = 0;
931
Linus Torvalds1da177e2005-04-16 15:20:36 -0700932 dprintk(4, "%p\n", av7110);
933
934 if (dvbdmxfeed->pes_type <= 1) {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700935 ret = av7110_av_stop(av7110, dvbdmxfeed->pes_type ? RP_VIDEO : RP_AUDIO);
936 if (ret)
937 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700938 if (!av7110->rec_mode)
939 dvbdmx->recording = 0;
940 if (!av7110->playing)
941 dvbdmx->playing = 0;
942 }
943 npids[0] = npids[1] = npids[2] = npids[3] = npids[4] = 0xffff;
944 i = dvbdmxfeed->pes_type;
945 switch (i) {
946 case 2: //teletext
947 if (dvbdmxfeed->ts_type & TS_PACKET)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700948 ret = StopHWFilter(dvbdmxfeed->filter);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700949 npids[2] = 0;
950 break;
951 case 0:
952 case 1:
953 case 4:
954 if (!pids_off)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700955 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700956 npids[i] = (pid[i]&0x8000) ? 0 : pid[i];
957 break;
958 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700959 if (!ret)
960 ret = ChangePIDs(av7110, npids[1], npids[0], npids[2], npids[3], npids[4]);
961 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700962}
963
964static int av7110_start_feed(struct dvb_demux_feed *feed)
965{
966 struct dvb_demux *demux = feed->demux;
967 struct av7110 *av7110 = demux->priv;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700968 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700969
970 dprintk(4, "%p\n", av7110);
971
972 if (!demux->dmx.frontend)
973 return -EINVAL;
974
975 if (feed->pid > 0x1fff)
976 return -EINVAL;
977
978 if (feed->type == DMX_TYPE_TS) {
979 if ((feed->ts_type & TS_DECODER) &&
980 (feed->pes_type < DMX_TS_PES_OTHER)) {
981 switch (demux->dmx.frontend->source) {
982 case DMX_MEMORY_FE:
983 if (feed->ts_type & TS_DECODER)
984 if (feed->pes_type < 2 &&
985 !(demux->pids[0] & 0x8000) &&
986 !(demux->pids[1] & 0x8000)) {
987 dvb_ringbuffer_flush_spinlock_wakeup(&av7110->avout);
988 dvb_ringbuffer_flush_spinlock_wakeup(&av7110->aout);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700989 ret = av7110_av_start_play(av7110,RP_AV);
990 if (!ret)
991 demux->playing = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700992 }
993 break;
994 default:
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700995 ret = dvb_feed_start_pid(feed);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700996 break;
997 }
998 } else if ((feed->ts_type & TS_PACKET) &&
999 (demux->dmx.frontend->source != DMX_MEMORY_FE)) {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001000 ret = StartHWFilter(feed->filter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001001 }
1002 }
1003
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001004 else if (feed->type == DMX_TYPE_SEC) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001005 int i;
1006
1007 for (i = 0; i < demux->filternum; i++) {
1008 if (demux->filter[i].state != DMX_STATE_READY)
1009 continue;
1010 if (demux->filter[i].type != DMX_TYPE_SEC)
1011 continue;
1012 if (demux->filter[i].filter.parent != &feed->feed.sec)
1013 continue;
1014 demux->filter[i].state = DMX_STATE_GO;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001015 if (demux->dmx.frontend->source != DMX_MEMORY_FE) {
1016 ret = StartHWFilter(&demux->filter[i]);
1017 if (ret)
1018 break;
1019 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001020 }
1021 }
1022
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001023 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001024}
1025
1026
1027static int av7110_stop_feed(struct dvb_demux_feed *feed)
1028{
1029 struct dvb_demux *demux = feed->demux;
1030 struct av7110 *av7110 = demux->priv;
Johannes Stezenbach12ba0502005-07-07 17:58:00 -07001031 int i, rc, ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001032 dprintk(4, "%p\n", av7110);
1033
1034 if (feed->type == DMX_TYPE_TS) {
1035 if (feed->ts_type & TS_DECODER) {
1036 if (feed->pes_type >= DMX_TS_PES_OTHER ||
1037 !demux->pesfilter[feed->pes_type])
1038 return -EINVAL;
1039 demux->pids[feed->pes_type] |= 0x8000;
1040 demux->pesfilter[feed->pes_type] = NULL;
1041 }
1042 if (feed->ts_type & TS_DECODER &&
1043 feed->pes_type < DMX_TS_PES_OTHER) {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001044 ret = dvb_feed_stop_pid(feed);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001045 } else
1046 if ((feed->ts_type & TS_PACKET) &&
1047 (demux->dmx.frontend->source != DMX_MEMORY_FE))
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001048 ret = StopHWFilter(feed->filter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049 }
1050
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001051 if (!ret && feed->type == DMX_TYPE_SEC) {
Johannes Stezenbach12ba0502005-07-07 17:58:00 -07001052 for (i = 0; i<demux->filternum; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053 if (demux->filter[i].state == DMX_STATE_GO &&
1054 demux->filter[i].filter.parent == &feed->feed.sec) {
1055 demux->filter[i].state = DMX_STATE_READY;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001056 if (demux->dmx.frontend->source != DMX_MEMORY_FE) {
Johannes Stezenbach12ba0502005-07-07 17:58:00 -07001057 rc = StopHWFilter(&demux->filter[i]);
1058 if (!ret)
1059 ret = rc;
1060 /* keep going, stop as many filters as possible */
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001061 }
Johannes Stezenbach12ba0502005-07-07 17:58:00 -07001062 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001063 }
1064 }
1065
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001066 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067}
1068
1069
1070static void restart_feeds(struct av7110 *av7110)
1071{
1072 struct dvb_demux *dvbdmx = &av7110->demux;
1073 struct dvb_demux_feed *feed;
1074 int mode;
Oliver Endriss66190a22006-01-09 15:32:42 -02001075 int i, j;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076
1077 dprintk(4, "%p\n", av7110);
1078
1079 mode = av7110->playing;
1080 av7110->playing = 0;
1081 av7110->rec_mode = 0;
1082
Oliver Endriss66190a22006-01-09 15:32:42 -02001083 for (i = 0; i < dvbdmx->feednum; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001084 feed = &dvbdmx->feed[i];
Oliver Endriss66190a22006-01-09 15:32:42 -02001085 if (feed->state == DMX_STATE_GO) {
1086 if (feed->type == DMX_TYPE_SEC) {
1087 for (j = 0; j < dvbdmx->filternum; j++) {
1088 if (dvbdmx->filter[j].type != DMX_TYPE_SEC)
1089 continue;
1090 if (dvbdmx->filter[j].filter.parent != &feed->feed.sec)
1091 continue;
1092 if (dvbdmx->filter[j].state == DMX_STATE_GO)
1093 dvbdmx->filter[j].state = DMX_STATE_READY;
1094 }
1095 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001096 av7110_start_feed(feed);
Oliver Endriss66190a22006-01-09 15:32:42 -02001097 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001098 }
1099
1100 if (mode)
1101 av7110_av_start_play(av7110, mode);
1102}
1103
1104static int dvb_get_stc(struct dmx_demux *demux, unsigned int num,
1105 uint64_t *stc, unsigned int *base)
1106{
1107 int ret;
1108 u16 fwstc[4];
1109 u16 tag = ((COMTYPE_REQUEST << 8) + ReqSTC);
1110 struct dvb_demux *dvbdemux;
1111 struct av7110 *av7110;
1112
1113 /* pointer casting paranoia... */
Eric Sesterhennae246012006-03-13 13:17:11 -03001114 BUG_ON(!demux);
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001115 dvbdemux = demux->priv;
Eric Sesterhennae246012006-03-13 13:17:11 -03001116 BUG_ON(!dvbdemux);
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001117 av7110 = dvbdemux->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001118
1119 dprintk(4, "%p\n", av7110);
1120
1121 if (num != 0)
1122 return -EINVAL;
1123
1124 ret = av7110_fw_request(av7110, &tag, 0, fwstc, 4);
1125 if (ret) {
1126 printk(KERN_ERR "%s: av7110_fw_request error\n", __FUNCTION__);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001127 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001128 }
1129 dprintk(2, "fwstc = %04hx %04hx %04hx %04hx\n",
1130 fwstc[0], fwstc[1], fwstc[2], fwstc[3]);
1131
1132 *stc = (((uint64_t) ((fwstc[3] & 0x8000) >> 15)) << 32) |
1133 (((uint64_t) fwstc[1]) << 16) | ((uint64_t) fwstc[0]);
1134 *base = 1;
1135
1136 dprintk(4, "stc = %lu\n", (unsigned long)*stc);
1137
1138 return 0;
1139}
1140
1141
1142/******************************************************************************
1143 * SEC device file operations
1144 ******************************************************************************/
1145
1146
1147static int av7110_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
1148{
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001149 struct av7110* av7110 = fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001150
1151 switch (tone) {
1152 case SEC_TONE_ON:
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001153 return Set22K(av7110, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001154
1155 case SEC_TONE_OFF:
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001156 return Set22K(av7110, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001157
1158 default:
1159 return -EINVAL;
1160 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001161}
1162
1163static int av7110_diseqc_send_master_cmd(struct dvb_frontend* fe,
1164 struct dvb_diseqc_master_cmd* cmd)
1165{
1166 struct av7110* av7110 = fe->dvb->priv;
1167
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001168 return av7110_diseqc_send(av7110, cmd->msg_len, cmd->msg, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001169}
1170
1171static int av7110_diseqc_send_burst(struct dvb_frontend* fe,
1172 fe_sec_mini_cmd_t minicmd)
1173{
1174 struct av7110* av7110 = fe->dvb->priv;
1175
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001176 return av7110_diseqc_send(av7110, 0, NULL, minicmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001177}
1178
1179/* simplified code from budget-core.c */
1180static int stop_ts_capture(struct av7110 *budget)
1181{
1182 dprintk(2, "budget: %p\n", budget);
1183
1184 if (--budget->feeding1)
1185 return budget->feeding1;
1186 saa7146_write(budget->dev, MC1, MASK_20); /* DMA3 off */
1187 SAA7146_IER_DISABLE(budget->dev, MASK_10);
1188 SAA7146_ISR_CLEAR(budget->dev, MASK_10);
1189 return 0;
1190}
1191
1192static int start_ts_capture(struct av7110 *budget)
1193{
1194 dprintk(2, "budget: %p\n", budget);
1195
1196 if (budget->feeding1)
1197 return ++budget->feeding1;
1198 memset(budget->grabbing, 0x00, TS_HEIGHT * TS_WIDTH);
1199 budget->tsf = 0xff;
1200 budget->ttbp = 0;
1201 SAA7146_IER_ENABLE(budget->dev, MASK_10); /* VPE */
1202 saa7146_write(budget->dev, MC1, (MASK_04 | MASK_20)); /* DMA3 on */
1203 return ++budget->feeding1;
1204}
1205
1206static int budget_start_feed(struct dvb_demux_feed *feed)
1207{
1208 struct dvb_demux *demux = feed->demux;
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001209 struct av7110 *budget = demux->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001210 int status;
1211
1212 dprintk(2, "av7110: %p\n", budget);
1213
1214 spin_lock(&budget->feedlock1);
1215 feed->pusi_seen = 0; /* have a clean section start */
1216 status = start_ts_capture(budget);
1217 spin_unlock(&budget->feedlock1);
1218 return status;
1219}
1220
1221static int budget_stop_feed(struct dvb_demux_feed *feed)
1222{
1223 struct dvb_demux *demux = feed->demux;
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001224 struct av7110 *budget = demux->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001225 int status;
1226
1227 dprintk(2, "budget: %p\n", budget);
1228
1229 spin_lock(&budget->feedlock1);
1230 status = stop_ts_capture(budget);
1231 spin_unlock(&budget->feedlock1);
1232 return status;
1233}
1234
1235static void vpeirq(unsigned long data)
1236{
1237 struct av7110 *budget = (struct av7110 *) data;
1238 u8 *mem = (u8 *) (budget->grabbing);
1239 u32 olddma = budget->ttbp;
1240 u32 newdma = saa7146_read(budget->dev, PCI_VDP3);
1241
1242 if (!budgetpatch) {
1243 printk("av7110.c: vpeirq() called while budgetpatch disabled!"
1244 " check saa7146 IER register\n");
1245 BUG();
1246 }
1247 /* nearest lower position divisible by 188 */
1248 newdma -= newdma % 188;
1249
1250 if (newdma >= TS_BUFLEN)
1251 return;
1252
1253 budget->ttbp = newdma;
1254
1255 if (!budget->feeding1 || (newdma == olddma))
1256 return;
1257
Jon Burgess87c30192007-05-03 12:23:44 -03001258 /* Ensure streamed PCI data is synced to CPU */
1259 pci_dma_sync_sg_for_cpu(budget->dev->pci, budget->pt.slist, budget->pt.nents, PCI_DMA_FROMDEVICE);
1260
Linus Torvalds1da177e2005-04-16 15:20:36 -07001261#if 0
1262 /* track rps1 activity */
1263 printk("vpeirq: %02x Event Counter 1 0x%04x\n",
1264 mem[olddma],
1265 saa7146_read(budget->dev, EC1R) & 0x3fff);
1266#endif
1267
1268 if (newdma > olddma)
1269 /* no wraparound, dump olddma..newdma */
1270 dvb_dmx_swfilter_packets(&budget->demux1, mem + olddma, (newdma - olddma) / 188);
1271 else {
1272 /* wraparound, dump olddma..buflen and 0..newdma */
1273 dvb_dmx_swfilter_packets(&budget->demux1, mem + olddma, (TS_BUFLEN - olddma) / 188);
1274 dvb_dmx_swfilter_packets(&budget->demux1, mem, newdma / 188);
1275 }
1276}
1277
1278static int av7110_register(struct av7110 *av7110)
1279{
1280 int ret, i;
1281 struct dvb_demux *dvbdemux = &av7110->demux;
1282 struct dvb_demux *dvbdemux1 = &av7110->demux1;
1283
1284 dprintk(4, "%p\n", av7110);
1285
1286 if (av7110->registered)
1287 return -1;
1288
1289 av7110->registered = 1;
1290
1291 dvbdemux->priv = (void *) av7110;
1292
1293 for (i = 0; i < 32; i++)
1294 av7110->handle2filter[i] = NULL;
1295
1296 dvbdemux->filternum = 32;
1297 dvbdemux->feednum = 32;
1298 dvbdemux->start_feed = av7110_start_feed;
1299 dvbdemux->stop_feed = av7110_stop_feed;
1300 dvbdemux->write_to_decoder = av7110_write_to_decoder;
1301 dvbdemux->dmx.capabilities = (DMX_TS_FILTERING | DMX_SECTION_FILTERING |
1302 DMX_MEMORY_BASED_FILTERING);
1303
1304 dvb_dmx_init(&av7110->demux);
1305 av7110->demux.dmx.get_stc = dvb_get_stc;
1306
1307 av7110->dmxdev.filternum = 32;
1308 av7110->dmxdev.demux = &dvbdemux->dmx;
1309 av7110->dmxdev.capabilities = 0;
1310
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001311 dvb_dmxdev_init(&av7110->dmxdev, &av7110->dvb_adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001312
1313 av7110->hw_frontend.source = DMX_FRONTEND_0;
1314
1315 ret = dvbdemux->dmx.add_frontend(&dvbdemux->dmx, &av7110->hw_frontend);
1316
1317 if (ret < 0)
1318 return ret;
1319
1320 av7110->mem_frontend.source = DMX_MEMORY_FE;
1321
1322 ret = dvbdemux->dmx.add_frontend(&dvbdemux->dmx, &av7110->mem_frontend);
1323
1324 if (ret < 0)
1325 return ret;
1326
1327 ret = dvbdemux->dmx.connect_frontend(&dvbdemux->dmx,
1328 &av7110->hw_frontend);
1329 if (ret < 0)
1330 return ret;
1331
1332 av7110_av_register(av7110);
1333 av7110_ca_register(av7110);
1334
1335#ifdef CONFIG_DVB_AV7110_OSD
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001336 dvb_register_device(&av7110->dvb_adapter, &av7110->osd_dev,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001337 &dvbdev_osd, av7110, DVB_DEVICE_OSD);
1338#endif
1339
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001340 dvb_net_init(&av7110->dvb_adapter, &av7110->dvb_net, &dvbdemux->dmx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001341
1342 if (budgetpatch) {
1343 /* initialize software demux1 without its own frontend
1344 * demux1 hardware is connected to frontend0 of demux0
1345 */
1346 dvbdemux1->priv = (void *) av7110;
1347
1348 dvbdemux1->filternum = 256;
1349 dvbdemux1->feednum = 256;
1350 dvbdemux1->start_feed = budget_start_feed;
1351 dvbdemux1->stop_feed = budget_stop_feed;
1352 dvbdemux1->write_to_decoder = NULL;
1353
1354 dvbdemux1->dmx.capabilities = (DMX_TS_FILTERING | DMX_SECTION_FILTERING |
1355 DMX_MEMORY_BASED_FILTERING);
1356
1357 dvb_dmx_init(&av7110->demux1);
1358
1359 av7110->dmxdev1.filternum = 256;
1360 av7110->dmxdev1.demux = &dvbdemux1->dmx;
1361 av7110->dmxdev1.capabilities = 0;
1362
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001363 dvb_dmxdev_init(&av7110->dmxdev1, &av7110->dvb_adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001364
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001365 dvb_net_init(&av7110->dvb_adapter, &av7110->dvb_net1, &dvbdemux1->dmx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001366 printk("dvb-ttpci: additional demux1 for budget-patch registered\n");
1367 }
1368 return 0;
1369}
1370
1371
1372static void dvb_unregister(struct av7110 *av7110)
1373{
1374 struct dvb_demux *dvbdemux = &av7110->demux;
1375 struct dvb_demux *dvbdemux1 = &av7110->demux1;
1376
1377 dprintk(4, "%p\n", av7110);
1378
1379 if (!av7110->registered)
1380 return;
1381
1382 if (budgetpatch) {
1383 dvb_net_release(&av7110->dvb_net1);
1384 dvbdemux->dmx.close(&dvbdemux1->dmx);
1385 dvb_dmxdev_release(&av7110->dmxdev1);
1386 dvb_dmx_release(&av7110->demux1);
1387 }
1388
1389 dvb_net_release(&av7110->dvb_net);
1390
1391 dvbdemux->dmx.close(&dvbdemux->dmx);
1392 dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &av7110->hw_frontend);
1393 dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &av7110->mem_frontend);
1394
1395 dvb_dmxdev_release(&av7110->dmxdev);
1396 dvb_dmx_release(&av7110->demux);
1397
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001398 if (av7110->fe != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001399 dvb_unregister_frontend(av7110->fe);
Andrew de Quinceyf52a8382006-08-08 09:10:09 -03001400 dvb_frontend_detach(av7110->fe);
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001401 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001402 dvb_unregister_device(av7110->osd_dev);
1403 av7110_av_unregister(av7110);
1404 av7110_ca_unregister(av7110);
1405}
1406
1407
1408/****************************************************************************
1409 * I2C client commands
1410 ****************************************************************************/
1411
1412int i2c_writereg(struct av7110 *av7110, u8 id, u8 reg, u8 val)
1413{
1414 u8 msg[2] = { reg, val };
1415 struct i2c_msg msgs;
1416
1417 msgs.flags = 0;
1418 msgs.addr = id / 2;
1419 msgs.len = 2;
1420 msgs.buf = msg;
1421 return i2c_transfer(&av7110->i2c_adap, &msgs, 1);
1422}
1423
1424#if 0
1425u8 i2c_readreg(struct av7110 *av7110, u8 id, u8 reg)
1426{
1427 u8 mm1[] = {0x00};
1428 u8 mm2[] = {0x00};
1429 struct i2c_msg msgs[2];
1430
1431 msgs[0].flags = 0;
1432 msgs[1].flags = I2C_M_RD;
1433 msgs[0].addr = msgs[1].addr = id / 2;
1434 mm1[0] = reg;
1435 msgs[0].len = 1; msgs[1].len = 1;
1436 msgs[0].buf = mm1; msgs[1].buf = mm2;
1437 i2c_transfer(&av7110->i2c_adap, msgs, 2);
1438
1439 return mm2[0];
1440}
1441#endif
1442
1443/****************************************************************************
1444 * INITIALIZATION
1445 ****************************************************************************/
1446
1447
1448static int check_firmware(struct av7110* av7110)
1449{
1450 u32 crc = 0, len = 0;
1451 unsigned char *ptr;
1452
1453 /* check for firmware magic */
1454 ptr = av7110->bin_fw;
1455 if (ptr[0] != 'A' || ptr[1] != 'V' ||
1456 ptr[2] != 'F' || ptr[3] != 'W') {
1457 printk("dvb-ttpci: this is not an av7110 firmware\n");
1458 return -EINVAL;
1459 }
1460 ptr += 4;
1461
1462 /* check dpram file */
1463 crc = ntohl(*(u32*) ptr);
1464 ptr += 4;
1465 len = ntohl(*(u32*) ptr);
1466 ptr += 4;
1467 if (len >= 512) {
Alexey Dobriyanbe787ac2006-03-07 22:20:23 -03001468 printk("dvb-ttpci: dpram file is way too big.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001469 return -EINVAL;
1470 }
1471 if (crc != crc32_le(0, ptr, len)) {
1472 printk("dvb-ttpci: crc32 of dpram file does not match.\n");
1473 return -EINVAL;
1474 }
1475 av7110->bin_dpram = ptr;
1476 av7110->size_dpram = len;
1477 ptr += len;
1478
1479 /* check root file */
1480 crc = ntohl(*(u32*) ptr);
1481 ptr += 4;
1482 len = ntohl(*(u32*) ptr);
1483 ptr += 4;
1484
1485 if (len <= 200000 || len >= 300000 ||
1486 len > ((av7110->bin_fw + av7110->size_fw) - ptr)) {
1487 printk("dvb-ttpci: root file has strange size (%d). aborting.\n", len);
1488 return -EINVAL;
1489 }
1490 if( crc != crc32_le(0, ptr, len)) {
1491 printk("dvb-ttpci: crc32 of root file does not match.\n");
1492 return -EINVAL;
1493 }
1494 av7110->bin_root = ptr;
1495 av7110->size_root = len;
1496 return 0;
1497}
1498
1499#ifdef CONFIG_DVB_AV7110_FIRMWARE_FILE
1500#include "av7110_firm.h"
1501static void put_firmware(struct av7110* av7110)
1502{
1503 av7110->bin_fw = NULL;
1504}
1505
1506static inline int get_firmware(struct av7110* av7110)
1507{
1508 av7110->bin_fw = dvb_ttpci_fw;
1509 av7110->size_fw = sizeof(dvb_ttpci_fw);
1510 return check_firmware(av7110);
1511}
1512#else
1513static void put_firmware(struct av7110* av7110)
1514{
1515 vfree(av7110->bin_fw);
1516}
1517
1518static int get_firmware(struct av7110* av7110)
1519{
1520 int ret;
1521 const struct firmware *fw;
1522
1523 /* request the av7110 firmware, this will block until someone uploads it */
1524 ret = request_firmware(&fw, "dvb-ttpci-01.fw", &av7110->dev->pci->dev);
1525 if (ret) {
1526 if (ret == -ENOENT) {
1527 printk(KERN_ERR "dvb-ttpci: could not load firmware,"
1528 " file not found: dvb-ttpci-01.fw\n");
Ville Skytt\ä12e66f62006-01-09 15:25:38 -02001529 printk(KERN_ERR "dvb-ttpci: usually this should be in "
1530 "/usr/lib/hotplug/firmware or /lib/firmware\n");
1531 printk(KERN_ERR "dvb-ttpci: and can be downloaded from"
Linus Torvalds1da177e2005-04-16 15:20:36 -07001532 " http://www.linuxtv.org/download/dvb/firmware/\n");
1533 } else
1534 printk(KERN_ERR "dvb-ttpci: cannot request firmware"
1535 " (error %i)\n", ret);
1536 return -EINVAL;
1537 }
1538
1539 if (fw->size <= 200000) {
1540 printk("dvb-ttpci: this firmware is way too small.\n");
1541 release_firmware(fw);
1542 return -EINVAL;
1543 }
1544
1545 /* check if the firmware is available */
1546 av7110->bin_fw = (unsigned char *) vmalloc(fw->size);
1547 if (NULL == av7110->bin_fw) {
1548 dprintk(1, "out of memory\n");
1549 release_firmware(fw);
1550 return -ENOMEM;
1551 }
1552
1553 memcpy(av7110->bin_fw, fw->data, fw->size);
1554 av7110->size_fw = fw->size;
1555 if ((ret = check_firmware(av7110)))
1556 vfree(av7110->bin_fw);
1557
1558 release_firmware(fw);
1559 return ret;
1560}
1561#endif
1562
1563
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001564static int alps_bsrv2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001565{
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001566 struct av7110* av7110 = fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001567 u8 pwr = 0;
1568 u8 buf[4];
1569 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
1570 u32 div = (params->frequency + 479500) / 125;
1571
1572 if (params->frequency > 2000000) pwr = 3;
1573 else if (params->frequency > 1800000) pwr = 2;
1574 else if (params->frequency > 1600000) pwr = 1;
1575 else if (params->frequency > 1200000) pwr = 0;
1576 else if (params->frequency >= 1100000) pwr = 1;
1577 else pwr = 2;
1578
1579 buf[0] = (div >> 8) & 0x7f;
1580 buf[1] = div & 0xff;
1581 buf[2] = ((div & 0x18000) >> 10) | 0x95;
1582 buf[3] = (pwr << 6) | 0x30;
1583
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -08001584 // NOTE: since we're using a prescaler of 2, we set the
Linus Torvalds1da177e2005-04-16 15:20:36 -07001585 // divisor frequency to 62.5kHz and divide by 125 above
1586
Patrick Boettcherdea74862006-05-14 05:01:31 -03001587 if (fe->ops.i2c_gate_ctrl)
1588 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001589 if (i2c_transfer (&av7110->i2c_adap, &msg, 1) != 1)
1590 return -EIO;
1591 return 0;
1592}
1593
1594static struct ves1x93_config alps_bsrv2_config = {
1595 .demod_address = 0x08,
1596 .xin = 90100000UL,
1597 .invert_pwm = 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001598};
1599
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001600static int alps_tdbe2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001601{
1602 struct av7110* av7110 = fe->dvb->priv;
1603 u32 div;
1604 u8 data[4];
1605 struct i2c_msg msg = { .addr = 0x62, .flags = 0, .buf = data, .len = sizeof(data) };
1606
1607 div = (params->frequency + 35937500 + 31250) / 62500;
1608
1609 data[0] = (div >> 8) & 0x7f;
1610 data[1] = div & 0xff;
1611 data[2] = 0x85 | ((div >> 10) & 0x60);
1612 data[3] = (params->frequency < 174000000 ? 0x88 : params->frequency < 470000000 ? 0x84 : 0x81);
1613
Patrick Boettcherdea74862006-05-14 05:01:31 -03001614 if (fe->ops.i2c_gate_ctrl)
1615 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001616 if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
1617 return -EIO;
1618 return 0;
1619}
1620
1621static struct ves1820_config alps_tdbe2_config = {
1622 .demod_address = 0x09,
1623 .xin = 57840000UL,
1624 .invert = 1,
1625 .selagc = VES1820_SELAGC_SIGNAMPERR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001626};
1627
1628
1629
1630
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001631static int grundig_29504_451_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001632{
1633 struct av7110* av7110 = fe->dvb->priv;
1634 u32 div;
1635 u8 data[4];
1636 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
1637
1638 div = params->frequency / 125;
1639 data[0] = (div >> 8) & 0x7f;
1640 data[1] = div & 0xff;
1641 data[2] = 0x8e;
1642 data[3] = 0x00;
1643
Patrick Boettcherdea74862006-05-14 05:01:31 -03001644 if (fe->ops.i2c_gate_ctrl)
1645 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001646 if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
1647 return -EIO;
1648 return 0;
1649}
1650
1651static struct tda8083_config grundig_29504_451_config = {
1652 .demod_address = 0x68,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001653};
1654
1655
1656
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001657static int philips_cd1516_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001658{
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -08001659 struct av7110* av7110 = fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001660 u32 div;
1661 u32 f = params->frequency;
1662 u8 data[4];
1663 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
1664
1665 div = (f + 36125000 + 31250) / 62500;
1666
1667 data[0] = (div >> 8) & 0x7f;
1668 data[1] = div & 0xff;
1669 data[2] = 0x8e;
1670 data[3] = (f < 174000000 ? 0xa1 : f < 470000000 ? 0x92 : 0x34);
1671
Patrick Boettcherdea74862006-05-14 05:01:31 -03001672 if (fe->ops.i2c_gate_ctrl)
1673 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001674 if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
1675 return -EIO;
1676 return 0;
1677}
1678
1679static struct ves1820_config philips_cd1516_config = {
1680 .demod_address = 0x09,
1681 .xin = 57840000UL,
1682 .invert = 1,
1683 .selagc = VES1820_SELAGC_SIGNAMPERR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001684};
1685
1686
1687
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001688static int alps_tdlb7_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001689{
1690 struct av7110* av7110 = fe->dvb->priv;
1691 u32 div, pwr;
1692 u8 data[4];
1693 struct i2c_msg msg = { .addr = 0x60, .flags = 0, .buf = data, .len = sizeof(data) };
1694
1695 div = (params->frequency + 36200000) / 166666;
1696
1697 if (params->frequency <= 782000000)
1698 pwr = 1;
1699 else
1700 pwr = 2;
1701
1702 data[0] = (div >> 8) & 0x7f;
1703 data[1] = div & 0xff;
1704 data[2] = 0x85;
1705 data[3] = pwr << 6;
1706
Patrick Boettcherdea74862006-05-14 05:01:31 -03001707 if (fe->ops.i2c_gate_ctrl)
1708 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001709 if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
1710 return -EIO;
1711 return 0;
1712}
1713
1714static int alps_tdlb7_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name)
1715{
Oliver Endrissd98821e2006-09-14 00:15:13 -03001716#if defined(CONFIG_DVB_SP8870) || defined(CONFIG_DVB_SP8870_MODULE)
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001717 struct av7110* av7110 = fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001718
1719 return request_firmware(fw, name, &av7110->dev->pci->dev);
Oliver Endrissd98821e2006-09-14 00:15:13 -03001720#else
1721 return -EINVAL;
1722#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001723}
1724
1725static struct sp8870_config alps_tdlb7_config = {
1726
1727 .demod_address = 0x71,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001728 .request_firmware = alps_tdlb7_request_firmware,
1729};
1730
1731
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001732static u8 nexusca_stv0297_inittab[] = {
1733 0x80, 0x01,
1734 0x80, 0x00,
1735 0x81, 0x01,
1736 0x81, 0x00,
1737 0x00, 0x09,
1738 0x01, 0x69,
1739 0x03, 0x00,
1740 0x04, 0x00,
1741 0x07, 0x00,
1742 0x08, 0x00,
1743 0x20, 0x00,
1744 0x21, 0x40,
1745 0x22, 0x00,
1746 0x23, 0x00,
1747 0x24, 0x40,
1748 0x25, 0x88,
1749 0x30, 0xff,
1750 0x31, 0x00,
1751 0x32, 0xff,
1752 0x33, 0x00,
1753 0x34, 0x50,
1754 0x35, 0x7f,
1755 0x36, 0x00,
1756 0x37, 0x20,
1757 0x38, 0x00,
1758 0x40, 0x1c,
1759 0x41, 0xff,
1760 0x42, 0x29,
1761 0x43, 0x00,
1762 0x44, 0xff,
1763 0x45, 0x00,
1764 0x46, 0x00,
1765 0x49, 0x04,
1766 0x4a, 0x00,
1767 0x4b, 0x7b,
1768 0x52, 0x30,
1769 0x55, 0xae,
1770 0x56, 0x47,
1771 0x57, 0xe1,
1772 0x58, 0x3a,
1773 0x5a, 0x1e,
1774 0x5b, 0x34,
1775 0x60, 0x00,
1776 0x63, 0x00,
1777 0x64, 0x00,
1778 0x65, 0x00,
1779 0x66, 0x00,
1780 0x67, 0x00,
1781 0x68, 0x00,
1782 0x69, 0x00,
1783 0x6a, 0x02,
1784 0x6b, 0x00,
1785 0x70, 0xff,
1786 0x71, 0x00,
1787 0x72, 0x00,
1788 0x73, 0x00,
1789 0x74, 0x0c,
1790 0x80, 0x00,
1791 0x81, 0x00,
1792 0x82, 0x00,
1793 0x83, 0x00,
1794 0x84, 0x04,
1795 0x85, 0x80,
1796 0x86, 0x24,
1797 0x87, 0x78,
1798 0x88, 0x10,
1799 0x89, 0x00,
1800 0x90, 0x01,
1801 0x91, 0x01,
1802 0xa0, 0x04,
1803 0xa1, 0x00,
1804 0xa2, 0x00,
1805 0xb0, 0x91,
1806 0xb1, 0x0b,
1807 0xc0, 0x53,
1808 0xc1, 0x70,
1809 0xc2, 0x12,
1810 0xd0, 0x00,
1811 0xd1, 0x00,
1812 0xd2, 0x00,
1813 0xd3, 0x00,
1814 0xd4, 0x00,
1815 0xd5, 0x00,
1816 0xde, 0x00,
1817 0xdf, 0x00,
1818 0x61, 0x49,
1819 0x62, 0x0b,
1820 0x53, 0x08,
1821 0x59, 0x08,
1822 0xff, 0xff,
1823};
Linus Torvalds1da177e2005-04-16 15:20:36 -07001824
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001825static int nexusca_stv0297_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001826{
1827 struct av7110* av7110 = fe->dvb->priv;
1828 u32 div;
1829 u8 data[4];
1830 struct i2c_msg msg = { .addr = 0x63, .flags = 0, .buf = data, .len = sizeof(data) };
1831 struct i2c_msg readmsg = { .addr = 0x63, .flags = I2C_M_RD, .buf = data, .len = 1 };
1832 int i;
1833
1834 div = (params->frequency + 36150000 + 31250) / 62500;
1835
1836 data[0] = (div >> 8) & 0x7f;
1837 data[1] = div & 0xff;
1838 data[2] = 0xce;
1839
1840 if (params->frequency < 45000000)
1841 return -EINVAL;
1842 else if (params->frequency < 137000000)
1843 data[3] = 0x01;
1844 else if (params->frequency < 403000000)
1845 data[3] = 0x02;
1846 else if (params->frequency < 860000000)
1847 data[3] = 0x04;
1848 else
1849 return -EINVAL;
1850
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, &msg, 1) != 1) {
1854 printk("nexusca: pll transfer failed!\n");
1855 return -EIO;
1856 }
1857
1858 // wait for PLL lock
1859 for(i = 0; i < 20; i++) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001860 if (fe->ops.i2c_gate_ctrl)
1861 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001862 if (i2c_transfer(&av7110->i2c_adap, &readmsg, 1) == 1)
1863 if (data[0] & 0x40) break;
1864 msleep(10);
1865 }
1866
1867 return 0;
1868}
1869
1870static struct stv0297_config nexusca_stv0297_config = {
1871
1872 .demod_address = 0x1C,
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001873 .inittab = nexusca_stv0297_inittab,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001874 .invert = 1,
Thomas Kaiserb8d4c232006-04-27 21:45:20 -03001875 .stop_during_read = 1,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001876};
1877
1878
1879
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001880static int grundig_29504_401_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001881{
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001882 struct av7110* av7110 = fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001883 u32 div;
1884 u8 cfg, cpump, band_select;
1885 u8 data[4];
1886 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
1887
1888 div = (36125000 + params->frequency) / 166666;
1889
1890 cfg = 0x88;
1891
1892 if (params->frequency < 175000000) cpump = 2;
1893 else if (params->frequency < 390000000) cpump = 1;
1894 else if (params->frequency < 470000000) cpump = 2;
1895 else if (params->frequency < 750000000) cpump = 1;
1896 else cpump = 3;
1897
1898 if (params->frequency < 175000000) band_select = 0x0e;
1899 else if (params->frequency < 470000000) band_select = 0x05;
1900 else band_select = 0x03;
1901
1902 data[0] = (div >> 8) & 0x7f;
1903 data[1] = div & 0xff;
1904 data[2] = ((div >> 10) & 0x60) | cfg;
1905 data[3] = (cpump << 6) | band_select;
1906
Patrick Boettcherdea74862006-05-14 05:01:31 -03001907 if (fe->ops.i2c_gate_ctrl)
1908 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001909 if (i2c_transfer (&av7110->i2c_adap, &msg, 1) != 1) return -EIO;
1910 return 0;
1911}
1912
1913static struct l64781_config grundig_29504_401_config = {
1914 .demod_address = 0x55,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001915};
1916
1917
1918
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001919static int av7110_fe_lock_fix(struct av7110* av7110, fe_status_t status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001920{
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001921 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001922 int synced = (status & FE_HAS_LOCK) ? 1 : 0;
1923
1924 av7110->fe_status = status;
1925
1926 if (av7110->fe_synced == synced)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001927 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001928
Oliver Endriss14500d42007-03-03 14:45:48 -03001929 if (av7110->playing) {
1930 av7110->fe_synced = synced;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001931 return 0;
Oliver Endriss14500d42007-03-03 14:45:48 -03001932 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001933
Ingo Molnar3593cab2006-02-07 06:49:14 -02001934 if (mutex_lock_interruptible(&av7110->pid_mutex))
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001935 return -ERESTARTSYS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001936
Oliver Endriss34612152005-07-07 17:58:02 -07001937 if (synced) {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001938 ret = SetPIDs(av7110, av7110->pids[DMX_PES_VIDEO],
Linus Torvalds1da177e2005-04-16 15:20:36 -07001939 av7110->pids[DMX_PES_AUDIO],
1940 av7110->pids[DMX_PES_TELETEXT], 0,
1941 av7110->pids[DMX_PES_PCR]);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001942 if (!ret)
1943 ret = av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, Scan, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001944 } else {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001945 ret = SetPIDs(av7110, 0, 0, 0, 0, 0);
1946 if (!ret) {
1947 ret = av7110_fw_cmd(av7110, COMTYPE_PID_FILTER, FlushTSQueue, 0);
1948 if (!ret)
1949 ret = av7110_wait_msgstate(av7110, GPMQBusy);
1950 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001951 }
1952
Oliver Endriss34612152005-07-07 17:58:02 -07001953 if (!ret)
1954 av7110->fe_synced = synced;
1955
Ingo Molnar3593cab2006-02-07 06:49:14 -02001956 mutex_unlock(&av7110->pid_mutex);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001957 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001958}
1959
1960static int av7110_fe_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
1961{
1962 struct av7110* av7110 = fe->dvb->priv;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001963
1964 int ret = av7110_fe_lock_fix(av7110, 0);
Oliver Endriss66190a22006-01-09 15:32:42 -02001965 if (!ret) {
1966 av7110->saved_fe_params = *params;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001967 ret = av7110->fe_set_frontend(fe, params);
Oliver Endriss66190a22006-01-09 15:32:42 -02001968 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001969 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001970}
1971
1972static int av7110_fe_init(struct dvb_frontend* fe)
1973{
1974 struct av7110* av7110 = fe->dvb->priv;
1975
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001976 int ret = av7110_fe_lock_fix(av7110, 0);
1977 if (!ret)
1978 ret = av7110->fe_init(fe);
1979 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001980}
1981
1982static int av7110_fe_read_status(struct dvb_frontend* fe, fe_status_t* status)
1983{
1984 struct av7110* av7110 = fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001985
1986 /* call the real implementation */
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001987 int ret = av7110->fe_read_status(fe, status);
1988 if (!ret)
1989 if (((*status ^ av7110->fe_status) & FE_HAS_LOCK) && (*status & FE_HAS_LOCK))
1990 ret = av7110_fe_lock_fix(av7110, *status);
1991 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001992}
1993
1994static int av7110_fe_diseqc_reset_overload(struct dvb_frontend* fe)
1995{
1996 struct av7110* av7110 = fe->dvb->priv;
1997
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001998 int ret = av7110_fe_lock_fix(av7110, 0);
1999 if (!ret)
2000 ret = av7110->fe_diseqc_reset_overload(fe);
2001 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002002}
2003
2004static int av7110_fe_diseqc_send_master_cmd(struct dvb_frontend* fe,
2005 struct dvb_diseqc_master_cmd* cmd)
2006{
2007 struct av7110* av7110 = fe->dvb->priv;
2008
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002009 int ret = av7110_fe_lock_fix(av7110, 0);
Oliver Endriss66190a22006-01-09 15:32:42 -02002010 if (!ret) {
2011 av7110->saved_master_cmd = *cmd;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002012 ret = av7110->fe_diseqc_send_master_cmd(fe, cmd);
Oliver Endriss66190a22006-01-09 15:32:42 -02002013 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002014 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002015}
2016
2017static int av7110_fe_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd)
2018{
2019 struct av7110* av7110 = fe->dvb->priv;
2020
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002021 int ret = av7110_fe_lock_fix(av7110, 0);
Oliver Endriss66190a22006-01-09 15:32:42 -02002022 if (!ret) {
2023 av7110->saved_minicmd = minicmd;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002024 ret = av7110->fe_diseqc_send_burst(fe, minicmd);
Oliver Endriss66190a22006-01-09 15:32:42 -02002025 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002026 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002027}
2028
2029static int av7110_fe_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
2030{
2031 struct av7110* av7110 = fe->dvb->priv;
2032
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002033 int ret = av7110_fe_lock_fix(av7110, 0);
Oliver Endriss66190a22006-01-09 15:32:42 -02002034 if (!ret) {
2035 av7110->saved_tone = tone;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002036 ret = av7110->fe_set_tone(fe, tone);
Oliver Endriss66190a22006-01-09 15:32:42 -02002037 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002038 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002039}
2040
2041static int av7110_fe_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
2042{
2043 struct av7110* av7110 = fe->dvb->priv;
2044
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002045 int ret = av7110_fe_lock_fix(av7110, 0);
Oliver Endriss66190a22006-01-09 15:32:42 -02002046 if (!ret) {
2047 av7110->saved_voltage = voltage;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002048 ret = av7110->fe_set_voltage(fe, voltage);
Oliver Endriss66190a22006-01-09 15:32:42 -02002049 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002050 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002051}
2052
Peter Beutner400b7082006-01-09 15:32:43 -02002053static int av7110_fe_dishnetwork_send_legacy_command(struct dvb_frontend* fe, unsigned long cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002054{
2055 struct av7110* av7110 = fe->dvb->priv;
2056
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002057 int ret = av7110_fe_lock_fix(av7110, 0);
2058 if (!ret)
2059 ret = av7110->fe_dishnetwork_send_legacy_command(fe, cmd);
2060 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002061}
2062
Oliver Endriss66190a22006-01-09 15:32:42 -02002063static void dvb_s_recover(struct av7110* av7110)
2064{
2065 av7110_fe_init(av7110->fe);
2066
2067 av7110_fe_set_voltage(av7110->fe, av7110->saved_voltage);
2068 if (av7110->saved_master_cmd.msg_len) {
2069 msleep(20);
2070 av7110_fe_diseqc_send_master_cmd(av7110->fe, &av7110->saved_master_cmd);
2071 }
2072 msleep(20);
2073 av7110_fe_diseqc_send_burst(av7110->fe, av7110->saved_minicmd);
2074 msleep(20);
2075 av7110_fe_set_tone(av7110->fe, av7110->saved_tone);
2076
2077 av7110_fe_set_frontend(av7110->fe, &av7110->saved_fe_params);
2078}
2079
Linus Torvalds1da177e2005-04-16 15:20:36 -07002080static u8 read_pwm(struct av7110* av7110)
2081{
2082 u8 b = 0xff;
2083 u8 pwm;
2084 struct i2c_msg msg[] = { { .addr = 0x50,.flags = 0,.buf = &b,.len = 1 },
2085 { .addr = 0x50,.flags = I2C_M_RD,.buf = &pwm,.len = 1} };
2086
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -08002087 if ((i2c_transfer(&av7110->i2c_adap, msg, 2) != 2) || (pwm == 0xff))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002088 pwm = 0x48;
2089
2090 return pwm;
2091}
2092
2093static int frontend_init(struct av7110 *av7110)
2094{
2095 int ret;
2096
2097 if (av7110->dev->pci->subsystem_vendor == 0x110a) {
2098 switch(av7110->dev->pci->subsystem_device) {
2099 case 0x0000: // Fujitsu/Siemens DVB-Cable (ves1820/Philips CD1516(??))
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002100 av7110->fe = dvb_attach(ves1820_attach, &philips_cd1516_config,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002101 &av7110->i2c_adap, read_pwm(av7110));
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002102 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002103 av7110->fe->ops.tuner_ops.set_params = philips_cd1516_tuner_set_params;
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002104 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002105 break;
2106 }
2107
2108 } else if (av7110->dev->pci->subsystem_vendor == 0x13c2) {
2109 switch(av7110->dev->pci->subsystem_device) {
2110 case 0x0000: // Hauppauge/TT WinTV DVB-S rev1.X
2111 case 0x0003: // Hauppauge/TT WinTV Nexus-S Rev 2.X
2112 case 0x1002: // Hauppauge/TT WinTV DVB-S rev1.3SE
2113
2114 // try the ALPS BSRV2 first of all
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002115 av7110->fe = dvb_attach(ves1x93_attach, &alps_bsrv2_config, &av7110->i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002116 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002117 av7110->fe->ops.tuner_ops.set_params = alps_bsrv2_tuner_set_params;
2118 av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
2119 av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
2120 av7110->fe->ops.set_tone = av7110_set_tone;
Oliver Endriss66190a22006-01-09 15:32:42 -02002121 av7110->recover = dvb_s_recover;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002122 break;
2123 }
2124
2125 // try the ALPS BSRU6 now
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002126 av7110->fe = dvb_attach(stv0299_attach, &alps_bsru6_config, &av7110->i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002127 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002128 av7110->fe->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03002129 av7110->fe->tuner_priv = &av7110->i2c_adap;
2130
Patrick Boettcherdea74862006-05-14 05:01:31 -03002131 av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
2132 av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
2133 av7110->fe->ops.set_tone = av7110_set_tone;
Oliver Endriss66190a22006-01-09 15:32:42 -02002134 av7110->recover = dvb_s_recover;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002135 break;
2136 }
2137
2138 // Try the grundig 29504-451
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002139 av7110->fe = dvb_attach(tda8083_attach, &grundig_29504_451_config, &av7110->i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002140 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002141 av7110->fe->ops.tuner_ops.set_params = grundig_29504_451_tuner_set_params;
2142 av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
2143 av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
2144 av7110->fe->ops.set_tone = av7110_set_tone;
Oliver Endriss66190a22006-01-09 15:32:42 -02002145 av7110->recover = dvb_s_recover;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002146 break;
2147 }
2148
2149 /* Try DVB-C cards */
2150 switch(av7110->dev->pci->subsystem_device) {
2151 case 0x0000:
2152 /* Siemens DVB-C (full-length card) VES1820/Philips CD1516 */
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002153 av7110->fe = dvb_attach(ves1820_attach, &philips_cd1516_config, &av7110->i2c_adap,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002154 read_pwm(av7110));
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002155 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002156 av7110->fe->ops.tuner_ops.set_params = philips_cd1516_tuner_set_params;
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002157 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002158 break;
2159 case 0x0003:
Adrian Bunkf3688fc2006-03-29 22:46:12 -03002160 /* Hauppauge DVB-C 2.1 VES1820/ALPS TDBE2 */
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002161 av7110->fe = dvb_attach(ves1820_attach, &alps_tdbe2_config, &av7110->i2c_adap,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002162 read_pwm(av7110));
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002163 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002164 av7110->fe->ops.tuner_ops.set_params = alps_tdbe2_tuner_set_params;
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002165 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002166 break;
2167 }
2168 break;
2169
2170 case 0x0001: // Hauppauge/TT Nexus-T premium rev1.X
Oliver Endriss8d90ee52006-08-07 02:04:26 -03002171 // try ALPS TDLB7 first, then Grundig 29504-401
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002172 av7110->fe = dvb_attach(sp8870_attach, &alps_tdlb7_config, &av7110->i2c_adap);
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002173 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002174 av7110->fe->ops.tuner_ops.set_params = alps_tdlb7_tuner_set_params;
Oliver Endriss8d90ee52006-08-07 02:04:26 -03002175 break;
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002176 }
Oliver Endriss8d90ee52006-08-07 02:04:26 -03002177 /* fall-thru */
2178
2179 case 0x0008: // Hauppauge/TT DVB-T
2180 // Grundig 29504-401
2181 av7110->fe = dvb_attach(l64781_attach, &grundig_29504_401_config, &av7110->i2c_adap);
2182 if (av7110->fe)
2183 av7110->fe->ops.tuner_ops.set_params = grundig_29504_401_tuner_set_params;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002184 break;
2185
2186 case 0x0002: // Hauppauge/TT DVB-C premium rev2.X
2187
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002188 av7110->fe = dvb_attach(ves1820_attach, &alps_tdbe2_config, &av7110->i2c_adap, read_pwm(av7110));
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002189 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002190 av7110->fe->ops.tuner_ops.set_params = alps_tdbe2_tuner_set_params;
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002191 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002192 break;
2193
Oliver Endriss8bd63012006-02-07 06:49:11 -02002194 case 0x0004: // Galaxis DVB-S rev1.3
2195 /* ALPS BSRV2 */
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002196 av7110->fe = dvb_attach(ves1x93_attach, &alps_bsrv2_config, &av7110->i2c_adap);
Oliver Endriss8bd63012006-02-07 06:49:11 -02002197 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002198 av7110->fe->ops.tuner_ops.set_params = alps_bsrv2_tuner_set_params;
2199 av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
2200 av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
2201 av7110->fe->ops.set_tone = av7110_set_tone;
Oliver Endriss8bd63012006-02-07 06:49:11 -02002202 av7110->recover = dvb_s_recover;
2203 }
2204 break;
2205
Linus Torvalds1da177e2005-04-16 15:20:36 -07002206 case 0x0006: /* Fujitsu-Siemens DVB-S rev 1.6 */
2207 /* Grundig 29504-451 */
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002208 av7110->fe = dvb_attach(tda8083_attach, &grundig_29504_451_config, &av7110->i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002209 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002210 av7110->fe->ops.tuner_ops.set_params = grundig_29504_451_tuner_set_params;
2211 av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
2212 av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
2213 av7110->fe->ops.set_tone = av7110_set_tone;
Oliver Endriss66190a22006-01-09 15:32:42 -02002214 av7110->recover = dvb_s_recover;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002215 }
2216 break;
2217
Linus Torvalds1da177e2005-04-16 15:20:36 -07002218 case 0x000A: // Hauppauge/TT Nexus-CA rev1.X
2219
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002220 av7110->fe = dvb_attach(stv0297_attach, &nexusca_stv0297_config, &av7110->i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002221 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002222 av7110->fe->ops.tuner_ops.set_params = nexusca_stv0297_tuner_set_params;
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03002223
Linus Torvalds1da177e2005-04-16 15:20:36 -07002224 /* set TDA9819 into DVB mode */
Marco Schluessler6a857742006-07-10 03:34:16 -03002225 saa7146_setgpio(av7110->dev, 1, SAA7146_GPIO_OUTLO); // TDA9819 pin9(STD)
2226 saa7146_setgpio(av7110->dev, 3, SAA7146_GPIO_OUTLO); // TDA9819 pin30(VIF)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002227
2228 /* tuner on this needs a slower i2c bus speed */
2229 av7110->dev->i2c_bitrate = SAA7146_I2C_BUS_BIT_RATE_240;
2230 break;
2231 }
Johannes Stezenbach3dfaebd2005-05-16 21:54:19 -07002232 break;
2233
2234 case 0x000E: /* Hauppauge/TT Nexus-S rev 2.3 */
2235 /* ALPS BSBE1 */
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002236 av7110->fe = dvb_attach(stv0299_attach, &alps_bsbe1_config, &av7110->i2c_adap);
Oliver Endrisseb3daf32006-01-09 15:25:05 -02002237 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002238 av7110->fe->ops.tuner_ops.set_params = alps_bsbe1_tuner_set_params;
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03002239 av7110->fe->tuner_priv = &av7110->i2c_adap;
2240
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002241 if (dvb_attach(lnbp21_attach, av7110->fe, &av7110->i2c_adap, 0, 0) == NULL) {
Oliver Endrissdb5d91e2006-02-28 10:32:25 -03002242 printk("dvb-ttpci: LNBP21 not found!\n");
Patrick Boettcherdea74862006-05-14 05:01:31 -03002243 if (av7110->fe->ops.release)
2244 av7110->fe->ops.release(av7110->fe);
Oliver Endrissdb5d91e2006-02-28 10:32:25 -03002245 av7110->fe = NULL;
2246 } else {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002247 av7110->fe->ops.dishnetwork_send_legacy_command = NULL;
Oliver Endrissdb5d91e2006-02-28 10:32:25 -03002248 av7110->recover = dvb_s_recover;
2249 }
Oliver Endrisseb3daf32006-01-09 15:25:05 -02002250 }
Johannes Stezenbach3dfaebd2005-05-16 21:54:19 -07002251 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002252 }
2253 }
2254
2255 if (!av7110->fe) {
2256 /* FIXME: propagate the failure code from the lower layers */
2257 ret = -ENOMEM;
2258 printk("dvb-ttpci: A frontend driver was not found for device %04x/%04x subsystem %04x/%04x\n",
2259 av7110->dev->pci->vendor,
2260 av7110->dev->pci->device,
2261 av7110->dev->pci->subsystem_vendor,
2262 av7110->dev->pci->subsystem_device);
2263 } else {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002264 FE_FUNC_OVERRIDE(av7110->fe->ops.init, av7110->fe_init, av7110_fe_init);
2265 FE_FUNC_OVERRIDE(av7110->fe->ops.read_status, av7110->fe_read_status, av7110_fe_read_status);
2266 FE_FUNC_OVERRIDE(av7110->fe->ops.diseqc_reset_overload, av7110->fe_diseqc_reset_overload, av7110_fe_diseqc_reset_overload);
2267 FE_FUNC_OVERRIDE(av7110->fe->ops.diseqc_send_master_cmd, av7110->fe_diseqc_send_master_cmd, av7110_fe_diseqc_send_master_cmd);
2268 FE_FUNC_OVERRIDE(av7110->fe->ops.diseqc_send_burst, av7110->fe_diseqc_send_burst, av7110_fe_diseqc_send_burst);
2269 FE_FUNC_OVERRIDE(av7110->fe->ops.set_tone, av7110->fe_set_tone, av7110_fe_set_tone);
2270 FE_FUNC_OVERRIDE(av7110->fe->ops.set_voltage, av7110->fe_set_voltage, av7110_fe_set_voltage;)
2271 FE_FUNC_OVERRIDE(av7110->fe->ops.dishnetwork_send_legacy_command, av7110->fe_dishnetwork_send_legacy_command, av7110_fe_dishnetwork_send_legacy_command);
2272 FE_FUNC_OVERRIDE(av7110->fe->ops.set_frontend, av7110->fe_set_frontend, av7110_fe_set_frontend);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002273
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07002274 ret = dvb_register_frontend(&av7110->dvb_adapter, av7110->fe);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002275 if (ret < 0) {
2276 printk("av7110: Frontend registration failed!\n");
Andrew de Quinceyf52a8382006-08-08 09:10:09 -03002277 dvb_frontend_detach(av7110->fe);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002278 av7110->fe = NULL;
2279 }
2280 }
2281 return ret;
2282}
2283
2284/* Budgetpatch note:
2285 * Original hardware design by Roberto Deza:
2286 * There is a DVB_Wiki at
2287 * http://212.227.36.83/linuxtv/wiki/index.php/Main_Page
2288 * where is described this 'DVB TT Budget Patch', on Card Modding:
2289 * http://212.227.36.83/linuxtv/wiki/index.php/DVB_TT_Budget_Patch
2290 * On the short description there is also a link to a external file,
2291 * with more details:
2292 * http://perso.wanadoo.es/jesussolano/Ttf_tsc1.zip
2293 *
2294 * New software triggering design by Emard that works on
2295 * original Roberto Deza's hardware:
2296 *
2297 * rps1 code for budgetpatch will copy internal HS event to GPIO3 pin.
2298 * GPIO3 is in budget-patch hardware connectd to port B VSYNC
2299 * HS is an internal event of 7146, accessible with RPS
2300 * and temporarily raised high every n lines
2301 * (n in defined in the RPS_THRESH1 counter threshold)
2302 * I think HS is raised high on the beginning of the n-th line
2303 * and remains high until this n-th line that triggered
2304 * it is completely received. When the receiption of n-th line
2305 * ends, HS is lowered.
2306 *
2307 * To transmit data over DMA, 7146 needs changing state at
2308 * port B VSYNC pin. Any changing of port B VSYNC will
2309 * cause some DMA data transfer, with more or less packets loss.
2310 * It depends on the phase and frequency of VSYNC and
2311 * the way of 7146 is instructed to trigger on port B (defined
2312 * in DD1_INIT register, 3rd nibble from the right valid
2313 * numbers are 0-7, see datasheet)
2314 *
2315 * The correct triggering can minimize packet loss,
2316 * dvbtraffic should give this stable bandwidths:
2317 * 22k transponder = 33814 kbit/s
2318 * 27.5k transponder = 38045 kbit/s
2319 * by experiment it is found that the best results
2320 * (stable bandwidths and almost no packet loss)
2321 * are obtained using DD1_INIT triggering number 2
2322 * (Va at rising edge of VS Fa = HS x VS-failing forced toggle)
2323 * and a VSYNC phase that occurs in the middle of DMA transfer
2324 * (about byte 188*512=96256 in the DMA window).
2325 *
2326 * Phase of HS is still not clear to me how to control,
2327 * It just happens to be so. It can be seen if one enables
2328 * RPS_IRQ and print Event Counter 1 in vpeirq(). Every
2329 * time RPS_INTERRUPT is called, the Event Counter 1 will
2330 * increment. That's how the 7146 is programmed to do event
2331 * counting in this budget-patch.c
2332 * I *think* HPS setting has something to do with the phase
2333 * of HS but I cant be 100% sure in that.
2334 *
2335 * hardware debug note: a working budget card (including budget patch)
2336 * with vpeirq() interrupt setup in mode "0x90" (every 64K) will
2337 * generate 3 interrupts per 25-Hz DMA frame of 2*188*512 bytes
2338 * and that means 3*25=75 Hz of interrupt freqency, as seen by
2339 * watch cat /proc/interrupts
2340 *
2341 * If this frequency is 3x lower (and data received in the DMA
2342 * buffer don't start with 0x47, but in the middle of packets,
2343 * whose lengths appear to be like 188 292 188 104 etc.
2344 * this means VSYNC line is not connected in the hardware.
2345 * (check soldering pcb and pins)
2346 * The same behaviour of missing VSYNC can be duplicated on budget
2347 * cards, by seting DD1_INIT trigger mode 7 in 3rd nibble.
2348 */
Johannes Stezenbach1be11e32006-02-27 00:09:20 -03002349static int __devinit av7110_attach(struct saa7146_dev* dev,
2350 struct saa7146_pci_extension_data *pci_ext)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002351{
2352 const int length = TS_WIDTH * TS_HEIGHT;
2353 struct pci_dev *pdev = dev->pci;
2354 struct av7110 *av7110;
Herbert Poetzl8eec1422007-02-08 14:32:43 -03002355 struct task_struct *thread;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002356 int ret, count = 0;
2357
2358 dprintk(4, "dev: %p\n", dev);
2359
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -08002360 /* Set RPS_IRQ to 1 to track rps1 activity.
2361 * Enabling this won't send any interrupt to PC CPU.
2362 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002363#define RPS_IRQ 0
2364
2365 if (budgetpatch == 1) {
2366 budgetpatch = 0;
2367 /* autodetect the presence of budget patch
2368 * this only works if saa7146 has been recently
2369 * reset with with MASK_31 to MC1
2370 *
2371 * will wait for VBI_B event (vertical blank at port B)
2372 * and will reset GPIO3 after VBI_B is detected.
2373 * (GPIO3 should be raised high by CPU to
2374 * test if GPIO3 will generate vertical blank signal
2375 * in budget patch GPIO3 is connected to VSYNC_B
2376 */
2377
2378 /* RESET SAA7146 */
2379 saa7146_write(dev, MC1, MASK_31);
2380 /* autodetection success seems to be time-dependend after reset */
2381
2382 /* Fix VSYNC level */
2383 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
2384 /* set vsync_b triggering */
2385 saa7146_write(dev, DD1_STREAM_B, 0);
2386 /* port B VSYNC at rising edge */
2387 saa7146_write(dev, DD1_INIT, 0x00000200);
2388 saa7146_write(dev, BRS_CTRL, 0x00000000); // VBI
2389 saa7146_write(dev, MC2,
2390 1 * (MASK_08 | MASK_24) | // BRS control
2391 0 * (MASK_09 | MASK_25) | // a
2392 1 * (MASK_10 | MASK_26) | // b
2393 0 * (MASK_06 | MASK_22) | // HPS_CTRL1
2394 0 * (MASK_05 | MASK_21) | // HPS_CTRL2
2395 0 * (MASK_01 | MASK_15) // DEBI
2396 );
2397
2398 /* start writing RPS1 code from beginning */
2399 count = 0;
2400 /* Disable RPS1 */
2401 saa7146_write(dev, MC1, MASK_29);
2402 /* RPS1 timeout disable */
2403 saa7146_write(dev, RPS_TOV1, 0);
2404 WRITE_RPS1(cpu_to_le32(CMD_PAUSE | EVT_VBI_B));
2405 WRITE_RPS1(cpu_to_le32(CMD_WR_REG_MASK | (GPIO_CTRL>>2)));
2406 WRITE_RPS1(cpu_to_le32(GPIO3_MSK));
2407 WRITE_RPS1(cpu_to_le32(SAA7146_GPIO_OUTLO<<24));
2408#if RPS_IRQ
2409 /* issue RPS1 interrupt to increment counter */
2410 WRITE_RPS1(cpu_to_le32(CMD_INTERRUPT));
2411#endif
2412 WRITE_RPS1(cpu_to_le32(CMD_STOP));
2413 /* Jump to begin of RPS program as safety measure (p37) */
2414 WRITE_RPS1(cpu_to_le32(CMD_JUMP));
2415 WRITE_RPS1(cpu_to_le32(dev->d_rps1.dma_handle));
2416
2417#if RPS_IRQ
2418 /* set event counter 1 source as RPS1 interrupt (0x03) (rE4 p53)
2419 * use 0x03 to track RPS1 interrupts - increase by 1 every gpio3 is toggled
2420 * use 0x15 to track VPE interrupts - increase by 1 every vpeirq() is called
2421 */
2422 saa7146_write(dev, EC1SSR, (0x03<<2) | 3 );
2423 /* set event counter 1 treshold to maximum allowed value (rEC p55) */
2424 saa7146_write(dev, ECT1R, 0x3fff );
2425#endif
2426 /* Set RPS1 Address register to point to RPS code (r108 p42) */
2427 saa7146_write(dev, RPS_ADDR1, dev->d_rps1.dma_handle);
2428 /* Enable RPS1, (rFC p33) */
2429 saa7146_write(dev, MC1, (MASK_13 | MASK_29 ));
2430
2431 mdelay(10);
2432 /* now send VSYNC_B to rps1 by rising GPIO3 */
2433 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI);
2434 mdelay(10);
2435 /* if rps1 responded by lowering the GPIO3,
2436 * then we have budgetpatch hardware
2437 */
2438 if ((saa7146_read(dev, GPIO_CTRL) & 0x10000000) == 0) {
2439 budgetpatch = 1;
2440 printk("dvb-ttpci: BUDGET-PATCH DETECTED.\n");
2441 }
2442 /* Disable RPS1 */
2443 saa7146_write(dev, MC1, ( MASK_29 ));
2444#if RPS_IRQ
2445 printk("dvb-ttpci: Event Counter 1 0x%04x\n", saa7146_read(dev, EC1R) & 0x3fff );
2446#endif
2447 }
2448
2449 /* prepare the av7110 device struct */
Panagiotis Issaris74081872006-01-11 19:40:56 -02002450 av7110 = kzalloc(sizeof(struct av7110), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002451 if (!av7110) {
2452 dprintk(1, "out of memory\n");
2453 return -ENOMEM;
2454 }
2455
Linus Torvalds1da177e2005-04-16 15:20:36 -07002456 av7110->card_name = (char*) pci_ext->ext_priv;
2457 av7110->dev = dev;
2458 dev->ext_priv = av7110;
2459
2460 ret = get_firmware(av7110);
2461 if (ret < 0)
2462 goto err_kfree_0;
2463
2464 ret = dvb_register_adapter(&av7110->dvb_adapter, av7110->card_name,
Andrew de Quinceyd09dbf92006-04-10 09:27:37 -03002465 THIS_MODULE, &dev->pci->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002466 if (ret < 0)
2467 goto err_put_firmware_1;
2468
2469 /* the Siemens DVB needs this if you want to have the i2c chips
2470 get recognized before the main driver is fully loaded */
2471 saa7146_write(dev, GPIO_CTRL, 0x500000);
2472
2473#ifdef I2C_ADAP_CLASS_TV_DIGITAL
2474 av7110->i2c_adap.class = I2C_ADAP_CLASS_TV_DIGITAL;
2475#else
2476 av7110->i2c_adap.class = I2C_CLASS_TV_DIGITAL;
2477#endif
2478 strlcpy(av7110->i2c_adap.name, pci_ext->ext_priv, sizeof(av7110->i2c_adap.name));
2479
2480 saa7146_i2c_adapter_prepare(dev, &av7110->i2c_adap, SAA7146_I2C_BUS_BIT_RATE_120); /* 275 kHz */
2481
2482 ret = i2c_add_adapter(&av7110->i2c_adap);
2483 if (ret < 0)
2484 goto err_dvb_unregister_adapter_2;
2485
2486 ttpci_eeprom_parse_mac(&av7110->i2c_adap,
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07002487 av7110->dvb_adapter.proposed_mac);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002488 ret = -ENOMEM;
2489
2490 if (budgetpatch) {
2491 spin_lock_init(&av7110->feedlock1);
2492 av7110->grabbing = saa7146_vmalloc_build_pgtable(pdev, length,
2493 &av7110->pt);
2494 if (!av7110->grabbing)
2495 goto err_i2c_del_3;
2496
2497 saa7146_write(dev, PCI_BT_V1, 0x1c1f101f);
2498 saa7146_write(dev, BCS_CTRL, 0x80400040);
2499 /* set dd1 stream a & b */
2500 saa7146_write(dev, DD1_STREAM_B, 0x00000000);
2501 saa7146_write(dev, DD1_INIT, 0x03000200);
2502 saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
2503 saa7146_write(dev, BRS_CTRL, 0x60000000);
2504 saa7146_write(dev, BASE_ODD3, 0);
2505 saa7146_write(dev, BASE_EVEN3, 0);
2506 saa7146_write(dev, PROT_ADDR3, TS_WIDTH * TS_HEIGHT);
2507 saa7146_write(dev, BASE_PAGE3, av7110->pt.dma | ME1 | 0x90);
2508
2509 saa7146_write(dev, PITCH3, TS_WIDTH);
2510 saa7146_write(dev, NUM_LINE_BYTE3, (TS_HEIGHT << 16) | TS_WIDTH);
2511
2512 /* upload all */
2513 saa7146_write(dev, MC2, 0x077c077c);
2514 saa7146_write(dev, GPIO_CTRL, 0x000000);
2515#if RPS_IRQ
2516 /* set event counter 1 source as RPS1 interrupt (0x03) (rE4 p53)
2517 * use 0x03 to track RPS1 interrupts - increase by 1 every gpio3 is toggled
2518 * use 0x15 to track VPE interrupts - increase by 1 every vpeirq() is called
2519 */
2520 saa7146_write(dev, EC1SSR, (0x03<<2) | 3 );
2521 /* set event counter 1 treshold to maximum allowed value (rEC p55) */
2522 saa7146_write(dev, ECT1R, 0x3fff );
2523#endif
2524 /* Setup BUDGETPATCH MAIN RPS1 "program" (p35) */
2525 count = 0;
2526
2527 /* Wait Source Line Counter Threshold (p36) */
2528 WRITE_RPS1(cpu_to_le32(CMD_PAUSE | EVT_HS));
2529 /* Set GPIO3=1 (p42) */
2530 WRITE_RPS1(cpu_to_le32(CMD_WR_REG_MASK | (GPIO_CTRL>>2)));
2531 WRITE_RPS1(cpu_to_le32(GPIO3_MSK));
2532 WRITE_RPS1(cpu_to_le32(SAA7146_GPIO_OUTHI<<24));
2533#if RPS_IRQ
2534 /* issue RPS1 interrupt */
2535 WRITE_RPS1(cpu_to_le32(CMD_INTERRUPT));
2536#endif
2537 /* Wait reset Source Line Counter Threshold (p36) */
2538 WRITE_RPS1(cpu_to_le32(CMD_PAUSE | RPS_INV | EVT_HS));
2539 /* Set GPIO3=0 (p42) */
2540 WRITE_RPS1(cpu_to_le32(CMD_WR_REG_MASK | (GPIO_CTRL>>2)));
2541 WRITE_RPS1(cpu_to_le32(GPIO3_MSK));
2542 WRITE_RPS1(cpu_to_le32(SAA7146_GPIO_OUTLO<<24));
2543#if RPS_IRQ
2544 /* issue RPS1 interrupt */
2545 WRITE_RPS1(cpu_to_le32(CMD_INTERRUPT));
2546#endif
2547 /* Jump to begin of RPS program (p37) */
2548 WRITE_RPS1(cpu_to_le32(CMD_JUMP));
2549 WRITE_RPS1(cpu_to_le32(dev->d_rps1.dma_handle));
2550
2551 /* Fix VSYNC level */
2552 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
2553 /* Set RPS1 Address register to point to RPS code (r108 p42) */
2554 saa7146_write(dev, RPS_ADDR1, dev->d_rps1.dma_handle);
2555 /* Set Source Line Counter Threshold, using BRS (rCC p43)
2556 * It generates HS event every TS_HEIGHT lines
2557 * this is related to TS_WIDTH set in register
2558 * NUM_LINE_BYTE3. If NUM_LINE_BYTE low 16 bits
2559 * are set to TS_WIDTH bytes (TS_WIDTH=2*188),
2560 * then RPS_THRESH1 should be set to trigger
2561 * every TS_HEIGHT (512) lines.
2562 */
2563 saa7146_write(dev, RPS_THRESH1, (TS_HEIGHT*1) | MASK_12 );
2564
2565 /* Enable RPS1 (rFC p33) */
2566 saa7146_write(dev, MC1, (MASK_13 | MASK_29));
2567
2568 /* end of budgetpatch register initialization */
2569 tasklet_init (&av7110->vpe_tasklet, vpeirq, (unsigned long) av7110);
2570 } else {
2571 saa7146_write(dev, PCI_BT_V1, 0x1c00101f);
2572 saa7146_write(dev, BCS_CTRL, 0x80400040);
2573
2574 /* set dd1 stream a & b */
2575 saa7146_write(dev, DD1_STREAM_B, 0x00000000);
2576 saa7146_write(dev, DD1_INIT, 0x03000000);
2577 saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
2578
2579 /* upload all */
2580 saa7146_write(dev, MC2, 0x077c077c);
2581 saa7146_write(dev, GPIO_CTRL, 0x000000);
2582 }
2583
2584 tasklet_init (&av7110->debi_tasklet, debiirq, (unsigned long) av7110);
2585 tasklet_init (&av7110->gpio_tasklet, gpioirq, (unsigned long) av7110);
2586
Ingo Molnar3593cab2006-02-07 06:49:14 -02002587 mutex_init(&av7110->pid_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002588
2589 /* locks for data transfers from/to AV7110 */
2590 spin_lock_init(&av7110->debilock);
Ingo Molnar3593cab2006-02-07 06:49:14 -02002591 mutex_init(&av7110->dcomlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002592 av7110->debitype = -1;
2593
2594 /* default OSD window */
2595 av7110->osdwin = 1;
Ingo Molnar3593cab2006-02-07 06:49:14 -02002596 mutex_init(&av7110->osd_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002597
C.Y.M2f03ee82006-03-30 04:31:48 -03002598 /* TV standard */
2599 av7110->vidmode = tv_standard == 1 ? VIDEO_MODE_NTSC : VIDEO_MODE_PAL;
2600
Linus Torvalds1da177e2005-04-16 15:20:36 -07002601 /* ARM "watchdog" */
2602 init_waitqueue_head(&av7110->arm_wait);
2603 av7110->arm_thread = NULL;
2604
2605 /* allocate and init buffers */
2606 av7110->debi_virt = pci_alloc_consistent(pdev, 8192, &av7110->debi_bus);
2607 if (!av7110->debi_virt)
2608 goto err_saa71466_vfree_4;
2609
2610
2611 av7110->iobuf = vmalloc(AVOUTLEN+AOUTLEN+BMPLEN+4*IPACKS);
2612 if (!av7110->iobuf)
2613 goto err_pci_free_5;
2614
2615 ret = av7110_av_init(av7110);
2616 if (ret < 0)
2617 goto err_iobuf_vfree_6;
2618
2619 /* init BMP buffer */
2620 av7110->bmpbuf = av7110->iobuf+AVOUTLEN+AOUTLEN;
2621 init_waitqueue_head(&av7110->bmpq);
2622
2623 ret = av7110_ca_init(av7110);
2624 if (ret < 0)
2625 goto err_av7110_av_exit_7;
2626
2627 /* load firmware into AV7110 cards */
2628 ret = av7110_bootarm(av7110);
2629 if (ret < 0)
2630 goto err_av7110_ca_exit_8;
2631
2632 ret = av7110_firmversion(av7110);
2633 if (ret < 0)
2634 goto err_stop_arm_9;
2635
2636 if (FW_VERSION(av7110->arm_app)<0x2501)
2637 printk ("dvb-ttpci: Warning, firmware version 0x%04x is too old. "
2638 "System might be unstable!\n", FW_VERSION(av7110->arm_app));
2639
Herbert Poetzl8eec1422007-02-08 14:32:43 -03002640 thread = kthread_run(arm_thread, (void *) av7110, "arm_mon");
2641 if (IS_ERR(thread)) {
2642 ret = PTR_ERR(thread);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002643 goto err_stop_arm_9;
Herbert Poetzl8eec1422007-02-08 14:32:43 -03002644 }
2645 av7110->arm_thread = thread;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002646
2647 /* set initial volume in mixer struct */
2648 av7110->mixer.volume_left = volume;
2649 av7110->mixer.volume_right = volume;
2650
Linus Torvalds1da177e2005-04-16 15:20:36 -07002651 ret = av7110_register(av7110);
2652 if (ret < 0)
2653 goto err_arm_thread_stop_10;
2654
Oliver Endrissdefd574e2007-07-12 23:08:07 -03002655 init_av7110_av(av7110);
2656
Linus Torvalds1da177e2005-04-16 15:20:36 -07002657 /* special case DVB-C: these cards have an analog tuner
2658 plus need some special handling, so we have separate
2659 saa7146_ext_vv data for these... */
2660 ret = av7110_init_v4l(av7110);
2661 if (ret < 0)
2662 goto err_av7110_unregister_11;
2663
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07002664 av7110->dvb_adapter.priv = av7110;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002665 ret = frontend_init(av7110);
2666 if (ret < 0)
2667 goto err_av7110_exit_v4l_12;
2668
2669#if defined(CONFIG_INPUT_EVDEV) || defined(CONFIG_INPUT_EVDEV_MODULE)
Oliver Endriss03388ae2005-09-09 13:03:12 -07002670 av7110_ir_init(av7110);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002671#endif
2672 printk(KERN_INFO "dvb-ttpci: found av7110-%d.\n", av7110_num);
2673 av7110_num++;
2674out:
2675 return ret;
2676
2677err_av7110_exit_v4l_12:
2678 av7110_exit_v4l(av7110);
2679err_av7110_unregister_11:
2680 dvb_unregister(av7110);
2681err_arm_thread_stop_10:
2682 av7110_arm_sync(av7110);
2683err_stop_arm_9:
2684 /* Nothing to do. Rejoice. */
2685err_av7110_ca_exit_8:
2686 av7110_ca_exit(av7110);
2687err_av7110_av_exit_7:
2688 av7110_av_exit(av7110);
2689err_iobuf_vfree_6:
2690 vfree(av7110->iobuf);
2691err_pci_free_5:
2692 pci_free_consistent(pdev, 8192, av7110->debi_virt, av7110->debi_bus);
2693err_saa71466_vfree_4:
Jon Burgess87c30192007-05-03 12:23:44 -03002694 if (av7110->grabbing)
2695 saa7146_vfree_destroy_pgtable(pdev, av7110->grabbing, &av7110->pt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002696err_i2c_del_3:
2697 i2c_del_adapter(&av7110->i2c_adap);
2698err_dvb_unregister_adapter_2:
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07002699 dvb_unregister_adapter(&av7110->dvb_adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002700err_put_firmware_1:
2701 put_firmware(av7110);
2702err_kfree_0:
2703 kfree(av7110);
2704 goto out;
2705}
2706
Johannes Stezenbach1be11e32006-02-27 00:09:20 -03002707static int __devexit av7110_detach(struct saa7146_dev* saa)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002708{
2709 struct av7110 *av7110 = saa->ext_priv;
2710 dprintk(4, "%p\n", av7110);
2711
Oliver Endriss03388ae2005-09-09 13:03:12 -07002712#if defined(CONFIG_INPUT_EVDEV) || defined(CONFIG_INPUT_EVDEV_MODULE)
2713 av7110_ir_exit(av7110);
2714#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07002715 if (budgetpatch) {
2716 /* Disable RPS1 */
2717 saa7146_write(saa, MC1, MASK_29);
2718 /* VSYNC LOW (inactive) */
2719 saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);
2720 saa7146_write(saa, MC1, MASK_20); /* DMA3 off */
2721 SAA7146_IER_DISABLE(saa, MASK_10);
2722 SAA7146_ISR_CLEAR(saa, MASK_10);
2723 msleep(50);
2724 tasklet_kill(&av7110->vpe_tasklet);
Jon Burgess87c30192007-05-03 12:23:44 -03002725 saa7146_vfree_destroy_pgtable(saa->pci, av7110->grabbing, &av7110->pt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002726 }
2727 av7110_exit_v4l(av7110);
2728
2729 av7110_arm_sync(av7110);
2730
2731 tasklet_kill(&av7110->debi_tasklet);
2732 tasklet_kill(&av7110->gpio_tasklet);
2733
2734 dvb_unregister(av7110);
2735
2736 SAA7146_IER_DISABLE(saa, MASK_19 | MASK_03);
2737 SAA7146_ISR_CLEAR(saa, MASK_19 | MASK_03);
2738
2739 av7110_ca_exit(av7110);
2740 av7110_av_exit(av7110);
2741
2742 vfree(av7110->iobuf);
2743 pci_free_consistent(saa->pci, 8192, av7110->debi_virt,
2744 av7110->debi_bus);
2745
2746 i2c_del_adapter(&av7110->i2c_adap);
2747
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07002748 dvb_unregister_adapter (&av7110->dvb_adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002749
2750 av7110_num--;
2751
2752 put_firmware(av7110);
2753
2754 kfree(av7110);
2755
2756 saa->ext_priv = NULL;
2757
2758 return 0;
2759}
2760
2761
2762static void av7110_irq(struct saa7146_dev* dev, u32 *isr)
2763{
2764 struct av7110 *av7110 = dev->ext_priv;
2765
2766 //print_time("av7110_irq");
2767
2768 /* Note: Don't try to handle the DEBI error irq (MASK_18), in
2769 * intel mode the timeout is asserted all the time...
2770 */
2771
2772 if (*isr & MASK_19) {
2773 //printk("av7110_irq: DEBI\n");
2774 /* Note 1: The DEBI irq is level triggered: We must enable it
2775 * only after we started a DMA xfer, and disable it here
2776 * immediately, or it will be signalled all the time while
2777 * DEBI is idle.
2778 * Note 2: You would think that an irq which is masked is
2779 * not signalled by the hardware. Not so for the SAA7146:
2780 * An irq is signalled as long as the corresponding bit
2781 * in the ISR is set, and disabling irqs just prevents the
2782 * hardware from setting the ISR bit. This means a) that we
2783 * must clear the ISR *after* disabling the irq (which is why
2784 * we must do it here even though saa7146_core did it already),
2785 * and b) that if we were to disable an edge triggered irq
2786 * (like the gpio irqs sadly are) temporarily we would likely
2787 * loose some. This sucks :-(
2788 */
2789 SAA7146_IER_DISABLE(av7110->dev, MASK_19);
2790 SAA7146_ISR_CLEAR(av7110->dev, MASK_19);
2791 tasklet_schedule(&av7110->debi_tasklet);
2792 }
2793
2794 if (*isr & MASK_03) {
2795 //printk("av7110_irq: GPIO\n");
2796 tasklet_schedule(&av7110->gpio_tasklet);
2797 }
2798
2799 if ((*isr & MASK_10) && budgetpatch)
2800 tasklet_schedule(&av7110->vpe_tasklet);
2801}
2802
2803
2804static struct saa7146_extension av7110_extension;
2805
2806#define MAKE_AV7110_INFO(x_var,x_name) \
2807static struct saa7146_pci_extension_data x_var = { \
2808 .ext_priv = x_name, \
2809 .ext = &av7110_extension }
2810
Karl Herz6af4ee12005-09-09 13:03:13 -07002811MAKE_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 -07002812MAKE_AV7110_INFO(ttt_1_X, "Technotrend/Hauppauge WinTV DVB-T rev1.X");
2813MAKE_AV7110_INFO(ttc_1_X, "Technotrend/Hauppauge WinTV Nexus-CA rev1.X");
2814MAKE_AV7110_INFO(ttc_2_X, "Technotrend/Hauppauge WinTV DVB-C rev2.X");
2815MAKE_AV7110_INFO(tts_2_X, "Technotrend/Hauppauge WinTV Nexus-S rev2.X");
Johannes Stezenbach3dfaebd2005-05-16 21:54:19 -07002816MAKE_AV7110_INFO(tts_2_3, "Technotrend/Hauppauge WinTV Nexus-S rev2.3");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002817MAKE_AV7110_INFO(tts_1_3se, "Technotrend/Hauppauge WinTV DVB-S rev1.3 SE");
2818MAKE_AV7110_INFO(ttt, "Technotrend/Hauppauge DVB-T");
2819MAKE_AV7110_INFO(fsc, "Fujitsu Siemens DVB-C");
2820MAKE_AV7110_INFO(fss, "Fujitsu Siemens DVB-S rev1.6");
Oliver Endriss8bd63012006-02-07 06:49:11 -02002821MAKE_AV7110_INFO(gxs_1_3, "Galaxis DVB-S rev1.3");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002822
2823static struct pci_device_id pci_tbl[] = {
Karl Herz6af4ee12005-09-09 13:03:13 -07002824 MAKE_EXTENSION_PCI(fsc, 0x110a, 0x0000),
2825 MAKE_EXTENSION_PCI(tts_1_X_fsc, 0x13c2, 0x0000),
2826 MAKE_EXTENSION_PCI(ttt_1_X, 0x13c2, 0x0001),
2827 MAKE_EXTENSION_PCI(ttc_2_X, 0x13c2, 0x0002),
2828 MAKE_EXTENSION_PCI(tts_2_X, 0x13c2, 0x0003),
Oliver Endriss8bd63012006-02-07 06:49:11 -02002829 MAKE_EXTENSION_PCI(gxs_1_3, 0x13c2, 0x0004),
Karl Herz6af4ee12005-09-09 13:03:13 -07002830 MAKE_EXTENSION_PCI(fss, 0x13c2, 0x0006),
2831 MAKE_EXTENSION_PCI(ttt, 0x13c2, 0x0008),
2832 MAKE_EXTENSION_PCI(ttc_1_X, 0x13c2, 0x000a),
2833 MAKE_EXTENSION_PCI(tts_2_3, 0x13c2, 0x000e),
2834 MAKE_EXTENSION_PCI(tts_1_3se, 0x13c2, 0x1002),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002835
Linus Torvalds1da177e2005-04-16 15:20:36 -07002836/* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0005), UNDEFINED CARD */ // Technisat SkyStar1
2837/* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0009), UNDEFINED CARD */ // TT/Hauppauge WinTV Nexus-CA v????
2838
2839 {
2840 .vendor = 0,
2841 }
2842};
2843
2844MODULE_DEVICE_TABLE(pci, pci_tbl);
2845
2846
2847static struct saa7146_extension av7110_extension = {
Dave Jones0e367a12006-08-07 13:18:56 -03002848 .name = "dvb",
Oliver Endriss00c4cc62006-11-01 13:09:51 -03002849 .flags = SAA7146_USE_I2C_IRQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002850
2851 .module = THIS_MODULE,
2852 .pci_tbl = &pci_tbl[0],
2853 .attach = av7110_attach,
Johannes Stezenbach1be11e32006-02-27 00:09:20 -03002854 .detach = __devexit_p(av7110_detach),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002855
2856 .irq_mask = MASK_19 | MASK_03 | MASK_10,
2857 .irq_func = av7110_irq,
2858};
2859
2860
2861static int __init av7110_init(void)
2862{
2863 int retval;
2864 retval = saa7146_register_extension(&av7110_extension);
2865 return retval;
2866}
2867
2868
2869static void __exit av7110_exit(void)
2870{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002871 saa7146_unregister_extension(&av7110_extension);
2872}
2873
2874module_init(av7110_init);
2875module_exit(av7110_exit);
2876
2877MODULE_DESCRIPTION("driver for the SAA7146 based AV110 PCI DVB cards by "
2878 "Siemens, Technotrend, Hauppauge");
2879MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, others");
2880MODULE_LICENSE("GPL");