blob: 3b641804f6cb0bec069a3c7c7b72766a05864107 [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
Al Virob0ba0e32008-06-22 14:20:29 -0300590 dvb_ringbuffer_read(cibuf, av7110->debi_virt, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700591
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);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001201 budget->ttbp = 0;
1202 SAA7146_IER_ENABLE(budget->dev, MASK_10); /* VPE */
1203 saa7146_write(budget->dev, MC1, (MASK_04 | MASK_20)); /* DMA3 on */
1204 return ++budget->feeding1;
1205}
1206
1207static int budget_start_feed(struct dvb_demux_feed *feed)
1208{
1209 struct dvb_demux *demux = feed->demux;
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001210 struct av7110 *budget = demux->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001211 int status;
1212
1213 dprintk(2, "av7110: %p\n", budget);
1214
1215 spin_lock(&budget->feedlock1);
1216 feed->pusi_seen = 0; /* have a clean section start */
1217 status = start_ts_capture(budget);
1218 spin_unlock(&budget->feedlock1);
1219 return status;
1220}
1221
1222static int budget_stop_feed(struct dvb_demux_feed *feed)
1223{
1224 struct dvb_demux *demux = feed->demux;
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001225 struct av7110 *budget = demux->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001226 int status;
1227
1228 dprintk(2, "budget: %p\n", budget);
1229
1230 spin_lock(&budget->feedlock1);
1231 status = stop_ts_capture(budget);
1232 spin_unlock(&budget->feedlock1);
1233 return status;
1234}
1235
1236static void vpeirq(unsigned long data)
1237{
1238 struct av7110 *budget = (struct av7110 *) data;
1239 u8 *mem = (u8 *) (budget->grabbing);
1240 u32 olddma = budget->ttbp;
1241 u32 newdma = saa7146_read(budget->dev, PCI_VDP3);
1242
1243 if (!budgetpatch) {
1244 printk("av7110.c: vpeirq() called while budgetpatch disabled!"
1245 " check saa7146 IER register\n");
1246 BUG();
1247 }
1248 /* nearest lower position divisible by 188 */
1249 newdma -= newdma % 188;
1250
1251 if (newdma >= TS_BUFLEN)
1252 return;
1253
1254 budget->ttbp = newdma;
1255
1256 if (!budget->feeding1 || (newdma == olddma))
1257 return;
1258
Jon Burgess87c30192007-05-03 12:23:44 -03001259 /* Ensure streamed PCI data is synced to CPU */
1260 pci_dma_sync_sg_for_cpu(budget->dev->pci, budget->pt.slist, budget->pt.nents, PCI_DMA_FROMDEVICE);
1261
Linus Torvalds1da177e2005-04-16 15:20:36 -07001262#if 0
1263 /* track rps1 activity */
1264 printk("vpeirq: %02x Event Counter 1 0x%04x\n",
1265 mem[olddma],
1266 saa7146_read(budget->dev, EC1R) & 0x3fff);
1267#endif
1268
1269 if (newdma > olddma)
1270 /* no wraparound, dump olddma..newdma */
1271 dvb_dmx_swfilter_packets(&budget->demux1, mem + olddma, (newdma - olddma) / 188);
1272 else {
1273 /* wraparound, dump olddma..buflen and 0..newdma */
1274 dvb_dmx_swfilter_packets(&budget->demux1, mem + olddma, (TS_BUFLEN - olddma) / 188);
1275 dvb_dmx_swfilter_packets(&budget->demux1, mem, newdma / 188);
1276 }
1277}
1278
1279static int av7110_register(struct av7110 *av7110)
1280{
1281 int ret, i;
1282 struct dvb_demux *dvbdemux = &av7110->demux;
1283 struct dvb_demux *dvbdemux1 = &av7110->demux1;
1284
1285 dprintk(4, "%p\n", av7110);
1286
1287 if (av7110->registered)
1288 return -1;
1289
1290 av7110->registered = 1;
1291
1292 dvbdemux->priv = (void *) av7110;
1293
1294 for (i = 0; i < 32; i++)
1295 av7110->handle2filter[i] = NULL;
1296
1297 dvbdemux->filternum = 32;
1298 dvbdemux->feednum = 32;
1299 dvbdemux->start_feed = av7110_start_feed;
1300 dvbdemux->stop_feed = av7110_stop_feed;
1301 dvbdemux->write_to_decoder = av7110_write_to_decoder;
1302 dvbdemux->dmx.capabilities = (DMX_TS_FILTERING | DMX_SECTION_FILTERING |
1303 DMX_MEMORY_BASED_FILTERING);
1304
1305 dvb_dmx_init(&av7110->demux);
1306 av7110->demux.dmx.get_stc = dvb_get_stc;
1307
1308 av7110->dmxdev.filternum = 32;
1309 av7110->dmxdev.demux = &dvbdemux->dmx;
1310 av7110->dmxdev.capabilities = 0;
1311
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001312 dvb_dmxdev_init(&av7110->dmxdev, &av7110->dvb_adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001313
1314 av7110->hw_frontend.source = DMX_FRONTEND_0;
1315
1316 ret = dvbdemux->dmx.add_frontend(&dvbdemux->dmx, &av7110->hw_frontend);
1317
1318 if (ret < 0)
1319 return ret;
1320
1321 av7110->mem_frontend.source = DMX_MEMORY_FE;
1322
1323 ret = dvbdemux->dmx.add_frontend(&dvbdemux->dmx, &av7110->mem_frontend);
1324
1325 if (ret < 0)
1326 return ret;
1327
1328 ret = dvbdemux->dmx.connect_frontend(&dvbdemux->dmx,
1329 &av7110->hw_frontend);
1330 if (ret < 0)
1331 return ret;
1332
1333 av7110_av_register(av7110);
1334 av7110_ca_register(av7110);
1335
1336#ifdef CONFIG_DVB_AV7110_OSD
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001337 dvb_register_device(&av7110->dvb_adapter, &av7110->osd_dev,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001338 &dvbdev_osd, av7110, DVB_DEVICE_OSD);
1339#endif
1340
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001341 dvb_net_init(&av7110->dvb_adapter, &av7110->dvb_net, &dvbdemux->dmx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001342
1343 if (budgetpatch) {
1344 /* initialize software demux1 without its own frontend
1345 * demux1 hardware is connected to frontend0 of demux0
1346 */
1347 dvbdemux1->priv = (void *) av7110;
1348
1349 dvbdemux1->filternum = 256;
1350 dvbdemux1->feednum = 256;
1351 dvbdemux1->start_feed = budget_start_feed;
1352 dvbdemux1->stop_feed = budget_stop_feed;
1353 dvbdemux1->write_to_decoder = NULL;
1354
1355 dvbdemux1->dmx.capabilities = (DMX_TS_FILTERING | DMX_SECTION_FILTERING |
1356 DMX_MEMORY_BASED_FILTERING);
1357
1358 dvb_dmx_init(&av7110->demux1);
1359
1360 av7110->dmxdev1.filternum = 256;
1361 av7110->dmxdev1.demux = &dvbdemux1->dmx;
1362 av7110->dmxdev1.capabilities = 0;
1363
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001364 dvb_dmxdev_init(&av7110->dmxdev1, &av7110->dvb_adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001365
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001366 dvb_net_init(&av7110->dvb_adapter, &av7110->dvb_net1, &dvbdemux1->dmx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001367 printk("dvb-ttpci: additional demux1 for budget-patch registered\n");
1368 }
1369 return 0;
1370}
1371
1372
1373static void dvb_unregister(struct av7110 *av7110)
1374{
1375 struct dvb_demux *dvbdemux = &av7110->demux;
1376 struct dvb_demux *dvbdemux1 = &av7110->demux1;
1377
1378 dprintk(4, "%p\n", av7110);
1379
1380 if (!av7110->registered)
1381 return;
1382
1383 if (budgetpatch) {
1384 dvb_net_release(&av7110->dvb_net1);
1385 dvbdemux->dmx.close(&dvbdemux1->dmx);
1386 dvb_dmxdev_release(&av7110->dmxdev1);
1387 dvb_dmx_release(&av7110->demux1);
1388 }
1389
1390 dvb_net_release(&av7110->dvb_net);
1391
1392 dvbdemux->dmx.close(&dvbdemux->dmx);
1393 dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &av7110->hw_frontend);
1394 dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &av7110->mem_frontend);
1395
1396 dvb_dmxdev_release(&av7110->dmxdev);
1397 dvb_dmx_release(&av7110->demux);
1398
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001399 if (av7110->fe != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001400 dvb_unregister_frontend(av7110->fe);
Andrew de Quinceyf52a8382006-08-08 09:10:09 -03001401 dvb_frontend_detach(av7110->fe);
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001402 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001403 dvb_unregister_device(av7110->osd_dev);
1404 av7110_av_unregister(av7110);
1405 av7110_ca_unregister(av7110);
1406}
1407
1408
1409/****************************************************************************
1410 * I2C client commands
1411 ****************************************************************************/
1412
1413int i2c_writereg(struct av7110 *av7110, u8 id, u8 reg, u8 val)
1414{
1415 u8 msg[2] = { reg, val };
1416 struct i2c_msg msgs;
1417
1418 msgs.flags = 0;
1419 msgs.addr = id / 2;
1420 msgs.len = 2;
1421 msgs.buf = msg;
1422 return i2c_transfer(&av7110->i2c_adap, &msgs, 1);
1423}
1424
1425#if 0
1426u8 i2c_readreg(struct av7110 *av7110, u8 id, u8 reg)
1427{
1428 u8 mm1[] = {0x00};
1429 u8 mm2[] = {0x00};
1430 struct i2c_msg msgs[2];
1431
1432 msgs[0].flags = 0;
1433 msgs[1].flags = I2C_M_RD;
1434 msgs[0].addr = msgs[1].addr = id / 2;
1435 mm1[0] = reg;
1436 msgs[0].len = 1; msgs[1].len = 1;
1437 msgs[0].buf = mm1; msgs[1].buf = mm2;
1438 i2c_transfer(&av7110->i2c_adap, msgs, 2);
1439
1440 return mm2[0];
1441}
1442#endif
1443
1444/****************************************************************************
1445 * INITIALIZATION
1446 ****************************************************************************/
1447
1448
1449static int check_firmware(struct av7110* av7110)
1450{
1451 u32 crc = 0, len = 0;
1452 unsigned char *ptr;
1453
1454 /* check for firmware magic */
1455 ptr = av7110->bin_fw;
1456 if (ptr[0] != 'A' || ptr[1] != 'V' ||
1457 ptr[2] != 'F' || ptr[3] != 'W') {
1458 printk("dvb-ttpci: this is not an av7110 firmware\n");
1459 return -EINVAL;
1460 }
1461 ptr += 4;
1462
1463 /* check dpram file */
Al Viro3e085622008-05-21 00:30:51 -03001464 crc = get_unaligned_be32(ptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001465 ptr += 4;
Al Viro3e085622008-05-21 00:30:51 -03001466 len = get_unaligned_be32(ptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001467 ptr += 4;
1468 if (len >= 512) {
Alexey Dobriyanbe787ac2006-03-07 22:20:23 -03001469 printk("dvb-ttpci: dpram file is way too big.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001470 return -EINVAL;
1471 }
1472 if (crc != crc32_le(0, ptr, len)) {
1473 printk("dvb-ttpci: crc32 of dpram file does not match.\n");
1474 return -EINVAL;
1475 }
1476 av7110->bin_dpram = ptr;
1477 av7110->size_dpram = len;
1478 ptr += len;
1479
1480 /* check root file */
Al Viro3e085622008-05-21 00:30:51 -03001481 crc = get_unaligned_be32(ptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001482 ptr += 4;
Al Viro3e085622008-05-21 00:30:51 -03001483 len = get_unaligned_be32(ptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001484 ptr += 4;
1485
1486 if (len <= 200000 || len >= 300000 ||
1487 len > ((av7110->bin_fw + av7110->size_fw) - ptr)) {
1488 printk("dvb-ttpci: root file has strange size (%d). aborting.\n", len);
1489 return -EINVAL;
1490 }
1491 if( crc != crc32_le(0, ptr, len)) {
1492 printk("dvb-ttpci: crc32 of root file does not match.\n");
1493 return -EINVAL;
1494 }
1495 av7110->bin_root = ptr;
1496 av7110->size_root = len;
1497 return 0;
1498}
1499
1500#ifdef CONFIG_DVB_AV7110_FIRMWARE_FILE
1501#include "av7110_firm.h"
1502static void put_firmware(struct av7110* av7110)
1503{
1504 av7110->bin_fw = NULL;
1505}
1506
1507static inline int get_firmware(struct av7110* av7110)
1508{
1509 av7110->bin_fw = dvb_ttpci_fw;
1510 av7110->size_fw = sizeof(dvb_ttpci_fw);
1511 return check_firmware(av7110);
1512}
1513#else
1514static void put_firmware(struct av7110* av7110)
1515{
1516 vfree(av7110->bin_fw);
1517}
1518
1519static int get_firmware(struct av7110* av7110)
1520{
1521 int ret;
1522 const struct firmware *fw;
1523
1524 /* request the av7110 firmware, this will block until someone uploads it */
1525 ret = request_firmware(&fw, "dvb-ttpci-01.fw", &av7110->dev->pci->dev);
1526 if (ret) {
1527 if (ret == -ENOENT) {
1528 printk(KERN_ERR "dvb-ttpci: could not load firmware,"
1529 " file not found: dvb-ttpci-01.fw\n");
Ville Skytt\ä12e66f62006-01-09 15:25:38 -02001530 printk(KERN_ERR "dvb-ttpci: usually this should be in "
1531 "/usr/lib/hotplug/firmware or /lib/firmware\n");
1532 printk(KERN_ERR "dvb-ttpci: and can be downloaded from"
Linus Torvalds1da177e2005-04-16 15:20:36 -07001533 " http://www.linuxtv.org/download/dvb/firmware/\n");
1534 } else
1535 printk(KERN_ERR "dvb-ttpci: cannot request firmware"
1536 " (error %i)\n", ret);
1537 return -EINVAL;
1538 }
1539
1540 if (fw->size <= 200000) {
1541 printk("dvb-ttpci: this firmware is way too small.\n");
1542 release_firmware(fw);
1543 return -EINVAL;
1544 }
1545
1546 /* check if the firmware is available */
Jesper Juhld9bf2c02007-08-25 11:23:54 -03001547 av7110->bin_fw = vmalloc(fw->size);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001548 if (NULL == av7110->bin_fw) {
1549 dprintk(1, "out of memory\n");
1550 release_firmware(fw);
1551 return -ENOMEM;
1552 }
1553
1554 memcpy(av7110->bin_fw, fw->data, fw->size);
1555 av7110->size_fw = fw->size;
1556 if ((ret = check_firmware(av7110)))
1557 vfree(av7110->bin_fw);
1558
1559 release_firmware(fw);
1560 return ret;
1561}
1562#endif
1563
1564
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001565static int alps_bsrv2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001566{
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001567 struct av7110* av7110 = fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001568 u8 pwr = 0;
1569 u8 buf[4];
1570 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
1571 u32 div = (params->frequency + 479500) / 125;
1572
1573 if (params->frequency > 2000000) pwr = 3;
1574 else if (params->frequency > 1800000) pwr = 2;
1575 else if (params->frequency > 1600000) pwr = 1;
1576 else if (params->frequency > 1200000) pwr = 0;
1577 else if (params->frequency >= 1100000) pwr = 1;
1578 else pwr = 2;
1579
1580 buf[0] = (div >> 8) & 0x7f;
1581 buf[1] = div & 0xff;
1582 buf[2] = ((div & 0x18000) >> 10) | 0x95;
1583 buf[3] = (pwr << 6) | 0x30;
1584
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -08001585 // NOTE: since we're using a prescaler of 2, we set the
Linus Torvalds1da177e2005-04-16 15:20:36 -07001586 // divisor frequency to 62.5kHz and divide by 125 above
1587
Patrick Boettcherdea74862006-05-14 05:01:31 -03001588 if (fe->ops.i2c_gate_ctrl)
1589 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001590 if (i2c_transfer (&av7110->i2c_adap, &msg, 1) != 1)
1591 return -EIO;
1592 return 0;
1593}
1594
1595static struct ves1x93_config alps_bsrv2_config = {
1596 .demod_address = 0x08,
1597 .xin = 90100000UL,
1598 .invert_pwm = 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001599};
1600
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001601static int alps_tdbe2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001602{
1603 struct av7110* av7110 = fe->dvb->priv;
1604 u32 div;
1605 u8 data[4];
1606 struct i2c_msg msg = { .addr = 0x62, .flags = 0, .buf = data, .len = sizeof(data) };
1607
1608 div = (params->frequency + 35937500 + 31250) / 62500;
1609
1610 data[0] = (div >> 8) & 0x7f;
1611 data[1] = div & 0xff;
1612 data[2] = 0x85 | ((div >> 10) & 0x60);
1613 data[3] = (params->frequency < 174000000 ? 0x88 : params->frequency < 470000000 ? 0x84 : 0x81);
1614
Patrick Boettcherdea74862006-05-14 05:01:31 -03001615 if (fe->ops.i2c_gate_ctrl)
1616 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001617 if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
1618 return -EIO;
1619 return 0;
1620}
1621
1622static struct ves1820_config alps_tdbe2_config = {
1623 .demod_address = 0x09,
1624 .xin = 57840000UL,
1625 .invert = 1,
1626 .selagc = VES1820_SELAGC_SIGNAMPERR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001627};
1628
1629
1630
1631
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001632static int grundig_29504_451_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001633{
1634 struct av7110* av7110 = fe->dvb->priv;
1635 u32 div;
1636 u8 data[4];
1637 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
1638
1639 div = params->frequency / 125;
1640 data[0] = (div >> 8) & 0x7f;
1641 data[1] = div & 0xff;
1642 data[2] = 0x8e;
1643 data[3] = 0x00;
1644
Patrick Boettcherdea74862006-05-14 05:01:31 -03001645 if (fe->ops.i2c_gate_ctrl)
1646 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001647 if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
1648 return -EIO;
1649 return 0;
1650}
1651
1652static struct tda8083_config grundig_29504_451_config = {
1653 .demod_address = 0x68,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001654};
1655
1656
1657
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001658static int philips_cd1516_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001659{
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -08001660 struct av7110* av7110 = fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001661 u32 div;
1662 u32 f = params->frequency;
1663 u8 data[4];
1664 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
1665
1666 div = (f + 36125000 + 31250) / 62500;
1667
1668 data[0] = (div >> 8) & 0x7f;
1669 data[1] = div & 0xff;
1670 data[2] = 0x8e;
1671 data[3] = (f < 174000000 ? 0xa1 : f < 470000000 ? 0x92 : 0x34);
1672
Patrick Boettcherdea74862006-05-14 05:01:31 -03001673 if (fe->ops.i2c_gate_ctrl)
1674 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001675 if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
1676 return -EIO;
1677 return 0;
1678}
1679
1680static struct ves1820_config philips_cd1516_config = {
1681 .demod_address = 0x09,
1682 .xin = 57840000UL,
1683 .invert = 1,
1684 .selagc = VES1820_SELAGC_SIGNAMPERR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001685};
1686
1687
1688
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001689static int alps_tdlb7_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001690{
1691 struct av7110* av7110 = fe->dvb->priv;
1692 u32 div, pwr;
1693 u8 data[4];
1694 struct i2c_msg msg = { .addr = 0x60, .flags = 0, .buf = data, .len = sizeof(data) };
1695
1696 div = (params->frequency + 36200000) / 166666;
1697
1698 if (params->frequency <= 782000000)
1699 pwr = 1;
1700 else
1701 pwr = 2;
1702
1703 data[0] = (div >> 8) & 0x7f;
1704 data[1] = div & 0xff;
1705 data[2] = 0x85;
1706 data[3] = pwr << 6;
1707
Patrick Boettcherdea74862006-05-14 05:01:31 -03001708 if (fe->ops.i2c_gate_ctrl)
1709 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001710 if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
1711 return -EIO;
1712 return 0;
1713}
1714
1715static int alps_tdlb7_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name)
1716{
Oliver Endrissd98821e2006-09-14 00:15:13 -03001717#if defined(CONFIG_DVB_SP8870) || defined(CONFIG_DVB_SP8870_MODULE)
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001718 struct av7110* av7110 = fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001719
1720 return request_firmware(fw, name, &av7110->dev->pci->dev);
Oliver Endrissd98821e2006-09-14 00:15:13 -03001721#else
1722 return -EINVAL;
1723#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001724}
1725
1726static struct sp8870_config alps_tdlb7_config = {
1727
1728 .demod_address = 0x71,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001729 .request_firmware = alps_tdlb7_request_firmware,
1730};
1731
1732
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001733static u8 nexusca_stv0297_inittab[] = {
1734 0x80, 0x01,
1735 0x80, 0x00,
1736 0x81, 0x01,
1737 0x81, 0x00,
1738 0x00, 0x09,
1739 0x01, 0x69,
1740 0x03, 0x00,
1741 0x04, 0x00,
1742 0x07, 0x00,
1743 0x08, 0x00,
1744 0x20, 0x00,
1745 0x21, 0x40,
1746 0x22, 0x00,
1747 0x23, 0x00,
1748 0x24, 0x40,
1749 0x25, 0x88,
1750 0x30, 0xff,
1751 0x31, 0x00,
1752 0x32, 0xff,
1753 0x33, 0x00,
1754 0x34, 0x50,
1755 0x35, 0x7f,
1756 0x36, 0x00,
1757 0x37, 0x20,
1758 0x38, 0x00,
1759 0x40, 0x1c,
1760 0x41, 0xff,
1761 0x42, 0x29,
1762 0x43, 0x00,
1763 0x44, 0xff,
1764 0x45, 0x00,
1765 0x46, 0x00,
1766 0x49, 0x04,
1767 0x4a, 0x00,
1768 0x4b, 0x7b,
1769 0x52, 0x30,
1770 0x55, 0xae,
1771 0x56, 0x47,
1772 0x57, 0xe1,
1773 0x58, 0x3a,
1774 0x5a, 0x1e,
1775 0x5b, 0x34,
1776 0x60, 0x00,
1777 0x63, 0x00,
1778 0x64, 0x00,
1779 0x65, 0x00,
1780 0x66, 0x00,
1781 0x67, 0x00,
1782 0x68, 0x00,
1783 0x69, 0x00,
1784 0x6a, 0x02,
1785 0x6b, 0x00,
1786 0x70, 0xff,
1787 0x71, 0x00,
1788 0x72, 0x00,
1789 0x73, 0x00,
1790 0x74, 0x0c,
1791 0x80, 0x00,
1792 0x81, 0x00,
1793 0x82, 0x00,
1794 0x83, 0x00,
1795 0x84, 0x04,
1796 0x85, 0x80,
1797 0x86, 0x24,
1798 0x87, 0x78,
1799 0x88, 0x10,
1800 0x89, 0x00,
1801 0x90, 0x01,
1802 0x91, 0x01,
1803 0xa0, 0x04,
1804 0xa1, 0x00,
1805 0xa2, 0x00,
1806 0xb0, 0x91,
1807 0xb1, 0x0b,
1808 0xc0, 0x53,
1809 0xc1, 0x70,
1810 0xc2, 0x12,
1811 0xd0, 0x00,
1812 0xd1, 0x00,
1813 0xd2, 0x00,
1814 0xd3, 0x00,
1815 0xd4, 0x00,
1816 0xd5, 0x00,
1817 0xde, 0x00,
1818 0xdf, 0x00,
1819 0x61, 0x49,
1820 0x62, 0x0b,
1821 0x53, 0x08,
1822 0x59, 0x08,
1823 0xff, 0xff,
1824};
Linus Torvalds1da177e2005-04-16 15:20:36 -07001825
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001826static int nexusca_stv0297_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001827{
1828 struct av7110* av7110 = fe->dvb->priv;
1829 u32 div;
1830 u8 data[4];
1831 struct i2c_msg msg = { .addr = 0x63, .flags = 0, .buf = data, .len = sizeof(data) };
1832 struct i2c_msg readmsg = { .addr = 0x63, .flags = I2C_M_RD, .buf = data, .len = 1 };
1833 int i;
1834
1835 div = (params->frequency + 36150000 + 31250) / 62500;
1836
1837 data[0] = (div >> 8) & 0x7f;
1838 data[1] = div & 0xff;
1839 data[2] = 0xce;
1840
1841 if (params->frequency < 45000000)
1842 return -EINVAL;
1843 else if (params->frequency < 137000000)
1844 data[3] = 0x01;
1845 else if (params->frequency < 403000000)
1846 data[3] = 0x02;
1847 else if (params->frequency < 860000000)
1848 data[3] = 0x04;
1849 else
1850 return -EINVAL;
1851
Patrick Boettcherdea74862006-05-14 05:01:31 -03001852 if (fe->ops.i2c_gate_ctrl)
1853 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001854 if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1) {
1855 printk("nexusca: pll transfer failed!\n");
1856 return -EIO;
1857 }
1858
1859 // wait for PLL lock
1860 for(i = 0; i < 20; i++) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001861 if (fe->ops.i2c_gate_ctrl)
1862 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001863 if (i2c_transfer(&av7110->i2c_adap, &readmsg, 1) == 1)
1864 if (data[0] & 0x40) break;
1865 msleep(10);
1866 }
1867
1868 return 0;
1869}
1870
1871static struct stv0297_config nexusca_stv0297_config = {
1872
1873 .demod_address = 0x1C,
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001874 .inittab = nexusca_stv0297_inittab,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001875 .invert = 1,
Thomas Kaiserb8d4c232006-04-27 21:45:20 -03001876 .stop_during_read = 1,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001877};
1878
1879
1880
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001881static int grundig_29504_401_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001882{
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001883 struct av7110* av7110 = fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001884 u32 div;
1885 u8 cfg, cpump, band_select;
1886 u8 data[4];
1887 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
1888
1889 div = (36125000 + params->frequency) / 166666;
1890
1891 cfg = 0x88;
1892
1893 if (params->frequency < 175000000) cpump = 2;
1894 else if (params->frequency < 390000000) cpump = 1;
1895 else if (params->frequency < 470000000) cpump = 2;
1896 else if (params->frequency < 750000000) cpump = 1;
1897 else cpump = 3;
1898
1899 if (params->frequency < 175000000) band_select = 0x0e;
1900 else if (params->frequency < 470000000) band_select = 0x05;
1901 else band_select = 0x03;
1902
1903 data[0] = (div >> 8) & 0x7f;
1904 data[1] = div & 0xff;
1905 data[2] = ((div >> 10) & 0x60) | cfg;
1906 data[3] = (cpump << 6) | band_select;
1907
Patrick Boettcherdea74862006-05-14 05:01:31 -03001908 if (fe->ops.i2c_gate_ctrl)
1909 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001910 if (i2c_transfer (&av7110->i2c_adap, &msg, 1) != 1) return -EIO;
1911 return 0;
1912}
1913
1914static struct l64781_config grundig_29504_401_config = {
1915 .demod_address = 0x55,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001916};
1917
1918
1919
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001920static int av7110_fe_lock_fix(struct av7110* av7110, fe_status_t status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001921{
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001922 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001923 int synced = (status & FE_HAS_LOCK) ? 1 : 0;
1924
1925 av7110->fe_status = status;
1926
1927 if (av7110->fe_synced == synced)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001928 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001929
Oliver Endriss14500d42007-03-03 14:45:48 -03001930 if (av7110->playing) {
1931 av7110->fe_synced = synced;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001932 return 0;
Oliver Endriss14500d42007-03-03 14:45:48 -03001933 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001934
Ingo Molnar3593cab2006-02-07 06:49:14 -02001935 if (mutex_lock_interruptible(&av7110->pid_mutex))
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001936 return -ERESTARTSYS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001937
Oliver Endriss34612152005-07-07 17:58:02 -07001938 if (synced) {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001939 ret = SetPIDs(av7110, av7110->pids[DMX_PES_VIDEO],
Linus Torvalds1da177e2005-04-16 15:20:36 -07001940 av7110->pids[DMX_PES_AUDIO],
1941 av7110->pids[DMX_PES_TELETEXT], 0,
1942 av7110->pids[DMX_PES_PCR]);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001943 if (!ret)
1944 ret = av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, Scan, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001945 } else {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001946 ret = SetPIDs(av7110, 0, 0, 0, 0, 0);
1947 if (!ret) {
1948 ret = av7110_fw_cmd(av7110, COMTYPE_PID_FILTER, FlushTSQueue, 0);
1949 if (!ret)
1950 ret = av7110_wait_msgstate(av7110, GPMQBusy);
1951 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001952 }
1953
Oliver Endriss34612152005-07-07 17:58:02 -07001954 if (!ret)
1955 av7110->fe_synced = synced;
1956
Ingo Molnar3593cab2006-02-07 06:49:14 -02001957 mutex_unlock(&av7110->pid_mutex);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001958 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001959}
1960
1961static int av7110_fe_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
1962{
1963 struct av7110* av7110 = fe->dvb->priv;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001964
1965 int ret = av7110_fe_lock_fix(av7110, 0);
Oliver Endriss66190a22006-01-09 15:32:42 -02001966 if (!ret) {
1967 av7110->saved_fe_params = *params;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001968 ret = av7110->fe_set_frontend(fe, params);
Oliver Endriss66190a22006-01-09 15:32:42 -02001969 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001970 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001971}
1972
1973static int av7110_fe_init(struct dvb_frontend* fe)
1974{
1975 struct av7110* av7110 = fe->dvb->priv;
1976
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001977 int ret = av7110_fe_lock_fix(av7110, 0);
1978 if (!ret)
1979 ret = av7110->fe_init(fe);
1980 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001981}
1982
1983static int av7110_fe_read_status(struct dvb_frontend* fe, fe_status_t* status)
1984{
1985 struct av7110* av7110 = fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001986
1987 /* call the real implementation */
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001988 int ret = av7110->fe_read_status(fe, status);
1989 if (!ret)
1990 if (((*status ^ av7110->fe_status) & FE_HAS_LOCK) && (*status & FE_HAS_LOCK))
1991 ret = av7110_fe_lock_fix(av7110, *status);
1992 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001993}
1994
1995static int av7110_fe_diseqc_reset_overload(struct dvb_frontend* fe)
1996{
1997 struct av7110* av7110 = fe->dvb->priv;
1998
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001999 int ret = av7110_fe_lock_fix(av7110, 0);
2000 if (!ret)
2001 ret = av7110->fe_diseqc_reset_overload(fe);
2002 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002003}
2004
2005static int av7110_fe_diseqc_send_master_cmd(struct dvb_frontend* fe,
2006 struct dvb_diseqc_master_cmd* cmd)
2007{
2008 struct av7110* av7110 = fe->dvb->priv;
2009
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002010 int ret = av7110_fe_lock_fix(av7110, 0);
Oliver Endriss66190a22006-01-09 15:32:42 -02002011 if (!ret) {
2012 av7110->saved_master_cmd = *cmd;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002013 ret = av7110->fe_diseqc_send_master_cmd(fe, cmd);
Oliver Endriss66190a22006-01-09 15:32:42 -02002014 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002015 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002016}
2017
2018static int av7110_fe_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd)
2019{
2020 struct av7110* av7110 = fe->dvb->priv;
2021
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002022 int ret = av7110_fe_lock_fix(av7110, 0);
Oliver Endriss66190a22006-01-09 15:32:42 -02002023 if (!ret) {
2024 av7110->saved_minicmd = minicmd;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002025 ret = av7110->fe_diseqc_send_burst(fe, minicmd);
Oliver Endriss66190a22006-01-09 15:32:42 -02002026 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002027 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002028}
2029
2030static int av7110_fe_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
2031{
2032 struct av7110* av7110 = fe->dvb->priv;
2033
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002034 int ret = av7110_fe_lock_fix(av7110, 0);
Oliver Endriss66190a22006-01-09 15:32:42 -02002035 if (!ret) {
2036 av7110->saved_tone = tone;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002037 ret = av7110->fe_set_tone(fe, tone);
Oliver Endriss66190a22006-01-09 15:32:42 -02002038 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002039 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002040}
2041
2042static int av7110_fe_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
2043{
2044 struct av7110* av7110 = fe->dvb->priv;
2045
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002046 int ret = av7110_fe_lock_fix(av7110, 0);
Oliver Endriss66190a22006-01-09 15:32:42 -02002047 if (!ret) {
2048 av7110->saved_voltage = voltage;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002049 ret = av7110->fe_set_voltage(fe, voltage);
Oliver Endriss66190a22006-01-09 15:32:42 -02002050 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002051 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002052}
2053
Peter Beutner400b7082006-01-09 15:32:43 -02002054static int av7110_fe_dishnetwork_send_legacy_command(struct dvb_frontend* fe, unsigned long cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002055{
2056 struct av7110* av7110 = fe->dvb->priv;
2057
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002058 int ret = av7110_fe_lock_fix(av7110, 0);
2059 if (!ret)
2060 ret = av7110->fe_dishnetwork_send_legacy_command(fe, cmd);
2061 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002062}
2063
Oliver Endriss66190a22006-01-09 15:32:42 -02002064static void dvb_s_recover(struct av7110* av7110)
2065{
2066 av7110_fe_init(av7110->fe);
2067
2068 av7110_fe_set_voltage(av7110->fe, av7110->saved_voltage);
2069 if (av7110->saved_master_cmd.msg_len) {
2070 msleep(20);
2071 av7110_fe_diseqc_send_master_cmd(av7110->fe, &av7110->saved_master_cmd);
2072 }
2073 msleep(20);
2074 av7110_fe_diseqc_send_burst(av7110->fe, av7110->saved_minicmd);
2075 msleep(20);
2076 av7110_fe_set_tone(av7110->fe, av7110->saved_tone);
2077
2078 av7110_fe_set_frontend(av7110->fe, &av7110->saved_fe_params);
2079}
2080
Linus Torvalds1da177e2005-04-16 15:20:36 -07002081static u8 read_pwm(struct av7110* av7110)
2082{
2083 u8 b = 0xff;
2084 u8 pwm;
2085 struct i2c_msg msg[] = { { .addr = 0x50,.flags = 0,.buf = &b,.len = 1 },
2086 { .addr = 0x50,.flags = I2C_M_RD,.buf = &pwm,.len = 1} };
2087
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -08002088 if ((i2c_transfer(&av7110->i2c_adap, msg, 2) != 2) || (pwm == 0xff))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002089 pwm = 0x48;
2090
2091 return pwm;
2092}
2093
2094static int frontend_init(struct av7110 *av7110)
2095{
2096 int ret;
2097
2098 if (av7110->dev->pci->subsystem_vendor == 0x110a) {
2099 switch(av7110->dev->pci->subsystem_device) {
2100 case 0x0000: // Fujitsu/Siemens DVB-Cable (ves1820/Philips CD1516(??))
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002101 av7110->fe = dvb_attach(ves1820_attach, &philips_cd1516_config,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002102 &av7110->i2c_adap, read_pwm(av7110));
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002103 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002104 av7110->fe->ops.tuner_ops.set_params = philips_cd1516_tuner_set_params;
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002105 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002106 break;
2107 }
2108
2109 } else if (av7110->dev->pci->subsystem_vendor == 0x13c2) {
2110 switch(av7110->dev->pci->subsystem_device) {
2111 case 0x0000: // Hauppauge/TT WinTV DVB-S rev1.X
2112 case 0x0003: // Hauppauge/TT WinTV Nexus-S Rev 2.X
2113 case 0x1002: // Hauppauge/TT WinTV DVB-S rev1.3SE
2114
2115 // try the ALPS BSRV2 first of all
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002116 av7110->fe = dvb_attach(ves1x93_attach, &alps_bsrv2_config, &av7110->i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002117 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002118 av7110->fe->ops.tuner_ops.set_params = alps_bsrv2_tuner_set_params;
2119 av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
2120 av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
2121 av7110->fe->ops.set_tone = av7110_set_tone;
Oliver Endriss66190a22006-01-09 15:32:42 -02002122 av7110->recover = dvb_s_recover;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002123 break;
2124 }
2125
2126 // try the ALPS BSRU6 now
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002127 av7110->fe = dvb_attach(stv0299_attach, &alps_bsru6_config, &av7110->i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002128 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002129 av7110->fe->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03002130 av7110->fe->tuner_priv = &av7110->i2c_adap;
2131
Patrick Boettcherdea74862006-05-14 05:01:31 -03002132 av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
2133 av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
2134 av7110->fe->ops.set_tone = av7110_set_tone;
Oliver Endriss66190a22006-01-09 15:32:42 -02002135 av7110->recover = dvb_s_recover;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002136 break;
2137 }
2138
2139 // Try the grundig 29504-451
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002140 av7110->fe = dvb_attach(tda8083_attach, &grundig_29504_451_config, &av7110->i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002141 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002142 av7110->fe->ops.tuner_ops.set_params = grundig_29504_451_tuner_set_params;
2143 av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
2144 av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
2145 av7110->fe->ops.set_tone = av7110_set_tone;
Oliver Endriss66190a22006-01-09 15:32:42 -02002146 av7110->recover = dvb_s_recover;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002147 break;
2148 }
2149
2150 /* Try DVB-C cards */
2151 switch(av7110->dev->pci->subsystem_device) {
2152 case 0x0000:
2153 /* Siemens DVB-C (full-length card) VES1820/Philips CD1516 */
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002154 av7110->fe = dvb_attach(ves1820_attach, &philips_cd1516_config, &av7110->i2c_adap,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002155 read_pwm(av7110));
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002156 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002157 av7110->fe->ops.tuner_ops.set_params = philips_cd1516_tuner_set_params;
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002158 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002159 break;
2160 case 0x0003:
Adrian Bunkf3688fc2006-03-29 22:46:12 -03002161 /* Hauppauge DVB-C 2.1 VES1820/ALPS TDBE2 */
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002162 av7110->fe = dvb_attach(ves1820_attach, &alps_tdbe2_config, &av7110->i2c_adap,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002163 read_pwm(av7110));
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002164 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002165 av7110->fe->ops.tuner_ops.set_params = alps_tdbe2_tuner_set_params;
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002166 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002167 break;
2168 }
2169 break;
2170
2171 case 0x0001: // Hauppauge/TT Nexus-T premium rev1.X
Oliver Endriss8d90ee52006-08-07 02:04:26 -03002172 // try ALPS TDLB7 first, then Grundig 29504-401
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002173 av7110->fe = dvb_attach(sp8870_attach, &alps_tdlb7_config, &av7110->i2c_adap);
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002174 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002175 av7110->fe->ops.tuner_ops.set_params = alps_tdlb7_tuner_set_params;
Oliver Endriss8d90ee52006-08-07 02:04:26 -03002176 break;
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002177 }
Oliver Endriss8d90ee52006-08-07 02:04:26 -03002178 /* fall-thru */
2179
2180 case 0x0008: // Hauppauge/TT DVB-T
2181 // Grundig 29504-401
2182 av7110->fe = dvb_attach(l64781_attach, &grundig_29504_401_config, &av7110->i2c_adap);
2183 if (av7110->fe)
2184 av7110->fe->ops.tuner_ops.set_params = grundig_29504_401_tuner_set_params;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002185 break;
2186
2187 case 0x0002: // Hauppauge/TT DVB-C premium rev2.X
2188
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002189 av7110->fe = dvb_attach(ves1820_attach, &alps_tdbe2_config, &av7110->i2c_adap, read_pwm(av7110));
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002190 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002191 av7110->fe->ops.tuner_ops.set_params = alps_tdbe2_tuner_set_params;
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002192 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002193 break;
2194
Oliver Endriss8bd63012006-02-07 06:49:11 -02002195 case 0x0004: // Galaxis DVB-S rev1.3
2196 /* ALPS BSRV2 */
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002197 av7110->fe = dvb_attach(ves1x93_attach, &alps_bsrv2_config, &av7110->i2c_adap);
Oliver Endriss8bd63012006-02-07 06:49:11 -02002198 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002199 av7110->fe->ops.tuner_ops.set_params = alps_bsrv2_tuner_set_params;
2200 av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
2201 av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
2202 av7110->fe->ops.set_tone = av7110_set_tone;
Oliver Endriss8bd63012006-02-07 06:49:11 -02002203 av7110->recover = dvb_s_recover;
2204 }
2205 break;
2206
Linus Torvalds1da177e2005-04-16 15:20:36 -07002207 case 0x0006: /* Fujitsu-Siemens DVB-S rev 1.6 */
2208 /* Grundig 29504-451 */
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002209 av7110->fe = dvb_attach(tda8083_attach, &grundig_29504_451_config, &av7110->i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002210 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002211 av7110->fe->ops.tuner_ops.set_params = grundig_29504_451_tuner_set_params;
2212 av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
2213 av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
2214 av7110->fe->ops.set_tone = av7110_set_tone;
Oliver Endriss66190a22006-01-09 15:32:42 -02002215 av7110->recover = dvb_s_recover;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002216 }
2217 break;
2218
Linus Torvalds1da177e2005-04-16 15:20:36 -07002219 case 0x000A: // Hauppauge/TT Nexus-CA rev1.X
2220
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002221 av7110->fe = dvb_attach(stv0297_attach, &nexusca_stv0297_config, &av7110->i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002222 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002223 av7110->fe->ops.tuner_ops.set_params = nexusca_stv0297_tuner_set_params;
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03002224
Linus Torvalds1da177e2005-04-16 15:20:36 -07002225 /* set TDA9819 into DVB mode */
Marco Schluessler6a857742006-07-10 03:34:16 -03002226 saa7146_setgpio(av7110->dev, 1, SAA7146_GPIO_OUTLO); // TDA9819 pin9(STD)
2227 saa7146_setgpio(av7110->dev, 3, SAA7146_GPIO_OUTLO); // TDA9819 pin30(VIF)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002228
2229 /* tuner on this needs a slower i2c bus speed */
2230 av7110->dev->i2c_bitrate = SAA7146_I2C_BUS_BIT_RATE_240;
2231 break;
2232 }
Johannes Stezenbach3dfaebd2005-05-16 21:54:19 -07002233 break;
2234
2235 case 0x000E: /* Hauppauge/TT Nexus-S rev 2.3 */
2236 /* ALPS BSBE1 */
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002237 av7110->fe = dvb_attach(stv0299_attach, &alps_bsbe1_config, &av7110->i2c_adap);
Oliver Endrisseb3daf32006-01-09 15:25:05 -02002238 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002239 av7110->fe->ops.tuner_ops.set_params = alps_bsbe1_tuner_set_params;
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03002240 av7110->fe->tuner_priv = &av7110->i2c_adap;
2241
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002242 if (dvb_attach(lnbp21_attach, av7110->fe, &av7110->i2c_adap, 0, 0) == NULL) {
Oliver Endrissdb5d91e2006-02-28 10:32:25 -03002243 printk("dvb-ttpci: LNBP21 not found!\n");
Patrick Boettcherdea74862006-05-14 05:01:31 -03002244 if (av7110->fe->ops.release)
2245 av7110->fe->ops.release(av7110->fe);
Oliver Endrissdb5d91e2006-02-28 10:32:25 -03002246 av7110->fe = NULL;
2247 } else {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002248 av7110->fe->ops.dishnetwork_send_legacy_command = NULL;
Oliver Endrissdb5d91e2006-02-28 10:32:25 -03002249 av7110->recover = dvb_s_recover;
2250 }
Oliver Endrisseb3daf32006-01-09 15:25:05 -02002251 }
Johannes Stezenbach3dfaebd2005-05-16 21:54:19 -07002252 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002253 }
2254 }
2255
2256 if (!av7110->fe) {
2257 /* FIXME: propagate the failure code from the lower layers */
2258 ret = -ENOMEM;
Bjorn Helgaas29e66a62008-09-04 17:24:51 -03002259 printk("dvb-ttpci: A frontend driver was not found for device [%04x:%04x] subsystem [%04x:%04x]\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002260 av7110->dev->pci->vendor,
2261 av7110->dev->pci->device,
2262 av7110->dev->pci->subsystem_vendor,
2263 av7110->dev->pci->subsystem_device);
2264 } else {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002265 FE_FUNC_OVERRIDE(av7110->fe->ops.init, av7110->fe_init, av7110_fe_init);
2266 FE_FUNC_OVERRIDE(av7110->fe->ops.read_status, av7110->fe_read_status, av7110_fe_read_status);
2267 FE_FUNC_OVERRIDE(av7110->fe->ops.diseqc_reset_overload, av7110->fe_diseqc_reset_overload, av7110_fe_diseqc_reset_overload);
2268 FE_FUNC_OVERRIDE(av7110->fe->ops.diseqc_send_master_cmd, av7110->fe_diseqc_send_master_cmd, av7110_fe_diseqc_send_master_cmd);
2269 FE_FUNC_OVERRIDE(av7110->fe->ops.diseqc_send_burst, av7110->fe_diseqc_send_burst, av7110_fe_diseqc_send_burst);
2270 FE_FUNC_OVERRIDE(av7110->fe->ops.set_tone, av7110->fe_set_tone, av7110_fe_set_tone);
Yoann Padioleau8f40a9f2007-07-16 16:54:49 -03002271 FE_FUNC_OVERRIDE(av7110->fe->ops.set_voltage, av7110->fe_set_voltage, av7110_fe_set_voltage);
Patrick Boettcherdea74862006-05-14 05:01:31 -03002272 FE_FUNC_OVERRIDE(av7110->fe->ops.dishnetwork_send_legacy_command, av7110->fe_dishnetwork_send_legacy_command, av7110_fe_dishnetwork_send_legacy_command);
2273 FE_FUNC_OVERRIDE(av7110->fe->ops.set_frontend, av7110->fe_set_frontend, av7110_fe_set_frontend);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002274
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07002275 ret = dvb_register_frontend(&av7110->dvb_adapter, av7110->fe);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002276 if (ret < 0) {
2277 printk("av7110: Frontend registration failed!\n");
Andrew de Quinceyf52a8382006-08-08 09:10:09 -03002278 dvb_frontend_detach(av7110->fe);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002279 av7110->fe = NULL;
2280 }
2281 }
2282 return ret;
2283}
2284
2285/* Budgetpatch note:
2286 * Original hardware design by Roberto Deza:
2287 * There is a DVB_Wiki at
2288 * http://212.227.36.83/linuxtv/wiki/index.php/Main_Page
2289 * where is described this 'DVB TT Budget Patch', on Card Modding:
2290 * http://212.227.36.83/linuxtv/wiki/index.php/DVB_TT_Budget_Patch
2291 * On the short description there is also a link to a external file,
2292 * with more details:
2293 * http://perso.wanadoo.es/jesussolano/Ttf_tsc1.zip
2294 *
2295 * New software triggering design by Emard that works on
2296 * original Roberto Deza's hardware:
2297 *
2298 * rps1 code for budgetpatch will copy internal HS event to GPIO3 pin.
2299 * GPIO3 is in budget-patch hardware connectd to port B VSYNC
2300 * HS is an internal event of 7146, accessible with RPS
2301 * and temporarily raised high every n lines
2302 * (n in defined in the RPS_THRESH1 counter threshold)
2303 * I think HS is raised high on the beginning of the n-th line
2304 * and remains high until this n-th line that triggered
2305 * it is completely received. When the receiption of n-th line
2306 * ends, HS is lowered.
2307 *
2308 * To transmit data over DMA, 7146 needs changing state at
2309 * port B VSYNC pin. Any changing of port B VSYNC will
2310 * cause some DMA data transfer, with more or less packets loss.
2311 * It depends on the phase and frequency of VSYNC and
2312 * the way of 7146 is instructed to trigger on port B (defined
2313 * in DD1_INIT register, 3rd nibble from the right valid
2314 * numbers are 0-7, see datasheet)
2315 *
2316 * The correct triggering can minimize packet loss,
2317 * dvbtraffic should give this stable bandwidths:
2318 * 22k transponder = 33814 kbit/s
2319 * 27.5k transponder = 38045 kbit/s
2320 * by experiment it is found that the best results
2321 * (stable bandwidths and almost no packet loss)
2322 * are obtained using DD1_INIT triggering number 2
2323 * (Va at rising edge of VS Fa = HS x VS-failing forced toggle)
2324 * and a VSYNC phase that occurs in the middle of DMA transfer
2325 * (about byte 188*512=96256 in the DMA window).
2326 *
2327 * Phase of HS is still not clear to me how to control,
2328 * It just happens to be so. It can be seen if one enables
2329 * RPS_IRQ and print Event Counter 1 in vpeirq(). Every
2330 * time RPS_INTERRUPT is called, the Event Counter 1 will
2331 * increment. That's how the 7146 is programmed to do event
2332 * counting in this budget-patch.c
2333 * I *think* HPS setting has something to do with the phase
2334 * of HS but I cant be 100% sure in that.
2335 *
2336 * hardware debug note: a working budget card (including budget patch)
2337 * with vpeirq() interrupt setup in mode "0x90" (every 64K) will
2338 * generate 3 interrupts per 25-Hz DMA frame of 2*188*512 bytes
2339 * and that means 3*25=75 Hz of interrupt freqency, as seen by
2340 * watch cat /proc/interrupts
2341 *
2342 * If this frequency is 3x lower (and data received in the DMA
2343 * buffer don't start with 0x47, but in the middle of packets,
2344 * whose lengths appear to be like 188 292 188 104 etc.
2345 * this means VSYNC line is not connected in the hardware.
2346 * (check soldering pcb and pins)
2347 * The same behaviour of missing VSYNC can be duplicated on budget
2348 * cards, by seting DD1_INIT trigger mode 7 in 3rd nibble.
2349 */
Johannes Stezenbach1be11e32006-02-27 00:09:20 -03002350static int __devinit av7110_attach(struct saa7146_dev* dev,
2351 struct saa7146_pci_extension_data *pci_ext)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002352{
2353 const int length = TS_WIDTH * TS_HEIGHT;
2354 struct pci_dev *pdev = dev->pci;
2355 struct av7110 *av7110;
Herbert Poetzl8eec1422007-02-08 14:32:43 -03002356 struct task_struct *thread;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002357 int ret, count = 0;
2358
2359 dprintk(4, "dev: %p\n", dev);
2360
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -08002361 /* Set RPS_IRQ to 1 to track rps1 activity.
2362 * Enabling this won't send any interrupt to PC CPU.
2363 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002364#define RPS_IRQ 0
2365
2366 if (budgetpatch == 1) {
2367 budgetpatch = 0;
2368 /* autodetect the presence of budget patch
2369 * this only works if saa7146 has been recently
2370 * reset with with MASK_31 to MC1
2371 *
2372 * will wait for VBI_B event (vertical blank at port B)
2373 * and will reset GPIO3 after VBI_B is detected.
2374 * (GPIO3 should be raised high by CPU to
2375 * test if GPIO3 will generate vertical blank signal
2376 * in budget patch GPIO3 is connected to VSYNC_B
2377 */
2378
2379 /* RESET SAA7146 */
2380 saa7146_write(dev, MC1, MASK_31);
2381 /* autodetection success seems to be time-dependend after reset */
2382
2383 /* Fix VSYNC level */
2384 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
2385 /* set vsync_b triggering */
2386 saa7146_write(dev, DD1_STREAM_B, 0);
2387 /* port B VSYNC at rising edge */
2388 saa7146_write(dev, DD1_INIT, 0x00000200);
2389 saa7146_write(dev, BRS_CTRL, 0x00000000); // VBI
2390 saa7146_write(dev, MC2,
2391 1 * (MASK_08 | MASK_24) | // BRS control
2392 0 * (MASK_09 | MASK_25) | // a
2393 1 * (MASK_10 | MASK_26) | // b
2394 0 * (MASK_06 | MASK_22) | // HPS_CTRL1
2395 0 * (MASK_05 | MASK_21) | // HPS_CTRL2
2396 0 * (MASK_01 | MASK_15) // DEBI
2397 );
2398
2399 /* start writing RPS1 code from beginning */
2400 count = 0;
2401 /* Disable RPS1 */
2402 saa7146_write(dev, MC1, MASK_29);
2403 /* RPS1 timeout disable */
2404 saa7146_write(dev, RPS_TOV1, 0);
Al Viro153755a2008-06-22 14:19:39 -03002405 WRITE_RPS1(CMD_PAUSE | EVT_VBI_B);
2406 WRITE_RPS1(CMD_WR_REG_MASK | (GPIO_CTRL>>2));
2407 WRITE_RPS1(GPIO3_MSK);
2408 WRITE_RPS1(SAA7146_GPIO_OUTLO<<24);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002409#if RPS_IRQ
2410 /* issue RPS1 interrupt to increment counter */
Al Viro153755a2008-06-22 14:19:39 -03002411 WRITE_RPS1(CMD_INTERRUPT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002412#endif
Al Viro153755a2008-06-22 14:19:39 -03002413 WRITE_RPS1(CMD_STOP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002414 /* Jump to begin of RPS program as safety measure (p37) */
Al Viro153755a2008-06-22 14:19:39 -03002415 WRITE_RPS1(CMD_JUMP);
2416 WRITE_RPS1(dev->d_rps1.dma_handle);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002417
2418#if RPS_IRQ
2419 /* set event counter 1 source as RPS1 interrupt (0x03) (rE4 p53)
2420 * use 0x03 to track RPS1 interrupts - increase by 1 every gpio3 is toggled
2421 * use 0x15 to track VPE interrupts - increase by 1 every vpeirq() is called
2422 */
2423 saa7146_write(dev, EC1SSR, (0x03<<2) | 3 );
2424 /* set event counter 1 treshold to maximum allowed value (rEC p55) */
2425 saa7146_write(dev, ECT1R, 0x3fff );
2426#endif
2427 /* Set RPS1 Address register to point to RPS code (r108 p42) */
2428 saa7146_write(dev, RPS_ADDR1, dev->d_rps1.dma_handle);
2429 /* Enable RPS1, (rFC p33) */
2430 saa7146_write(dev, MC1, (MASK_13 | MASK_29 ));
2431
2432 mdelay(10);
2433 /* now send VSYNC_B to rps1 by rising GPIO3 */
2434 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI);
2435 mdelay(10);
2436 /* if rps1 responded by lowering the GPIO3,
2437 * then we have budgetpatch hardware
2438 */
2439 if ((saa7146_read(dev, GPIO_CTRL) & 0x10000000) == 0) {
2440 budgetpatch = 1;
2441 printk("dvb-ttpci: BUDGET-PATCH DETECTED.\n");
2442 }
2443 /* Disable RPS1 */
2444 saa7146_write(dev, MC1, ( MASK_29 ));
2445#if RPS_IRQ
2446 printk("dvb-ttpci: Event Counter 1 0x%04x\n", saa7146_read(dev, EC1R) & 0x3fff );
2447#endif
2448 }
2449
2450 /* prepare the av7110 device struct */
Panagiotis Issaris74081872006-01-11 19:40:56 -02002451 av7110 = kzalloc(sizeof(struct av7110), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002452 if (!av7110) {
2453 dprintk(1, "out of memory\n");
2454 return -ENOMEM;
2455 }
2456
Linus Torvalds1da177e2005-04-16 15:20:36 -07002457 av7110->card_name = (char*) pci_ext->ext_priv;
2458 av7110->dev = dev;
2459 dev->ext_priv = av7110;
2460
2461 ret = get_firmware(av7110);
2462 if (ret < 0)
2463 goto err_kfree_0;
2464
2465 ret = dvb_register_adapter(&av7110->dvb_adapter, av7110->card_name,
Janne Grunau78e92002008-04-09 19:13:13 -03002466 THIS_MODULE, &dev->pci->dev, adapter_nr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002467 if (ret < 0)
2468 goto err_put_firmware_1;
2469
2470 /* the Siemens DVB needs this if you want to have the i2c chips
2471 get recognized before the main driver is fully loaded */
2472 saa7146_write(dev, GPIO_CTRL, 0x500000);
2473
Linus Torvalds1da177e2005-04-16 15:20:36 -07002474 av7110->i2c_adap.class = I2C_CLASS_TV_DIGITAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002475 strlcpy(av7110->i2c_adap.name, pci_ext->ext_priv, sizeof(av7110->i2c_adap.name));
2476
2477 saa7146_i2c_adapter_prepare(dev, &av7110->i2c_adap, SAA7146_I2C_BUS_BIT_RATE_120); /* 275 kHz */
2478
2479 ret = i2c_add_adapter(&av7110->i2c_adap);
2480 if (ret < 0)
2481 goto err_dvb_unregister_adapter_2;
2482
2483 ttpci_eeprom_parse_mac(&av7110->i2c_adap,
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07002484 av7110->dvb_adapter.proposed_mac);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002485 ret = -ENOMEM;
2486
2487 if (budgetpatch) {
2488 spin_lock_init(&av7110->feedlock1);
2489 av7110->grabbing = saa7146_vmalloc_build_pgtable(pdev, length,
2490 &av7110->pt);
2491 if (!av7110->grabbing)
2492 goto err_i2c_del_3;
2493
2494 saa7146_write(dev, PCI_BT_V1, 0x1c1f101f);
2495 saa7146_write(dev, BCS_CTRL, 0x80400040);
2496 /* set dd1 stream a & b */
2497 saa7146_write(dev, DD1_STREAM_B, 0x00000000);
2498 saa7146_write(dev, DD1_INIT, 0x03000200);
2499 saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
2500 saa7146_write(dev, BRS_CTRL, 0x60000000);
2501 saa7146_write(dev, BASE_ODD3, 0);
2502 saa7146_write(dev, BASE_EVEN3, 0);
2503 saa7146_write(dev, PROT_ADDR3, TS_WIDTH * TS_HEIGHT);
2504 saa7146_write(dev, BASE_PAGE3, av7110->pt.dma | ME1 | 0x90);
2505
2506 saa7146_write(dev, PITCH3, TS_WIDTH);
2507 saa7146_write(dev, NUM_LINE_BYTE3, (TS_HEIGHT << 16) | TS_WIDTH);
2508
2509 /* upload all */
2510 saa7146_write(dev, MC2, 0x077c077c);
2511 saa7146_write(dev, GPIO_CTRL, 0x000000);
2512#if RPS_IRQ
2513 /* set event counter 1 source as RPS1 interrupt (0x03) (rE4 p53)
2514 * use 0x03 to track RPS1 interrupts - increase by 1 every gpio3 is toggled
2515 * use 0x15 to track VPE interrupts - increase by 1 every vpeirq() is called
2516 */
2517 saa7146_write(dev, EC1SSR, (0x03<<2) | 3 );
2518 /* set event counter 1 treshold to maximum allowed value (rEC p55) */
2519 saa7146_write(dev, ECT1R, 0x3fff );
2520#endif
2521 /* Setup BUDGETPATCH MAIN RPS1 "program" (p35) */
2522 count = 0;
2523
2524 /* Wait Source Line Counter Threshold (p36) */
Al Viro153755a2008-06-22 14:19:39 -03002525 WRITE_RPS1(CMD_PAUSE | EVT_HS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002526 /* Set GPIO3=1 (p42) */
Al Viro153755a2008-06-22 14:19:39 -03002527 WRITE_RPS1(CMD_WR_REG_MASK | (GPIO_CTRL>>2));
2528 WRITE_RPS1(GPIO3_MSK);
2529 WRITE_RPS1(SAA7146_GPIO_OUTHI<<24);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002530#if RPS_IRQ
2531 /* issue RPS1 interrupt */
Al Viro153755a2008-06-22 14:19:39 -03002532 WRITE_RPS1(CMD_INTERRUPT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002533#endif
2534 /* Wait reset Source Line Counter Threshold (p36) */
Al Viro153755a2008-06-22 14:19:39 -03002535 WRITE_RPS1(CMD_PAUSE | RPS_INV | EVT_HS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002536 /* Set GPIO3=0 (p42) */
Al Viro153755a2008-06-22 14:19:39 -03002537 WRITE_RPS1(CMD_WR_REG_MASK | (GPIO_CTRL>>2));
2538 WRITE_RPS1(GPIO3_MSK);
2539 WRITE_RPS1(SAA7146_GPIO_OUTLO<<24);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002540#if RPS_IRQ
2541 /* issue RPS1 interrupt */
Al Viro153755a2008-06-22 14:19:39 -03002542 WRITE_RPS1(CMD_INTERRUPT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002543#endif
2544 /* Jump to begin of RPS program (p37) */
Al Viro153755a2008-06-22 14:19:39 -03002545 WRITE_RPS1(CMD_JUMP);
2546 WRITE_RPS1(dev->d_rps1.dma_handle);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002547
2548 /* Fix VSYNC level */
2549 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
2550 /* Set RPS1 Address register to point to RPS code (r108 p42) */
2551 saa7146_write(dev, RPS_ADDR1, dev->d_rps1.dma_handle);
2552 /* Set Source Line Counter Threshold, using BRS (rCC p43)
2553 * It generates HS event every TS_HEIGHT lines
2554 * this is related to TS_WIDTH set in register
2555 * NUM_LINE_BYTE3. If NUM_LINE_BYTE low 16 bits
2556 * are set to TS_WIDTH bytes (TS_WIDTH=2*188),
2557 * then RPS_THRESH1 should be set to trigger
2558 * every TS_HEIGHT (512) lines.
2559 */
2560 saa7146_write(dev, RPS_THRESH1, (TS_HEIGHT*1) | MASK_12 );
2561
2562 /* Enable RPS1 (rFC p33) */
2563 saa7146_write(dev, MC1, (MASK_13 | MASK_29));
2564
2565 /* end of budgetpatch register initialization */
2566 tasklet_init (&av7110->vpe_tasklet, vpeirq, (unsigned long) av7110);
2567 } else {
2568 saa7146_write(dev, PCI_BT_V1, 0x1c00101f);
2569 saa7146_write(dev, BCS_CTRL, 0x80400040);
2570
2571 /* set dd1 stream a & b */
2572 saa7146_write(dev, DD1_STREAM_B, 0x00000000);
2573 saa7146_write(dev, DD1_INIT, 0x03000000);
2574 saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
2575
2576 /* upload all */
2577 saa7146_write(dev, MC2, 0x077c077c);
2578 saa7146_write(dev, GPIO_CTRL, 0x000000);
2579 }
2580
2581 tasklet_init (&av7110->debi_tasklet, debiirq, (unsigned long) av7110);
2582 tasklet_init (&av7110->gpio_tasklet, gpioirq, (unsigned long) av7110);
2583
Ingo Molnar3593cab2006-02-07 06:49:14 -02002584 mutex_init(&av7110->pid_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002585
2586 /* locks for data transfers from/to AV7110 */
2587 spin_lock_init(&av7110->debilock);
Ingo Molnar3593cab2006-02-07 06:49:14 -02002588 mutex_init(&av7110->dcomlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002589 av7110->debitype = -1;
2590
2591 /* default OSD window */
2592 av7110->osdwin = 1;
Ingo Molnar3593cab2006-02-07 06:49:14 -02002593 mutex_init(&av7110->osd_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002594
C.Y.M2f03ee82006-03-30 04:31:48 -03002595 /* TV standard */
Marco Schluessler58a44042007-10-31 01:20:42 -03002596 av7110->vidmode = tv_standard == 1 ? AV7110_VIDEO_MODE_NTSC
2597 : AV7110_VIDEO_MODE_PAL;
C.Y.M2f03ee82006-03-30 04:31:48 -03002598
Linus Torvalds1da177e2005-04-16 15:20:36 -07002599 /* ARM "watchdog" */
2600 init_waitqueue_head(&av7110->arm_wait);
2601 av7110->arm_thread = NULL;
2602
2603 /* allocate and init buffers */
2604 av7110->debi_virt = pci_alloc_consistent(pdev, 8192, &av7110->debi_bus);
2605 if (!av7110->debi_virt)
2606 goto err_saa71466_vfree_4;
2607
2608
2609 av7110->iobuf = vmalloc(AVOUTLEN+AOUTLEN+BMPLEN+4*IPACKS);
2610 if (!av7110->iobuf)
2611 goto err_pci_free_5;
2612
2613 ret = av7110_av_init(av7110);
2614 if (ret < 0)
2615 goto err_iobuf_vfree_6;
2616
2617 /* init BMP buffer */
2618 av7110->bmpbuf = av7110->iobuf+AVOUTLEN+AOUTLEN;
2619 init_waitqueue_head(&av7110->bmpq);
2620
2621 ret = av7110_ca_init(av7110);
2622 if (ret < 0)
2623 goto err_av7110_av_exit_7;
2624
2625 /* load firmware into AV7110 cards */
2626 ret = av7110_bootarm(av7110);
2627 if (ret < 0)
2628 goto err_av7110_ca_exit_8;
2629
2630 ret = av7110_firmversion(av7110);
2631 if (ret < 0)
2632 goto err_stop_arm_9;
2633
2634 if (FW_VERSION(av7110->arm_app)<0x2501)
2635 printk ("dvb-ttpci: Warning, firmware version 0x%04x is too old. "
2636 "System might be unstable!\n", FW_VERSION(av7110->arm_app));
2637
Herbert Poetzl8eec1422007-02-08 14:32:43 -03002638 thread = kthread_run(arm_thread, (void *) av7110, "arm_mon");
2639 if (IS_ERR(thread)) {
2640 ret = PTR_ERR(thread);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002641 goto err_stop_arm_9;
Herbert Poetzl8eec1422007-02-08 14:32:43 -03002642 }
2643 av7110->arm_thread = thread;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002644
2645 /* set initial volume in mixer struct */
2646 av7110->mixer.volume_left = volume;
2647 av7110->mixer.volume_right = volume;
2648
Linus Torvalds1da177e2005-04-16 15:20:36 -07002649 ret = av7110_register(av7110);
2650 if (ret < 0)
2651 goto err_arm_thread_stop_10;
2652
Oliver Endrissdefd574e2007-07-12 23:08:07 -03002653 init_av7110_av(av7110);
2654
Linus Torvalds1da177e2005-04-16 15:20:36 -07002655 /* special case DVB-C: these cards have an analog tuner
2656 plus need some special handling, so we have separate
2657 saa7146_ext_vv data for these... */
2658 ret = av7110_init_v4l(av7110);
2659 if (ret < 0)
2660 goto err_av7110_unregister_11;
2661
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07002662 av7110->dvb_adapter.priv = av7110;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002663 ret = frontend_init(av7110);
2664 if (ret < 0)
2665 goto err_av7110_exit_v4l_12;
2666
2667#if defined(CONFIG_INPUT_EVDEV) || defined(CONFIG_INPUT_EVDEV_MODULE)
Oliver Endriss03388ae2005-09-09 13:03:12 -07002668 av7110_ir_init(av7110);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002669#endif
2670 printk(KERN_INFO "dvb-ttpci: found av7110-%d.\n", av7110_num);
2671 av7110_num++;
2672out:
2673 return ret;
2674
2675err_av7110_exit_v4l_12:
2676 av7110_exit_v4l(av7110);
2677err_av7110_unregister_11:
2678 dvb_unregister(av7110);
2679err_arm_thread_stop_10:
2680 av7110_arm_sync(av7110);
2681err_stop_arm_9:
2682 /* Nothing to do. Rejoice. */
2683err_av7110_ca_exit_8:
2684 av7110_ca_exit(av7110);
2685err_av7110_av_exit_7:
2686 av7110_av_exit(av7110);
2687err_iobuf_vfree_6:
2688 vfree(av7110->iobuf);
2689err_pci_free_5:
2690 pci_free_consistent(pdev, 8192, av7110->debi_virt, av7110->debi_bus);
2691err_saa71466_vfree_4:
Jon Burgess87c30192007-05-03 12:23:44 -03002692 if (av7110->grabbing)
2693 saa7146_vfree_destroy_pgtable(pdev, av7110->grabbing, &av7110->pt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002694err_i2c_del_3:
2695 i2c_del_adapter(&av7110->i2c_adap);
2696err_dvb_unregister_adapter_2:
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07002697 dvb_unregister_adapter(&av7110->dvb_adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002698err_put_firmware_1:
2699 put_firmware(av7110);
2700err_kfree_0:
2701 kfree(av7110);
2702 goto out;
2703}
2704
Johannes Stezenbach1be11e32006-02-27 00:09:20 -03002705static int __devexit av7110_detach(struct saa7146_dev* saa)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002706{
2707 struct av7110 *av7110 = saa->ext_priv;
2708 dprintk(4, "%p\n", av7110);
2709
Oliver Endriss03388ae2005-09-09 13:03:12 -07002710#if defined(CONFIG_INPUT_EVDEV) || defined(CONFIG_INPUT_EVDEV_MODULE)
2711 av7110_ir_exit(av7110);
2712#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07002713 if (budgetpatch) {
2714 /* Disable RPS1 */
2715 saa7146_write(saa, MC1, MASK_29);
2716 /* VSYNC LOW (inactive) */
2717 saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);
2718 saa7146_write(saa, MC1, MASK_20); /* DMA3 off */
2719 SAA7146_IER_DISABLE(saa, MASK_10);
2720 SAA7146_ISR_CLEAR(saa, MASK_10);
2721 msleep(50);
2722 tasklet_kill(&av7110->vpe_tasklet);
Jon Burgess87c30192007-05-03 12:23:44 -03002723 saa7146_vfree_destroy_pgtable(saa->pci, av7110->grabbing, &av7110->pt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002724 }
2725 av7110_exit_v4l(av7110);
2726
2727 av7110_arm_sync(av7110);
2728
2729 tasklet_kill(&av7110->debi_tasklet);
2730 tasklet_kill(&av7110->gpio_tasklet);
2731
2732 dvb_unregister(av7110);
2733
2734 SAA7146_IER_DISABLE(saa, MASK_19 | MASK_03);
2735 SAA7146_ISR_CLEAR(saa, MASK_19 | MASK_03);
2736
2737 av7110_ca_exit(av7110);
2738 av7110_av_exit(av7110);
2739
2740 vfree(av7110->iobuf);
2741 pci_free_consistent(saa->pci, 8192, av7110->debi_virt,
2742 av7110->debi_bus);
2743
2744 i2c_del_adapter(&av7110->i2c_adap);
2745
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07002746 dvb_unregister_adapter (&av7110->dvb_adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002747
2748 av7110_num--;
2749
2750 put_firmware(av7110);
2751
2752 kfree(av7110);
2753
2754 saa->ext_priv = NULL;
2755
2756 return 0;
2757}
2758
2759
2760static void av7110_irq(struct saa7146_dev* dev, u32 *isr)
2761{
2762 struct av7110 *av7110 = dev->ext_priv;
2763
2764 //print_time("av7110_irq");
2765
2766 /* Note: Don't try to handle the DEBI error irq (MASK_18), in
2767 * intel mode the timeout is asserted all the time...
2768 */
2769
2770 if (*isr & MASK_19) {
2771 //printk("av7110_irq: DEBI\n");
2772 /* Note 1: The DEBI irq is level triggered: We must enable it
2773 * only after we started a DMA xfer, and disable it here
2774 * immediately, or it will be signalled all the time while
2775 * DEBI is idle.
2776 * Note 2: You would think that an irq which is masked is
2777 * not signalled by the hardware. Not so for the SAA7146:
2778 * An irq is signalled as long as the corresponding bit
2779 * in the ISR is set, and disabling irqs just prevents the
2780 * hardware from setting the ISR bit. This means a) that we
2781 * must clear the ISR *after* disabling the irq (which is why
2782 * we must do it here even though saa7146_core did it already),
2783 * and b) that if we were to disable an edge triggered irq
2784 * (like the gpio irqs sadly are) temporarily we would likely
2785 * loose some. This sucks :-(
2786 */
2787 SAA7146_IER_DISABLE(av7110->dev, MASK_19);
2788 SAA7146_ISR_CLEAR(av7110->dev, MASK_19);
2789 tasklet_schedule(&av7110->debi_tasklet);
2790 }
2791
2792 if (*isr & MASK_03) {
2793 //printk("av7110_irq: GPIO\n");
2794 tasklet_schedule(&av7110->gpio_tasklet);
2795 }
2796
2797 if ((*isr & MASK_10) && budgetpatch)
2798 tasklet_schedule(&av7110->vpe_tasklet);
2799}
2800
2801
Randy Dunlapda517162008-01-10 19:31:47 -03002802static struct saa7146_extension av7110_extension_driver;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002803
2804#define MAKE_AV7110_INFO(x_var,x_name) \
2805static struct saa7146_pci_extension_data x_var = { \
2806 .ext_priv = x_name, \
Randy Dunlapda517162008-01-10 19:31:47 -03002807 .ext = &av7110_extension_driver }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002808
Karl Herz6af4ee12005-09-09 13:03:13 -07002809MAKE_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 -07002810MAKE_AV7110_INFO(ttt_1_X, "Technotrend/Hauppauge WinTV DVB-T rev1.X");
2811MAKE_AV7110_INFO(ttc_1_X, "Technotrend/Hauppauge WinTV Nexus-CA rev1.X");
2812MAKE_AV7110_INFO(ttc_2_X, "Technotrend/Hauppauge WinTV DVB-C rev2.X");
2813MAKE_AV7110_INFO(tts_2_X, "Technotrend/Hauppauge WinTV Nexus-S rev2.X");
Johannes Stezenbach3dfaebd2005-05-16 21:54:19 -07002814MAKE_AV7110_INFO(tts_2_3, "Technotrend/Hauppauge WinTV Nexus-S rev2.3");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002815MAKE_AV7110_INFO(tts_1_3se, "Technotrend/Hauppauge WinTV DVB-S rev1.3 SE");
2816MAKE_AV7110_INFO(ttt, "Technotrend/Hauppauge DVB-T");
2817MAKE_AV7110_INFO(fsc, "Fujitsu Siemens DVB-C");
2818MAKE_AV7110_INFO(fss, "Fujitsu Siemens DVB-S rev1.6");
Oliver Endriss8bd63012006-02-07 06:49:11 -02002819MAKE_AV7110_INFO(gxs_1_3, "Galaxis DVB-S rev1.3");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002820
2821static struct pci_device_id pci_tbl[] = {
Karl Herz6af4ee12005-09-09 13:03:13 -07002822 MAKE_EXTENSION_PCI(fsc, 0x110a, 0x0000),
2823 MAKE_EXTENSION_PCI(tts_1_X_fsc, 0x13c2, 0x0000),
2824 MAKE_EXTENSION_PCI(ttt_1_X, 0x13c2, 0x0001),
2825 MAKE_EXTENSION_PCI(ttc_2_X, 0x13c2, 0x0002),
2826 MAKE_EXTENSION_PCI(tts_2_X, 0x13c2, 0x0003),
Oliver Endriss8bd63012006-02-07 06:49:11 -02002827 MAKE_EXTENSION_PCI(gxs_1_3, 0x13c2, 0x0004),
Karl Herz6af4ee12005-09-09 13:03:13 -07002828 MAKE_EXTENSION_PCI(fss, 0x13c2, 0x0006),
2829 MAKE_EXTENSION_PCI(ttt, 0x13c2, 0x0008),
2830 MAKE_EXTENSION_PCI(ttc_1_X, 0x13c2, 0x000a),
2831 MAKE_EXTENSION_PCI(tts_2_3, 0x13c2, 0x000e),
2832 MAKE_EXTENSION_PCI(tts_1_3se, 0x13c2, 0x1002),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002833
Linus Torvalds1da177e2005-04-16 15:20:36 -07002834/* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0005), UNDEFINED CARD */ // Technisat SkyStar1
2835/* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0009), UNDEFINED CARD */ // TT/Hauppauge WinTV Nexus-CA v????
2836
2837 {
2838 .vendor = 0,
2839 }
2840};
2841
2842MODULE_DEVICE_TABLE(pci, pci_tbl);
2843
2844
Randy Dunlapda517162008-01-10 19:31:47 -03002845static struct saa7146_extension av7110_extension_driver = {
Dave Jones0e367a12006-08-07 13:18:56 -03002846 .name = "dvb",
Oliver Endriss00c4cc62006-11-01 13:09:51 -03002847 .flags = SAA7146_USE_I2C_IRQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002848
2849 .module = THIS_MODULE,
2850 .pci_tbl = &pci_tbl[0],
2851 .attach = av7110_attach,
Johannes Stezenbach1be11e32006-02-27 00:09:20 -03002852 .detach = __devexit_p(av7110_detach),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002853
2854 .irq_mask = MASK_19 | MASK_03 | MASK_10,
2855 .irq_func = av7110_irq,
2856};
2857
2858
2859static int __init av7110_init(void)
2860{
2861 int retval;
Randy Dunlapda517162008-01-10 19:31:47 -03002862 retval = saa7146_register_extension(&av7110_extension_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002863 return retval;
2864}
2865
2866
2867static void __exit av7110_exit(void)
2868{
Randy Dunlapda517162008-01-10 19:31:47 -03002869 saa7146_unregister_extension(&av7110_extension_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002870}
2871
2872module_init(av7110_init);
2873module_exit(av7110_exit);
2874
2875MODULE_DESCRIPTION("driver for the SAA7146 based AV110 PCI DVB cards by "
2876 "Siemens, Technotrend, Hauppauge");
2877MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, others");
2878MODULE_LICENSE("GPL");