blob: f05d43d8b5cf25cfef2bdc0e866c97080ffca257 [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>
Linus Torvalds1da177e2005-04-16 15:20:36 -070043#include <linux/sched.h>
44#include <linux/types.h>
45#include <linux/fcntl.h>
46#include <linux/interrupt.h>
47#include <linux/string.h>
48#include <linux/pci.h>
49#include <linux/vmalloc.h>
50#include <linux/firmware.h>
51#include <linux/crc32.h>
52#include <linux/i2c.h>
Herbert Poetzl8eec1422007-02-08 14:32:43 -030053#include <linux/kthread.h>
Al Viro3e085622008-05-21 00:30:51 -030054#include <asm/unaligned.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
Janne Grunau78e92002008-04-09 19:13:13 -0300116DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
117
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118static void restart_feeds(struct av7110 *av7110);
119
Mauro Carvalho Chehaba5ed4252006-01-13 14:10:19 -0200120static int av7110_num;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700121
122#define FE_FUNC_OVERRIDE(fe_func, av7110_copy, av7110_func) \
123{\
124 if (fe_func != NULL) { \
125 av7110_copy = fe_func; \
126 fe_func = av7110_func; \
127 } \
128}
129
130
131static void init_av7110_av(struct av7110 *av7110)
132{
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700133 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700134 struct saa7146_dev *dev = av7110->dev;
135
136 /* set internal volume control to maximum */
137 av7110->adac_type = DVB_ADAC_TI;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700138 ret = av7110_set_volume(av7110, av7110->mixer.volume_left, av7110->mixer.volume_right);
Johannes Stezenbach7a2fa902005-07-07 17:58:01 -0700139 if (ret < 0)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700140 printk("dvb-ttpci:cannot set internal volume to maximum:%d\n",ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700141
Oliver Endrissdefd574e2007-07-12 23:08:07 -0300142 ret = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetMonitorType,
143 1, (u16) av7110->display_ar);
144 if (ret < 0)
145 printk("dvb-ttpci: unable to set aspect ratio\n");
146 ret = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetPanScanType,
147 1, av7110->display_panscan);
148 if (ret < 0)
149 printk("dvb-ttpci: unable to set pan scan\n");
150
Oliver Endriss4caba422006-03-17 05:29:15 -0300151 ret = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetWSSConfig, 2, 2, wss_cfg_4_3);
152 if (ret < 0)
153 printk("dvb-ttpci: unable to configure 4:3 wss\n");
154 ret = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetWSSConfig, 2, 3, wss_cfg_16_9);
155 if (ret < 0)
156 printk("dvb-ttpci: unable to configure 16:9 wss\n");
157
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700158 ret = av7710_set_video_mode(av7110, vidmode);
Johannes Stezenbach7a2fa902005-07-07 17:58:01 -0700159 if (ret < 0)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700160 printk("dvb-ttpci:cannot set video mode:%d\n",ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700161
162 /* handle different card types */
163 /* remaining inits according to card and frontend type */
164 av7110->analog_tuner_flags = 0;
165 av7110->current_input = 0;
Tim Kaiser61391e02006-06-25 09:14:07 -0300166 if (dev->pci->subsystem_vendor == 0x13c2 && dev->pci->subsystem_device == 0x000a)
Marco Schluessler1c13b952006-01-09 15:25:06 -0200167 av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, ADSwitch, 1, 0); // SPDIF on
Tim Kaiser61391e02006-06-25 09:14:07 -0300168 if (i2c_writereg(av7110, 0x20, 0x00, 0x00) == 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700169 printk ("dvb-ttpci: Crystal audio DAC @ card %d detected\n",
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -0700170 av7110->dvb_adapter.num);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700171 av7110->adac_type = DVB_ADAC_CRYSTAL;
172 i2c_writereg(av7110, 0x20, 0x01, 0xd2);
173 i2c_writereg(av7110, 0x20, 0x02, 0x49);
174 i2c_writereg(av7110, 0x20, 0x03, 0x00);
175 i2c_writereg(av7110, 0x20, 0x04, 0x00);
176
177 /**
178 * some special handling for the Siemens DVB-C cards...
179 */
180 } else if (0 == av7110_init_analog_module(av7110)) {
181 /* done. */
182 }
183 else if (dev->pci->subsystem_vendor == 0x110a) {
184 printk("dvb-ttpci: DVB-C w/o analog module @ card %d detected\n",
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -0700185 av7110->dvb_adapter.num);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700186 av7110->adac_type = DVB_ADAC_NONE;
187 }
188 else {
189 av7110->adac_type = adac;
190 printk("dvb-ttpci: adac type set to %d @ card %d\n",
Marco Schluessler1c13b952006-01-09 15:25:06 -0200191 av7110->adac_type, av7110->dvb_adapter.num);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700192 }
193
Marco Schluessler1c13b952006-01-09 15:25:06 -0200194 if (av7110->adac_type == DVB_ADAC_NONE || av7110->adac_type == DVB_ADAC_MSP34x0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700195 // switch DVB SCART on
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700196 ret = av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, MainSwitch, 1, 0);
Johannes Stezenbach7a2fa902005-07-07 17:58:01 -0700197 if (ret < 0)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700198 printk("dvb-ttpci:cannot switch on SCART(Main):%d\n",ret);
199 ret = av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, ADSwitch, 1, 1);
Johannes Stezenbach7a2fa902005-07-07 17:58:01 -0700200 if (ret < 0)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700201 printk("dvb-ttpci:cannot switch on SCART(AD):%d\n",ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700202 if (rgb_on &&
Karl Herz6af4ee12005-09-09 13:03:13 -0700203 ((av7110->dev->pci->subsystem_vendor == 0x110a) ||
204 (av7110->dev->pci->subsystem_vendor == 0x13c2)) &&
205 (av7110->dev->pci->subsystem_device == 0x0000)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700206 saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); // RGB on, SCART pin 16
207 //saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); // SCARTpin 8
208 }
209 }
210
Oliver Endriss60edb132005-12-19 08:54:11 -0200211 if (dev->pci->subsystem_vendor == 0x13c2 && dev->pci->subsystem_device == 0x000e)
212 av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, SpdifSwitch, 1, 0); // SPDIF on
213
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700214 ret = av7110_set_volume(av7110, av7110->mixer.volume_left, av7110->mixer.volume_right);
Johannes Stezenbach7a2fa902005-07-07 17:58:01 -0700215 if (ret < 0)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700216 printk("dvb-ttpci:cannot set volume :%d\n",ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700217}
218
219static void recover_arm(struct av7110 *av7110)
220{
221 dprintk(4, "%p\n",av7110);
222
223 av7110_bootarm(av7110);
224 msleep(100);
Oliver Endriss66190a22006-01-09 15:32:42 -0200225
226 init_av7110_av(av7110);
227
228 /* card-specific recovery */
229 if (av7110->recover)
230 av7110->recover(av7110);
231
Linus Torvalds1da177e2005-04-16 15:20:36 -0700232 restart_feeds(av7110);
Oliver Endrissee820a62007-04-27 12:31:21 -0300233
234#if defined(CONFIG_INPUT_EVDEV) || defined(CONFIG_INPUT_EVDEV_MODULE)
235 av7110_check_ir_config(av7110, true);
236#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700237}
238
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239static void av7110_arm_sync(struct av7110 *av7110)
240{
Herbert Poetzl8eec1422007-02-08 14:32:43 -0300241 if (av7110->arm_thread)
242 kthread_stop(av7110->arm_thread);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700243
Herbert Poetzl8eec1422007-02-08 14:32:43 -0300244 av7110->arm_thread = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700245}
246
247static int arm_thread(void *data)
248{
249 struct av7110 *av7110 = data;
250 u16 newloops = 0;
251 int timeout;
252
253 dprintk(4, "%p\n",av7110);
254
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255 for (;;) {
256 timeout = wait_event_interruptible_timeout(av7110->arm_wait,
Herbert Poetzl8eec1422007-02-08 14:32:43 -0300257 kthread_should_stop(), 5 * HZ);
258
259 if (-ERESTARTSYS == timeout || kthread_should_stop()) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700260 /* got signal or told to quit*/
261 break;
262 }
263
264 if (!av7110->arm_ready)
265 continue;
266
Oliver Endrissee820a62007-04-27 12:31:21 -0300267#if defined(CONFIG_INPUT_EVDEV) || defined(CONFIG_INPUT_EVDEV_MODULE)
268 av7110_check_ir_config(av7110, false);
269#endif
270
Ingo Molnar3593cab2006-02-07 06:49:14 -0200271 if (mutex_lock_interruptible(&av7110->dcomlock))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700272 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273 newloops = rdebi(av7110, DEBINOSWAP, STATUS_LOOPS, 0, 2);
Ingo Molnar3593cab2006-02-07 06:49:14 -0200274 mutex_unlock(&av7110->dcomlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275
Oliver Endriss66190a22006-01-09 15:32:42 -0200276 if (newloops == av7110->arm_loops || av7110->arm_errors > 3) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700277 printk(KERN_ERR "dvb-ttpci: ARM crashed @ card %d\n",
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -0700278 av7110->dvb_adapter.num);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279
Oliver Endriss66190a22006-01-09 15:32:42 -0200280 recover_arm(av7110);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700281
Ingo Molnar3593cab2006-02-07 06:49:14 -0200282 if (mutex_lock_interruptible(&av7110->dcomlock))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284 newloops = rdebi(av7110, DEBINOSWAP, STATUS_LOOPS, 0, 2) - 1;
Ingo Molnar3593cab2006-02-07 06:49:14 -0200285 mutex_unlock(&av7110->dcomlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286 }
287 av7110->arm_loops = newloops;
Oliver Endriss66190a22006-01-09 15:32:42 -0200288 av7110->arm_errors = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700289 }
290
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291 return 0;
292}
293
294
Linus Torvalds1da177e2005-04-16 15:20:36 -0700295/****************************************************************************
296 * IRQ handling
297 ****************************************************************************/
298
299static int DvbDmxFilterCallback(u8 *buffer1, size_t buffer1_len,
300 u8 *buffer2, size_t buffer2_len,
301 struct dvb_demux_filter *dvbdmxfilter,
302 enum dmx_success success,
303 struct av7110 *av7110)
304{
305 if (!dvbdmxfilter->feed->demux->dmx.frontend)
306 return 0;
307 if (dvbdmxfilter->feed->demux->dmx.frontend->source == DMX_MEMORY_FE)
308 return 0;
309
310 switch (dvbdmxfilter->type) {
311 case DMX_TYPE_SEC:
312 if ((((buffer1[1] << 8) | buffer1[2]) & 0xfff) + 3 != buffer1_len)
313 return 0;
314 if (dvbdmxfilter->doneq) {
315 struct dmx_section_filter *filter = &dvbdmxfilter->filter;
316 int i;
317 u8 xor, neq = 0;
318
319 for (i = 0; i < DVB_DEMUX_MASK_MAX; i++) {
320 xor = filter->filter_value[i] ^ buffer1[i];
321 neq |= dvbdmxfilter->maskandnotmode[i] & xor;
322 }
323 if (!neq)
324 return 0;
325 }
326 return dvbdmxfilter->feed->cb.sec(buffer1, buffer1_len,
327 buffer2, buffer2_len,
328 &dvbdmxfilter->filter,
329 DMX_OK);
330 case DMX_TYPE_TS:
331 if (!(dvbdmxfilter->feed->ts_type & TS_PACKET))
332 return 0;
333 if (dvbdmxfilter->feed->ts_type & TS_PAYLOAD_ONLY)
334 return dvbdmxfilter->feed->cb.ts(buffer1, buffer1_len,
335 buffer2, buffer2_len,
336 &dvbdmxfilter->feed->feed.ts,
337 DMX_OK);
338 else
339 av7110_p2t_write(buffer1, buffer1_len,
340 dvbdmxfilter->feed->pid,
341 &av7110->p2t_filter[dvbdmxfilter->index]);
342 default:
343 return 0;
344 }
345}
346
347
348//#define DEBUG_TIMING
349static inline void print_time(char *s)
350{
351#ifdef DEBUG_TIMING
352 struct timeval tv;
353 do_gettimeofday(&tv);
354 printk("%s: %d.%d\n", s, (int)tv.tv_sec, (int)tv.tv_usec);
355#endif
356}
357
358#define DEBI_READ 0
359#define DEBI_WRITE 1
360static inline void start_debi_dma(struct av7110 *av7110, int dir,
361 unsigned long addr, unsigned int len)
362{
363 dprintk(8, "%c %08lx %u\n", dir == DEBI_READ ? 'R' : 'W', addr, len);
364 if (saa7146_wait_for_debi_done(av7110->dev, 0)) {
Harvey Harrison3ca7fc82008-04-08 23:20:00 -0300365 printk(KERN_ERR "%s: saa7146_wait_for_debi_done timed out\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366 return;
367 }
368
369 SAA7146_ISR_CLEAR(av7110->dev, MASK_19); /* for good measure */
370 SAA7146_IER_ENABLE(av7110->dev, MASK_19);
371 if (len < 5)
372 len = 5; /* we want a real DEBI DMA */
373 if (dir == DEBI_WRITE)
374 iwdebi(av7110, DEBISWAB, addr, 0, (len + 3) & ~3);
375 else
376 irdebi(av7110, DEBISWAB, addr, 0, len);
377}
378
379static void debiirq(unsigned long data)
380{
381 struct av7110 *av7110 = (struct av7110 *) data;
382 int type = av7110->debitype;
383 int handle = (type >> 8) & 0x1f;
384 unsigned int xfer = 0;
385
386 print_time("debi");
387 dprintk(4, "type 0x%04x\n", type);
388
389 if (type == -1) {
390 printk("DEBI irq oops @ %ld, psr:0x%08x, ssr:0x%08x\n",
391 jiffies, saa7146_read(av7110->dev, PSR),
392 saa7146_read(av7110->dev, SSR));
393 goto debi_done;
394 }
395 av7110->debitype = -1;
396
397 switch (type & 0xff) {
398
399 case DATA_TS_RECORD:
400 dvb_dmx_swfilter_packets(&av7110->demux,
401 (const u8 *) av7110->debi_virt,
402 av7110->debilen / 188);
403 xfer = RX_BUFF;
404 break;
405
406 case DATA_PES_RECORD:
407 if (av7110->demux.recording)
408 av7110_record_cb(&av7110->p2t[handle],
409 (u8 *) av7110->debi_virt,
410 av7110->debilen);
411 xfer = RX_BUFF;
412 break;
413
414 case DATA_IPMPE:
415 case DATA_FSECTION:
416 case DATA_PIPING:
417 if (av7110->handle2filter[handle])
418 DvbDmxFilterCallback((u8 *)av7110->debi_virt,
419 av7110->debilen, NULL, 0,
420 av7110->handle2filter[handle],
421 DMX_OK, av7110);
422 xfer = RX_BUFF;
423 break;
424
425 case DATA_CI_GET:
426 {
427 u8 *data = av7110->debi_virt;
428
429 if ((data[0] < 2) && data[2] == 0xff) {
430 int flags = 0;
431 if (data[5] > 0)
432 flags |= CA_CI_MODULE_PRESENT;
433 if (data[5] > 5)
434 flags |= CA_CI_MODULE_READY;
435 av7110->ci_slot[data[0]].flags = flags;
436 } else
437 ci_get_data(&av7110->ci_rbuffer,
438 av7110->debi_virt,
439 av7110->debilen);
440 xfer = RX_BUFF;
441 break;
442 }
443
444 case DATA_COMMON_INTERFACE:
445 CI_handle(av7110, (u8 *)av7110->debi_virt, av7110->debilen);
446#if 0
447 {
448 int i;
449
450 printk("av7110%d: ", av7110->num);
451 printk("%02x ", *(u8 *)av7110->debi_virt);
452 printk("%02x ", *(1+(u8 *)av7110->debi_virt));
453 for (i = 2; i < av7110->debilen; i++)
454 printk("%02x ", (*(i+(unsigned char *)av7110->debi_virt)));
455 for (i = 2; i < av7110->debilen; i++)
456 printk("%c", chtrans(*(i+(unsigned char *)av7110->debi_virt)));
457
458 printk("\n");
459 }
460#endif
461 xfer = RX_BUFF;
462 break;
463
464 case DATA_DEBUG_MESSAGE:
465 ((s8*)av7110->debi_virt)[Reserved_SIZE - 1] = 0;
466 printk("%s\n", (s8 *) av7110->debi_virt);
467 xfer = RX_BUFF;
468 break;
469
470 case DATA_CI_PUT:
471 dprintk(4, "debi DATA_CI_PUT\n");
472 case DATA_MPEG_PLAY:
473 dprintk(4, "debi DATA_MPEG_PLAY\n");
474 case DATA_BMP_LOAD:
475 dprintk(4, "debi DATA_BMP_LOAD\n");
476 xfer = TX_BUFF;
477 break;
478 default:
479 break;
480 }
481debi_done:
482 spin_lock(&av7110->debilock);
483 if (xfer)
484 iwdebi(av7110, DEBINOSWAP, xfer, 0, 2);
485 ARM_ClearMailBox(av7110);
486 spin_unlock(&av7110->debilock);
487}
488
489/* irq from av7110 firmware writing the mailbox register in the DPRAM */
490static void gpioirq(unsigned long data)
491{
492 struct av7110 *av7110 = (struct av7110 *) data;
493 u32 rxbuf, txbuf;
494 int len;
495
496 if (av7110->debitype != -1)
497 /* we shouldn't get any irq while a debi xfer is running */
498 printk("dvb-ttpci: GPIO0 irq oops @ %ld, psr:0x%08x, ssr:0x%08x\n",
499 jiffies, saa7146_read(av7110->dev, PSR),
500 saa7146_read(av7110->dev, SSR));
501
502 if (saa7146_wait_for_debi_done(av7110->dev, 0)) {
Harvey Harrison3ca7fc82008-04-08 23:20:00 -0300503 printk(KERN_ERR "%s: saa7146_wait_for_debi_done timed out\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700504 BUG(); /* maybe we should try resetting the debi? */
505 }
506
507 spin_lock(&av7110->debilock);
508 ARM_ClearIrq(av7110);
509
510 /* see what the av7110 wants */
511 av7110->debitype = irdebi(av7110, DEBINOSWAP, IRQ_STATE, 0, 2);
512 av7110->debilen = irdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
513 rxbuf = irdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
514 txbuf = irdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
515 len = (av7110->debilen + 3) & ~3;
516
517 print_time("gpio");
518 dprintk(8, "GPIO0 irq 0x%04x %d\n", av7110->debitype, av7110->debilen);
519
520 switch (av7110->debitype & 0xff) {
521
522 case DATA_TS_PLAY:
523 case DATA_PES_PLAY:
524 break;
525
526 case DATA_MPEG_VIDEO_EVENT:
527 {
528 u32 h_ar;
529 struct video_event event;
530
531 av7110->video_size.w = irdebi(av7110, DEBINOSWAP, STATUS_MPEG_WIDTH, 0, 2);
532 h_ar = irdebi(av7110, DEBINOSWAP, STATUS_MPEG_HEIGHT_AR, 0, 2);
533
534 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
535 iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
536
537 av7110->video_size.h = h_ar & 0xfff;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538
539 event.type = VIDEO_EVENT_SIZE_CHANGED;
540 event.u.size.w = av7110->video_size.w;
541 event.u.size.h = av7110->video_size.h;
542 switch ((h_ar >> 12) & 0xf)
543 {
544 case 3:
545 av7110->video_size.aspect_ratio = VIDEO_FORMAT_16_9;
546 event.u.size.aspect_ratio = VIDEO_FORMAT_16_9;
547 av7110->videostate.video_format = VIDEO_FORMAT_16_9;
548 break;
549 case 4:
550 av7110->video_size.aspect_ratio = VIDEO_FORMAT_221_1;
551 event.u.size.aspect_ratio = VIDEO_FORMAT_221_1;
552 av7110->videostate.video_format = VIDEO_FORMAT_221_1;
553 break;
554 default:
555 av7110->video_size.aspect_ratio = VIDEO_FORMAT_4_3;
556 event.u.size.aspect_ratio = VIDEO_FORMAT_4_3;
557 av7110->videostate.video_format = VIDEO_FORMAT_4_3;
558 }
Oliver Endriss66190a22006-01-09 15:32:42 -0200559
560 dprintk(8, "GPIO0 irq: DATA_MPEG_VIDEO_EVENT: w/h/ar = %u/%u/%u\n",
561 av7110->video_size.w, av7110->video_size.h,
562 av7110->video_size.aspect_ratio);
563
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564 dvb_video_add_event(av7110, &event);
565 break;
566 }
567
568 case DATA_CI_PUT:
569 {
570 int avail;
571 struct dvb_ringbuffer *cibuf = &av7110->ci_wbuffer;
572
573 avail = dvb_ringbuffer_avail(cibuf);
574 if (avail <= 2) {
575 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
576 iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
577 iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
578 break;
579 }
580 len = DVB_RINGBUFFER_PEEK(cibuf, 0) << 8;
581 len |= DVB_RINGBUFFER_PEEK(cibuf, 1);
582 if (avail < len + 2) {
583 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
584 iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
585 iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
586 break;
587 }
588 DVB_RINGBUFFER_SKIP(cibuf, 2);
589
590 dvb_ringbuffer_read(cibuf, av7110->debi_virt, len, 0);
591
592 iwdebi(av7110, DEBINOSWAP, TX_LEN, len, 2);
593 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, len, 2);
594 dprintk(8, "DMA: CI\n");
595 start_debi_dma(av7110, DEBI_WRITE, DPRAM_BASE + txbuf, len);
596 spin_unlock(&av7110->debilock);
597 wake_up(&cibuf->queue);
598 return;
599 }
600
601 case DATA_MPEG_PLAY:
602 if (!av7110->playing) {
603 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
604 iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
605 iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
606 break;
607 }
608 len = 0;
609 if (av7110->debitype & 0x100) {
610 spin_lock(&av7110->aout.lock);
611 len = av7110_pes_play(av7110->debi_virt, &av7110->aout, 2048);
612 spin_unlock(&av7110->aout.lock);
613 }
614 if (len <= 0 && (av7110->debitype & 0x200)
615 &&av7110->videostate.play_state != VIDEO_FREEZED) {
616 spin_lock(&av7110->avout.lock);
617 len = av7110_pes_play(av7110->debi_virt, &av7110->avout, 2048);
618 spin_unlock(&av7110->avout.lock);
619 }
620 if (len <= 0) {
621 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
622 iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
623 iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
624 break;
625 }
626 dprintk(8, "GPIO0 PES_PLAY len=%04x\n", len);
627 iwdebi(av7110, DEBINOSWAP, TX_LEN, len, 2);
628 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, len, 2);
629 dprintk(8, "DMA: MPEG_PLAY\n");
630 start_debi_dma(av7110, DEBI_WRITE, DPRAM_BASE + txbuf, len);
631 spin_unlock(&av7110->debilock);
632 return;
633
634 case DATA_BMP_LOAD:
635 len = av7110->debilen;
636 dprintk(8, "gpio DATA_BMP_LOAD len %d\n", len);
637 if (!len) {
638 av7110->bmp_state = BMP_LOADED;
639 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
640 iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
641 iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
642 wake_up(&av7110->bmpq);
643 dprintk(8, "gpio DATA_BMP_LOAD done\n");
644 break;
645 }
646 if (len > av7110->bmplen)
647 len = av7110->bmplen;
648 if (len > 2 * 1024)
649 len = 2 * 1024;
650 iwdebi(av7110, DEBINOSWAP, TX_LEN, len, 2);
651 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, len, 2);
652 memcpy(av7110->debi_virt, av7110->bmpbuf+av7110->bmpp, len);
653 av7110->bmpp += len;
654 av7110->bmplen -= len;
655 dprintk(8, "gpio DATA_BMP_LOAD DMA len %d\n", len);
656 start_debi_dma(av7110, DEBI_WRITE, DPRAM_BASE+txbuf, len);
657 spin_unlock(&av7110->debilock);
658 return;
659
660 case DATA_CI_GET:
661 case DATA_COMMON_INTERFACE:
662 case DATA_FSECTION:
663 case DATA_IPMPE:
664 case DATA_PIPING:
665 if (!len || len > 4 * 1024) {
666 iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
667 break;
668 }
669 /* fall through */
670
671 case DATA_TS_RECORD:
672 case DATA_PES_RECORD:
673 dprintk(8, "DMA: TS_REC etc.\n");
674 start_debi_dma(av7110, DEBI_READ, DPRAM_BASE+rxbuf, len);
675 spin_unlock(&av7110->debilock);
676 return;
677
678 case DATA_DEBUG_MESSAGE:
679 if (!len || len > 0xff) {
680 iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
681 break;
682 }
683 start_debi_dma(av7110, DEBI_READ, Reserved, len);
684 spin_unlock(&av7110->debilock);
685 return;
686
687 case DATA_IRCOMMAND:
Oliver Endrissee820a62007-04-27 12:31:21 -0300688 if (av7110->ir.ir_handler)
689 av7110->ir.ir_handler(av7110,
Oliver Endriss03388ae2005-09-09 13:03:12 -0700690 swahw32(irdebi(av7110, DEBINOSWAP, Reserved, 0, 4)));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700691 iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
692 break;
693
694 default:
695 printk("dvb-ttpci: gpioirq unknown type=%d len=%d\n",
696 av7110->debitype, av7110->debilen);
697 break;
698 }
699 av7110->debitype = -1;
700 ARM_ClearMailBox(av7110);
701 spin_unlock(&av7110->debilock);
702}
703
704
705#ifdef CONFIG_DVB_AV7110_OSD
706static int dvb_osd_ioctl(struct inode *inode, struct file *file,
707 unsigned int cmd, void *parg)
708{
Tobias Klauserd9bdf772006-12-26 07:33:48 -0300709 struct dvb_device *dvbdev = file->private_data;
710 struct av7110 *av7110 = dvbdev->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711
712 dprintk(4, "%p\n", av7110);
713
714 if (cmd == OSD_SEND_CMD)
715 return av7110_osd_cmd(av7110, (osd_cmd_t *) parg);
716 if (cmd == OSD_GET_CAPABILITY)
717 return av7110_osd_capability(av7110, (osd_cap_t *) parg);
718
719 return -EINVAL;
720}
721
722
723static struct file_operations dvb_osd_fops = {
724 .owner = THIS_MODULE,
725 .ioctl = dvb_generic_ioctl,
726 .open = dvb_generic_open,
727 .release = dvb_generic_release,
728};
729
730static struct dvb_device dvbdev_osd = {
731 .priv = NULL,
732 .users = 1,
733 .writers = 1,
734 .fops = &dvb_osd_fops,
735 .kernel_ioctl = dvb_osd_ioctl,
736};
737#endif /* CONFIG_DVB_AV7110_OSD */
738
739
740static inline int SetPIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid,
741 u16 subpid, u16 pcrpid)
742{
Dr. Werner Fink47f36922006-01-09 15:25:07 -0200743 u16 aflags = 0;
744
Linus Torvalds1da177e2005-04-16 15:20:36 -0700745 dprintk(4, "%p\n", av7110);
746
747 if (vpid == 0x1fff || apid == 0x1fff ||
748 ttpid == 0x1fff || subpid == 0x1fff || pcrpid == 0x1fff) {
749 vpid = apid = ttpid = subpid = pcrpid = 0;
750 av7110->pids[DMX_PES_VIDEO] = 0;
751 av7110->pids[DMX_PES_AUDIO] = 0;
752 av7110->pids[DMX_PES_TELETEXT] = 0;
753 av7110->pids[DMX_PES_PCR] = 0;
754 }
755
Dr. Werner Fink47f36922006-01-09 15:25:07 -0200756 if (av7110->audiostate.bypass_mode)
757 aflags |= 0x8000;
758
759 return av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, MultiPID, 6,
760 pcrpid, vpid, apid, ttpid, subpid, aflags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761}
762
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700763int ChangePIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700764 u16 subpid, u16 pcrpid)
765{
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700766 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700767 dprintk(4, "%p\n", av7110);
768
Ingo Molnar3593cab2006-02-07 06:49:14 -0200769 if (mutex_lock_interruptible(&av7110->pid_mutex))
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700770 return -ERESTARTSYS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700771
772 if (!(vpid & 0x8000))
773 av7110->pids[DMX_PES_VIDEO] = vpid;
774 if (!(apid & 0x8000))
775 av7110->pids[DMX_PES_AUDIO] = apid;
776 if (!(ttpid & 0x8000))
777 av7110->pids[DMX_PES_TELETEXT] = ttpid;
778 if (!(pcrpid & 0x8000))
779 av7110->pids[DMX_PES_PCR] = pcrpid;
780
781 av7110->pids[DMX_PES_SUBTITLE] = 0;
782
783 if (av7110->fe_synced) {
784 pcrpid = av7110->pids[DMX_PES_PCR];
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700785 ret = SetPIDs(av7110, vpid, apid, ttpid, subpid, pcrpid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700786 }
787
Ingo Molnar3593cab2006-02-07 06:49:14 -0200788 mutex_unlock(&av7110->pid_mutex);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700789 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790}
791
792
793/******************************************************************************
794 * hardware filter functions
795 ******************************************************************************/
796
797static int StartHWFilter(struct dvb_demux_filter *dvbdmxfilter)
798{
799 struct dvb_demux_feed *dvbdmxfeed = dvbdmxfilter->feed;
Tobias Klauserd9bdf772006-12-26 07:33:48 -0300800 struct av7110 *av7110 = dvbdmxfeed->demux->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700801 u16 buf[20];
802 int ret, i;
803 u16 handle;
804// u16 mode = 0x0320;
805 u16 mode = 0xb96a;
806
807 dprintk(4, "%p\n", av7110);
808
809 if (dvbdmxfilter->type == DMX_TYPE_SEC) {
810 if (hw_sections) {
811 buf[4] = (dvbdmxfilter->filter.filter_value[0] << 8) |
812 dvbdmxfilter->maskandmode[0];
813 for (i = 3; i < 18; i++)
814 buf[i + 4 - 2] =
815 (dvbdmxfilter->filter.filter_value[i] << 8) |
816 dvbdmxfilter->maskandmode[i];
817 mode = 4;
818 }
819 } else if ((dvbdmxfeed->ts_type & TS_PACKET) &&
820 !(dvbdmxfeed->ts_type & TS_PAYLOAD_ONLY)) {
821 av7110_p2t_init(&av7110->p2t_filter[dvbdmxfilter->index], dvbdmxfeed);
822 }
823
824 buf[0] = (COMTYPE_PID_FILTER << 8) + AddPIDFilter;
825 buf[1] = 16;
826 buf[2] = dvbdmxfeed->pid;
827 buf[3] = mode;
828
829 ret = av7110_fw_request(av7110, buf, 20, &handle, 1);
830 if (ret != 0 || handle >= 32) {
831 printk("dvb-ttpci: %s error buf %04x %04x %04x %04x "
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700832 "ret %d handle %04x\n",
Harvey Harrison3ca7fc82008-04-08 23:20:00 -0300833 __func__, buf[0], buf[1], buf[2], buf[3],
Linus Torvalds1da177e2005-04-16 15:20:36 -0700834 ret, handle);
835 dvbdmxfilter->hw_handle = 0xffff;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700836 if (!ret)
837 ret = -1;
838 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700839 }
840
841 av7110->handle2filter[handle] = dvbdmxfilter;
842 dvbdmxfilter->hw_handle = handle;
843
844 return ret;
845}
846
847static int StopHWFilter(struct dvb_demux_filter *dvbdmxfilter)
848{
Tobias Klauserd9bdf772006-12-26 07:33:48 -0300849 struct av7110 *av7110 = dvbdmxfilter->feed->demux->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700850 u16 buf[3];
851 u16 answ[2];
852 int ret;
853 u16 handle;
854
855 dprintk(4, "%p\n", av7110);
856
857 handle = dvbdmxfilter->hw_handle;
858 if (handle >= 32) {
859 printk("%s tried to stop invalid filter %04x, filter type = %x\n",
Harvey Harrison3ca7fc82008-04-08 23:20:00 -0300860 __func__, handle, dvbdmxfilter->type);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700861 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700862 }
863
864 av7110->handle2filter[handle] = NULL;
865
866 buf[0] = (COMTYPE_PID_FILTER << 8) + DelPIDFilter;
867 buf[1] = 1;
868 buf[2] = handle;
869 ret = av7110_fw_request(av7110, buf, 3, answ, 2);
870 if (ret != 0 || answ[1] != handle) {
871 printk("dvb-ttpci: %s error cmd %04x %04x %04x ret %x "
872 "resp %04x %04x pid %d\n",
Harvey Harrison3ca7fc82008-04-08 23:20:00 -0300873 __func__, buf[0], buf[1], buf[2], ret,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700874 answ[0], answ[1], dvbdmxfilter->feed->pid);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700875 if (!ret)
876 ret = -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700877 }
878 return ret;
879}
880
881
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700882static int dvb_feed_start_pid(struct dvb_demux_feed *dvbdmxfeed)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700883{
884 struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
Tobias Klauserd9bdf772006-12-26 07:33:48 -0300885 struct av7110 *av7110 = dvbdmx->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886 u16 *pid = dvbdmx->pids, npids[5];
887 int i;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700888 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700889
890 dprintk(4, "%p\n", av7110);
891
892 npids[0] = npids[1] = npids[2] = npids[3] = npids[4] = 0xffff;
893 i = dvbdmxfeed->pes_type;
894 npids[i] = (pid[i]&0x8000) ? 0 : pid[i];
895 if ((i == 2) && npids[i] && (dvbdmxfeed->ts_type & TS_PACKET)) {
896 npids[i] = 0;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700897 ret = ChangePIDs(av7110, npids[1], npids[0], npids[2], npids[3], npids[4]);
898 if (!ret)
899 ret = StartHWFilter(dvbdmxfeed->filter);
900 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700902 if (dvbdmxfeed->pes_type <= 2 || dvbdmxfeed->pes_type == 4) {
903 ret = ChangePIDs(av7110, npids[1], npids[0], npids[2], npids[3], npids[4]);
904 if (ret)
905 return ret;
906 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700907
908 if (dvbdmxfeed->pes_type < 2 && npids[0])
909 if (av7110->fe_synced)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700910 {
911 ret = av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, Scan, 0);
912 if (ret)
913 return ret;
914 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700915
916 if ((dvbdmxfeed->ts_type & TS_PACKET)) {
917 if (dvbdmxfeed->pes_type == 0 && !(dvbdmx->pids[0] & 0x8000))
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700918 ret = av7110_av_start_record(av7110, RP_AUDIO, dvbdmxfeed);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919 if (dvbdmxfeed->pes_type == 1 && !(dvbdmx->pids[1] & 0x8000))
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700920 ret = av7110_av_start_record(av7110, RP_VIDEO, dvbdmxfeed);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700921 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700922 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700923}
924
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700925static int dvb_feed_stop_pid(struct dvb_demux_feed *dvbdmxfeed)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700926{
927 struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
Tobias Klauserd9bdf772006-12-26 07:33:48 -0300928 struct av7110 *av7110 = dvbdmx->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700929 u16 *pid = dvbdmx->pids, npids[5];
930 int i;
931
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700932 int ret = 0;
933
Linus Torvalds1da177e2005-04-16 15:20:36 -0700934 dprintk(4, "%p\n", av7110);
935
936 if (dvbdmxfeed->pes_type <= 1) {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700937 ret = av7110_av_stop(av7110, dvbdmxfeed->pes_type ? RP_VIDEO : RP_AUDIO);
938 if (ret)
939 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700940 if (!av7110->rec_mode)
941 dvbdmx->recording = 0;
942 if (!av7110->playing)
943 dvbdmx->playing = 0;
944 }
945 npids[0] = npids[1] = npids[2] = npids[3] = npids[4] = 0xffff;
946 i = dvbdmxfeed->pes_type;
947 switch (i) {
948 case 2: //teletext
949 if (dvbdmxfeed->ts_type & TS_PACKET)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700950 ret = StopHWFilter(dvbdmxfeed->filter);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700951 npids[2] = 0;
952 break;
953 case 0:
954 case 1:
955 case 4:
956 if (!pids_off)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700957 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700958 npids[i] = (pid[i]&0x8000) ? 0 : pid[i];
959 break;
960 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700961 if (!ret)
962 ret = ChangePIDs(av7110, npids[1], npids[0], npids[2], npids[3], npids[4]);
963 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700964}
965
966static int av7110_start_feed(struct dvb_demux_feed *feed)
967{
968 struct dvb_demux *demux = feed->demux;
969 struct av7110 *av7110 = demux->priv;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700970 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700971
972 dprintk(4, "%p\n", av7110);
973
974 if (!demux->dmx.frontend)
975 return -EINVAL;
976
977 if (feed->pid > 0x1fff)
978 return -EINVAL;
979
980 if (feed->type == DMX_TYPE_TS) {
981 if ((feed->ts_type & TS_DECODER) &&
982 (feed->pes_type < DMX_TS_PES_OTHER)) {
983 switch (demux->dmx.frontend->source) {
984 case DMX_MEMORY_FE:
985 if (feed->ts_type & TS_DECODER)
986 if (feed->pes_type < 2 &&
987 !(demux->pids[0] & 0x8000) &&
988 !(demux->pids[1] & 0x8000)) {
989 dvb_ringbuffer_flush_spinlock_wakeup(&av7110->avout);
990 dvb_ringbuffer_flush_spinlock_wakeup(&av7110->aout);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700991 ret = av7110_av_start_play(av7110,RP_AV);
992 if (!ret)
993 demux->playing = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700994 }
995 break;
996 default:
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700997 ret = dvb_feed_start_pid(feed);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700998 break;
999 }
1000 } else if ((feed->ts_type & TS_PACKET) &&
1001 (demux->dmx.frontend->source != DMX_MEMORY_FE)) {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001002 ret = StartHWFilter(feed->filter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001003 }
1004 }
1005
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001006 else if (feed->type == DMX_TYPE_SEC) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001007 int i;
1008
1009 for (i = 0; i < demux->filternum; i++) {
1010 if (demux->filter[i].state != DMX_STATE_READY)
1011 continue;
1012 if (demux->filter[i].type != DMX_TYPE_SEC)
1013 continue;
1014 if (demux->filter[i].filter.parent != &feed->feed.sec)
1015 continue;
1016 demux->filter[i].state = DMX_STATE_GO;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001017 if (demux->dmx.frontend->source != DMX_MEMORY_FE) {
1018 ret = StartHWFilter(&demux->filter[i]);
1019 if (ret)
1020 break;
1021 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022 }
1023 }
1024
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001025 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001026}
1027
1028
1029static int av7110_stop_feed(struct dvb_demux_feed *feed)
1030{
1031 struct dvb_demux *demux = feed->demux;
1032 struct av7110 *av7110 = demux->priv;
Johannes Stezenbach12ba0502005-07-07 17:58:00 -07001033 int i, rc, ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001034 dprintk(4, "%p\n", av7110);
1035
1036 if (feed->type == DMX_TYPE_TS) {
1037 if (feed->ts_type & TS_DECODER) {
1038 if (feed->pes_type >= DMX_TS_PES_OTHER ||
1039 !demux->pesfilter[feed->pes_type])
1040 return -EINVAL;
1041 demux->pids[feed->pes_type] |= 0x8000;
1042 demux->pesfilter[feed->pes_type] = NULL;
1043 }
1044 if (feed->ts_type & TS_DECODER &&
1045 feed->pes_type < DMX_TS_PES_OTHER) {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001046 ret = dvb_feed_stop_pid(feed);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001047 } else
1048 if ((feed->ts_type & TS_PACKET) &&
1049 (demux->dmx.frontend->source != DMX_MEMORY_FE))
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001050 ret = StopHWFilter(feed->filter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051 }
1052
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001053 if (!ret && feed->type == DMX_TYPE_SEC) {
Johannes Stezenbach12ba0502005-07-07 17:58:00 -07001054 for (i = 0; i<demux->filternum; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001055 if (demux->filter[i].state == DMX_STATE_GO &&
1056 demux->filter[i].filter.parent == &feed->feed.sec) {
1057 demux->filter[i].state = DMX_STATE_READY;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001058 if (demux->dmx.frontend->source != DMX_MEMORY_FE) {
Johannes Stezenbach12ba0502005-07-07 17:58:00 -07001059 rc = StopHWFilter(&demux->filter[i]);
1060 if (!ret)
1061 ret = rc;
1062 /* keep going, stop as many filters as possible */
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001063 }
Johannes Stezenbach12ba0502005-07-07 17:58:00 -07001064 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001065 }
1066 }
1067
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001068 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069}
1070
1071
1072static void restart_feeds(struct av7110 *av7110)
1073{
1074 struct dvb_demux *dvbdmx = &av7110->demux;
1075 struct dvb_demux_feed *feed;
1076 int mode;
Oliver Endriss66190a22006-01-09 15:32:42 -02001077 int i, j;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001078
1079 dprintk(4, "%p\n", av7110);
1080
1081 mode = av7110->playing;
1082 av7110->playing = 0;
1083 av7110->rec_mode = 0;
1084
Oliver Endriss66190a22006-01-09 15:32:42 -02001085 for (i = 0; i < dvbdmx->feednum; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001086 feed = &dvbdmx->feed[i];
Oliver Endriss66190a22006-01-09 15:32:42 -02001087 if (feed->state == DMX_STATE_GO) {
1088 if (feed->type == DMX_TYPE_SEC) {
1089 for (j = 0; j < dvbdmx->filternum; j++) {
1090 if (dvbdmx->filter[j].type != DMX_TYPE_SEC)
1091 continue;
1092 if (dvbdmx->filter[j].filter.parent != &feed->feed.sec)
1093 continue;
1094 if (dvbdmx->filter[j].state == DMX_STATE_GO)
1095 dvbdmx->filter[j].state = DMX_STATE_READY;
1096 }
1097 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001098 av7110_start_feed(feed);
Oliver Endriss66190a22006-01-09 15:32:42 -02001099 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001100 }
1101
1102 if (mode)
1103 av7110_av_start_play(av7110, mode);
1104}
1105
1106static int dvb_get_stc(struct dmx_demux *demux, unsigned int num,
1107 uint64_t *stc, unsigned int *base)
1108{
1109 int ret;
1110 u16 fwstc[4];
1111 u16 tag = ((COMTYPE_REQUEST << 8) + ReqSTC);
1112 struct dvb_demux *dvbdemux;
1113 struct av7110 *av7110;
1114
1115 /* pointer casting paranoia... */
Eric Sesterhennae246012006-03-13 13:17:11 -03001116 BUG_ON(!demux);
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001117 dvbdemux = demux->priv;
Eric Sesterhennae246012006-03-13 13:17:11 -03001118 BUG_ON(!dvbdemux);
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001119 av7110 = dvbdemux->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120
1121 dprintk(4, "%p\n", av7110);
1122
1123 if (num != 0)
1124 return -EINVAL;
1125
1126 ret = av7110_fw_request(av7110, &tag, 0, fwstc, 4);
1127 if (ret) {
Harvey Harrison3ca7fc82008-04-08 23:20:00 -03001128 printk(KERN_ERR "%s: av7110_fw_request error\n", __func__);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001129 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001130 }
1131 dprintk(2, "fwstc = %04hx %04hx %04hx %04hx\n",
1132 fwstc[0], fwstc[1], fwstc[2], fwstc[3]);
1133
1134 *stc = (((uint64_t) ((fwstc[3] & 0x8000) >> 15)) << 32) |
1135 (((uint64_t) fwstc[1]) << 16) | ((uint64_t) fwstc[0]);
1136 *base = 1;
1137
1138 dprintk(4, "stc = %lu\n", (unsigned long)*stc);
1139
1140 return 0;
1141}
1142
1143
1144/******************************************************************************
1145 * SEC device file operations
1146 ******************************************************************************/
1147
1148
1149static int av7110_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
1150{
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001151 struct av7110* av7110 = fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001152
1153 switch (tone) {
1154 case SEC_TONE_ON:
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001155 return Set22K(av7110, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001156
1157 case SEC_TONE_OFF:
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001158 return Set22K(av7110, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001159
1160 default:
1161 return -EINVAL;
1162 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001163}
1164
1165static int av7110_diseqc_send_master_cmd(struct dvb_frontend* fe,
1166 struct dvb_diseqc_master_cmd* cmd)
1167{
1168 struct av7110* av7110 = fe->dvb->priv;
1169
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001170 return av7110_diseqc_send(av7110, cmd->msg_len, cmd->msg, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001171}
1172
1173static int av7110_diseqc_send_burst(struct dvb_frontend* fe,
1174 fe_sec_mini_cmd_t minicmd)
1175{
1176 struct av7110* av7110 = fe->dvb->priv;
1177
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001178 return av7110_diseqc_send(av7110, 0, NULL, minicmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001179}
1180
1181/* simplified code from budget-core.c */
1182static int stop_ts_capture(struct av7110 *budget)
1183{
1184 dprintk(2, "budget: %p\n", budget);
1185
1186 if (--budget->feeding1)
1187 return budget->feeding1;
1188 saa7146_write(budget->dev, MC1, MASK_20); /* DMA3 off */
1189 SAA7146_IER_DISABLE(budget->dev, MASK_10);
1190 SAA7146_ISR_CLEAR(budget->dev, MASK_10);
1191 return 0;
1192}
1193
1194static int start_ts_capture(struct av7110 *budget)
1195{
1196 dprintk(2, "budget: %p\n", budget);
1197
1198 if (budget->feeding1)
1199 return ++budget->feeding1;
1200 memset(budget->grabbing, 0x00, TS_HEIGHT * TS_WIDTH);
1201 budget->tsf = 0xff;
1202 budget->ttbp = 0;
1203 SAA7146_IER_ENABLE(budget->dev, MASK_10); /* VPE */
1204 saa7146_write(budget->dev, MC1, (MASK_04 | MASK_20)); /* DMA3 on */
1205 return ++budget->feeding1;
1206}
1207
1208static int budget_start_feed(struct dvb_demux_feed *feed)
1209{
1210 struct dvb_demux *demux = feed->demux;
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001211 struct av7110 *budget = demux->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001212 int status;
1213
1214 dprintk(2, "av7110: %p\n", budget);
1215
1216 spin_lock(&budget->feedlock1);
1217 feed->pusi_seen = 0; /* have a clean section start */
1218 status = start_ts_capture(budget);
1219 spin_unlock(&budget->feedlock1);
1220 return status;
1221}
1222
1223static int budget_stop_feed(struct dvb_demux_feed *feed)
1224{
1225 struct dvb_demux *demux = feed->demux;
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001226 struct av7110 *budget = demux->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001227 int status;
1228
1229 dprintk(2, "budget: %p\n", budget);
1230
1231 spin_lock(&budget->feedlock1);
1232 status = stop_ts_capture(budget);
1233 spin_unlock(&budget->feedlock1);
1234 return status;
1235}
1236
1237static void vpeirq(unsigned long data)
1238{
1239 struct av7110 *budget = (struct av7110 *) data;
1240 u8 *mem = (u8 *) (budget->grabbing);
1241 u32 olddma = budget->ttbp;
1242 u32 newdma = saa7146_read(budget->dev, PCI_VDP3);
1243
1244 if (!budgetpatch) {
1245 printk("av7110.c: vpeirq() called while budgetpatch disabled!"
1246 " check saa7146 IER register\n");
1247 BUG();
1248 }
1249 /* nearest lower position divisible by 188 */
1250 newdma -= newdma % 188;
1251
1252 if (newdma >= TS_BUFLEN)
1253 return;
1254
1255 budget->ttbp = newdma;
1256
1257 if (!budget->feeding1 || (newdma == olddma))
1258 return;
1259
Jon Burgess87c30192007-05-03 12:23:44 -03001260 /* Ensure streamed PCI data is synced to CPU */
1261 pci_dma_sync_sg_for_cpu(budget->dev->pci, budget->pt.slist, budget->pt.nents, PCI_DMA_FROMDEVICE);
1262
Linus Torvalds1da177e2005-04-16 15:20:36 -07001263#if 0
1264 /* track rps1 activity */
1265 printk("vpeirq: %02x Event Counter 1 0x%04x\n",
1266 mem[olddma],
1267 saa7146_read(budget->dev, EC1R) & 0x3fff);
1268#endif
1269
1270 if (newdma > olddma)
1271 /* no wraparound, dump olddma..newdma */
1272 dvb_dmx_swfilter_packets(&budget->demux1, mem + olddma, (newdma - olddma) / 188);
1273 else {
1274 /* wraparound, dump olddma..buflen and 0..newdma */
1275 dvb_dmx_swfilter_packets(&budget->demux1, mem + olddma, (TS_BUFLEN - olddma) / 188);
1276 dvb_dmx_swfilter_packets(&budget->demux1, mem, newdma / 188);
1277 }
1278}
1279
1280static int av7110_register(struct av7110 *av7110)
1281{
1282 int ret, i;
1283 struct dvb_demux *dvbdemux = &av7110->demux;
1284 struct dvb_demux *dvbdemux1 = &av7110->demux1;
1285
1286 dprintk(4, "%p\n", av7110);
1287
1288 if (av7110->registered)
1289 return -1;
1290
1291 av7110->registered = 1;
1292
1293 dvbdemux->priv = (void *) av7110;
1294
1295 for (i = 0; i < 32; i++)
1296 av7110->handle2filter[i] = NULL;
1297
1298 dvbdemux->filternum = 32;
1299 dvbdemux->feednum = 32;
1300 dvbdemux->start_feed = av7110_start_feed;
1301 dvbdemux->stop_feed = av7110_stop_feed;
1302 dvbdemux->write_to_decoder = av7110_write_to_decoder;
1303 dvbdemux->dmx.capabilities = (DMX_TS_FILTERING | DMX_SECTION_FILTERING |
1304 DMX_MEMORY_BASED_FILTERING);
1305
1306 dvb_dmx_init(&av7110->demux);
1307 av7110->demux.dmx.get_stc = dvb_get_stc;
1308
1309 av7110->dmxdev.filternum = 32;
1310 av7110->dmxdev.demux = &dvbdemux->dmx;
1311 av7110->dmxdev.capabilities = 0;
1312
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001313 dvb_dmxdev_init(&av7110->dmxdev, &av7110->dvb_adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001314
1315 av7110->hw_frontend.source = DMX_FRONTEND_0;
1316
1317 ret = dvbdemux->dmx.add_frontend(&dvbdemux->dmx, &av7110->hw_frontend);
1318
1319 if (ret < 0)
1320 return ret;
1321
1322 av7110->mem_frontend.source = DMX_MEMORY_FE;
1323
1324 ret = dvbdemux->dmx.add_frontend(&dvbdemux->dmx, &av7110->mem_frontend);
1325
1326 if (ret < 0)
1327 return ret;
1328
1329 ret = dvbdemux->dmx.connect_frontend(&dvbdemux->dmx,
1330 &av7110->hw_frontend);
1331 if (ret < 0)
1332 return ret;
1333
1334 av7110_av_register(av7110);
1335 av7110_ca_register(av7110);
1336
1337#ifdef CONFIG_DVB_AV7110_OSD
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001338 dvb_register_device(&av7110->dvb_adapter, &av7110->osd_dev,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001339 &dvbdev_osd, av7110, DVB_DEVICE_OSD);
1340#endif
1341
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001342 dvb_net_init(&av7110->dvb_adapter, &av7110->dvb_net, &dvbdemux->dmx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001343
1344 if (budgetpatch) {
1345 /* initialize software demux1 without its own frontend
1346 * demux1 hardware is connected to frontend0 of demux0
1347 */
1348 dvbdemux1->priv = (void *) av7110;
1349
1350 dvbdemux1->filternum = 256;
1351 dvbdemux1->feednum = 256;
1352 dvbdemux1->start_feed = budget_start_feed;
1353 dvbdemux1->stop_feed = budget_stop_feed;
1354 dvbdemux1->write_to_decoder = NULL;
1355
1356 dvbdemux1->dmx.capabilities = (DMX_TS_FILTERING | DMX_SECTION_FILTERING |
1357 DMX_MEMORY_BASED_FILTERING);
1358
1359 dvb_dmx_init(&av7110->demux1);
1360
1361 av7110->dmxdev1.filternum = 256;
1362 av7110->dmxdev1.demux = &dvbdemux1->dmx;
1363 av7110->dmxdev1.capabilities = 0;
1364
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001365 dvb_dmxdev_init(&av7110->dmxdev1, &av7110->dvb_adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001366
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001367 dvb_net_init(&av7110->dvb_adapter, &av7110->dvb_net1, &dvbdemux1->dmx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001368 printk("dvb-ttpci: additional demux1 for budget-patch registered\n");
1369 }
1370 return 0;
1371}
1372
1373
1374static void dvb_unregister(struct av7110 *av7110)
1375{
1376 struct dvb_demux *dvbdemux = &av7110->demux;
1377 struct dvb_demux *dvbdemux1 = &av7110->demux1;
1378
1379 dprintk(4, "%p\n", av7110);
1380
1381 if (!av7110->registered)
1382 return;
1383
1384 if (budgetpatch) {
1385 dvb_net_release(&av7110->dvb_net1);
1386 dvbdemux->dmx.close(&dvbdemux1->dmx);
1387 dvb_dmxdev_release(&av7110->dmxdev1);
1388 dvb_dmx_release(&av7110->demux1);
1389 }
1390
1391 dvb_net_release(&av7110->dvb_net);
1392
1393 dvbdemux->dmx.close(&dvbdemux->dmx);
1394 dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &av7110->hw_frontend);
1395 dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &av7110->mem_frontend);
1396
1397 dvb_dmxdev_release(&av7110->dmxdev);
1398 dvb_dmx_release(&av7110->demux);
1399
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001400 if (av7110->fe != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001401 dvb_unregister_frontend(av7110->fe);
Andrew de Quinceyf52a8382006-08-08 09:10:09 -03001402 dvb_frontend_detach(av7110->fe);
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001403 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001404 dvb_unregister_device(av7110->osd_dev);
1405 av7110_av_unregister(av7110);
1406 av7110_ca_unregister(av7110);
1407}
1408
1409
1410/****************************************************************************
1411 * I2C client commands
1412 ****************************************************************************/
1413
1414int i2c_writereg(struct av7110 *av7110, u8 id, u8 reg, u8 val)
1415{
1416 u8 msg[2] = { reg, val };
1417 struct i2c_msg msgs;
1418
1419 msgs.flags = 0;
1420 msgs.addr = id / 2;
1421 msgs.len = 2;
1422 msgs.buf = msg;
1423 return i2c_transfer(&av7110->i2c_adap, &msgs, 1);
1424}
1425
1426#if 0
1427u8 i2c_readreg(struct av7110 *av7110, u8 id, u8 reg)
1428{
1429 u8 mm1[] = {0x00};
1430 u8 mm2[] = {0x00};
1431 struct i2c_msg msgs[2];
1432
1433 msgs[0].flags = 0;
1434 msgs[1].flags = I2C_M_RD;
1435 msgs[0].addr = msgs[1].addr = id / 2;
1436 mm1[0] = reg;
1437 msgs[0].len = 1; msgs[1].len = 1;
1438 msgs[0].buf = mm1; msgs[1].buf = mm2;
1439 i2c_transfer(&av7110->i2c_adap, msgs, 2);
1440
1441 return mm2[0];
1442}
1443#endif
1444
1445/****************************************************************************
1446 * INITIALIZATION
1447 ****************************************************************************/
1448
1449
1450static int check_firmware(struct av7110* av7110)
1451{
1452 u32 crc = 0, len = 0;
1453 unsigned char *ptr;
1454
1455 /* check for firmware magic */
1456 ptr = av7110->bin_fw;
1457 if (ptr[0] != 'A' || ptr[1] != 'V' ||
1458 ptr[2] != 'F' || ptr[3] != 'W') {
1459 printk("dvb-ttpci: this is not an av7110 firmware\n");
1460 return -EINVAL;
1461 }
1462 ptr += 4;
1463
1464 /* check dpram file */
Al Viro3e085622008-05-21 00:30:51 -03001465 crc = get_unaligned_be32(ptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001466 ptr += 4;
Al Viro3e085622008-05-21 00:30:51 -03001467 len = get_unaligned_be32(ptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468 ptr += 4;
1469 if (len >= 512) {
Alexey Dobriyanbe787ac2006-03-07 22:20:23 -03001470 printk("dvb-ttpci: dpram file is way too big.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001471 return -EINVAL;
1472 }
1473 if (crc != crc32_le(0, ptr, len)) {
1474 printk("dvb-ttpci: crc32 of dpram file does not match.\n");
1475 return -EINVAL;
1476 }
1477 av7110->bin_dpram = ptr;
1478 av7110->size_dpram = len;
1479 ptr += len;
1480
1481 /* check root file */
Al Viro3e085622008-05-21 00:30:51 -03001482 crc = get_unaligned_be32(ptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001483 ptr += 4;
Al Viro3e085622008-05-21 00:30:51 -03001484 len = get_unaligned_be32(ptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001485 ptr += 4;
1486
1487 if (len <= 200000 || len >= 300000 ||
1488 len > ((av7110->bin_fw + av7110->size_fw) - ptr)) {
1489 printk("dvb-ttpci: root file has strange size (%d). aborting.\n", len);
1490 return -EINVAL;
1491 }
1492 if( crc != crc32_le(0, ptr, len)) {
1493 printk("dvb-ttpci: crc32 of root file does not match.\n");
1494 return -EINVAL;
1495 }
1496 av7110->bin_root = ptr;
1497 av7110->size_root = len;
1498 return 0;
1499}
1500
1501#ifdef CONFIG_DVB_AV7110_FIRMWARE_FILE
1502#include "av7110_firm.h"
1503static void put_firmware(struct av7110* av7110)
1504{
1505 av7110->bin_fw = NULL;
1506}
1507
1508static inline int get_firmware(struct av7110* av7110)
1509{
1510 av7110->bin_fw = dvb_ttpci_fw;
1511 av7110->size_fw = sizeof(dvb_ttpci_fw);
1512 return check_firmware(av7110);
1513}
1514#else
1515static void put_firmware(struct av7110* av7110)
1516{
1517 vfree(av7110->bin_fw);
1518}
1519
1520static int get_firmware(struct av7110* av7110)
1521{
1522 int ret;
1523 const struct firmware *fw;
1524
1525 /* request the av7110 firmware, this will block until someone uploads it */
1526 ret = request_firmware(&fw, "dvb-ttpci-01.fw", &av7110->dev->pci->dev);
1527 if (ret) {
1528 if (ret == -ENOENT) {
1529 printk(KERN_ERR "dvb-ttpci: could not load firmware,"
1530 " file not found: dvb-ttpci-01.fw\n");
Ville Skytt\ä12e66f62006-01-09 15:25:38 -02001531 printk(KERN_ERR "dvb-ttpci: usually this should be in "
1532 "/usr/lib/hotplug/firmware or /lib/firmware\n");
1533 printk(KERN_ERR "dvb-ttpci: and can be downloaded from"
Linus Torvalds1da177e2005-04-16 15:20:36 -07001534 " http://www.linuxtv.org/download/dvb/firmware/\n");
1535 } else
1536 printk(KERN_ERR "dvb-ttpci: cannot request firmware"
1537 " (error %i)\n", ret);
1538 return -EINVAL;
1539 }
1540
1541 if (fw->size <= 200000) {
1542 printk("dvb-ttpci: this firmware is way too small.\n");
1543 release_firmware(fw);
1544 return -EINVAL;
1545 }
1546
1547 /* check if the firmware is available */
Jesper Juhld9bf2c02007-08-25 11:23:54 -03001548 av7110->bin_fw = vmalloc(fw->size);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001549 if (NULL == av7110->bin_fw) {
1550 dprintk(1, "out of memory\n");
1551 release_firmware(fw);
1552 return -ENOMEM;
1553 }
1554
1555 memcpy(av7110->bin_fw, fw->data, fw->size);
1556 av7110->size_fw = fw->size;
1557 if ((ret = check_firmware(av7110)))
1558 vfree(av7110->bin_fw);
1559
1560 release_firmware(fw);
1561 return ret;
1562}
1563#endif
1564
1565
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001566static int alps_bsrv2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001567{
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001568 struct av7110* av7110 = fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001569 u8 pwr = 0;
1570 u8 buf[4];
1571 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
1572 u32 div = (params->frequency + 479500) / 125;
1573
1574 if (params->frequency > 2000000) pwr = 3;
1575 else if (params->frequency > 1800000) pwr = 2;
1576 else if (params->frequency > 1600000) pwr = 1;
1577 else if (params->frequency > 1200000) pwr = 0;
1578 else if (params->frequency >= 1100000) pwr = 1;
1579 else pwr = 2;
1580
1581 buf[0] = (div >> 8) & 0x7f;
1582 buf[1] = div & 0xff;
1583 buf[2] = ((div & 0x18000) >> 10) | 0x95;
1584 buf[3] = (pwr << 6) | 0x30;
1585
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -08001586 // NOTE: since we're using a prescaler of 2, we set the
Linus Torvalds1da177e2005-04-16 15:20:36 -07001587 // divisor frequency to 62.5kHz and divide by 125 above
1588
Patrick Boettcherdea74862006-05-14 05:01:31 -03001589 if (fe->ops.i2c_gate_ctrl)
1590 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001591 if (i2c_transfer (&av7110->i2c_adap, &msg, 1) != 1)
1592 return -EIO;
1593 return 0;
1594}
1595
1596static struct ves1x93_config alps_bsrv2_config = {
1597 .demod_address = 0x08,
1598 .xin = 90100000UL,
1599 .invert_pwm = 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001600};
1601
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001602static int alps_tdbe2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001603{
1604 struct av7110* av7110 = fe->dvb->priv;
1605 u32 div;
1606 u8 data[4];
1607 struct i2c_msg msg = { .addr = 0x62, .flags = 0, .buf = data, .len = sizeof(data) };
1608
1609 div = (params->frequency + 35937500 + 31250) / 62500;
1610
1611 data[0] = (div >> 8) & 0x7f;
1612 data[1] = div & 0xff;
1613 data[2] = 0x85 | ((div >> 10) & 0x60);
1614 data[3] = (params->frequency < 174000000 ? 0x88 : params->frequency < 470000000 ? 0x84 : 0x81);
1615
Patrick Boettcherdea74862006-05-14 05:01:31 -03001616 if (fe->ops.i2c_gate_ctrl)
1617 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001618 if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
1619 return -EIO;
1620 return 0;
1621}
1622
1623static struct ves1820_config alps_tdbe2_config = {
1624 .demod_address = 0x09,
1625 .xin = 57840000UL,
1626 .invert = 1,
1627 .selagc = VES1820_SELAGC_SIGNAMPERR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001628};
1629
1630
1631
1632
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001633static int grundig_29504_451_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001634{
1635 struct av7110* av7110 = fe->dvb->priv;
1636 u32 div;
1637 u8 data[4];
1638 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
1639
1640 div = params->frequency / 125;
1641 data[0] = (div >> 8) & 0x7f;
1642 data[1] = div & 0xff;
1643 data[2] = 0x8e;
1644 data[3] = 0x00;
1645
Patrick Boettcherdea74862006-05-14 05:01:31 -03001646 if (fe->ops.i2c_gate_ctrl)
1647 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001648 if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
1649 return -EIO;
1650 return 0;
1651}
1652
1653static struct tda8083_config grundig_29504_451_config = {
1654 .demod_address = 0x68,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001655};
1656
1657
1658
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001659static int philips_cd1516_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001660{
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -08001661 struct av7110* av7110 = fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001662 u32 div;
1663 u32 f = params->frequency;
1664 u8 data[4];
1665 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
1666
1667 div = (f + 36125000 + 31250) / 62500;
1668
1669 data[0] = (div >> 8) & 0x7f;
1670 data[1] = div & 0xff;
1671 data[2] = 0x8e;
1672 data[3] = (f < 174000000 ? 0xa1 : f < 470000000 ? 0x92 : 0x34);
1673
Patrick Boettcherdea74862006-05-14 05:01:31 -03001674 if (fe->ops.i2c_gate_ctrl)
1675 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001676 if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
1677 return -EIO;
1678 return 0;
1679}
1680
1681static struct ves1820_config philips_cd1516_config = {
1682 .demod_address = 0x09,
1683 .xin = 57840000UL,
1684 .invert = 1,
1685 .selagc = VES1820_SELAGC_SIGNAMPERR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001686};
1687
1688
1689
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001690static int alps_tdlb7_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001691{
1692 struct av7110* av7110 = fe->dvb->priv;
1693 u32 div, pwr;
1694 u8 data[4];
1695 struct i2c_msg msg = { .addr = 0x60, .flags = 0, .buf = data, .len = sizeof(data) };
1696
1697 div = (params->frequency + 36200000) / 166666;
1698
1699 if (params->frequency <= 782000000)
1700 pwr = 1;
1701 else
1702 pwr = 2;
1703
1704 data[0] = (div >> 8) & 0x7f;
1705 data[1] = div & 0xff;
1706 data[2] = 0x85;
1707 data[3] = pwr << 6;
1708
Patrick Boettcherdea74862006-05-14 05:01:31 -03001709 if (fe->ops.i2c_gate_ctrl)
1710 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001711 if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
1712 return -EIO;
1713 return 0;
1714}
1715
1716static int alps_tdlb7_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name)
1717{
Oliver Endrissd98821e2006-09-14 00:15:13 -03001718#if defined(CONFIG_DVB_SP8870) || defined(CONFIG_DVB_SP8870_MODULE)
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001719 struct av7110* av7110 = fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001720
1721 return request_firmware(fw, name, &av7110->dev->pci->dev);
Oliver Endrissd98821e2006-09-14 00:15:13 -03001722#else
1723 return -EINVAL;
1724#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001725}
1726
1727static struct sp8870_config alps_tdlb7_config = {
1728
1729 .demod_address = 0x71,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001730 .request_firmware = alps_tdlb7_request_firmware,
1731};
1732
1733
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001734static u8 nexusca_stv0297_inittab[] = {
1735 0x80, 0x01,
1736 0x80, 0x00,
1737 0x81, 0x01,
1738 0x81, 0x00,
1739 0x00, 0x09,
1740 0x01, 0x69,
1741 0x03, 0x00,
1742 0x04, 0x00,
1743 0x07, 0x00,
1744 0x08, 0x00,
1745 0x20, 0x00,
1746 0x21, 0x40,
1747 0x22, 0x00,
1748 0x23, 0x00,
1749 0x24, 0x40,
1750 0x25, 0x88,
1751 0x30, 0xff,
1752 0x31, 0x00,
1753 0x32, 0xff,
1754 0x33, 0x00,
1755 0x34, 0x50,
1756 0x35, 0x7f,
1757 0x36, 0x00,
1758 0x37, 0x20,
1759 0x38, 0x00,
1760 0x40, 0x1c,
1761 0x41, 0xff,
1762 0x42, 0x29,
1763 0x43, 0x00,
1764 0x44, 0xff,
1765 0x45, 0x00,
1766 0x46, 0x00,
1767 0x49, 0x04,
1768 0x4a, 0x00,
1769 0x4b, 0x7b,
1770 0x52, 0x30,
1771 0x55, 0xae,
1772 0x56, 0x47,
1773 0x57, 0xe1,
1774 0x58, 0x3a,
1775 0x5a, 0x1e,
1776 0x5b, 0x34,
1777 0x60, 0x00,
1778 0x63, 0x00,
1779 0x64, 0x00,
1780 0x65, 0x00,
1781 0x66, 0x00,
1782 0x67, 0x00,
1783 0x68, 0x00,
1784 0x69, 0x00,
1785 0x6a, 0x02,
1786 0x6b, 0x00,
1787 0x70, 0xff,
1788 0x71, 0x00,
1789 0x72, 0x00,
1790 0x73, 0x00,
1791 0x74, 0x0c,
1792 0x80, 0x00,
1793 0x81, 0x00,
1794 0x82, 0x00,
1795 0x83, 0x00,
1796 0x84, 0x04,
1797 0x85, 0x80,
1798 0x86, 0x24,
1799 0x87, 0x78,
1800 0x88, 0x10,
1801 0x89, 0x00,
1802 0x90, 0x01,
1803 0x91, 0x01,
1804 0xa0, 0x04,
1805 0xa1, 0x00,
1806 0xa2, 0x00,
1807 0xb0, 0x91,
1808 0xb1, 0x0b,
1809 0xc0, 0x53,
1810 0xc1, 0x70,
1811 0xc2, 0x12,
1812 0xd0, 0x00,
1813 0xd1, 0x00,
1814 0xd2, 0x00,
1815 0xd3, 0x00,
1816 0xd4, 0x00,
1817 0xd5, 0x00,
1818 0xde, 0x00,
1819 0xdf, 0x00,
1820 0x61, 0x49,
1821 0x62, 0x0b,
1822 0x53, 0x08,
1823 0x59, 0x08,
1824 0xff, 0xff,
1825};
Linus Torvalds1da177e2005-04-16 15:20:36 -07001826
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001827static int nexusca_stv0297_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001828{
1829 struct av7110* av7110 = fe->dvb->priv;
1830 u32 div;
1831 u8 data[4];
1832 struct i2c_msg msg = { .addr = 0x63, .flags = 0, .buf = data, .len = sizeof(data) };
1833 struct i2c_msg readmsg = { .addr = 0x63, .flags = I2C_M_RD, .buf = data, .len = 1 };
1834 int i;
1835
1836 div = (params->frequency + 36150000 + 31250) / 62500;
1837
1838 data[0] = (div >> 8) & 0x7f;
1839 data[1] = div & 0xff;
1840 data[2] = 0xce;
1841
1842 if (params->frequency < 45000000)
1843 return -EINVAL;
1844 else if (params->frequency < 137000000)
1845 data[3] = 0x01;
1846 else if (params->frequency < 403000000)
1847 data[3] = 0x02;
1848 else if (params->frequency < 860000000)
1849 data[3] = 0x04;
1850 else
1851 return -EINVAL;
1852
Patrick Boettcherdea74862006-05-14 05:01:31 -03001853 if (fe->ops.i2c_gate_ctrl)
1854 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001855 if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1) {
1856 printk("nexusca: pll transfer failed!\n");
1857 return -EIO;
1858 }
1859
1860 // wait for PLL lock
1861 for(i = 0; i < 20; i++) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001862 if (fe->ops.i2c_gate_ctrl)
1863 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001864 if (i2c_transfer(&av7110->i2c_adap, &readmsg, 1) == 1)
1865 if (data[0] & 0x40) break;
1866 msleep(10);
1867 }
1868
1869 return 0;
1870}
1871
1872static struct stv0297_config nexusca_stv0297_config = {
1873
1874 .demod_address = 0x1C,
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001875 .inittab = nexusca_stv0297_inittab,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001876 .invert = 1,
Thomas Kaiserb8d4c232006-04-27 21:45:20 -03001877 .stop_during_read = 1,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001878};
1879
1880
1881
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001882static int grundig_29504_401_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001883{
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001884 struct av7110* av7110 = fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001885 u32 div;
1886 u8 cfg, cpump, band_select;
1887 u8 data[4];
1888 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
1889
1890 div = (36125000 + params->frequency) / 166666;
1891
1892 cfg = 0x88;
1893
1894 if (params->frequency < 175000000) cpump = 2;
1895 else if (params->frequency < 390000000) cpump = 1;
1896 else if (params->frequency < 470000000) cpump = 2;
1897 else if (params->frequency < 750000000) cpump = 1;
1898 else cpump = 3;
1899
1900 if (params->frequency < 175000000) band_select = 0x0e;
1901 else if (params->frequency < 470000000) band_select = 0x05;
1902 else band_select = 0x03;
1903
1904 data[0] = (div >> 8) & 0x7f;
1905 data[1] = div & 0xff;
1906 data[2] = ((div >> 10) & 0x60) | cfg;
1907 data[3] = (cpump << 6) | band_select;
1908
Patrick Boettcherdea74862006-05-14 05:01:31 -03001909 if (fe->ops.i2c_gate_ctrl)
1910 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001911 if (i2c_transfer (&av7110->i2c_adap, &msg, 1) != 1) return -EIO;
1912 return 0;
1913}
1914
1915static struct l64781_config grundig_29504_401_config = {
1916 .demod_address = 0x55,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001917};
1918
1919
1920
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001921static int av7110_fe_lock_fix(struct av7110* av7110, fe_status_t status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001922{
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001923 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001924 int synced = (status & FE_HAS_LOCK) ? 1 : 0;
1925
1926 av7110->fe_status = status;
1927
1928 if (av7110->fe_synced == synced)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001929 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001930
Oliver Endriss14500d42007-03-03 14:45:48 -03001931 if (av7110->playing) {
1932 av7110->fe_synced = synced;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001933 return 0;
Oliver Endriss14500d42007-03-03 14:45:48 -03001934 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001935
Ingo Molnar3593cab2006-02-07 06:49:14 -02001936 if (mutex_lock_interruptible(&av7110->pid_mutex))
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001937 return -ERESTARTSYS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001938
Oliver Endriss34612152005-07-07 17:58:02 -07001939 if (synced) {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001940 ret = SetPIDs(av7110, av7110->pids[DMX_PES_VIDEO],
Linus Torvalds1da177e2005-04-16 15:20:36 -07001941 av7110->pids[DMX_PES_AUDIO],
1942 av7110->pids[DMX_PES_TELETEXT], 0,
1943 av7110->pids[DMX_PES_PCR]);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001944 if (!ret)
1945 ret = av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, Scan, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001946 } else {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001947 ret = SetPIDs(av7110, 0, 0, 0, 0, 0);
1948 if (!ret) {
1949 ret = av7110_fw_cmd(av7110, COMTYPE_PID_FILTER, FlushTSQueue, 0);
1950 if (!ret)
1951 ret = av7110_wait_msgstate(av7110, GPMQBusy);
1952 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001953 }
1954
Oliver Endriss34612152005-07-07 17:58:02 -07001955 if (!ret)
1956 av7110->fe_synced = synced;
1957
Ingo Molnar3593cab2006-02-07 06:49:14 -02001958 mutex_unlock(&av7110->pid_mutex);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001959 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001960}
1961
1962static int av7110_fe_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
1963{
1964 struct av7110* av7110 = fe->dvb->priv;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001965
1966 int ret = av7110_fe_lock_fix(av7110, 0);
Oliver Endriss66190a22006-01-09 15:32:42 -02001967 if (!ret) {
1968 av7110->saved_fe_params = *params;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001969 ret = av7110->fe_set_frontend(fe, params);
Oliver Endriss66190a22006-01-09 15:32:42 -02001970 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001971 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001972}
1973
1974static int av7110_fe_init(struct dvb_frontend* fe)
1975{
1976 struct av7110* av7110 = fe->dvb->priv;
1977
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001978 int ret = av7110_fe_lock_fix(av7110, 0);
1979 if (!ret)
1980 ret = av7110->fe_init(fe);
1981 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001982}
1983
1984static int av7110_fe_read_status(struct dvb_frontend* fe, fe_status_t* status)
1985{
1986 struct av7110* av7110 = fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001987
1988 /* call the real implementation */
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001989 int ret = av7110->fe_read_status(fe, status);
1990 if (!ret)
1991 if (((*status ^ av7110->fe_status) & FE_HAS_LOCK) && (*status & FE_HAS_LOCK))
1992 ret = av7110_fe_lock_fix(av7110, *status);
1993 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001994}
1995
1996static int av7110_fe_diseqc_reset_overload(struct dvb_frontend* fe)
1997{
1998 struct av7110* av7110 = fe->dvb->priv;
1999
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002000 int ret = av7110_fe_lock_fix(av7110, 0);
2001 if (!ret)
2002 ret = av7110->fe_diseqc_reset_overload(fe);
2003 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002004}
2005
2006static int av7110_fe_diseqc_send_master_cmd(struct dvb_frontend* fe,
2007 struct dvb_diseqc_master_cmd* cmd)
2008{
2009 struct av7110* av7110 = fe->dvb->priv;
2010
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002011 int ret = av7110_fe_lock_fix(av7110, 0);
Oliver Endriss66190a22006-01-09 15:32:42 -02002012 if (!ret) {
2013 av7110->saved_master_cmd = *cmd;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002014 ret = av7110->fe_diseqc_send_master_cmd(fe, cmd);
Oliver Endriss66190a22006-01-09 15:32:42 -02002015 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002016 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002017}
2018
2019static int av7110_fe_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd)
2020{
2021 struct av7110* av7110 = fe->dvb->priv;
2022
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002023 int ret = av7110_fe_lock_fix(av7110, 0);
Oliver Endriss66190a22006-01-09 15:32:42 -02002024 if (!ret) {
2025 av7110->saved_minicmd = minicmd;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002026 ret = av7110->fe_diseqc_send_burst(fe, minicmd);
Oliver Endriss66190a22006-01-09 15:32:42 -02002027 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002028 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002029}
2030
2031static int av7110_fe_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
2032{
2033 struct av7110* av7110 = fe->dvb->priv;
2034
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002035 int ret = av7110_fe_lock_fix(av7110, 0);
Oliver Endriss66190a22006-01-09 15:32:42 -02002036 if (!ret) {
2037 av7110->saved_tone = tone;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002038 ret = av7110->fe_set_tone(fe, tone);
Oliver Endriss66190a22006-01-09 15:32:42 -02002039 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002040 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002041}
2042
2043static int av7110_fe_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
2044{
2045 struct av7110* av7110 = fe->dvb->priv;
2046
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002047 int ret = av7110_fe_lock_fix(av7110, 0);
Oliver Endriss66190a22006-01-09 15:32:42 -02002048 if (!ret) {
2049 av7110->saved_voltage = voltage;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002050 ret = av7110->fe_set_voltage(fe, voltage);
Oliver Endriss66190a22006-01-09 15:32:42 -02002051 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002052 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002053}
2054
Peter Beutner400b7082006-01-09 15:32:43 -02002055static int av7110_fe_dishnetwork_send_legacy_command(struct dvb_frontend* fe, unsigned long cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002056{
2057 struct av7110* av7110 = fe->dvb->priv;
2058
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002059 int ret = av7110_fe_lock_fix(av7110, 0);
2060 if (!ret)
2061 ret = av7110->fe_dishnetwork_send_legacy_command(fe, cmd);
2062 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002063}
2064
Oliver Endriss66190a22006-01-09 15:32:42 -02002065static void dvb_s_recover(struct av7110* av7110)
2066{
2067 av7110_fe_init(av7110->fe);
2068
2069 av7110_fe_set_voltage(av7110->fe, av7110->saved_voltage);
2070 if (av7110->saved_master_cmd.msg_len) {
2071 msleep(20);
2072 av7110_fe_diseqc_send_master_cmd(av7110->fe, &av7110->saved_master_cmd);
2073 }
2074 msleep(20);
2075 av7110_fe_diseqc_send_burst(av7110->fe, av7110->saved_minicmd);
2076 msleep(20);
2077 av7110_fe_set_tone(av7110->fe, av7110->saved_tone);
2078
2079 av7110_fe_set_frontend(av7110->fe, &av7110->saved_fe_params);
2080}
2081
Linus Torvalds1da177e2005-04-16 15:20:36 -07002082static u8 read_pwm(struct av7110* av7110)
2083{
2084 u8 b = 0xff;
2085 u8 pwm;
2086 struct i2c_msg msg[] = { { .addr = 0x50,.flags = 0,.buf = &b,.len = 1 },
2087 { .addr = 0x50,.flags = I2C_M_RD,.buf = &pwm,.len = 1} };
2088
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -08002089 if ((i2c_transfer(&av7110->i2c_adap, msg, 2) != 2) || (pwm == 0xff))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002090 pwm = 0x48;
2091
2092 return pwm;
2093}
2094
2095static int frontend_init(struct av7110 *av7110)
2096{
2097 int ret;
2098
2099 if (av7110->dev->pci->subsystem_vendor == 0x110a) {
2100 switch(av7110->dev->pci->subsystem_device) {
2101 case 0x0000: // Fujitsu/Siemens DVB-Cable (ves1820/Philips CD1516(??))
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002102 av7110->fe = dvb_attach(ves1820_attach, &philips_cd1516_config,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002103 &av7110->i2c_adap, read_pwm(av7110));
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002104 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002105 av7110->fe->ops.tuner_ops.set_params = philips_cd1516_tuner_set_params;
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002106 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002107 break;
2108 }
2109
2110 } else if (av7110->dev->pci->subsystem_vendor == 0x13c2) {
2111 switch(av7110->dev->pci->subsystem_device) {
2112 case 0x0000: // Hauppauge/TT WinTV DVB-S rev1.X
2113 case 0x0003: // Hauppauge/TT WinTV Nexus-S Rev 2.X
2114 case 0x1002: // Hauppauge/TT WinTV DVB-S rev1.3SE
2115
2116 // try the ALPS BSRV2 first of all
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002117 av7110->fe = dvb_attach(ves1x93_attach, &alps_bsrv2_config, &av7110->i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002118 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002119 av7110->fe->ops.tuner_ops.set_params = alps_bsrv2_tuner_set_params;
2120 av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
2121 av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
2122 av7110->fe->ops.set_tone = av7110_set_tone;
Oliver Endriss66190a22006-01-09 15:32:42 -02002123 av7110->recover = dvb_s_recover;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002124 break;
2125 }
2126
2127 // try the ALPS BSRU6 now
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002128 av7110->fe = dvb_attach(stv0299_attach, &alps_bsru6_config, &av7110->i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002129 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002130 av7110->fe->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03002131 av7110->fe->tuner_priv = &av7110->i2c_adap;
2132
Patrick Boettcherdea74862006-05-14 05:01:31 -03002133 av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
2134 av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
2135 av7110->fe->ops.set_tone = av7110_set_tone;
Oliver Endriss66190a22006-01-09 15:32:42 -02002136 av7110->recover = dvb_s_recover;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002137 break;
2138 }
2139
2140 // Try the grundig 29504-451
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002141 av7110->fe = dvb_attach(tda8083_attach, &grundig_29504_451_config, &av7110->i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002142 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002143 av7110->fe->ops.tuner_ops.set_params = grundig_29504_451_tuner_set_params;
2144 av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
2145 av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
2146 av7110->fe->ops.set_tone = av7110_set_tone;
Oliver Endriss66190a22006-01-09 15:32:42 -02002147 av7110->recover = dvb_s_recover;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002148 break;
2149 }
2150
2151 /* Try DVB-C cards */
2152 switch(av7110->dev->pci->subsystem_device) {
2153 case 0x0000:
2154 /* Siemens DVB-C (full-length card) VES1820/Philips CD1516 */
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002155 av7110->fe = dvb_attach(ves1820_attach, &philips_cd1516_config, &av7110->i2c_adap,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002156 read_pwm(av7110));
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002157 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002158 av7110->fe->ops.tuner_ops.set_params = philips_cd1516_tuner_set_params;
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002159 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002160 break;
2161 case 0x0003:
Adrian Bunkf3688fc2006-03-29 22:46:12 -03002162 /* Hauppauge DVB-C 2.1 VES1820/ALPS TDBE2 */
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002163 av7110->fe = dvb_attach(ves1820_attach, &alps_tdbe2_config, &av7110->i2c_adap,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002164 read_pwm(av7110));
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002165 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002166 av7110->fe->ops.tuner_ops.set_params = alps_tdbe2_tuner_set_params;
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002167 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002168 break;
2169 }
2170 break;
2171
2172 case 0x0001: // Hauppauge/TT Nexus-T premium rev1.X
Oliver Endriss8d90ee52006-08-07 02:04:26 -03002173 // try ALPS TDLB7 first, then Grundig 29504-401
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002174 av7110->fe = dvb_attach(sp8870_attach, &alps_tdlb7_config, &av7110->i2c_adap);
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002175 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002176 av7110->fe->ops.tuner_ops.set_params = alps_tdlb7_tuner_set_params;
Oliver Endriss8d90ee52006-08-07 02:04:26 -03002177 break;
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002178 }
Oliver Endriss8d90ee52006-08-07 02:04:26 -03002179 /* fall-thru */
2180
2181 case 0x0008: // Hauppauge/TT DVB-T
2182 // Grundig 29504-401
2183 av7110->fe = dvb_attach(l64781_attach, &grundig_29504_401_config, &av7110->i2c_adap);
2184 if (av7110->fe)
2185 av7110->fe->ops.tuner_ops.set_params = grundig_29504_401_tuner_set_params;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002186 break;
2187
2188 case 0x0002: // Hauppauge/TT DVB-C premium rev2.X
2189
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002190 av7110->fe = dvb_attach(ves1820_attach, &alps_tdbe2_config, &av7110->i2c_adap, read_pwm(av7110));
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002191 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002192 av7110->fe->ops.tuner_ops.set_params = alps_tdbe2_tuner_set_params;
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002193 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002194 break;
2195
Oliver Endriss8bd63012006-02-07 06:49:11 -02002196 case 0x0004: // Galaxis DVB-S rev1.3
2197 /* ALPS BSRV2 */
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002198 av7110->fe = dvb_attach(ves1x93_attach, &alps_bsrv2_config, &av7110->i2c_adap);
Oliver Endriss8bd63012006-02-07 06:49:11 -02002199 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002200 av7110->fe->ops.tuner_ops.set_params = alps_bsrv2_tuner_set_params;
2201 av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
2202 av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
2203 av7110->fe->ops.set_tone = av7110_set_tone;
Oliver Endriss8bd63012006-02-07 06:49:11 -02002204 av7110->recover = dvb_s_recover;
2205 }
2206 break;
2207
Linus Torvalds1da177e2005-04-16 15:20:36 -07002208 case 0x0006: /* Fujitsu-Siemens DVB-S rev 1.6 */
2209 /* Grundig 29504-451 */
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002210 av7110->fe = dvb_attach(tda8083_attach, &grundig_29504_451_config, &av7110->i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002211 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002212 av7110->fe->ops.tuner_ops.set_params = grundig_29504_451_tuner_set_params;
2213 av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
2214 av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
2215 av7110->fe->ops.set_tone = av7110_set_tone;
Oliver Endriss66190a22006-01-09 15:32:42 -02002216 av7110->recover = dvb_s_recover;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002217 }
2218 break;
2219
Linus Torvalds1da177e2005-04-16 15:20:36 -07002220 case 0x000A: // Hauppauge/TT Nexus-CA rev1.X
2221
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002222 av7110->fe = dvb_attach(stv0297_attach, &nexusca_stv0297_config, &av7110->i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002223 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002224 av7110->fe->ops.tuner_ops.set_params = nexusca_stv0297_tuner_set_params;
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03002225
Linus Torvalds1da177e2005-04-16 15:20:36 -07002226 /* set TDA9819 into DVB mode */
Marco Schluessler6a857742006-07-10 03:34:16 -03002227 saa7146_setgpio(av7110->dev, 1, SAA7146_GPIO_OUTLO); // TDA9819 pin9(STD)
2228 saa7146_setgpio(av7110->dev, 3, SAA7146_GPIO_OUTLO); // TDA9819 pin30(VIF)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002229
2230 /* tuner on this needs a slower i2c bus speed */
2231 av7110->dev->i2c_bitrate = SAA7146_I2C_BUS_BIT_RATE_240;
2232 break;
2233 }
Johannes Stezenbach3dfaebd2005-05-16 21:54:19 -07002234 break;
2235
2236 case 0x000E: /* Hauppauge/TT Nexus-S rev 2.3 */
2237 /* ALPS BSBE1 */
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002238 av7110->fe = dvb_attach(stv0299_attach, &alps_bsbe1_config, &av7110->i2c_adap);
Oliver Endrisseb3daf32006-01-09 15:25:05 -02002239 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002240 av7110->fe->ops.tuner_ops.set_params = alps_bsbe1_tuner_set_params;
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03002241 av7110->fe->tuner_priv = &av7110->i2c_adap;
2242
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002243 if (dvb_attach(lnbp21_attach, av7110->fe, &av7110->i2c_adap, 0, 0) == NULL) {
Oliver Endrissdb5d91e2006-02-28 10:32:25 -03002244 printk("dvb-ttpci: LNBP21 not found!\n");
Patrick Boettcherdea74862006-05-14 05:01:31 -03002245 if (av7110->fe->ops.release)
2246 av7110->fe->ops.release(av7110->fe);
Oliver Endrissdb5d91e2006-02-28 10:32:25 -03002247 av7110->fe = NULL;
2248 } else {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002249 av7110->fe->ops.dishnetwork_send_legacy_command = NULL;
Oliver Endrissdb5d91e2006-02-28 10:32:25 -03002250 av7110->recover = dvb_s_recover;
2251 }
Oliver Endrisseb3daf32006-01-09 15:25:05 -02002252 }
Johannes Stezenbach3dfaebd2005-05-16 21:54:19 -07002253 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002254 }
2255 }
2256
2257 if (!av7110->fe) {
2258 /* FIXME: propagate the failure code from the lower layers */
2259 ret = -ENOMEM;
2260 printk("dvb-ttpci: A frontend driver was not found for device %04x/%04x subsystem %04x/%04x\n",
2261 av7110->dev->pci->vendor,
2262 av7110->dev->pci->device,
2263 av7110->dev->pci->subsystem_vendor,
2264 av7110->dev->pci->subsystem_device);
2265 } else {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002266 FE_FUNC_OVERRIDE(av7110->fe->ops.init, av7110->fe_init, av7110_fe_init);
2267 FE_FUNC_OVERRIDE(av7110->fe->ops.read_status, av7110->fe_read_status, av7110_fe_read_status);
2268 FE_FUNC_OVERRIDE(av7110->fe->ops.diseqc_reset_overload, av7110->fe_diseqc_reset_overload, av7110_fe_diseqc_reset_overload);
2269 FE_FUNC_OVERRIDE(av7110->fe->ops.diseqc_send_master_cmd, av7110->fe_diseqc_send_master_cmd, av7110_fe_diseqc_send_master_cmd);
2270 FE_FUNC_OVERRIDE(av7110->fe->ops.diseqc_send_burst, av7110->fe_diseqc_send_burst, av7110_fe_diseqc_send_burst);
2271 FE_FUNC_OVERRIDE(av7110->fe->ops.set_tone, av7110->fe_set_tone, av7110_fe_set_tone);
Yoann Padioleau8f40a9f2007-07-16 16:54:49 -03002272 FE_FUNC_OVERRIDE(av7110->fe->ops.set_voltage, av7110->fe_set_voltage, av7110_fe_set_voltage);
Patrick Boettcherdea74862006-05-14 05:01:31 -03002273 FE_FUNC_OVERRIDE(av7110->fe->ops.dishnetwork_send_legacy_command, av7110->fe_dishnetwork_send_legacy_command, av7110_fe_dishnetwork_send_legacy_command);
2274 FE_FUNC_OVERRIDE(av7110->fe->ops.set_frontend, av7110->fe_set_frontend, av7110_fe_set_frontend);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002275
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07002276 ret = dvb_register_frontend(&av7110->dvb_adapter, av7110->fe);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002277 if (ret < 0) {
2278 printk("av7110: Frontend registration failed!\n");
Andrew de Quinceyf52a8382006-08-08 09:10:09 -03002279 dvb_frontend_detach(av7110->fe);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002280 av7110->fe = NULL;
2281 }
2282 }
2283 return ret;
2284}
2285
2286/* Budgetpatch note:
2287 * Original hardware design by Roberto Deza:
2288 * There is a DVB_Wiki at
2289 * http://212.227.36.83/linuxtv/wiki/index.php/Main_Page
2290 * where is described this 'DVB TT Budget Patch', on Card Modding:
2291 * http://212.227.36.83/linuxtv/wiki/index.php/DVB_TT_Budget_Patch
2292 * On the short description there is also a link to a external file,
2293 * with more details:
2294 * http://perso.wanadoo.es/jesussolano/Ttf_tsc1.zip
2295 *
2296 * New software triggering design by Emard that works on
2297 * original Roberto Deza's hardware:
2298 *
2299 * rps1 code for budgetpatch will copy internal HS event to GPIO3 pin.
2300 * GPIO3 is in budget-patch hardware connectd to port B VSYNC
2301 * HS is an internal event of 7146, accessible with RPS
2302 * and temporarily raised high every n lines
2303 * (n in defined in the RPS_THRESH1 counter threshold)
2304 * I think HS is raised high on the beginning of the n-th line
2305 * and remains high until this n-th line that triggered
2306 * it is completely received. When the receiption of n-th line
2307 * ends, HS is lowered.
2308 *
2309 * To transmit data over DMA, 7146 needs changing state at
2310 * port B VSYNC pin. Any changing of port B VSYNC will
2311 * cause some DMA data transfer, with more or less packets loss.
2312 * It depends on the phase and frequency of VSYNC and
2313 * the way of 7146 is instructed to trigger on port B (defined
2314 * in DD1_INIT register, 3rd nibble from the right valid
2315 * numbers are 0-7, see datasheet)
2316 *
2317 * The correct triggering can minimize packet loss,
2318 * dvbtraffic should give this stable bandwidths:
2319 * 22k transponder = 33814 kbit/s
2320 * 27.5k transponder = 38045 kbit/s
2321 * by experiment it is found that the best results
2322 * (stable bandwidths and almost no packet loss)
2323 * are obtained using DD1_INIT triggering number 2
2324 * (Va at rising edge of VS Fa = HS x VS-failing forced toggle)
2325 * and a VSYNC phase that occurs in the middle of DMA transfer
2326 * (about byte 188*512=96256 in the DMA window).
2327 *
2328 * Phase of HS is still not clear to me how to control,
2329 * It just happens to be so. It can be seen if one enables
2330 * RPS_IRQ and print Event Counter 1 in vpeirq(). Every
2331 * time RPS_INTERRUPT is called, the Event Counter 1 will
2332 * increment. That's how the 7146 is programmed to do event
2333 * counting in this budget-patch.c
2334 * I *think* HPS setting has something to do with the phase
2335 * of HS but I cant be 100% sure in that.
2336 *
2337 * hardware debug note: a working budget card (including budget patch)
2338 * with vpeirq() interrupt setup in mode "0x90" (every 64K) will
2339 * generate 3 interrupts per 25-Hz DMA frame of 2*188*512 bytes
2340 * and that means 3*25=75 Hz of interrupt freqency, as seen by
2341 * watch cat /proc/interrupts
2342 *
2343 * If this frequency is 3x lower (and data received in the DMA
2344 * buffer don't start with 0x47, but in the middle of packets,
2345 * whose lengths appear to be like 188 292 188 104 etc.
2346 * this means VSYNC line is not connected in the hardware.
2347 * (check soldering pcb and pins)
2348 * The same behaviour of missing VSYNC can be duplicated on budget
2349 * cards, by seting DD1_INIT trigger mode 7 in 3rd nibble.
2350 */
Johannes Stezenbach1be11e32006-02-27 00:09:20 -03002351static int __devinit av7110_attach(struct saa7146_dev* dev,
2352 struct saa7146_pci_extension_data *pci_ext)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002353{
2354 const int length = TS_WIDTH * TS_HEIGHT;
2355 struct pci_dev *pdev = dev->pci;
2356 struct av7110 *av7110;
Herbert Poetzl8eec1422007-02-08 14:32:43 -03002357 struct task_struct *thread;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002358 int ret, count = 0;
2359
2360 dprintk(4, "dev: %p\n", dev);
2361
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -08002362 /* Set RPS_IRQ to 1 to track rps1 activity.
2363 * Enabling this won't send any interrupt to PC CPU.
2364 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002365#define RPS_IRQ 0
2366
2367 if (budgetpatch == 1) {
2368 budgetpatch = 0;
2369 /* autodetect the presence of budget patch
2370 * this only works if saa7146 has been recently
2371 * reset with with MASK_31 to MC1
2372 *
2373 * will wait for VBI_B event (vertical blank at port B)
2374 * and will reset GPIO3 after VBI_B is detected.
2375 * (GPIO3 should be raised high by CPU to
2376 * test if GPIO3 will generate vertical blank signal
2377 * in budget patch GPIO3 is connected to VSYNC_B
2378 */
2379
2380 /* RESET SAA7146 */
2381 saa7146_write(dev, MC1, MASK_31);
2382 /* autodetection success seems to be time-dependend after reset */
2383
2384 /* Fix VSYNC level */
2385 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
2386 /* set vsync_b triggering */
2387 saa7146_write(dev, DD1_STREAM_B, 0);
2388 /* port B VSYNC at rising edge */
2389 saa7146_write(dev, DD1_INIT, 0x00000200);
2390 saa7146_write(dev, BRS_CTRL, 0x00000000); // VBI
2391 saa7146_write(dev, MC2,
2392 1 * (MASK_08 | MASK_24) | // BRS control
2393 0 * (MASK_09 | MASK_25) | // a
2394 1 * (MASK_10 | MASK_26) | // b
2395 0 * (MASK_06 | MASK_22) | // HPS_CTRL1
2396 0 * (MASK_05 | MASK_21) | // HPS_CTRL2
2397 0 * (MASK_01 | MASK_15) // DEBI
2398 );
2399
2400 /* start writing RPS1 code from beginning */
2401 count = 0;
2402 /* Disable RPS1 */
2403 saa7146_write(dev, MC1, MASK_29);
2404 /* RPS1 timeout disable */
2405 saa7146_write(dev, RPS_TOV1, 0);
2406 WRITE_RPS1(cpu_to_le32(CMD_PAUSE | EVT_VBI_B));
2407 WRITE_RPS1(cpu_to_le32(CMD_WR_REG_MASK | (GPIO_CTRL>>2)));
2408 WRITE_RPS1(cpu_to_le32(GPIO3_MSK));
2409 WRITE_RPS1(cpu_to_le32(SAA7146_GPIO_OUTLO<<24));
2410#if RPS_IRQ
2411 /* issue RPS1 interrupt to increment counter */
2412 WRITE_RPS1(cpu_to_le32(CMD_INTERRUPT));
2413#endif
2414 WRITE_RPS1(cpu_to_le32(CMD_STOP));
2415 /* Jump to begin of RPS program as safety measure (p37) */
2416 WRITE_RPS1(cpu_to_le32(CMD_JUMP));
2417 WRITE_RPS1(cpu_to_le32(dev->d_rps1.dma_handle));
2418
2419#if RPS_IRQ
2420 /* set event counter 1 source as RPS1 interrupt (0x03) (rE4 p53)
2421 * use 0x03 to track RPS1 interrupts - increase by 1 every gpio3 is toggled
2422 * use 0x15 to track VPE interrupts - increase by 1 every vpeirq() is called
2423 */
2424 saa7146_write(dev, EC1SSR, (0x03<<2) | 3 );
2425 /* set event counter 1 treshold to maximum allowed value (rEC p55) */
2426 saa7146_write(dev, ECT1R, 0x3fff );
2427#endif
2428 /* Set RPS1 Address register to point to RPS code (r108 p42) */
2429 saa7146_write(dev, RPS_ADDR1, dev->d_rps1.dma_handle);
2430 /* Enable RPS1, (rFC p33) */
2431 saa7146_write(dev, MC1, (MASK_13 | MASK_29 ));
2432
2433 mdelay(10);
2434 /* now send VSYNC_B to rps1 by rising GPIO3 */
2435 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI);
2436 mdelay(10);
2437 /* if rps1 responded by lowering the GPIO3,
2438 * then we have budgetpatch hardware
2439 */
2440 if ((saa7146_read(dev, GPIO_CTRL) & 0x10000000) == 0) {
2441 budgetpatch = 1;
2442 printk("dvb-ttpci: BUDGET-PATCH DETECTED.\n");
2443 }
2444 /* Disable RPS1 */
2445 saa7146_write(dev, MC1, ( MASK_29 ));
2446#if RPS_IRQ
2447 printk("dvb-ttpci: Event Counter 1 0x%04x\n", saa7146_read(dev, EC1R) & 0x3fff );
2448#endif
2449 }
2450
2451 /* prepare the av7110 device struct */
Panagiotis Issaris74081872006-01-11 19:40:56 -02002452 av7110 = kzalloc(sizeof(struct av7110), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002453 if (!av7110) {
2454 dprintk(1, "out of memory\n");
2455 return -ENOMEM;
2456 }
2457
Linus Torvalds1da177e2005-04-16 15:20:36 -07002458 av7110->card_name = (char*) pci_ext->ext_priv;
2459 av7110->dev = dev;
2460 dev->ext_priv = av7110;
2461
2462 ret = get_firmware(av7110);
2463 if (ret < 0)
2464 goto err_kfree_0;
2465
2466 ret = dvb_register_adapter(&av7110->dvb_adapter, av7110->card_name,
Janne Grunau78e92002008-04-09 19:13:13 -03002467 THIS_MODULE, &dev->pci->dev, adapter_nr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002468 if (ret < 0)
2469 goto err_put_firmware_1;
2470
2471 /* the Siemens DVB needs this if you want to have the i2c chips
2472 get recognized before the main driver is fully loaded */
2473 saa7146_write(dev, GPIO_CTRL, 0x500000);
2474
2475#ifdef I2C_ADAP_CLASS_TV_DIGITAL
2476 av7110->i2c_adap.class = I2C_ADAP_CLASS_TV_DIGITAL;
2477#else
2478 av7110->i2c_adap.class = I2C_CLASS_TV_DIGITAL;
2479#endif
2480 strlcpy(av7110->i2c_adap.name, pci_ext->ext_priv, sizeof(av7110->i2c_adap.name));
2481
2482 saa7146_i2c_adapter_prepare(dev, &av7110->i2c_adap, SAA7146_I2C_BUS_BIT_RATE_120); /* 275 kHz */
2483
2484 ret = i2c_add_adapter(&av7110->i2c_adap);
2485 if (ret < 0)
2486 goto err_dvb_unregister_adapter_2;
2487
2488 ttpci_eeprom_parse_mac(&av7110->i2c_adap,
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07002489 av7110->dvb_adapter.proposed_mac);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002490 ret = -ENOMEM;
2491
2492 if (budgetpatch) {
2493 spin_lock_init(&av7110->feedlock1);
2494 av7110->grabbing = saa7146_vmalloc_build_pgtable(pdev, length,
2495 &av7110->pt);
2496 if (!av7110->grabbing)
2497 goto err_i2c_del_3;
2498
2499 saa7146_write(dev, PCI_BT_V1, 0x1c1f101f);
2500 saa7146_write(dev, BCS_CTRL, 0x80400040);
2501 /* set dd1 stream a & b */
2502 saa7146_write(dev, DD1_STREAM_B, 0x00000000);
2503 saa7146_write(dev, DD1_INIT, 0x03000200);
2504 saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
2505 saa7146_write(dev, BRS_CTRL, 0x60000000);
2506 saa7146_write(dev, BASE_ODD3, 0);
2507 saa7146_write(dev, BASE_EVEN3, 0);
2508 saa7146_write(dev, PROT_ADDR3, TS_WIDTH * TS_HEIGHT);
2509 saa7146_write(dev, BASE_PAGE3, av7110->pt.dma | ME1 | 0x90);
2510
2511 saa7146_write(dev, PITCH3, TS_WIDTH);
2512 saa7146_write(dev, NUM_LINE_BYTE3, (TS_HEIGHT << 16) | TS_WIDTH);
2513
2514 /* upload all */
2515 saa7146_write(dev, MC2, 0x077c077c);
2516 saa7146_write(dev, GPIO_CTRL, 0x000000);
2517#if RPS_IRQ
2518 /* set event counter 1 source as RPS1 interrupt (0x03) (rE4 p53)
2519 * use 0x03 to track RPS1 interrupts - increase by 1 every gpio3 is toggled
2520 * use 0x15 to track VPE interrupts - increase by 1 every vpeirq() is called
2521 */
2522 saa7146_write(dev, EC1SSR, (0x03<<2) | 3 );
2523 /* set event counter 1 treshold to maximum allowed value (rEC p55) */
2524 saa7146_write(dev, ECT1R, 0x3fff );
2525#endif
2526 /* Setup BUDGETPATCH MAIN RPS1 "program" (p35) */
2527 count = 0;
2528
2529 /* Wait Source Line Counter Threshold (p36) */
2530 WRITE_RPS1(cpu_to_le32(CMD_PAUSE | EVT_HS));
2531 /* Set GPIO3=1 (p42) */
2532 WRITE_RPS1(cpu_to_le32(CMD_WR_REG_MASK | (GPIO_CTRL>>2)));
2533 WRITE_RPS1(cpu_to_le32(GPIO3_MSK));
2534 WRITE_RPS1(cpu_to_le32(SAA7146_GPIO_OUTHI<<24));
2535#if RPS_IRQ
2536 /* issue RPS1 interrupt */
2537 WRITE_RPS1(cpu_to_le32(CMD_INTERRUPT));
2538#endif
2539 /* Wait reset Source Line Counter Threshold (p36) */
2540 WRITE_RPS1(cpu_to_le32(CMD_PAUSE | RPS_INV | EVT_HS));
2541 /* Set GPIO3=0 (p42) */
2542 WRITE_RPS1(cpu_to_le32(CMD_WR_REG_MASK | (GPIO_CTRL>>2)));
2543 WRITE_RPS1(cpu_to_le32(GPIO3_MSK));
2544 WRITE_RPS1(cpu_to_le32(SAA7146_GPIO_OUTLO<<24));
2545#if RPS_IRQ
2546 /* issue RPS1 interrupt */
2547 WRITE_RPS1(cpu_to_le32(CMD_INTERRUPT));
2548#endif
2549 /* Jump to begin of RPS program (p37) */
2550 WRITE_RPS1(cpu_to_le32(CMD_JUMP));
2551 WRITE_RPS1(cpu_to_le32(dev->d_rps1.dma_handle));
2552
2553 /* Fix VSYNC level */
2554 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
2555 /* Set RPS1 Address register to point to RPS code (r108 p42) */
2556 saa7146_write(dev, RPS_ADDR1, dev->d_rps1.dma_handle);
2557 /* Set Source Line Counter Threshold, using BRS (rCC p43)
2558 * It generates HS event every TS_HEIGHT lines
2559 * this is related to TS_WIDTH set in register
2560 * NUM_LINE_BYTE3. If NUM_LINE_BYTE low 16 bits
2561 * are set to TS_WIDTH bytes (TS_WIDTH=2*188),
2562 * then RPS_THRESH1 should be set to trigger
2563 * every TS_HEIGHT (512) lines.
2564 */
2565 saa7146_write(dev, RPS_THRESH1, (TS_HEIGHT*1) | MASK_12 );
2566
2567 /* Enable RPS1 (rFC p33) */
2568 saa7146_write(dev, MC1, (MASK_13 | MASK_29));
2569
2570 /* end of budgetpatch register initialization */
2571 tasklet_init (&av7110->vpe_tasklet, vpeirq, (unsigned long) av7110);
2572 } else {
2573 saa7146_write(dev, PCI_BT_V1, 0x1c00101f);
2574 saa7146_write(dev, BCS_CTRL, 0x80400040);
2575
2576 /* set dd1 stream a & b */
2577 saa7146_write(dev, DD1_STREAM_B, 0x00000000);
2578 saa7146_write(dev, DD1_INIT, 0x03000000);
2579 saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
2580
2581 /* upload all */
2582 saa7146_write(dev, MC2, 0x077c077c);
2583 saa7146_write(dev, GPIO_CTRL, 0x000000);
2584 }
2585
2586 tasklet_init (&av7110->debi_tasklet, debiirq, (unsigned long) av7110);
2587 tasklet_init (&av7110->gpio_tasklet, gpioirq, (unsigned long) av7110);
2588
Ingo Molnar3593cab2006-02-07 06:49:14 -02002589 mutex_init(&av7110->pid_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002590
2591 /* locks for data transfers from/to AV7110 */
2592 spin_lock_init(&av7110->debilock);
Ingo Molnar3593cab2006-02-07 06:49:14 -02002593 mutex_init(&av7110->dcomlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002594 av7110->debitype = -1;
2595
2596 /* default OSD window */
2597 av7110->osdwin = 1;
Ingo Molnar3593cab2006-02-07 06:49:14 -02002598 mutex_init(&av7110->osd_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002599
C.Y.M2f03ee82006-03-30 04:31:48 -03002600 /* TV standard */
Marco Schluessler58a44042007-10-31 01:20:42 -03002601 av7110->vidmode = tv_standard == 1 ? AV7110_VIDEO_MODE_NTSC
2602 : AV7110_VIDEO_MODE_PAL;
C.Y.M2f03ee82006-03-30 04:31:48 -03002603
Linus Torvalds1da177e2005-04-16 15:20:36 -07002604 /* ARM "watchdog" */
2605 init_waitqueue_head(&av7110->arm_wait);
2606 av7110->arm_thread = NULL;
2607
2608 /* allocate and init buffers */
2609 av7110->debi_virt = pci_alloc_consistent(pdev, 8192, &av7110->debi_bus);
2610 if (!av7110->debi_virt)
2611 goto err_saa71466_vfree_4;
2612
2613
2614 av7110->iobuf = vmalloc(AVOUTLEN+AOUTLEN+BMPLEN+4*IPACKS);
2615 if (!av7110->iobuf)
2616 goto err_pci_free_5;
2617
2618 ret = av7110_av_init(av7110);
2619 if (ret < 0)
2620 goto err_iobuf_vfree_6;
2621
2622 /* init BMP buffer */
2623 av7110->bmpbuf = av7110->iobuf+AVOUTLEN+AOUTLEN;
2624 init_waitqueue_head(&av7110->bmpq);
2625
2626 ret = av7110_ca_init(av7110);
2627 if (ret < 0)
2628 goto err_av7110_av_exit_7;
2629
2630 /* load firmware into AV7110 cards */
2631 ret = av7110_bootarm(av7110);
2632 if (ret < 0)
2633 goto err_av7110_ca_exit_8;
2634
2635 ret = av7110_firmversion(av7110);
2636 if (ret < 0)
2637 goto err_stop_arm_9;
2638
2639 if (FW_VERSION(av7110->arm_app)<0x2501)
2640 printk ("dvb-ttpci: Warning, firmware version 0x%04x is too old. "
2641 "System might be unstable!\n", FW_VERSION(av7110->arm_app));
2642
Herbert Poetzl8eec1422007-02-08 14:32:43 -03002643 thread = kthread_run(arm_thread, (void *) av7110, "arm_mon");
2644 if (IS_ERR(thread)) {
2645 ret = PTR_ERR(thread);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002646 goto err_stop_arm_9;
Herbert Poetzl8eec1422007-02-08 14:32:43 -03002647 }
2648 av7110->arm_thread = thread;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002649
2650 /* set initial volume in mixer struct */
2651 av7110->mixer.volume_left = volume;
2652 av7110->mixer.volume_right = volume;
2653
Linus Torvalds1da177e2005-04-16 15:20:36 -07002654 ret = av7110_register(av7110);
2655 if (ret < 0)
2656 goto err_arm_thread_stop_10;
2657
Oliver Endrissdefd574e2007-07-12 23:08:07 -03002658 init_av7110_av(av7110);
2659
Linus Torvalds1da177e2005-04-16 15:20:36 -07002660 /* special case DVB-C: these cards have an analog tuner
2661 plus need some special handling, so we have separate
2662 saa7146_ext_vv data for these... */
2663 ret = av7110_init_v4l(av7110);
2664 if (ret < 0)
2665 goto err_av7110_unregister_11;
2666
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07002667 av7110->dvb_adapter.priv = av7110;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002668 ret = frontend_init(av7110);
2669 if (ret < 0)
2670 goto err_av7110_exit_v4l_12;
2671
2672#if defined(CONFIG_INPUT_EVDEV) || defined(CONFIG_INPUT_EVDEV_MODULE)
Oliver Endriss03388ae2005-09-09 13:03:12 -07002673 av7110_ir_init(av7110);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002674#endif
2675 printk(KERN_INFO "dvb-ttpci: found av7110-%d.\n", av7110_num);
2676 av7110_num++;
2677out:
2678 return ret;
2679
2680err_av7110_exit_v4l_12:
2681 av7110_exit_v4l(av7110);
2682err_av7110_unregister_11:
2683 dvb_unregister(av7110);
2684err_arm_thread_stop_10:
2685 av7110_arm_sync(av7110);
2686err_stop_arm_9:
2687 /* Nothing to do. Rejoice. */
2688err_av7110_ca_exit_8:
2689 av7110_ca_exit(av7110);
2690err_av7110_av_exit_7:
2691 av7110_av_exit(av7110);
2692err_iobuf_vfree_6:
2693 vfree(av7110->iobuf);
2694err_pci_free_5:
2695 pci_free_consistent(pdev, 8192, av7110->debi_virt, av7110->debi_bus);
2696err_saa71466_vfree_4:
Jon Burgess87c30192007-05-03 12:23:44 -03002697 if (av7110->grabbing)
2698 saa7146_vfree_destroy_pgtable(pdev, av7110->grabbing, &av7110->pt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002699err_i2c_del_3:
2700 i2c_del_adapter(&av7110->i2c_adap);
2701err_dvb_unregister_adapter_2:
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07002702 dvb_unregister_adapter(&av7110->dvb_adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002703err_put_firmware_1:
2704 put_firmware(av7110);
2705err_kfree_0:
2706 kfree(av7110);
2707 goto out;
2708}
2709
Johannes Stezenbach1be11e32006-02-27 00:09:20 -03002710static int __devexit av7110_detach(struct saa7146_dev* saa)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002711{
2712 struct av7110 *av7110 = saa->ext_priv;
2713 dprintk(4, "%p\n", av7110);
2714
Oliver Endriss03388ae2005-09-09 13:03:12 -07002715#if defined(CONFIG_INPUT_EVDEV) || defined(CONFIG_INPUT_EVDEV_MODULE)
2716 av7110_ir_exit(av7110);
2717#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07002718 if (budgetpatch) {
2719 /* Disable RPS1 */
2720 saa7146_write(saa, MC1, MASK_29);
2721 /* VSYNC LOW (inactive) */
2722 saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);
2723 saa7146_write(saa, MC1, MASK_20); /* DMA3 off */
2724 SAA7146_IER_DISABLE(saa, MASK_10);
2725 SAA7146_ISR_CLEAR(saa, MASK_10);
2726 msleep(50);
2727 tasklet_kill(&av7110->vpe_tasklet);
Jon Burgess87c30192007-05-03 12:23:44 -03002728 saa7146_vfree_destroy_pgtable(saa->pci, av7110->grabbing, &av7110->pt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002729 }
2730 av7110_exit_v4l(av7110);
2731
2732 av7110_arm_sync(av7110);
2733
2734 tasklet_kill(&av7110->debi_tasklet);
2735 tasklet_kill(&av7110->gpio_tasklet);
2736
2737 dvb_unregister(av7110);
2738
2739 SAA7146_IER_DISABLE(saa, MASK_19 | MASK_03);
2740 SAA7146_ISR_CLEAR(saa, MASK_19 | MASK_03);
2741
2742 av7110_ca_exit(av7110);
2743 av7110_av_exit(av7110);
2744
2745 vfree(av7110->iobuf);
2746 pci_free_consistent(saa->pci, 8192, av7110->debi_virt,
2747 av7110->debi_bus);
2748
2749 i2c_del_adapter(&av7110->i2c_adap);
2750
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07002751 dvb_unregister_adapter (&av7110->dvb_adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002752
2753 av7110_num--;
2754
2755 put_firmware(av7110);
2756
2757 kfree(av7110);
2758
2759 saa->ext_priv = NULL;
2760
2761 return 0;
2762}
2763
2764
2765static void av7110_irq(struct saa7146_dev* dev, u32 *isr)
2766{
2767 struct av7110 *av7110 = dev->ext_priv;
2768
2769 //print_time("av7110_irq");
2770
2771 /* Note: Don't try to handle the DEBI error irq (MASK_18), in
2772 * intel mode the timeout is asserted all the time...
2773 */
2774
2775 if (*isr & MASK_19) {
2776 //printk("av7110_irq: DEBI\n");
2777 /* Note 1: The DEBI irq is level triggered: We must enable it
2778 * only after we started a DMA xfer, and disable it here
2779 * immediately, or it will be signalled all the time while
2780 * DEBI is idle.
2781 * Note 2: You would think that an irq which is masked is
2782 * not signalled by the hardware. Not so for the SAA7146:
2783 * An irq is signalled as long as the corresponding bit
2784 * in the ISR is set, and disabling irqs just prevents the
2785 * hardware from setting the ISR bit. This means a) that we
2786 * must clear the ISR *after* disabling the irq (which is why
2787 * we must do it here even though saa7146_core did it already),
2788 * and b) that if we were to disable an edge triggered irq
2789 * (like the gpio irqs sadly are) temporarily we would likely
2790 * loose some. This sucks :-(
2791 */
2792 SAA7146_IER_DISABLE(av7110->dev, MASK_19);
2793 SAA7146_ISR_CLEAR(av7110->dev, MASK_19);
2794 tasklet_schedule(&av7110->debi_tasklet);
2795 }
2796
2797 if (*isr & MASK_03) {
2798 //printk("av7110_irq: GPIO\n");
2799 tasklet_schedule(&av7110->gpio_tasklet);
2800 }
2801
2802 if ((*isr & MASK_10) && budgetpatch)
2803 tasklet_schedule(&av7110->vpe_tasklet);
2804}
2805
2806
Randy Dunlapda517162008-01-10 19:31:47 -03002807static struct saa7146_extension av7110_extension_driver;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002808
2809#define MAKE_AV7110_INFO(x_var,x_name) \
2810static struct saa7146_pci_extension_data x_var = { \
2811 .ext_priv = x_name, \
Randy Dunlapda517162008-01-10 19:31:47 -03002812 .ext = &av7110_extension_driver }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002813
Karl Herz6af4ee12005-09-09 13:03:13 -07002814MAKE_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 -07002815MAKE_AV7110_INFO(ttt_1_X, "Technotrend/Hauppauge WinTV DVB-T rev1.X");
2816MAKE_AV7110_INFO(ttc_1_X, "Technotrend/Hauppauge WinTV Nexus-CA rev1.X");
2817MAKE_AV7110_INFO(ttc_2_X, "Technotrend/Hauppauge WinTV DVB-C rev2.X");
2818MAKE_AV7110_INFO(tts_2_X, "Technotrend/Hauppauge WinTV Nexus-S rev2.X");
Johannes Stezenbach3dfaebd2005-05-16 21:54:19 -07002819MAKE_AV7110_INFO(tts_2_3, "Technotrend/Hauppauge WinTV Nexus-S rev2.3");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002820MAKE_AV7110_INFO(tts_1_3se, "Technotrend/Hauppauge WinTV DVB-S rev1.3 SE");
2821MAKE_AV7110_INFO(ttt, "Technotrend/Hauppauge DVB-T");
2822MAKE_AV7110_INFO(fsc, "Fujitsu Siemens DVB-C");
2823MAKE_AV7110_INFO(fss, "Fujitsu Siemens DVB-S rev1.6");
Oliver Endriss8bd63012006-02-07 06:49:11 -02002824MAKE_AV7110_INFO(gxs_1_3, "Galaxis DVB-S rev1.3");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002825
2826static struct pci_device_id pci_tbl[] = {
Karl Herz6af4ee12005-09-09 13:03:13 -07002827 MAKE_EXTENSION_PCI(fsc, 0x110a, 0x0000),
2828 MAKE_EXTENSION_PCI(tts_1_X_fsc, 0x13c2, 0x0000),
2829 MAKE_EXTENSION_PCI(ttt_1_X, 0x13c2, 0x0001),
2830 MAKE_EXTENSION_PCI(ttc_2_X, 0x13c2, 0x0002),
2831 MAKE_EXTENSION_PCI(tts_2_X, 0x13c2, 0x0003),
Oliver Endriss8bd63012006-02-07 06:49:11 -02002832 MAKE_EXTENSION_PCI(gxs_1_3, 0x13c2, 0x0004),
Karl Herz6af4ee12005-09-09 13:03:13 -07002833 MAKE_EXTENSION_PCI(fss, 0x13c2, 0x0006),
2834 MAKE_EXTENSION_PCI(ttt, 0x13c2, 0x0008),
2835 MAKE_EXTENSION_PCI(ttc_1_X, 0x13c2, 0x000a),
2836 MAKE_EXTENSION_PCI(tts_2_3, 0x13c2, 0x000e),
2837 MAKE_EXTENSION_PCI(tts_1_3se, 0x13c2, 0x1002),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002838
Linus Torvalds1da177e2005-04-16 15:20:36 -07002839/* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0005), UNDEFINED CARD */ // Technisat SkyStar1
2840/* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0009), UNDEFINED CARD */ // TT/Hauppauge WinTV Nexus-CA v????
2841
2842 {
2843 .vendor = 0,
2844 }
2845};
2846
2847MODULE_DEVICE_TABLE(pci, pci_tbl);
2848
2849
Randy Dunlapda517162008-01-10 19:31:47 -03002850static struct saa7146_extension av7110_extension_driver = {
Dave Jones0e367a12006-08-07 13:18:56 -03002851 .name = "dvb",
Oliver Endriss00c4cc62006-11-01 13:09:51 -03002852 .flags = SAA7146_USE_I2C_IRQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002853
2854 .module = THIS_MODULE,
2855 .pci_tbl = &pci_tbl[0],
2856 .attach = av7110_attach,
Johannes Stezenbach1be11e32006-02-27 00:09:20 -03002857 .detach = __devexit_p(av7110_detach),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002858
2859 .irq_mask = MASK_19 | MASK_03 | MASK_10,
2860 .irq_func = av7110_irq,
2861};
2862
2863
2864static int __init av7110_init(void)
2865{
2866 int retval;
Randy Dunlapda517162008-01-10 19:31:47 -03002867 retval = saa7146_register_extension(&av7110_extension_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002868 return retval;
2869}
2870
2871
2872static void __exit av7110_exit(void)
2873{
Randy Dunlapda517162008-01-10 19:31:47 -03002874 saa7146_unregister_extension(&av7110_extension_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002875}
2876
2877module_init(av7110_init);
2878module_exit(av7110_exit);
2879
2880MODULE_DESCRIPTION("driver for the SAA7146 based AV110 PCI DVB cards by "
2881 "Siemens, Technotrend, Hauppauge");
2882MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, others");
2883MODULE_LICENSE("GPL");