blob: 0e5701bdff19472bd08ec89a6b3219f9f634310e [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>
Linus Torvalds1da177e2005-04-16 15:20:36 -070054
55#include <asm/system.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070056
57#include <linux/dvb/frontend.h>
58
59#include "dvb_frontend.h"
60
61#include "ttpci-eeprom.h"
62#include "av7110.h"
63#include "av7110_hw.h"
64#include "av7110_av.h"
65#include "av7110_ca.h"
66#include "av7110_ipack.h"
67
Oliver Endrissdb5d91e2006-02-28 10:32:25 -030068#include "bsbe1.h"
69#include "lnbp21.h"
Perceval Anichini265366e2006-03-16 11:22:47 -030070#include "bsru6.h"
Oliver Endrissdb5d91e2006-02-28 10:32:25 -030071
Linus Torvalds1da177e2005-04-16 15:20:36 -070072#define TS_WIDTH 376
73#define TS_HEIGHT 512
74#define TS_BUFLEN (TS_WIDTH*TS_HEIGHT)
75#define TS_MAX_PACKETS (TS_BUFLEN/TS_SIZE)
76
77
78int av7110_debug;
79
80static int vidmode = CVBS_RGB_OUT;
81static int pids_off;
82static int adac = DVB_ADAC_TI;
83static int hw_sections;
84static int rgb_on;
85static int volume = 255;
Mauro Carvalho Chehaba5ed4252006-01-13 14:10:19 -020086static int budgetpatch;
Oliver Endriss4caba422006-03-17 05:29:15 -030087static int wss_cfg_4_3 = 0x4008;
88static int wss_cfg_16_9 = 0x0007;
C.Y.M2f03ee82006-03-30 04:31:48 -030089static int tv_standard;
Linus Torvalds1da177e2005-04-16 15:20:36 -070090
91module_param_named(debug, av7110_debug, int, 0644);
92MODULE_PARM_DESC(debug, "debug level (bitmask, default 0)");
93module_param(vidmode, int, 0444);
94MODULE_PARM_DESC(vidmode,"analog video out: 0 off, 1 CVBS+RGB (default), 2 CVBS+YC, 3 YC");
95module_param(pids_off, int, 0444);
96MODULE_PARM_DESC(pids_off,"clear video/audio/PCR PID filters when demux is closed");
97module_param(adac, int, 0444);
98MODULE_PARM_DESC(adac,"audio DAC type: 0 TI, 1 CRYSTAL, 2 MSP (use if autodetection fails)");
99module_param(hw_sections, int, 0444);
100MODULE_PARM_DESC(hw_sections, "0 use software section filter, 1 use hardware");
101module_param(rgb_on, int, 0444);
102MODULE_PARM_DESC(rgb_on, "For Siemens DVB-C cards only: Enable RGB control"
103 " signal on SCART pin 16 to switch SCART video mode from CVBS to RGB");
104module_param(volume, int, 0444);
105MODULE_PARM_DESC(volume, "initial volume: default 255 (range 0-255)");
106module_param(budgetpatch, int, 0444);
107MODULE_PARM_DESC(budgetpatch, "use budget-patch hardware modification: default 0 (0 no, 1 autodetect, 2 always)");
Oliver Endriss4caba422006-03-17 05:29:15 -0300108module_param(wss_cfg_4_3, int, 0444);
109MODULE_PARM_DESC(wss_cfg_4_3, "WSS 4:3 - default 0x4008 - bit 15: disable, 14: burst mode, 13..0: wss data");
110module_param(wss_cfg_16_9, int, 0444);
111MODULE_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 -0300112module_param(tv_standard, int, 0444);
113MODULE_PARM_DESC(tv_standard, "TV standard: 0 PAL (default), 1 NTSC");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114
115static void restart_feeds(struct av7110 *av7110);
116
Mauro Carvalho Chehaba5ed4252006-01-13 14:10:19 -0200117static int av7110_num;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118
119#define FE_FUNC_OVERRIDE(fe_func, av7110_copy, av7110_func) \
120{\
121 if (fe_func != NULL) { \
122 av7110_copy = fe_func; \
123 fe_func = av7110_func; \
124 } \
125}
126
127
128static void init_av7110_av(struct av7110 *av7110)
129{
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700130 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700131 struct saa7146_dev *dev = av7110->dev;
132
133 /* set internal volume control to maximum */
134 av7110->adac_type = DVB_ADAC_TI;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700135 ret = av7110_set_volume(av7110, av7110->mixer.volume_left, av7110->mixer.volume_right);
Johannes Stezenbach7a2fa902005-07-07 17:58:01 -0700136 if (ret < 0)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700137 printk("dvb-ttpci:cannot set internal volume to maximum:%d\n",ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700138
Oliver Endrissdefd574e2007-07-12 23:08:07 -0300139 ret = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetMonitorType,
140 1, (u16) av7110->display_ar);
141 if (ret < 0)
142 printk("dvb-ttpci: unable to set aspect ratio\n");
143 ret = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetPanScanType,
144 1, av7110->display_panscan);
145 if (ret < 0)
146 printk("dvb-ttpci: unable to set pan scan\n");
147
Oliver Endriss4caba422006-03-17 05:29:15 -0300148 ret = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetWSSConfig, 2, 2, wss_cfg_4_3);
149 if (ret < 0)
150 printk("dvb-ttpci: unable to configure 4:3 wss\n");
151 ret = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetWSSConfig, 2, 3, wss_cfg_16_9);
152 if (ret < 0)
153 printk("dvb-ttpci: unable to configure 16:9 wss\n");
154
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700155 ret = av7710_set_video_mode(av7110, vidmode);
Johannes Stezenbach7a2fa902005-07-07 17:58:01 -0700156 if (ret < 0)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700157 printk("dvb-ttpci:cannot set video mode:%d\n",ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700158
159 /* handle different card types */
160 /* remaining inits according to card and frontend type */
161 av7110->analog_tuner_flags = 0;
162 av7110->current_input = 0;
Tim Kaiser61391e02006-06-25 09:14:07 -0300163 if (dev->pci->subsystem_vendor == 0x13c2 && dev->pci->subsystem_device == 0x000a)
Marco Schluessler1c13b952006-01-09 15:25:06 -0200164 av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, ADSwitch, 1, 0); // SPDIF on
Tim Kaiser61391e02006-06-25 09:14:07 -0300165 if (i2c_writereg(av7110, 0x20, 0x00, 0x00) == 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700166 printk ("dvb-ttpci: Crystal audio DAC @ card %d detected\n",
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -0700167 av7110->dvb_adapter.num);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700168 av7110->adac_type = DVB_ADAC_CRYSTAL;
169 i2c_writereg(av7110, 0x20, 0x01, 0xd2);
170 i2c_writereg(av7110, 0x20, 0x02, 0x49);
171 i2c_writereg(av7110, 0x20, 0x03, 0x00);
172 i2c_writereg(av7110, 0x20, 0x04, 0x00);
173
174 /**
175 * some special handling for the Siemens DVB-C cards...
176 */
177 } else if (0 == av7110_init_analog_module(av7110)) {
178 /* done. */
179 }
180 else if (dev->pci->subsystem_vendor == 0x110a) {
181 printk("dvb-ttpci: DVB-C w/o analog module @ card %d detected\n",
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -0700182 av7110->dvb_adapter.num);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700183 av7110->adac_type = DVB_ADAC_NONE;
184 }
185 else {
186 av7110->adac_type = adac;
187 printk("dvb-ttpci: adac type set to %d @ card %d\n",
Marco Schluessler1c13b952006-01-09 15:25:06 -0200188 av7110->adac_type, av7110->dvb_adapter.num);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189 }
190
Marco Schluessler1c13b952006-01-09 15:25:06 -0200191 if (av7110->adac_type == DVB_ADAC_NONE || av7110->adac_type == DVB_ADAC_MSP34x0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700192 // switch DVB SCART on
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700193 ret = av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, MainSwitch, 1, 0);
Johannes Stezenbach7a2fa902005-07-07 17:58:01 -0700194 if (ret < 0)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700195 printk("dvb-ttpci:cannot switch on SCART(Main):%d\n",ret);
196 ret = av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, ADSwitch, 1, 1);
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(AD):%d\n",ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700199 if (rgb_on &&
Karl Herz6af4ee12005-09-09 13:03:13 -0700200 ((av7110->dev->pci->subsystem_vendor == 0x110a) ||
201 (av7110->dev->pci->subsystem_vendor == 0x13c2)) &&
202 (av7110->dev->pci->subsystem_device == 0x0000)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203 saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); // RGB on, SCART pin 16
204 //saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); // SCARTpin 8
205 }
206 }
207
Oliver Endriss60edb132005-12-19 08:54:11 -0200208 if (dev->pci->subsystem_vendor == 0x13c2 && dev->pci->subsystem_device == 0x000e)
209 av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, SpdifSwitch, 1, 0); // SPDIF on
210
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700211 ret = av7110_set_volume(av7110, av7110->mixer.volume_left, av7110->mixer.volume_right);
Johannes Stezenbach7a2fa902005-07-07 17:58:01 -0700212 if (ret < 0)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700213 printk("dvb-ttpci:cannot set volume :%d\n",ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700214}
215
216static void recover_arm(struct av7110 *av7110)
217{
218 dprintk(4, "%p\n",av7110);
219
220 av7110_bootarm(av7110);
221 msleep(100);
Oliver Endriss66190a22006-01-09 15:32:42 -0200222
223 init_av7110_av(av7110);
224
225 /* card-specific recovery */
226 if (av7110->recover)
227 av7110->recover(av7110);
228
Linus Torvalds1da177e2005-04-16 15:20:36 -0700229 restart_feeds(av7110);
Oliver Endrissee820a62007-04-27 12:31:21 -0300230
231#if defined(CONFIG_INPUT_EVDEV) || defined(CONFIG_INPUT_EVDEV_MODULE)
232 av7110_check_ir_config(av7110, true);
233#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234}
235
Linus Torvalds1da177e2005-04-16 15:20:36 -0700236static void av7110_arm_sync(struct av7110 *av7110)
237{
Herbert Poetzl8eec1422007-02-08 14:32:43 -0300238 if (av7110->arm_thread)
239 kthread_stop(av7110->arm_thread);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700240
Herbert Poetzl8eec1422007-02-08 14:32:43 -0300241 av7110->arm_thread = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700242}
243
244static int arm_thread(void *data)
245{
246 struct av7110 *av7110 = data;
247 u16 newloops = 0;
248 int timeout;
249
250 dprintk(4, "%p\n",av7110);
251
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252 for (;;) {
253 timeout = wait_event_interruptible_timeout(av7110->arm_wait,
Herbert Poetzl8eec1422007-02-08 14:32:43 -0300254 kthread_should_stop(), 5 * HZ);
255
256 if (-ERESTARTSYS == timeout || kthread_should_stop()) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257 /* got signal or told to quit*/
258 break;
259 }
260
261 if (!av7110->arm_ready)
262 continue;
263
Oliver Endrissee820a62007-04-27 12:31:21 -0300264#if defined(CONFIG_INPUT_EVDEV) || defined(CONFIG_INPUT_EVDEV_MODULE)
265 av7110_check_ir_config(av7110, false);
266#endif
267
Ingo Molnar3593cab2006-02-07 06:49:14 -0200268 if (mutex_lock_interruptible(&av7110->dcomlock))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700270 newloops = rdebi(av7110, DEBINOSWAP, STATUS_LOOPS, 0, 2);
Ingo Molnar3593cab2006-02-07 06:49:14 -0200271 mutex_unlock(&av7110->dcomlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700272
Oliver Endriss66190a22006-01-09 15:32:42 -0200273 if (newloops == av7110->arm_loops || av7110->arm_errors > 3) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700274 printk(KERN_ERR "dvb-ttpci: ARM crashed @ card %d\n",
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -0700275 av7110->dvb_adapter.num);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700276
Oliver Endriss66190a22006-01-09 15:32:42 -0200277 recover_arm(av7110);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278
Ingo Molnar3593cab2006-02-07 06:49:14 -0200279 if (mutex_lock_interruptible(&av7110->dcomlock))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700280 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700281 newloops = rdebi(av7110, DEBINOSWAP, STATUS_LOOPS, 0, 2) - 1;
Ingo Molnar3593cab2006-02-07 06:49:14 -0200282 mutex_unlock(&av7110->dcomlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283 }
284 av7110->arm_loops = newloops;
Oliver Endriss66190a22006-01-09 15:32:42 -0200285 av7110->arm_errors = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286 }
287
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288 return 0;
289}
290
291
Linus Torvalds1da177e2005-04-16 15:20:36 -0700292/****************************************************************************
293 * IRQ handling
294 ****************************************************************************/
295
296static int DvbDmxFilterCallback(u8 *buffer1, size_t buffer1_len,
297 u8 *buffer2, size_t buffer2_len,
298 struct dvb_demux_filter *dvbdmxfilter,
299 enum dmx_success success,
300 struct av7110 *av7110)
301{
302 if (!dvbdmxfilter->feed->demux->dmx.frontend)
303 return 0;
304 if (dvbdmxfilter->feed->demux->dmx.frontend->source == DMX_MEMORY_FE)
305 return 0;
306
307 switch (dvbdmxfilter->type) {
308 case DMX_TYPE_SEC:
309 if ((((buffer1[1] << 8) | buffer1[2]) & 0xfff) + 3 != buffer1_len)
310 return 0;
311 if (dvbdmxfilter->doneq) {
312 struct dmx_section_filter *filter = &dvbdmxfilter->filter;
313 int i;
314 u8 xor, neq = 0;
315
316 for (i = 0; i < DVB_DEMUX_MASK_MAX; i++) {
317 xor = filter->filter_value[i] ^ buffer1[i];
318 neq |= dvbdmxfilter->maskandnotmode[i] & xor;
319 }
320 if (!neq)
321 return 0;
322 }
323 return dvbdmxfilter->feed->cb.sec(buffer1, buffer1_len,
324 buffer2, buffer2_len,
325 &dvbdmxfilter->filter,
326 DMX_OK);
327 case DMX_TYPE_TS:
328 if (!(dvbdmxfilter->feed->ts_type & TS_PACKET))
329 return 0;
330 if (dvbdmxfilter->feed->ts_type & TS_PAYLOAD_ONLY)
331 return dvbdmxfilter->feed->cb.ts(buffer1, buffer1_len,
332 buffer2, buffer2_len,
333 &dvbdmxfilter->feed->feed.ts,
334 DMX_OK);
335 else
336 av7110_p2t_write(buffer1, buffer1_len,
337 dvbdmxfilter->feed->pid,
338 &av7110->p2t_filter[dvbdmxfilter->index]);
339 default:
340 return 0;
341 }
342}
343
344
345//#define DEBUG_TIMING
346static inline void print_time(char *s)
347{
348#ifdef DEBUG_TIMING
349 struct timeval tv;
350 do_gettimeofday(&tv);
351 printk("%s: %d.%d\n", s, (int)tv.tv_sec, (int)tv.tv_usec);
352#endif
353}
354
355#define DEBI_READ 0
356#define DEBI_WRITE 1
357static inline void start_debi_dma(struct av7110 *av7110, int dir,
358 unsigned long addr, unsigned int len)
359{
360 dprintk(8, "%c %08lx %u\n", dir == DEBI_READ ? 'R' : 'W', addr, len);
361 if (saa7146_wait_for_debi_done(av7110->dev, 0)) {
362 printk(KERN_ERR "%s: saa7146_wait_for_debi_done timed out\n", __FUNCTION__);
363 return;
364 }
365
366 SAA7146_ISR_CLEAR(av7110->dev, MASK_19); /* for good measure */
367 SAA7146_IER_ENABLE(av7110->dev, MASK_19);
368 if (len < 5)
369 len = 5; /* we want a real DEBI DMA */
370 if (dir == DEBI_WRITE)
371 iwdebi(av7110, DEBISWAB, addr, 0, (len + 3) & ~3);
372 else
373 irdebi(av7110, DEBISWAB, addr, 0, len);
374}
375
376static void debiirq(unsigned long data)
377{
378 struct av7110 *av7110 = (struct av7110 *) data;
379 int type = av7110->debitype;
380 int handle = (type >> 8) & 0x1f;
381 unsigned int xfer = 0;
382
383 print_time("debi");
384 dprintk(4, "type 0x%04x\n", type);
385
386 if (type == -1) {
387 printk("DEBI irq oops @ %ld, psr:0x%08x, ssr:0x%08x\n",
388 jiffies, saa7146_read(av7110->dev, PSR),
389 saa7146_read(av7110->dev, SSR));
390 goto debi_done;
391 }
392 av7110->debitype = -1;
393
394 switch (type & 0xff) {
395
396 case DATA_TS_RECORD:
397 dvb_dmx_swfilter_packets(&av7110->demux,
398 (const u8 *) av7110->debi_virt,
399 av7110->debilen / 188);
400 xfer = RX_BUFF;
401 break;
402
403 case DATA_PES_RECORD:
404 if (av7110->demux.recording)
405 av7110_record_cb(&av7110->p2t[handle],
406 (u8 *) av7110->debi_virt,
407 av7110->debilen);
408 xfer = RX_BUFF;
409 break;
410
411 case DATA_IPMPE:
412 case DATA_FSECTION:
413 case DATA_PIPING:
414 if (av7110->handle2filter[handle])
415 DvbDmxFilterCallback((u8 *)av7110->debi_virt,
416 av7110->debilen, NULL, 0,
417 av7110->handle2filter[handle],
418 DMX_OK, av7110);
419 xfer = RX_BUFF;
420 break;
421
422 case DATA_CI_GET:
423 {
424 u8 *data = av7110->debi_virt;
425
426 if ((data[0] < 2) && data[2] == 0xff) {
427 int flags = 0;
428 if (data[5] > 0)
429 flags |= CA_CI_MODULE_PRESENT;
430 if (data[5] > 5)
431 flags |= CA_CI_MODULE_READY;
432 av7110->ci_slot[data[0]].flags = flags;
433 } else
434 ci_get_data(&av7110->ci_rbuffer,
435 av7110->debi_virt,
436 av7110->debilen);
437 xfer = RX_BUFF;
438 break;
439 }
440
441 case DATA_COMMON_INTERFACE:
442 CI_handle(av7110, (u8 *)av7110->debi_virt, av7110->debilen);
443#if 0
444 {
445 int i;
446
447 printk("av7110%d: ", av7110->num);
448 printk("%02x ", *(u8 *)av7110->debi_virt);
449 printk("%02x ", *(1+(u8 *)av7110->debi_virt));
450 for (i = 2; i < av7110->debilen; i++)
451 printk("%02x ", (*(i+(unsigned char *)av7110->debi_virt)));
452 for (i = 2; i < av7110->debilen; i++)
453 printk("%c", chtrans(*(i+(unsigned char *)av7110->debi_virt)));
454
455 printk("\n");
456 }
457#endif
458 xfer = RX_BUFF;
459 break;
460
461 case DATA_DEBUG_MESSAGE:
462 ((s8*)av7110->debi_virt)[Reserved_SIZE - 1] = 0;
463 printk("%s\n", (s8 *) av7110->debi_virt);
464 xfer = RX_BUFF;
465 break;
466
467 case DATA_CI_PUT:
468 dprintk(4, "debi DATA_CI_PUT\n");
469 case DATA_MPEG_PLAY:
470 dprintk(4, "debi DATA_MPEG_PLAY\n");
471 case DATA_BMP_LOAD:
472 dprintk(4, "debi DATA_BMP_LOAD\n");
473 xfer = TX_BUFF;
474 break;
475 default:
476 break;
477 }
478debi_done:
479 spin_lock(&av7110->debilock);
480 if (xfer)
481 iwdebi(av7110, DEBINOSWAP, xfer, 0, 2);
482 ARM_ClearMailBox(av7110);
483 spin_unlock(&av7110->debilock);
484}
485
486/* irq from av7110 firmware writing the mailbox register in the DPRAM */
487static void gpioirq(unsigned long data)
488{
489 struct av7110 *av7110 = (struct av7110 *) data;
490 u32 rxbuf, txbuf;
491 int len;
492
493 if (av7110->debitype != -1)
494 /* we shouldn't get any irq while a debi xfer is running */
495 printk("dvb-ttpci: GPIO0 irq oops @ %ld, psr:0x%08x, ssr:0x%08x\n",
496 jiffies, saa7146_read(av7110->dev, PSR),
497 saa7146_read(av7110->dev, SSR));
498
499 if (saa7146_wait_for_debi_done(av7110->dev, 0)) {
500 printk(KERN_ERR "%s: saa7146_wait_for_debi_done timed out\n", __FUNCTION__);
501 BUG(); /* maybe we should try resetting the debi? */
502 }
503
504 spin_lock(&av7110->debilock);
505 ARM_ClearIrq(av7110);
506
507 /* see what the av7110 wants */
508 av7110->debitype = irdebi(av7110, DEBINOSWAP, IRQ_STATE, 0, 2);
509 av7110->debilen = irdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
510 rxbuf = irdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
511 txbuf = irdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
512 len = (av7110->debilen + 3) & ~3;
513
514 print_time("gpio");
515 dprintk(8, "GPIO0 irq 0x%04x %d\n", av7110->debitype, av7110->debilen);
516
517 switch (av7110->debitype & 0xff) {
518
519 case DATA_TS_PLAY:
520 case DATA_PES_PLAY:
521 break;
522
523 case DATA_MPEG_VIDEO_EVENT:
524 {
525 u32 h_ar;
526 struct video_event event;
527
528 av7110->video_size.w = irdebi(av7110, DEBINOSWAP, STATUS_MPEG_WIDTH, 0, 2);
529 h_ar = irdebi(av7110, DEBINOSWAP, STATUS_MPEG_HEIGHT_AR, 0, 2);
530
531 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
532 iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
533
534 av7110->video_size.h = h_ar & 0xfff;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700535
536 event.type = VIDEO_EVENT_SIZE_CHANGED;
537 event.u.size.w = av7110->video_size.w;
538 event.u.size.h = av7110->video_size.h;
539 switch ((h_ar >> 12) & 0xf)
540 {
541 case 3:
542 av7110->video_size.aspect_ratio = VIDEO_FORMAT_16_9;
543 event.u.size.aspect_ratio = VIDEO_FORMAT_16_9;
544 av7110->videostate.video_format = VIDEO_FORMAT_16_9;
545 break;
546 case 4:
547 av7110->video_size.aspect_ratio = VIDEO_FORMAT_221_1;
548 event.u.size.aspect_ratio = VIDEO_FORMAT_221_1;
549 av7110->videostate.video_format = VIDEO_FORMAT_221_1;
550 break;
551 default:
552 av7110->video_size.aspect_ratio = VIDEO_FORMAT_4_3;
553 event.u.size.aspect_ratio = VIDEO_FORMAT_4_3;
554 av7110->videostate.video_format = VIDEO_FORMAT_4_3;
555 }
Oliver Endriss66190a22006-01-09 15:32:42 -0200556
557 dprintk(8, "GPIO0 irq: DATA_MPEG_VIDEO_EVENT: w/h/ar = %u/%u/%u\n",
558 av7110->video_size.w, av7110->video_size.h,
559 av7110->video_size.aspect_ratio);
560
Linus Torvalds1da177e2005-04-16 15:20:36 -0700561 dvb_video_add_event(av7110, &event);
562 break;
563 }
564
565 case DATA_CI_PUT:
566 {
567 int avail;
568 struct dvb_ringbuffer *cibuf = &av7110->ci_wbuffer;
569
570 avail = dvb_ringbuffer_avail(cibuf);
571 if (avail <= 2) {
572 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
573 iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
574 iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
575 break;
576 }
577 len = DVB_RINGBUFFER_PEEK(cibuf, 0) << 8;
578 len |= DVB_RINGBUFFER_PEEK(cibuf, 1);
579 if (avail < len + 2) {
580 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
581 iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
582 iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
583 break;
584 }
585 DVB_RINGBUFFER_SKIP(cibuf, 2);
586
587 dvb_ringbuffer_read(cibuf, av7110->debi_virt, len, 0);
588
589 iwdebi(av7110, DEBINOSWAP, TX_LEN, len, 2);
590 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, len, 2);
591 dprintk(8, "DMA: CI\n");
592 start_debi_dma(av7110, DEBI_WRITE, DPRAM_BASE + txbuf, len);
593 spin_unlock(&av7110->debilock);
594 wake_up(&cibuf->queue);
595 return;
596 }
597
598 case DATA_MPEG_PLAY:
599 if (!av7110->playing) {
600 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
601 iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
602 iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
603 break;
604 }
605 len = 0;
606 if (av7110->debitype & 0x100) {
607 spin_lock(&av7110->aout.lock);
608 len = av7110_pes_play(av7110->debi_virt, &av7110->aout, 2048);
609 spin_unlock(&av7110->aout.lock);
610 }
611 if (len <= 0 && (av7110->debitype & 0x200)
612 &&av7110->videostate.play_state != VIDEO_FREEZED) {
613 spin_lock(&av7110->avout.lock);
614 len = av7110_pes_play(av7110->debi_virt, &av7110->avout, 2048);
615 spin_unlock(&av7110->avout.lock);
616 }
617 if (len <= 0) {
618 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
619 iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
620 iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
621 break;
622 }
623 dprintk(8, "GPIO0 PES_PLAY len=%04x\n", len);
624 iwdebi(av7110, DEBINOSWAP, TX_LEN, len, 2);
625 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, len, 2);
626 dprintk(8, "DMA: MPEG_PLAY\n");
627 start_debi_dma(av7110, DEBI_WRITE, DPRAM_BASE + txbuf, len);
628 spin_unlock(&av7110->debilock);
629 return;
630
631 case DATA_BMP_LOAD:
632 len = av7110->debilen;
633 dprintk(8, "gpio DATA_BMP_LOAD len %d\n", len);
634 if (!len) {
635 av7110->bmp_state = BMP_LOADED;
636 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
637 iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
638 iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
639 wake_up(&av7110->bmpq);
640 dprintk(8, "gpio DATA_BMP_LOAD done\n");
641 break;
642 }
643 if (len > av7110->bmplen)
644 len = av7110->bmplen;
645 if (len > 2 * 1024)
646 len = 2 * 1024;
647 iwdebi(av7110, DEBINOSWAP, TX_LEN, len, 2);
648 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, len, 2);
649 memcpy(av7110->debi_virt, av7110->bmpbuf+av7110->bmpp, len);
650 av7110->bmpp += len;
651 av7110->bmplen -= len;
652 dprintk(8, "gpio DATA_BMP_LOAD DMA len %d\n", len);
653 start_debi_dma(av7110, DEBI_WRITE, DPRAM_BASE+txbuf, len);
654 spin_unlock(&av7110->debilock);
655 return;
656
657 case DATA_CI_GET:
658 case DATA_COMMON_INTERFACE:
659 case DATA_FSECTION:
660 case DATA_IPMPE:
661 case DATA_PIPING:
662 if (!len || len > 4 * 1024) {
663 iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
664 break;
665 }
666 /* fall through */
667
668 case DATA_TS_RECORD:
669 case DATA_PES_RECORD:
670 dprintk(8, "DMA: TS_REC etc.\n");
671 start_debi_dma(av7110, DEBI_READ, DPRAM_BASE+rxbuf, len);
672 spin_unlock(&av7110->debilock);
673 return;
674
675 case DATA_DEBUG_MESSAGE:
676 if (!len || len > 0xff) {
677 iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
678 break;
679 }
680 start_debi_dma(av7110, DEBI_READ, Reserved, len);
681 spin_unlock(&av7110->debilock);
682 return;
683
684 case DATA_IRCOMMAND:
Oliver Endrissee820a62007-04-27 12:31:21 -0300685 if (av7110->ir.ir_handler)
686 av7110->ir.ir_handler(av7110,
Oliver Endriss03388ae2005-09-09 13:03:12 -0700687 swahw32(irdebi(av7110, DEBINOSWAP, Reserved, 0, 4)));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700688 iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
689 break;
690
691 default:
692 printk("dvb-ttpci: gpioirq unknown type=%d len=%d\n",
693 av7110->debitype, av7110->debilen);
694 break;
695 }
696 av7110->debitype = -1;
697 ARM_ClearMailBox(av7110);
698 spin_unlock(&av7110->debilock);
699}
700
701
702#ifdef CONFIG_DVB_AV7110_OSD
703static int dvb_osd_ioctl(struct inode *inode, struct file *file,
704 unsigned int cmd, void *parg)
705{
Tobias Klauserd9bdf772006-12-26 07:33:48 -0300706 struct dvb_device *dvbdev = file->private_data;
707 struct av7110 *av7110 = dvbdev->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708
709 dprintk(4, "%p\n", av7110);
710
711 if (cmd == OSD_SEND_CMD)
712 return av7110_osd_cmd(av7110, (osd_cmd_t *) parg);
713 if (cmd == OSD_GET_CAPABILITY)
714 return av7110_osd_capability(av7110, (osd_cap_t *) parg);
715
716 return -EINVAL;
717}
718
719
720static struct file_operations dvb_osd_fops = {
721 .owner = THIS_MODULE,
722 .ioctl = dvb_generic_ioctl,
723 .open = dvb_generic_open,
724 .release = dvb_generic_release,
725};
726
727static struct dvb_device dvbdev_osd = {
728 .priv = NULL,
729 .users = 1,
730 .writers = 1,
731 .fops = &dvb_osd_fops,
732 .kernel_ioctl = dvb_osd_ioctl,
733};
734#endif /* CONFIG_DVB_AV7110_OSD */
735
736
737static inline int SetPIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid,
738 u16 subpid, u16 pcrpid)
739{
Dr. Werner Fink47f36922006-01-09 15:25:07 -0200740 u16 aflags = 0;
741
Linus Torvalds1da177e2005-04-16 15:20:36 -0700742 dprintk(4, "%p\n", av7110);
743
744 if (vpid == 0x1fff || apid == 0x1fff ||
745 ttpid == 0x1fff || subpid == 0x1fff || pcrpid == 0x1fff) {
746 vpid = apid = ttpid = subpid = pcrpid = 0;
747 av7110->pids[DMX_PES_VIDEO] = 0;
748 av7110->pids[DMX_PES_AUDIO] = 0;
749 av7110->pids[DMX_PES_TELETEXT] = 0;
750 av7110->pids[DMX_PES_PCR] = 0;
751 }
752
Dr. Werner Fink47f36922006-01-09 15:25:07 -0200753 if (av7110->audiostate.bypass_mode)
754 aflags |= 0x8000;
755
756 return av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, MultiPID, 6,
757 pcrpid, vpid, apid, ttpid, subpid, aflags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700758}
759
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700760int ChangePIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761 u16 subpid, u16 pcrpid)
762{
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700763 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700764 dprintk(4, "%p\n", av7110);
765
Ingo Molnar3593cab2006-02-07 06:49:14 -0200766 if (mutex_lock_interruptible(&av7110->pid_mutex))
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700767 return -ERESTARTSYS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700768
769 if (!(vpid & 0x8000))
770 av7110->pids[DMX_PES_VIDEO] = vpid;
771 if (!(apid & 0x8000))
772 av7110->pids[DMX_PES_AUDIO] = apid;
773 if (!(ttpid & 0x8000))
774 av7110->pids[DMX_PES_TELETEXT] = ttpid;
775 if (!(pcrpid & 0x8000))
776 av7110->pids[DMX_PES_PCR] = pcrpid;
777
778 av7110->pids[DMX_PES_SUBTITLE] = 0;
779
780 if (av7110->fe_synced) {
781 pcrpid = av7110->pids[DMX_PES_PCR];
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700782 ret = SetPIDs(av7110, vpid, apid, ttpid, subpid, pcrpid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700783 }
784
Ingo Molnar3593cab2006-02-07 06:49:14 -0200785 mutex_unlock(&av7110->pid_mutex);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700786 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700787}
788
789
790/******************************************************************************
791 * hardware filter functions
792 ******************************************************************************/
793
794static int StartHWFilter(struct dvb_demux_filter *dvbdmxfilter)
795{
796 struct dvb_demux_feed *dvbdmxfeed = dvbdmxfilter->feed;
Tobias Klauserd9bdf772006-12-26 07:33:48 -0300797 struct av7110 *av7110 = dvbdmxfeed->demux->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700798 u16 buf[20];
799 int ret, i;
800 u16 handle;
801// u16 mode = 0x0320;
802 u16 mode = 0xb96a;
803
804 dprintk(4, "%p\n", av7110);
805
806 if (dvbdmxfilter->type == DMX_TYPE_SEC) {
807 if (hw_sections) {
808 buf[4] = (dvbdmxfilter->filter.filter_value[0] << 8) |
809 dvbdmxfilter->maskandmode[0];
810 for (i = 3; i < 18; i++)
811 buf[i + 4 - 2] =
812 (dvbdmxfilter->filter.filter_value[i] << 8) |
813 dvbdmxfilter->maskandmode[i];
814 mode = 4;
815 }
816 } else if ((dvbdmxfeed->ts_type & TS_PACKET) &&
817 !(dvbdmxfeed->ts_type & TS_PAYLOAD_ONLY)) {
818 av7110_p2t_init(&av7110->p2t_filter[dvbdmxfilter->index], dvbdmxfeed);
819 }
820
821 buf[0] = (COMTYPE_PID_FILTER << 8) + AddPIDFilter;
822 buf[1] = 16;
823 buf[2] = dvbdmxfeed->pid;
824 buf[3] = mode;
825
826 ret = av7110_fw_request(av7110, buf, 20, &handle, 1);
827 if (ret != 0 || handle >= 32) {
828 printk("dvb-ttpci: %s error buf %04x %04x %04x %04x "
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700829 "ret %d handle %04x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700830 __FUNCTION__, buf[0], buf[1], buf[2], buf[3],
831 ret, handle);
832 dvbdmxfilter->hw_handle = 0xffff;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700833 if (!ret)
834 ret = -1;
835 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700836 }
837
838 av7110->handle2filter[handle] = dvbdmxfilter;
839 dvbdmxfilter->hw_handle = handle;
840
841 return ret;
842}
843
844static int StopHWFilter(struct dvb_demux_filter *dvbdmxfilter)
845{
Tobias Klauserd9bdf772006-12-26 07:33:48 -0300846 struct av7110 *av7110 = dvbdmxfilter->feed->demux->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700847 u16 buf[3];
848 u16 answ[2];
849 int ret;
850 u16 handle;
851
852 dprintk(4, "%p\n", av7110);
853
854 handle = dvbdmxfilter->hw_handle;
855 if (handle >= 32) {
856 printk("%s tried to stop invalid filter %04x, filter type = %x\n",
857 __FUNCTION__, handle, dvbdmxfilter->type);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700858 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700859 }
860
861 av7110->handle2filter[handle] = NULL;
862
863 buf[0] = (COMTYPE_PID_FILTER << 8) + DelPIDFilter;
864 buf[1] = 1;
865 buf[2] = handle;
866 ret = av7110_fw_request(av7110, buf, 3, answ, 2);
867 if (ret != 0 || answ[1] != handle) {
868 printk("dvb-ttpci: %s error cmd %04x %04x %04x ret %x "
869 "resp %04x %04x pid %d\n",
870 __FUNCTION__, buf[0], buf[1], buf[2], ret,
871 answ[0], answ[1], dvbdmxfilter->feed->pid);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700872 if (!ret)
873 ret = -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700874 }
875 return ret;
876}
877
878
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700879static int dvb_feed_start_pid(struct dvb_demux_feed *dvbdmxfeed)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700880{
881 struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
Tobias Klauserd9bdf772006-12-26 07:33:48 -0300882 struct av7110 *av7110 = dvbdmx->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700883 u16 *pid = dvbdmx->pids, npids[5];
884 int i;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700885 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886
887 dprintk(4, "%p\n", av7110);
888
889 npids[0] = npids[1] = npids[2] = npids[3] = npids[4] = 0xffff;
890 i = dvbdmxfeed->pes_type;
891 npids[i] = (pid[i]&0x8000) ? 0 : pid[i];
892 if ((i == 2) && npids[i] && (dvbdmxfeed->ts_type & TS_PACKET)) {
893 npids[i] = 0;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700894 ret = ChangePIDs(av7110, npids[1], npids[0], npids[2], npids[3], npids[4]);
895 if (!ret)
896 ret = StartHWFilter(dvbdmxfeed->filter);
897 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700898 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700899 if (dvbdmxfeed->pes_type <= 2 || dvbdmxfeed->pes_type == 4) {
900 ret = ChangePIDs(av7110, npids[1], npids[0], npids[2], npids[3], npids[4]);
901 if (ret)
902 return ret;
903 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904
905 if (dvbdmxfeed->pes_type < 2 && npids[0])
906 if (av7110->fe_synced)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700907 {
908 ret = av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, Scan, 0);
909 if (ret)
910 return ret;
911 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912
913 if ((dvbdmxfeed->ts_type & TS_PACKET)) {
914 if (dvbdmxfeed->pes_type == 0 && !(dvbdmx->pids[0] & 0x8000))
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700915 ret = av7110_av_start_record(av7110, RP_AUDIO, dvbdmxfeed);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700916 if (dvbdmxfeed->pes_type == 1 && !(dvbdmx->pids[1] & 0x8000))
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700917 ret = av7110_av_start_record(av7110, RP_VIDEO, dvbdmxfeed);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700919 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700920}
921
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700922static int dvb_feed_stop_pid(struct dvb_demux_feed *dvbdmxfeed)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700923{
924 struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
Tobias Klauserd9bdf772006-12-26 07:33:48 -0300925 struct av7110 *av7110 = dvbdmx->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700926 u16 *pid = dvbdmx->pids, npids[5];
927 int i;
928
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700929 int ret = 0;
930
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931 dprintk(4, "%p\n", av7110);
932
933 if (dvbdmxfeed->pes_type <= 1) {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700934 ret = av7110_av_stop(av7110, dvbdmxfeed->pes_type ? RP_VIDEO : RP_AUDIO);
935 if (ret)
936 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700937 if (!av7110->rec_mode)
938 dvbdmx->recording = 0;
939 if (!av7110->playing)
940 dvbdmx->playing = 0;
941 }
942 npids[0] = npids[1] = npids[2] = npids[3] = npids[4] = 0xffff;
943 i = dvbdmxfeed->pes_type;
944 switch (i) {
945 case 2: //teletext
946 if (dvbdmxfeed->ts_type & TS_PACKET)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700947 ret = StopHWFilter(dvbdmxfeed->filter);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700948 npids[2] = 0;
949 break;
950 case 0:
951 case 1:
952 case 4:
953 if (!pids_off)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700954 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700955 npids[i] = (pid[i]&0x8000) ? 0 : pid[i];
956 break;
957 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700958 if (!ret)
959 ret = ChangePIDs(av7110, npids[1], npids[0], npids[2], npids[3], npids[4]);
960 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700961}
962
963static int av7110_start_feed(struct dvb_demux_feed *feed)
964{
965 struct dvb_demux *demux = feed->demux;
966 struct av7110 *av7110 = demux->priv;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700967 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700968
969 dprintk(4, "%p\n", av7110);
970
971 if (!demux->dmx.frontend)
972 return -EINVAL;
973
974 if (feed->pid > 0x1fff)
975 return -EINVAL;
976
977 if (feed->type == DMX_TYPE_TS) {
978 if ((feed->ts_type & TS_DECODER) &&
979 (feed->pes_type < DMX_TS_PES_OTHER)) {
980 switch (demux->dmx.frontend->source) {
981 case DMX_MEMORY_FE:
982 if (feed->ts_type & TS_DECODER)
983 if (feed->pes_type < 2 &&
984 !(demux->pids[0] & 0x8000) &&
985 !(demux->pids[1] & 0x8000)) {
986 dvb_ringbuffer_flush_spinlock_wakeup(&av7110->avout);
987 dvb_ringbuffer_flush_spinlock_wakeup(&av7110->aout);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700988 ret = av7110_av_start_play(av7110,RP_AV);
989 if (!ret)
990 demux->playing = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700991 }
992 break;
993 default:
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700994 ret = dvb_feed_start_pid(feed);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700995 break;
996 }
997 } else if ((feed->ts_type & TS_PACKET) &&
998 (demux->dmx.frontend->source != DMX_MEMORY_FE)) {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700999 ret = StartHWFilter(feed->filter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001000 }
1001 }
1002
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001003 else if (feed->type == DMX_TYPE_SEC) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001004 int i;
1005
1006 for (i = 0; i < demux->filternum; i++) {
1007 if (demux->filter[i].state != DMX_STATE_READY)
1008 continue;
1009 if (demux->filter[i].type != DMX_TYPE_SEC)
1010 continue;
1011 if (demux->filter[i].filter.parent != &feed->feed.sec)
1012 continue;
1013 demux->filter[i].state = DMX_STATE_GO;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001014 if (demux->dmx.frontend->source != DMX_MEMORY_FE) {
1015 ret = StartHWFilter(&demux->filter[i]);
1016 if (ret)
1017 break;
1018 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001019 }
1020 }
1021
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001022 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001023}
1024
1025
1026static int av7110_stop_feed(struct dvb_demux_feed *feed)
1027{
1028 struct dvb_demux *demux = feed->demux;
1029 struct av7110 *av7110 = demux->priv;
Johannes Stezenbach12ba0502005-07-07 17:58:00 -07001030 int i, rc, ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001031 dprintk(4, "%p\n", av7110);
1032
1033 if (feed->type == DMX_TYPE_TS) {
1034 if (feed->ts_type & TS_DECODER) {
1035 if (feed->pes_type >= DMX_TS_PES_OTHER ||
1036 !demux->pesfilter[feed->pes_type])
1037 return -EINVAL;
1038 demux->pids[feed->pes_type] |= 0x8000;
1039 demux->pesfilter[feed->pes_type] = NULL;
1040 }
1041 if (feed->ts_type & TS_DECODER &&
1042 feed->pes_type < DMX_TS_PES_OTHER) {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001043 ret = dvb_feed_stop_pid(feed);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001044 } else
1045 if ((feed->ts_type & TS_PACKET) &&
1046 (demux->dmx.frontend->source != DMX_MEMORY_FE))
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001047 ret = StopHWFilter(feed->filter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001048 }
1049
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001050 if (!ret && feed->type == DMX_TYPE_SEC) {
Johannes Stezenbach12ba0502005-07-07 17:58:00 -07001051 for (i = 0; i<demux->filternum; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001052 if (demux->filter[i].state == DMX_STATE_GO &&
1053 demux->filter[i].filter.parent == &feed->feed.sec) {
1054 demux->filter[i].state = DMX_STATE_READY;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001055 if (demux->dmx.frontend->source != DMX_MEMORY_FE) {
Johannes Stezenbach12ba0502005-07-07 17:58:00 -07001056 rc = StopHWFilter(&demux->filter[i]);
1057 if (!ret)
1058 ret = rc;
1059 /* keep going, stop as many filters as possible */
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001060 }
Johannes Stezenbach12ba0502005-07-07 17:58:00 -07001061 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062 }
1063 }
1064
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001065 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066}
1067
1068
1069static void restart_feeds(struct av7110 *av7110)
1070{
1071 struct dvb_demux *dvbdmx = &av7110->demux;
1072 struct dvb_demux_feed *feed;
1073 int mode;
Oliver Endriss66190a22006-01-09 15:32:42 -02001074 int i, j;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001075
1076 dprintk(4, "%p\n", av7110);
1077
1078 mode = av7110->playing;
1079 av7110->playing = 0;
1080 av7110->rec_mode = 0;
1081
Oliver Endriss66190a22006-01-09 15:32:42 -02001082 for (i = 0; i < dvbdmx->feednum; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001083 feed = &dvbdmx->feed[i];
Oliver Endriss66190a22006-01-09 15:32:42 -02001084 if (feed->state == DMX_STATE_GO) {
1085 if (feed->type == DMX_TYPE_SEC) {
1086 for (j = 0; j < dvbdmx->filternum; j++) {
1087 if (dvbdmx->filter[j].type != DMX_TYPE_SEC)
1088 continue;
1089 if (dvbdmx->filter[j].filter.parent != &feed->feed.sec)
1090 continue;
1091 if (dvbdmx->filter[j].state == DMX_STATE_GO)
1092 dvbdmx->filter[j].state = DMX_STATE_READY;
1093 }
1094 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001095 av7110_start_feed(feed);
Oliver Endriss66190a22006-01-09 15:32:42 -02001096 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097 }
1098
1099 if (mode)
1100 av7110_av_start_play(av7110, mode);
1101}
1102
1103static int dvb_get_stc(struct dmx_demux *demux, unsigned int num,
1104 uint64_t *stc, unsigned int *base)
1105{
1106 int ret;
1107 u16 fwstc[4];
1108 u16 tag = ((COMTYPE_REQUEST << 8) + ReqSTC);
1109 struct dvb_demux *dvbdemux;
1110 struct av7110 *av7110;
1111
1112 /* pointer casting paranoia... */
Eric Sesterhennae246012006-03-13 13:17:11 -03001113 BUG_ON(!demux);
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001114 dvbdemux = demux->priv;
Eric Sesterhennae246012006-03-13 13:17:11 -03001115 BUG_ON(!dvbdemux);
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001116 av7110 = dvbdemux->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001117
1118 dprintk(4, "%p\n", av7110);
1119
1120 if (num != 0)
1121 return -EINVAL;
1122
1123 ret = av7110_fw_request(av7110, &tag, 0, fwstc, 4);
1124 if (ret) {
1125 printk(KERN_ERR "%s: av7110_fw_request error\n", __FUNCTION__);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001126 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001127 }
1128 dprintk(2, "fwstc = %04hx %04hx %04hx %04hx\n",
1129 fwstc[0], fwstc[1], fwstc[2], fwstc[3]);
1130
1131 *stc = (((uint64_t) ((fwstc[3] & 0x8000) >> 15)) << 32) |
1132 (((uint64_t) fwstc[1]) << 16) | ((uint64_t) fwstc[0]);
1133 *base = 1;
1134
1135 dprintk(4, "stc = %lu\n", (unsigned long)*stc);
1136
1137 return 0;
1138}
1139
1140
1141/******************************************************************************
1142 * SEC device file operations
1143 ******************************************************************************/
1144
1145
1146static int av7110_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
1147{
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001148 struct av7110* av7110 = fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001149
1150 switch (tone) {
1151 case SEC_TONE_ON:
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001152 return Set22K(av7110, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001153
1154 case SEC_TONE_OFF:
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001155 return Set22K(av7110, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001156
1157 default:
1158 return -EINVAL;
1159 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001160}
1161
1162static int av7110_diseqc_send_master_cmd(struct dvb_frontend* fe,
1163 struct dvb_diseqc_master_cmd* cmd)
1164{
1165 struct av7110* av7110 = fe->dvb->priv;
1166
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001167 return av7110_diseqc_send(av7110, cmd->msg_len, cmd->msg, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001168}
1169
1170static int av7110_diseqc_send_burst(struct dvb_frontend* fe,
1171 fe_sec_mini_cmd_t minicmd)
1172{
1173 struct av7110* av7110 = fe->dvb->priv;
1174
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001175 return av7110_diseqc_send(av7110, 0, NULL, minicmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001176}
1177
1178/* simplified code from budget-core.c */
1179static int stop_ts_capture(struct av7110 *budget)
1180{
1181 dprintk(2, "budget: %p\n", budget);
1182
1183 if (--budget->feeding1)
1184 return budget->feeding1;
1185 saa7146_write(budget->dev, MC1, MASK_20); /* DMA3 off */
1186 SAA7146_IER_DISABLE(budget->dev, MASK_10);
1187 SAA7146_ISR_CLEAR(budget->dev, MASK_10);
1188 return 0;
1189}
1190
1191static int start_ts_capture(struct av7110 *budget)
1192{
1193 dprintk(2, "budget: %p\n", budget);
1194
1195 if (budget->feeding1)
1196 return ++budget->feeding1;
1197 memset(budget->grabbing, 0x00, TS_HEIGHT * TS_WIDTH);
1198 budget->tsf = 0xff;
1199 budget->ttbp = 0;
1200 SAA7146_IER_ENABLE(budget->dev, MASK_10); /* VPE */
1201 saa7146_write(budget->dev, MC1, (MASK_04 | MASK_20)); /* DMA3 on */
1202 return ++budget->feeding1;
1203}
1204
1205static int budget_start_feed(struct dvb_demux_feed *feed)
1206{
1207 struct dvb_demux *demux = feed->demux;
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001208 struct av7110 *budget = demux->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001209 int status;
1210
1211 dprintk(2, "av7110: %p\n", budget);
1212
1213 spin_lock(&budget->feedlock1);
1214 feed->pusi_seen = 0; /* have a clean section start */
1215 status = start_ts_capture(budget);
1216 spin_unlock(&budget->feedlock1);
1217 return status;
1218}
1219
1220static int budget_stop_feed(struct dvb_demux_feed *feed)
1221{
1222 struct dvb_demux *demux = feed->demux;
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001223 struct av7110 *budget = demux->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001224 int status;
1225
1226 dprintk(2, "budget: %p\n", budget);
1227
1228 spin_lock(&budget->feedlock1);
1229 status = stop_ts_capture(budget);
1230 spin_unlock(&budget->feedlock1);
1231 return status;
1232}
1233
1234static void vpeirq(unsigned long data)
1235{
1236 struct av7110 *budget = (struct av7110 *) data;
1237 u8 *mem = (u8 *) (budget->grabbing);
1238 u32 olddma = budget->ttbp;
1239 u32 newdma = saa7146_read(budget->dev, PCI_VDP3);
1240
1241 if (!budgetpatch) {
1242 printk("av7110.c: vpeirq() called while budgetpatch disabled!"
1243 " check saa7146 IER register\n");
1244 BUG();
1245 }
1246 /* nearest lower position divisible by 188 */
1247 newdma -= newdma % 188;
1248
1249 if (newdma >= TS_BUFLEN)
1250 return;
1251
1252 budget->ttbp = newdma;
1253
1254 if (!budget->feeding1 || (newdma == olddma))
1255 return;
1256
Jon Burgess87c30192007-05-03 12:23:44 -03001257 /* Ensure streamed PCI data is synced to CPU */
1258 pci_dma_sync_sg_for_cpu(budget->dev->pci, budget->pt.slist, budget->pt.nents, PCI_DMA_FROMDEVICE);
1259
Linus Torvalds1da177e2005-04-16 15:20:36 -07001260#if 0
1261 /* track rps1 activity */
1262 printk("vpeirq: %02x Event Counter 1 0x%04x\n",
1263 mem[olddma],
1264 saa7146_read(budget->dev, EC1R) & 0x3fff);
1265#endif
1266
1267 if (newdma > olddma)
1268 /* no wraparound, dump olddma..newdma */
1269 dvb_dmx_swfilter_packets(&budget->demux1, mem + olddma, (newdma - olddma) / 188);
1270 else {
1271 /* wraparound, dump olddma..buflen and 0..newdma */
1272 dvb_dmx_swfilter_packets(&budget->demux1, mem + olddma, (TS_BUFLEN - olddma) / 188);
1273 dvb_dmx_swfilter_packets(&budget->demux1, mem, newdma / 188);
1274 }
1275}
1276
1277static int av7110_register(struct av7110 *av7110)
1278{
1279 int ret, i;
1280 struct dvb_demux *dvbdemux = &av7110->demux;
1281 struct dvb_demux *dvbdemux1 = &av7110->demux1;
1282
1283 dprintk(4, "%p\n", av7110);
1284
1285 if (av7110->registered)
1286 return -1;
1287
1288 av7110->registered = 1;
1289
1290 dvbdemux->priv = (void *) av7110;
1291
1292 for (i = 0; i < 32; i++)
1293 av7110->handle2filter[i] = NULL;
1294
1295 dvbdemux->filternum = 32;
1296 dvbdemux->feednum = 32;
1297 dvbdemux->start_feed = av7110_start_feed;
1298 dvbdemux->stop_feed = av7110_stop_feed;
1299 dvbdemux->write_to_decoder = av7110_write_to_decoder;
1300 dvbdemux->dmx.capabilities = (DMX_TS_FILTERING | DMX_SECTION_FILTERING |
1301 DMX_MEMORY_BASED_FILTERING);
1302
1303 dvb_dmx_init(&av7110->demux);
1304 av7110->demux.dmx.get_stc = dvb_get_stc;
1305
1306 av7110->dmxdev.filternum = 32;
1307 av7110->dmxdev.demux = &dvbdemux->dmx;
1308 av7110->dmxdev.capabilities = 0;
1309
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001310 dvb_dmxdev_init(&av7110->dmxdev, &av7110->dvb_adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001311
1312 av7110->hw_frontend.source = DMX_FRONTEND_0;
1313
1314 ret = dvbdemux->dmx.add_frontend(&dvbdemux->dmx, &av7110->hw_frontend);
1315
1316 if (ret < 0)
1317 return ret;
1318
1319 av7110->mem_frontend.source = DMX_MEMORY_FE;
1320
1321 ret = dvbdemux->dmx.add_frontend(&dvbdemux->dmx, &av7110->mem_frontend);
1322
1323 if (ret < 0)
1324 return ret;
1325
1326 ret = dvbdemux->dmx.connect_frontend(&dvbdemux->dmx,
1327 &av7110->hw_frontend);
1328 if (ret < 0)
1329 return ret;
1330
1331 av7110_av_register(av7110);
1332 av7110_ca_register(av7110);
1333
1334#ifdef CONFIG_DVB_AV7110_OSD
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001335 dvb_register_device(&av7110->dvb_adapter, &av7110->osd_dev,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001336 &dvbdev_osd, av7110, DVB_DEVICE_OSD);
1337#endif
1338
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001339 dvb_net_init(&av7110->dvb_adapter, &av7110->dvb_net, &dvbdemux->dmx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001340
1341 if (budgetpatch) {
1342 /* initialize software demux1 without its own frontend
1343 * demux1 hardware is connected to frontend0 of demux0
1344 */
1345 dvbdemux1->priv = (void *) av7110;
1346
1347 dvbdemux1->filternum = 256;
1348 dvbdemux1->feednum = 256;
1349 dvbdemux1->start_feed = budget_start_feed;
1350 dvbdemux1->stop_feed = budget_stop_feed;
1351 dvbdemux1->write_to_decoder = NULL;
1352
1353 dvbdemux1->dmx.capabilities = (DMX_TS_FILTERING | DMX_SECTION_FILTERING |
1354 DMX_MEMORY_BASED_FILTERING);
1355
1356 dvb_dmx_init(&av7110->demux1);
1357
1358 av7110->dmxdev1.filternum = 256;
1359 av7110->dmxdev1.demux = &dvbdemux1->dmx;
1360 av7110->dmxdev1.capabilities = 0;
1361
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001362 dvb_dmxdev_init(&av7110->dmxdev1, &av7110->dvb_adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001363
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001364 dvb_net_init(&av7110->dvb_adapter, &av7110->dvb_net1, &dvbdemux1->dmx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001365 printk("dvb-ttpci: additional demux1 for budget-patch registered\n");
1366 }
1367 return 0;
1368}
1369
1370
1371static void dvb_unregister(struct av7110 *av7110)
1372{
1373 struct dvb_demux *dvbdemux = &av7110->demux;
1374 struct dvb_demux *dvbdemux1 = &av7110->demux1;
1375
1376 dprintk(4, "%p\n", av7110);
1377
1378 if (!av7110->registered)
1379 return;
1380
1381 if (budgetpatch) {
1382 dvb_net_release(&av7110->dvb_net1);
1383 dvbdemux->dmx.close(&dvbdemux1->dmx);
1384 dvb_dmxdev_release(&av7110->dmxdev1);
1385 dvb_dmx_release(&av7110->demux1);
1386 }
1387
1388 dvb_net_release(&av7110->dvb_net);
1389
1390 dvbdemux->dmx.close(&dvbdemux->dmx);
1391 dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &av7110->hw_frontend);
1392 dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &av7110->mem_frontend);
1393
1394 dvb_dmxdev_release(&av7110->dmxdev);
1395 dvb_dmx_release(&av7110->demux);
1396
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001397 if (av7110->fe != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001398 dvb_unregister_frontend(av7110->fe);
Andrew de Quinceyf52a8382006-08-08 09:10:09 -03001399 dvb_frontend_detach(av7110->fe);
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001400 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001401 dvb_unregister_device(av7110->osd_dev);
1402 av7110_av_unregister(av7110);
1403 av7110_ca_unregister(av7110);
1404}
1405
1406
1407/****************************************************************************
1408 * I2C client commands
1409 ****************************************************************************/
1410
1411int i2c_writereg(struct av7110 *av7110, u8 id, u8 reg, u8 val)
1412{
1413 u8 msg[2] = { reg, val };
1414 struct i2c_msg msgs;
1415
1416 msgs.flags = 0;
1417 msgs.addr = id / 2;
1418 msgs.len = 2;
1419 msgs.buf = msg;
1420 return i2c_transfer(&av7110->i2c_adap, &msgs, 1);
1421}
1422
1423#if 0
1424u8 i2c_readreg(struct av7110 *av7110, u8 id, u8 reg)
1425{
1426 u8 mm1[] = {0x00};
1427 u8 mm2[] = {0x00};
1428 struct i2c_msg msgs[2];
1429
1430 msgs[0].flags = 0;
1431 msgs[1].flags = I2C_M_RD;
1432 msgs[0].addr = msgs[1].addr = id / 2;
1433 mm1[0] = reg;
1434 msgs[0].len = 1; msgs[1].len = 1;
1435 msgs[0].buf = mm1; msgs[1].buf = mm2;
1436 i2c_transfer(&av7110->i2c_adap, msgs, 2);
1437
1438 return mm2[0];
1439}
1440#endif
1441
1442/****************************************************************************
1443 * INITIALIZATION
1444 ****************************************************************************/
1445
1446
1447static int check_firmware(struct av7110* av7110)
1448{
1449 u32 crc = 0, len = 0;
1450 unsigned char *ptr;
1451
1452 /* check for firmware magic */
1453 ptr = av7110->bin_fw;
1454 if (ptr[0] != 'A' || ptr[1] != 'V' ||
1455 ptr[2] != 'F' || ptr[3] != 'W') {
1456 printk("dvb-ttpci: this is not an av7110 firmware\n");
1457 return -EINVAL;
1458 }
1459 ptr += 4;
1460
1461 /* check dpram file */
1462 crc = ntohl(*(u32*) ptr);
1463 ptr += 4;
1464 len = ntohl(*(u32*) ptr);
1465 ptr += 4;
1466 if (len >= 512) {
Alexey Dobriyanbe787ac2006-03-07 22:20:23 -03001467 printk("dvb-ttpci: dpram file is way too big.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468 return -EINVAL;
1469 }
1470 if (crc != crc32_le(0, ptr, len)) {
1471 printk("dvb-ttpci: crc32 of dpram file does not match.\n");
1472 return -EINVAL;
1473 }
1474 av7110->bin_dpram = ptr;
1475 av7110->size_dpram = len;
1476 ptr += len;
1477
1478 /* check root file */
1479 crc = ntohl(*(u32*) ptr);
1480 ptr += 4;
1481 len = ntohl(*(u32*) ptr);
1482 ptr += 4;
1483
1484 if (len <= 200000 || len >= 300000 ||
1485 len > ((av7110->bin_fw + av7110->size_fw) - ptr)) {
1486 printk("dvb-ttpci: root file has strange size (%d). aborting.\n", len);
1487 return -EINVAL;
1488 }
1489 if( crc != crc32_le(0, ptr, len)) {
1490 printk("dvb-ttpci: crc32 of root file does not match.\n");
1491 return -EINVAL;
1492 }
1493 av7110->bin_root = ptr;
1494 av7110->size_root = len;
1495 return 0;
1496}
1497
1498#ifdef CONFIG_DVB_AV7110_FIRMWARE_FILE
1499#include "av7110_firm.h"
1500static void put_firmware(struct av7110* av7110)
1501{
1502 av7110->bin_fw = NULL;
1503}
1504
1505static inline int get_firmware(struct av7110* av7110)
1506{
1507 av7110->bin_fw = dvb_ttpci_fw;
1508 av7110->size_fw = sizeof(dvb_ttpci_fw);
1509 return check_firmware(av7110);
1510}
1511#else
1512static void put_firmware(struct av7110* av7110)
1513{
1514 vfree(av7110->bin_fw);
1515}
1516
1517static int get_firmware(struct av7110* av7110)
1518{
1519 int ret;
1520 const struct firmware *fw;
1521
1522 /* request the av7110 firmware, this will block until someone uploads it */
1523 ret = request_firmware(&fw, "dvb-ttpci-01.fw", &av7110->dev->pci->dev);
1524 if (ret) {
1525 if (ret == -ENOENT) {
1526 printk(KERN_ERR "dvb-ttpci: could not load firmware,"
1527 " file not found: dvb-ttpci-01.fw\n");
Ville Skytt\ä12e66f62006-01-09 15:25:38 -02001528 printk(KERN_ERR "dvb-ttpci: usually this should be in "
1529 "/usr/lib/hotplug/firmware or /lib/firmware\n");
1530 printk(KERN_ERR "dvb-ttpci: and can be downloaded from"
Linus Torvalds1da177e2005-04-16 15:20:36 -07001531 " http://www.linuxtv.org/download/dvb/firmware/\n");
1532 } else
1533 printk(KERN_ERR "dvb-ttpci: cannot request firmware"
1534 " (error %i)\n", ret);
1535 return -EINVAL;
1536 }
1537
1538 if (fw->size <= 200000) {
1539 printk("dvb-ttpci: this firmware is way too small.\n");
1540 release_firmware(fw);
1541 return -EINVAL;
1542 }
1543
1544 /* check if the firmware is available */
Jesper Juhld9bf2c02007-08-25 11:23:54 -03001545 av7110->bin_fw = vmalloc(fw->size);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001546 if (NULL == av7110->bin_fw) {
1547 dprintk(1, "out of memory\n");
1548 release_firmware(fw);
1549 return -ENOMEM;
1550 }
1551
1552 memcpy(av7110->bin_fw, fw->data, fw->size);
1553 av7110->size_fw = fw->size;
1554 if ((ret = check_firmware(av7110)))
1555 vfree(av7110->bin_fw);
1556
1557 release_firmware(fw);
1558 return ret;
1559}
1560#endif
1561
1562
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001563static int alps_bsrv2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001564{
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001565 struct av7110* av7110 = fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001566 u8 pwr = 0;
1567 u8 buf[4];
1568 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
1569 u32 div = (params->frequency + 479500) / 125;
1570
1571 if (params->frequency > 2000000) pwr = 3;
1572 else if (params->frequency > 1800000) pwr = 2;
1573 else if (params->frequency > 1600000) pwr = 1;
1574 else if (params->frequency > 1200000) pwr = 0;
1575 else if (params->frequency >= 1100000) pwr = 1;
1576 else pwr = 2;
1577
1578 buf[0] = (div >> 8) & 0x7f;
1579 buf[1] = div & 0xff;
1580 buf[2] = ((div & 0x18000) >> 10) | 0x95;
1581 buf[3] = (pwr << 6) | 0x30;
1582
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -08001583 // NOTE: since we're using a prescaler of 2, we set the
Linus Torvalds1da177e2005-04-16 15:20:36 -07001584 // divisor frequency to 62.5kHz and divide by 125 above
1585
Patrick Boettcherdea74862006-05-14 05:01:31 -03001586 if (fe->ops.i2c_gate_ctrl)
1587 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001588 if (i2c_transfer (&av7110->i2c_adap, &msg, 1) != 1)
1589 return -EIO;
1590 return 0;
1591}
1592
1593static struct ves1x93_config alps_bsrv2_config = {
1594 .demod_address = 0x08,
1595 .xin = 90100000UL,
1596 .invert_pwm = 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001597};
1598
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001599static int alps_tdbe2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001600{
1601 struct av7110* av7110 = fe->dvb->priv;
1602 u32 div;
1603 u8 data[4];
1604 struct i2c_msg msg = { .addr = 0x62, .flags = 0, .buf = data, .len = sizeof(data) };
1605
1606 div = (params->frequency + 35937500 + 31250) / 62500;
1607
1608 data[0] = (div >> 8) & 0x7f;
1609 data[1] = div & 0xff;
1610 data[2] = 0x85 | ((div >> 10) & 0x60);
1611 data[3] = (params->frequency < 174000000 ? 0x88 : params->frequency < 470000000 ? 0x84 : 0x81);
1612
Patrick Boettcherdea74862006-05-14 05:01:31 -03001613 if (fe->ops.i2c_gate_ctrl)
1614 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001615 if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
1616 return -EIO;
1617 return 0;
1618}
1619
1620static struct ves1820_config alps_tdbe2_config = {
1621 .demod_address = 0x09,
1622 .xin = 57840000UL,
1623 .invert = 1,
1624 .selagc = VES1820_SELAGC_SIGNAMPERR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001625};
1626
1627
1628
1629
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001630static int grundig_29504_451_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001631{
1632 struct av7110* av7110 = fe->dvb->priv;
1633 u32 div;
1634 u8 data[4];
1635 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
1636
1637 div = params->frequency / 125;
1638 data[0] = (div >> 8) & 0x7f;
1639 data[1] = div & 0xff;
1640 data[2] = 0x8e;
1641 data[3] = 0x00;
1642
Patrick Boettcherdea74862006-05-14 05:01:31 -03001643 if (fe->ops.i2c_gate_ctrl)
1644 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001645 if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
1646 return -EIO;
1647 return 0;
1648}
1649
1650static struct tda8083_config grundig_29504_451_config = {
1651 .demod_address = 0x68,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001652};
1653
1654
1655
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001656static int philips_cd1516_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001657{
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -08001658 struct av7110* av7110 = fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001659 u32 div;
1660 u32 f = params->frequency;
1661 u8 data[4];
1662 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
1663
1664 div = (f + 36125000 + 31250) / 62500;
1665
1666 data[0] = (div >> 8) & 0x7f;
1667 data[1] = div & 0xff;
1668 data[2] = 0x8e;
1669 data[3] = (f < 174000000 ? 0xa1 : f < 470000000 ? 0x92 : 0x34);
1670
Patrick Boettcherdea74862006-05-14 05:01:31 -03001671 if (fe->ops.i2c_gate_ctrl)
1672 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001673 if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
1674 return -EIO;
1675 return 0;
1676}
1677
1678static struct ves1820_config philips_cd1516_config = {
1679 .demod_address = 0x09,
1680 .xin = 57840000UL,
1681 .invert = 1,
1682 .selagc = VES1820_SELAGC_SIGNAMPERR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001683};
1684
1685
1686
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001687static int alps_tdlb7_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001688{
1689 struct av7110* av7110 = fe->dvb->priv;
1690 u32 div, pwr;
1691 u8 data[4];
1692 struct i2c_msg msg = { .addr = 0x60, .flags = 0, .buf = data, .len = sizeof(data) };
1693
1694 div = (params->frequency + 36200000) / 166666;
1695
1696 if (params->frequency <= 782000000)
1697 pwr = 1;
1698 else
1699 pwr = 2;
1700
1701 data[0] = (div >> 8) & 0x7f;
1702 data[1] = div & 0xff;
1703 data[2] = 0x85;
1704 data[3] = pwr << 6;
1705
Patrick Boettcherdea74862006-05-14 05:01:31 -03001706 if (fe->ops.i2c_gate_ctrl)
1707 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001708 if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
1709 return -EIO;
1710 return 0;
1711}
1712
1713static int alps_tdlb7_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name)
1714{
Oliver Endrissd98821e2006-09-14 00:15:13 -03001715#if defined(CONFIG_DVB_SP8870) || defined(CONFIG_DVB_SP8870_MODULE)
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001716 struct av7110* av7110 = fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001717
1718 return request_firmware(fw, name, &av7110->dev->pci->dev);
Oliver Endrissd98821e2006-09-14 00:15:13 -03001719#else
1720 return -EINVAL;
1721#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001722}
1723
1724static struct sp8870_config alps_tdlb7_config = {
1725
1726 .demod_address = 0x71,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001727 .request_firmware = alps_tdlb7_request_firmware,
1728};
1729
1730
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001731static u8 nexusca_stv0297_inittab[] = {
1732 0x80, 0x01,
1733 0x80, 0x00,
1734 0x81, 0x01,
1735 0x81, 0x00,
1736 0x00, 0x09,
1737 0x01, 0x69,
1738 0x03, 0x00,
1739 0x04, 0x00,
1740 0x07, 0x00,
1741 0x08, 0x00,
1742 0x20, 0x00,
1743 0x21, 0x40,
1744 0x22, 0x00,
1745 0x23, 0x00,
1746 0x24, 0x40,
1747 0x25, 0x88,
1748 0x30, 0xff,
1749 0x31, 0x00,
1750 0x32, 0xff,
1751 0x33, 0x00,
1752 0x34, 0x50,
1753 0x35, 0x7f,
1754 0x36, 0x00,
1755 0x37, 0x20,
1756 0x38, 0x00,
1757 0x40, 0x1c,
1758 0x41, 0xff,
1759 0x42, 0x29,
1760 0x43, 0x00,
1761 0x44, 0xff,
1762 0x45, 0x00,
1763 0x46, 0x00,
1764 0x49, 0x04,
1765 0x4a, 0x00,
1766 0x4b, 0x7b,
1767 0x52, 0x30,
1768 0x55, 0xae,
1769 0x56, 0x47,
1770 0x57, 0xe1,
1771 0x58, 0x3a,
1772 0x5a, 0x1e,
1773 0x5b, 0x34,
1774 0x60, 0x00,
1775 0x63, 0x00,
1776 0x64, 0x00,
1777 0x65, 0x00,
1778 0x66, 0x00,
1779 0x67, 0x00,
1780 0x68, 0x00,
1781 0x69, 0x00,
1782 0x6a, 0x02,
1783 0x6b, 0x00,
1784 0x70, 0xff,
1785 0x71, 0x00,
1786 0x72, 0x00,
1787 0x73, 0x00,
1788 0x74, 0x0c,
1789 0x80, 0x00,
1790 0x81, 0x00,
1791 0x82, 0x00,
1792 0x83, 0x00,
1793 0x84, 0x04,
1794 0x85, 0x80,
1795 0x86, 0x24,
1796 0x87, 0x78,
1797 0x88, 0x10,
1798 0x89, 0x00,
1799 0x90, 0x01,
1800 0x91, 0x01,
1801 0xa0, 0x04,
1802 0xa1, 0x00,
1803 0xa2, 0x00,
1804 0xb0, 0x91,
1805 0xb1, 0x0b,
1806 0xc0, 0x53,
1807 0xc1, 0x70,
1808 0xc2, 0x12,
1809 0xd0, 0x00,
1810 0xd1, 0x00,
1811 0xd2, 0x00,
1812 0xd3, 0x00,
1813 0xd4, 0x00,
1814 0xd5, 0x00,
1815 0xde, 0x00,
1816 0xdf, 0x00,
1817 0x61, 0x49,
1818 0x62, 0x0b,
1819 0x53, 0x08,
1820 0x59, 0x08,
1821 0xff, 0xff,
1822};
Linus Torvalds1da177e2005-04-16 15:20:36 -07001823
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001824static int nexusca_stv0297_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001825{
1826 struct av7110* av7110 = fe->dvb->priv;
1827 u32 div;
1828 u8 data[4];
1829 struct i2c_msg msg = { .addr = 0x63, .flags = 0, .buf = data, .len = sizeof(data) };
1830 struct i2c_msg readmsg = { .addr = 0x63, .flags = I2C_M_RD, .buf = data, .len = 1 };
1831 int i;
1832
1833 div = (params->frequency + 36150000 + 31250) / 62500;
1834
1835 data[0] = (div >> 8) & 0x7f;
1836 data[1] = div & 0xff;
1837 data[2] = 0xce;
1838
1839 if (params->frequency < 45000000)
1840 return -EINVAL;
1841 else if (params->frequency < 137000000)
1842 data[3] = 0x01;
1843 else if (params->frequency < 403000000)
1844 data[3] = 0x02;
1845 else if (params->frequency < 860000000)
1846 data[3] = 0x04;
1847 else
1848 return -EINVAL;
1849
Patrick Boettcherdea74862006-05-14 05:01:31 -03001850 if (fe->ops.i2c_gate_ctrl)
1851 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001852 if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1) {
1853 printk("nexusca: pll transfer failed!\n");
1854 return -EIO;
1855 }
1856
1857 // wait for PLL lock
1858 for(i = 0; i < 20; i++) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001859 if (fe->ops.i2c_gate_ctrl)
1860 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001861 if (i2c_transfer(&av7110->i2c_adap, &readmsg, 1) == 1)
1862 if (data[0] & 0x40) break;
1863 msleep(10);
1864 }
1865
1866 return 0;
1867}
1868
1869static struct stv0297_config nexusca_stv0297_config = {
1870
1871 .demod_address = 0x1C,
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001872 .inittab = nexusca_stv0297_inittab,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001873 .invert = 1,
Thomas Kaiserb8d4c232006-04-27 21:45:20 -03001874 .stop_during_read = 1,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001875};
1876
1877
1878
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001879static int grundig_29504_401_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001880{
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001881 struct av7110* av7110 = fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001882 u32 div;
1883 u8 cfg, cpump, band_select;
1884 u8 data[4];
1885 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
1886
1887 div = (36125000 + params->frequency) / 166666;
1888
1889 cfg = 0x88;
1890
1891 if (params->frequency < 175000000) cpump = 2;
1892 else if (params->frequency < 390000000) cpump = 1;
1893 else if (params->frequency < 470000000) cpump = 2;
1894 else if (params->frequency < 750000000) cpump = 1;
1895 else cpump = 3;
1896
1897 if (params->frequency < 175000000) band_select = 0x0e;
1898 else if (params->frequency < 470000000) band_select = 0x05;
1899 else band_select = 0x03;
1900
1901 data[0] = (div >> 8) & 0x7f;
1902 data[1] = div & 0xff;
1903 data[2] = ((div >> 10) & 0x60) | cfg;
1904 data[3] = (cpump << 6) | band_select;
1905
Patrick Boettcherdea74862006-05-14 05:01:31 -03001906 if (fe->ops.i2c_gate_ctrl)
1907 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001908 if (i2c_transfer (&av7110->i2c_adap, &msg, 1) != 1) return -EIO;
1909 return 0;
1910}
1911
1912static struct l64781_config grundig_29504_401_config = {
1913 .demod_address = 0x55,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001914};
1915
1916
1917
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001918static int av7110_fe_lock_fix(struct av7110* av7110, fe_status_t status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001919{
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001920 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001921 int synced = (status & FE_HAS_LOCK) ? 1 : 0;
1922
1923 av7110->fe_status = status;
1924
1925 if (av7110->fe_synced == synced)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001926 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001927
Oliver Endriss14500d42007-03-03 14:45:48 -03001928 if (av7110->playing) {
1929 av7110->fe_synced = synced;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001930 return 0;
Oliver Endriss14500d42007-03-03 14:45:48 -03001931 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001932
Ingo Molnar3593cab2006-02-07 06:49:14 -02001933 if (mutex_lock_interruptible(&av7110->pid_mutex))
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001934 return -ERESTARTSYS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001935
Oliver Endriss34612152005-07-07 17:58:02 -07001936 if (synced) {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001937 ret = SetPIDs(av7110, av7110->pids[DMX_PES_VIDEO],
Linus Torvalds1da177e2005-04-16 15:20:36 -07001938 av7110->pids[DMX_PES_AUDIO],
1939 av7110->pids[DMX_PES_TELETEXT], 0,
1940 av7110->pids[DMX_PES_PCR]);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001941 if (!ret)
1942 ret = av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, Scan, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001943 } else {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001944 ret = SetPIDs(av7110, 0, 0, 0, 0, 0);
1945 if (!ret) {
1946 ret = av7110_fw_cmd(av7110, COMTYPE_PID_FILTER, FlushTSQueue, 0);
1947 if (!ret)
1948 ret = av7110_wait_msgstate(av7110, GPMQBusy);
1949 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001950 }
1951
Oliver Endriss34612152005-07-07 17:58:02 -07001952 if (!ret)
1953 av7110->fe_synced = synced;
1954
Ingo Molnar3593cab2006-02-07 06:49:14 -02001955 mutex_unlock(&av7110->pid_mutex);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001956 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001957}
1958
1959static int av7110_fe_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
1960{
1961 struct av7110* av7110 = fe->dvb->priv;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001962
1963 int ret = av7110_fe_lock_fix(av7110, 0);
Oliver Endriss66190a22006-01-09 15:32:42 -02001964 if (!ret) {
1965 av7110->saved_fe_params = *params;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001966 ret = av7110->fe_set_frontend(fe, params);
Oliver Endriss66190a22006-01-09 15:32:42 -02001967 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001968 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001969}
1970
1971static int av7110_fe_init(struct dvb_frontend* fe)
1972{
1973 struct av7110* av7110 = fe->dvb->priv;
1974
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001975 int ret = av7110_fe_lock_fix(av7110, 0);
1976 if (!ret)
1977 ret = av7110->fe_init(fe);
1978 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001979}
1980
1981static int av7110_fe_read_status(struct dvb_frontend* fe, fe_status_t* status)
1982{
1983 struct av7110* av7110 = fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001984
1985 /* call the real implementation */
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001986 int ret = av7110->fe_read_status(fe, status);
1987 if (!ret)
1988 if (((*status ^ av7110->fe_status) & FE_HAS_LOCK) && (*status & FE_HAS_LOCK))
1989 ret = av7110_fe_lock_fix(av7110, *status);
1990 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001991}
1992
1993static int av7110_fe_diseqc_reset_overload(struct dvb_frontend* fe)
1994{
1995 struct av7110* av7110 = fe->dvb->priv;
1996
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001997 int ret = av7110_fe_lock_fix(av7110, 0);
1998 if (!ret)
1999 ret = av7110->fe_diseqc_reset_overload(fe);
2000 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002001}
2002
2003static int av7110_fe_diseqc_send_master_cmd(struct dvb_frontend* fe,
2004 struct dvb_diseqc_master_cmd* cmd)
2005{
2006 struct av7110* av7110 = fe->dvb->priv;
2007
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002008 int ret = av7110_fe_lock_fix(av7110, 0);
Oliver Endriss66190a22006-01-09 15:32:42 -02002009 if (!ret) {
2010 av7110->saved_master_cmd = *cmd;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002011 ret = av7110->fe_diseqc_send_master_cmd(fe, cmd);
Oliver Endriss66190a22006-01-09 15:32:42 -02002012 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002013 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002014}
2015
2016static int av7110_fe_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd)
2017{
2018 struct av7110* av7110 = fe->dvb->priv;
2019
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002020 int ret = av7110_fe_lock_fix(av7110, 0);
Oliver Endriss66190a22006-01-09 15:32:42 -02002021 if (!ret) {
2022 av7110->saved_minicmd = minicmd;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002023 ret = av7110->fe_diseqc_send_burst(fe, minicmd);
Oliver Endriss66190a22006-01-09 15:32:42 -02002024 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002025 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002026}
2027
2028static int av7110_fe_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
2029{
2030 struct av7110* av7110 = fe->dvb->priv;
2031
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002032 int ret = av7110_fe_lock_fix(av7110, 0);
Oliver Endriss66190a22006-01-09 15:32:42 -02002033 if (!ret) {
2034 av7110->saved_tone = tone;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002035 ret = av7110->fe_set_tone(fe, tone);
Oliver Endriss66190a22006-01-09 15:32:42 -02002036 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002037 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002038}
2039
2040static int av7110_fe_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
2041{
2042 struct av7110* av7110 = fe->dvb->priv;
2043
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002044 int ret = av7110_fe_lock_fix(av7110, 0);
Oliver Endriss66190a22006-01-09 15:32:42 -02002045 if (!ret) {
2046 av7110->saved_voltage = voltage;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002047 ret = av7110->fe_set_voltage(fe, voltage);
Oliver Endriss66190a22006-01-09 15:32:42 -02002048 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002049 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002050}
2051
Peter Beutner400b7082006-01-09 15:32:43 -02002052static int av7110_fe_dishnetwork_send_legacy_command(struct dvb_frontend* fe, unsigned long cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002053{
2054 struct av7110* av7110 = fe->dvb->priv;
2055
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002056 int ret = av7110_fe_lock_fix(av7110, 0);
2057 if (!ret)
2058 ret = av7110->fe_dishnetwork_send_legacy_command(fe, cmd);
2059 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002060}
2061
Oliver Endriss66190a22006-01-09 15:32:42 -02002062static void dvb_s_recover(struct av7110* av7110)
2063{
2064 av7110_fe_init(av7110->fe);
2065
2066 av7110_fe_set_voltage(av7110->fe, av7110->saved_voltage);
2067 if (av7110->saved_master_cmd.msg_len) {
2068 msleep(20);
2069 av7110_fe_diseqc_send_master_cmd(av7110->fe, &av7110->saved_master_cmd);
2070 }
2071 msleep(20);
2072 av7110_fe_diseqc_send_burst(av7110->fe, av7110->saved_minicmd);
2073 msleep(20);
2074 av7110_fe_set_tone(av7110->fe, av7110->saved_tone);
2075
2076 av7110_fe_set_frontend(av7110->fe, &av7110->saved_fe_params);
2077}
2078
Linus Torvalds1da177e2005-04-16 15:20:36 -07002079static u8 read_pwm(struct av7110* av7110)
2080{
2081 u8 b = 0xff;
2082 u8 pwm;
2083 struct i2c_msg msg[] = { { .addr = 0x50,.flags = 0,.buf = &b,.len = 1 },
2084 { .addr = 0x50,.flags = I2C_M_RD,.buf = &pwm,.len = 1} };
2085
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -08002086 if ((i2c_transfer(&av7110->i2c_adap, msg, 2) != 2) || (pwm == 0xff))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002087 pwm = 0x48;
2088
2089 return pwm;
2090}
2091
2092static int frontend_init(struct av7110 *av7110)
2093{
2094 int ret;
2095
2096 if (av7110->dev->pci->subsystem_vendor == 0x110a) {
2097 switch(av7110->dev->pci->subsystem_device) {
2098 case 0x0000: // Fujitsu/Siemens DVB-Cable (ves1820/Philips CD1516(??))
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002099 av7110->fe = dvb_attach(ves1820_attach, &philips_cd1516_config,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002100 &av7110->i2c_adap, read_pwm(av7110));
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002101 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002102 av7110->fe->ops.tuner_ops.set_params = philips_cd1516_tuner_set_params;
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002103 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002104 break;
2105 }
2106
2107 } else if (av7110->dev->pci->subsystem_vendor == 0x13c2) {
2108 switch(av7110->dev->pci->subsystem_device) {
2109 case 0x0000: // Hauppauge/TT WinTV DVB-S rev1.X
2110 case 0x0003: // Hauppauge/TT WinTV Nexus-S Rev 2.X
2111 case 0x1002: // Hauppauge/TT WinTV DVB-S rev1.3SE
2112
2113 // try the ALPS BSRV2 first of all
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002114 av7110->fe = dvb_attach(ves1x93_attach, &alps_bsrv2_config, &av7110->i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002115 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002116 av7110->fe->ops.tuner_ops.set_params = alps_bsrv2_tuner_set_params;
2117 av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
2118 av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
2119 av7110->fe->ops.set_tone = av7110_set_tone;
Oliver Endriss66190a22006-01-09 15:32:42 -02002120 av7110->recover = dvb_s_recover;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002121 break;
2122 }
2123
2124 // try the ALPS BSRU6 now
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002125 av7110->fe = dvb_attach(stv0299_attach, &alps_bsru6_config, &av7110->i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002126 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002127 av7110->fe->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03002128 av7110->fe->tuner_priv = &av7110->i2c_adap;
2129
Patrick Boettcherdea74862006-05-14 05:01:31 -03002130 av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
2131 av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
2132 av7110->fe->ops.set_tone = av7110_set_tone;
Oliver Endriss66190a22006-01-09 15:32:42 -02002133 av7110->recover = dvb_s_recover;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002134 break;
2135 }
2136
2137 // Try the grundig 29504-451
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002138 av7110->fe = dvb_attach(tda8083_attach, &grundig_29504_451_config, &av7110->i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002139 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002140 av7110->fe->ops.tuner_ops.set_params = grundig_29504_451_tuner_set_params;
2141 av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
2142 av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
2143 av7110->fe->ops.set_tone = av7110_set_tone;
Oliver Endriss66190a22006-01-09 15:32:42 -02002144 av7110->recover = dvb_s_recover;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002145 break;
2146 }
2147
2148 /* Try DVB-C cards */
2149 switch(av7110->dev->pci->subsystem_device) {
2150 case 0x0000:
2151 /* Siemens DVB-C (full-length card) VES1820/Philips CD1516 */
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002152 av7110->fe = dvb_attach(ves1820_attach, &philips_cd1516_config, &av7110->i2c_adap,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002153 read_pwm(av7110));
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002154 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002155 av7110->fe->ops.tuner_ops.set_params = philips_cd1516_tuner_set_params;
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002156 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002157 break;
2158 case 0x0003:
Adrian Bunkf3688fc2006-03-29 22:46:12 -03002159 /* Hauppauge DVB-C 2.1 VES1820/ALPS TDBE2 */
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002160 av7110->fe = dvb_attach(ves1820_attach, &alps_tdbe2_config, &av7110->i2c_adap,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002161 read_pwm(av7110));
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002162 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002163 av7110->fe->ops.tuner_ops.set_params = alps_tdbe2_tuner_set_params;
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002164 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002165 break;
2166 }
2167 break;
2168
2169 case 0x0001: // Hauppauge/TT Nexus-T premium rev1.X
Oliver Endriss8d90ee52006-08-07 02:04:26 -03002170 // try ALPS TDLB7 first, then Grundig 29504-401
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002171 av7110->fe = dvb_attach(sp8870_attach, &alps_tdlb7_config, &av7110->i2c_adap);
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002172 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002173 av7110->fe->ops.tuner_ops.set_params = alps_tdlb7_tuner_set_params;
Oliver Endriss8d90ee52006-08-07 02:04:26 -03002174 break;
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002175 }
Oliver Endriss8d90ee52006-08-07 02:04:26 -03002176 /* fall-thru */
2177
2178 case 0x0008: // Hauppauge/TT DVB-T
2179 // Grundig 29504-401
2180 av7110->fe = dvb_attach(l64781_attach, &grundig_29504_401_config, &av7110->i2c_adap);
2181 if (av7110->fe)
2182 av7110->fe->ops.tuner_ops.set_params = grundig_29504_401_tuner_set_params;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002183 break;
2184
2185 case 0x0002: // Hauppauge/TT DVB-C premium rev2.X
2186
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002187 av7110->fe = dvb_attach(ves1820_attach, &alps_tdbe2_config, &av7110->i2c_adap, read_pwm(av7110));
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002188 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002189 av7110->fe->ops.tuner_ops.set_params = alps_tdbe2_tuner_set_params;
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002190 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002191 break;
2192
Oliver Endriss8bd63012006-02-07 06:49:11 -02002193 case 0x0004: // Galaxis DVB-S rev1.3
2194 /* ALPS BSRV2 */
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002195 av7110->fe = dvb_attach(ves1x93_attach, &alps_bsrv2_config, &av7110->i2c_adap);
Oliver Endriss8bd63012006-02-07 06:49:11 -02002196 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002197 av7110->fe->ops.tuner_ops.set_params = alps_bsrv2_tuner_set_params;
2198 av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
2199 av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
2200 av7110->fe->ops.set_tone = av7110_set_tone;
Oliver Endriss8bd63012006-02-07 06:49:11 -02002201 av7110->recover = dvb_s_recover;
2202 }
2203 break;
2204
Linus Torvalds1da177e2005-04-16 15:20:36 -07002205 case 0x0006: /* Fujitsu-Siemens DVB-S rev 1.6 */
2206 /* Grundig 29504-451 */
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002207 av7110->fe = dvb_attach(tda8083_attach, &grundig_29504_451_config, &av7110->i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002208 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002209 av7110->fe->ops.tuner_ops.set_params = grundig_29504_451_tuner_set_params;
2210 av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
2211 av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
2212 av7110->fe->ops.set_tone = av7110_set_tone;
Oliver Endriss66190a22006-01-09 15:32:42 -02002213 av7110->recover = dvb_s_recover;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002214 }
2215 break;
2216
Linus Torvalds1da177e2005-04-16 15:20:36 -07002217 case 0x000A: // Hauppauge/TT Nexus-CA rev1.X
2218
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002219 av7110->fe = dvb_attach(stv0297_attach, &nexusca_stv0297_config, &av7110->i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002220 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002221 av7110->fe->ops.tuner_ops.set_params = nexusca_stv0297_tuner_set_params;
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03002222
Linus Torvalds1da177e2005-04-16 15:20:36 -07002223 /* set TDA9819 into DVB mode */
Marco Schluessler6a857742006-07-10 03:34:16 -03002224 saa7146_setgpio(av7110->dev, 1, SAA7146_GPIO_OUTLO); // TDA9819 pin9(STD)
2225 saa7146_setgpio(av7110->dev, 3, SAA7146_GPIO_OUTLO); // TDA9819 pin30(VIF)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002226
2227 /* tuner on this needs a slower i2c bus speed */
2228 av7110->dev->i2c_bitrate = SAA7146_I2C_BUS_BIT_RATE_240;
2229 break;
2230 }
Johannes Stezenbach3dfaebd2005-05-16 21:54:19 -07002231 break;
2232
2233 case 0x000E: /* Hauppauge/TT Nexus-S rev 2.3 */
2234 /* ALPS BSBE1 */
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002235 av7110->fe = dvb_attach(stv0299_attach, &alps_bsbe1_config, &av7110->i2c_adap);
Oliver Endrisseb3daf32006-01-09 15:25:05 -02002236 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002237 av7110->fe->ops.tuner_ops.set_params = alps_bsbe1_tuner_set_params;
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03002238 av7110->fe->tuner_priv = &av7110->i2c_adap;
2239
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002240 if (dvb_attach(lnbp21_attach, av7110->fe, &av7110->i2c_adap, 0, 0) == NULL) {
Oliver Endrissdb5d91e2006-02-28 10:32:25 -03002241 printk("dvb-ttpci: LNBP21 not found!\n");
Patrick Boettcherdea74862006-05-14 05:01:31 -03002242 if (av7110->fe->ops.release)
2243 av7110->fe->ops.release(av7110->fe);
Oliver Endrissdb5d91e2006-02-28 10:32:25 -03002244 av7110->fe = NULL;
2245 } else {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002246 av7110->fe->ops.dishnetwork_send_legacy_command = NULL;
Oliver Endrissdb5d91e2006-02-28 10:32:25 -03002247 av7110->recover = dvb_s_recover;
2248 }
Oliver Endrisseb3daf32006-01-09 15:25:05 -02002249 }
Johannes Stezenbach3dfaebd2005-05-16 21:54:19 -07002250 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002251 }
2252 }
2253
2254 if (!av7110->fe) {
2255 /* FIXME: propagate the failure code from the lower layers */
2256 ret = -ENOMEM;
2257 printk("dvb-ttpci: A frontend driver was not found for device %04x/%04x subsystem %04x/%04x\n",
2258 av7110->dev->pci->vendor,
2259 av7110->dev->pci->device,
2260 av7110->dev->pci->subsystem_vendor,
2261 av7110->dev->pci->subsystem_device);
2262 } else {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002263 FE_FUNC_OVERRIDE(av7110->fe->ops.init, av7110->fe_init, av7110_fe_init);
2264 FE_FUNC_OVERRIDE(av7110->fe->ops.read_status, av7110->fe_read_status, av7110_fe_read_status);
2265 FE_FUNC_OVERRIDE(av7110->fe->ops.diseqc_reset_overload, av7110->fe_diseqc_reset_overload, av7110_fe_diseqc_reset_overload);
2266 FE_FUNC_OVERRIDE(av7110->fe->ops.diseqc_send_master_cmd, av7110->fe_diseqc_send_master_cmd, av7110_fe_diseqc_send_master_cmd);
2267 FE_FUNC_OVERRIDE(av7110->fe->ops.diseqc_send_burst, av7110->fe_diseqc_send_burst, av7110_fe_diseqc_send_burst);
2268 FE_FUNC_OVERRIDE(av7110->fe->ops.set_tone, av7110->fe_set_tone, av7110_fe_set_tone);
Yoann Padioleau8f40a9f2007-07-16 16:54:49 -03002269 FE_FUNC_OVERRIDE(av7110->fe->ops.set_voltage, av7110->fe_set_voltage, av7110_fe_set_voltage);
Patrick Boettcherdea74862006-05-14 05:01:31 -03002270 FE_FUNC_OVERRIDE(av7110->fe->ops.dishnetwork_send_legacy_command, av7110->fe_dishnetwork_send_legacy_command, av7110_fe_dishnetwork_send_legacy_command);
2271 FE_FUNC_OVERRIDE(av7110->fe->ops.set_frontend, av7110->fe_set_frontend, av7110_fe_set_frontend);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002272
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07002273 ret = dvb_register_frontend(&av7110->dvb_adapter, av7110->fe);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002274 if (ret < 0) {
2275 printk("av7110: Frontend registration failed!\n");
Andrew de Quinceyf52a8382006-08-08 09:10:09 -03002276 dvb_frontend_detach(av7110->fe);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002277 av7110->fe = NULL;
2278 }
2279 }
2280 return ret;
2281}
2282
2283/* Budgetpatch note:
2284 * Original hardware design by Roberto Deza:
2285 * There is a DVB_Wiki at
2286 * http://212.227.36.83/linuxtv/wiki/index.php/Main_Page
2287 * where is described this 'DVB TT Budget Patch', on Card Modding:
2288 * http://212.227.36.83/linuxtv/wiki/index.php/DVB_TT_Budget_Patch
2289 * On the short description there is also a link to a external file,
2290 * with more details:
2291 * http://perso.wanadoo.es/jesussolano/Ttf_tsc1.zip
2292 *
2293 * New software triggering design by Emard that works on
2294 * original Roberto Deza's hardware:
2295 *
2296 * rps1 code for budgetpatch will copy internal HS event to GPIO3 pin.
2297 * GPIO3 is in budget-patch hardware connectd to port B VSYNC
2298 * HS is an internal event of 7146, accessible with RPS
2299 * and temporarily raised high every n lines
2300 * (n in defined in the RPS_THRESH1 counter threshold)
2301 * I think HS is raised high on the beginning of the n-th line
2302 * and remains high until this n-th line that triggered
2303 * it is completely received. When the receiption of n-th line
2304 * ends, HS is lowered.
2305 *
2306 * To transmit data over DMA, 7146 needs changing state at
2307 * port B VSYNC pin. Any changing of port B VSYNC will
2308 * cause some DMA data transfer, with more or less packets loss.
2309 * It depends on the phase and frequency of VSYNC and
2310 * the way of 7146 is instructed to trigger on port B (defined
2311 * in DD1_INIT register, 3rd nibble from the right valid
2312 * numbers are 0-7, see datasheet)
2313 *
2314 * The correct triggering can minimize packet loss,
2315 * dvbtraffic should give this stable bandwidths:
2316 * 22k transponder = 33814 kbit/s
2317 * 27.5k transponder = 38045 kbit/s
2318 * by experiment it is found that the best results
2319 * (stable bandwidths and almost no packet loss)
2320 * are obtained using DD1_INIT triggering number 2
2321 * (Va at rising edge of VS Fa = HS x VS-failing forced toggle)
2322 * and a VSYNC phase that occurs in the middle of DMA transfer
2323 * (about byte 188*512=96256 in the DMA window).
2324 *
2325 * Phase of HS is still not clear to me how to control,
2326 * It just happens to be so. It can be seen if one enables
2327 * RPS_IRQ and print Event Counter 1 in vpeirq(). Every
2328 * time RPS_INTERRUPT is called, the Event Counter 1 will
2329 * increment. That's how the 7146 is programmed to do event
2330 * counting in this budget-patch.c
2331 * I *think* HPS setting has something to do with the phase
2332 * of HS but I cant be 100% sure in that.
2333 *
2334 * hardware debug note: a working budget card (including budget patch)
2335 * with vpeirq() interrupt setup in mode "0x90" (every 64K) will
2336 * generate 3 interrupts per 25-Hz DMA frame of 2*188*512 bytes
2337 * and that means 3*25=75 Hz of interrupt freqency, as seen by
2338 * watch cat /proc/interrupts
2339 *
2340 * If this frequency is 3x lower (and data received in the DMA
2341 * buffer don't start with 0x47, but in the middle of packets,
2342 * whose lengths appear to be like 188 292 188 104 etc.
2343 * this means VSYNC line is not connected in the hardware.
2344 * (check soldering pcb and pins)
2345 * The same behaviour of missing VSYNC can be duplicated on budget
2346 * cards, by seting DD1_INIT trigger mode 7 in 3rd nibble.
2347 */
Johannes Stezenbach1be11e32006-02-27 00:09:20 -03002348static int __devinit av7110_attach(struct saa7146_dev* dev,
2349 struct saa7146_pci_extension_data *pci_ext)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002350{
2351 const int length = TS_WIDTH * TS_HEIGHT;
2352 struct pci_dev *pdev = dev->pci;
2353 struct av7110 *av7110;
Herbert Poetzl8eec1422007-02-08 14:32:43 -03002354 struct task_struct *thread;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002355 int ret, count = 0;
2356
2357 dprintk(4, "dev: %p\n", dev);
2358
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -08002359 /* Set RPS_IRQ to 1 to track rps1 activity.
2360 * Enabling this won't send any interrupt to PC CPU.
2361 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002362#define RPS_IRQ 0
2363
2364 if (budgetpatch == 1) {
2365 budgetpatch = 0;
2366 /* autodetect the presence of budget patch
2367 * this only works if saa7146 has been recently
2368 * reset with with MASK_31 to MC1
2369 *
2370 * will wait for VBI_B event (vertical blank at port B)
2371 * and will reset GPIO3 after VBI_B is detected.
2372 * (GPIO3 should be raised high by CPU to
2373 * test if GPIO3 will generate vertical blank signal
2374 * in budget patch GPIO3 is connected to VSYNC_B
2375 */
2376
2377 /* RESET SAA7146 */
2378 saa7146_write(dev, MC1, MASK_31);
2379 /* autodetection success seems to be time-dependend after reset */
2380
2381 /* Fix VSYNC level */
2382 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
2383 /* set vsync_b triggering */
2384 saa7146_write(dev, DD1_STREAM_B, 0);
2385 /* port B VSYNC at rising edge */
2386 saa7146_write(dev, DD1_INIT, 0x00000200);
2387 saa7146_write(dev, BRS_CTRL, 0x00000000); // VBI
2388 saa7146_write(dev, MC2,
2389 1 * (MASK_08 | MASK_24) | // BRS control
2390 0 * (MASK_09 | MASK_25) | // a
2391 1 * (MASK_10 | MASK_26) | // b
2392 0 * (MASK_06 | MASK_22) | // HPS_CTRL1
2393 0 * (MASK_05 | MASK_21) | // HPS_CTRL2
2394 0 * (MASK_01 | MASK_15) // DEBI
2395 );
2396
2397 /* start writing RPS1 code from beginning */
2398 count = 0;
2399 /* Disable RPS1 */
2400 saa7146_write(dev, MC1, MASK_29);
2401 /* RPS1 timeout disable */
2402 saa7146_write(dev, RPS_TOV1, 0);
2403 WRITE_RPS1(cpu_to_le32(CMD_PAUSE | EVT_VBI_B));
2404 WRITE_RPS1(cpu_to_le32(CMD_WR_REG_MASK | (GPIO_CTRL>>2)));
2405 WRITE_RPS1(cpu_to_le32(GPIO3_MSK));
2406 WRITE_RPS1(cpu_to_le32(SAA7146_GPIO_OUTLO<<24));
2407#if RPS_IRQ
2408 /* issue RPS1 interrupt to increment counter */
2409 WRITE_RPS1(cpu_to_le32(CMD_INTERRUPT));
2410#endif
2411 WRITE_RPS1(cpu_to_le32(CMD_STOP));
2412 /* Jump to begin of RPS program as safety measure (p37) */
2413 WRITE_RPS1(cpu_to_le32(CMD_JUMP));
2414 WRITE_RPS1(cpu_to_le32(dev->d_rps1.dma_handle));
2415
2416#if RPS_IRQ
2417 /* set event counter 1 source as RPS1 interrupt (0x03) (rE4 p53)
2418 * use 0x03 to track RPS1 interrupts - increase by 1 every gpio3 is toggled
2419 * use 0x15 to track VPE interrupts - increase by 1 every vpeirq() is called
2420 */
2421 saa7146_write(dev, EC1SSR, (0x03<<2) | 3 );
2422 /* set event counter 1 treshold to maximum allowed value (rEC p55) */
2423 saa7146_write(dev, ECT1R, 0x3fff );
2424#endif
2425 /* Set RPS1 Address register to point to RPS code (r108 p42) */
2426 saa7146_write(dev, RPS_ADDR1, dev->d_rps1.dma_handle);
2427 /* Enable RPS1, (rFC p33) */
2428 saa7146_write(dev, MC1, (MASK_13 | MASK_29 ));
2429
2430 mdelay(10);
2431 /* now send VSYNC_B to rps1 by rising GPIO3 */
2432 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI);
2433 mdelay(10);
2434 /* if rps1 responded by lowering the GPIO3,
2435 * then we have budgetpatch hardware
2436 */
2437 if ((saa7146_read(dev, GPIO_CTRL) & 0x10000000) == 0) {
2438 budgetpatch = 1;
2439 printk("dvb-ttpci: BUDGET-PATCH DETECTED.\n");
2440 }
2441 /* Disable RPS1 */
2442 saa7146_write(dev, MC1, ( MASK_29 ));
2443#if RPS_IRQ
2444 printk("dvb-ttpci: Event Counter 1 0x%04x\n", saa7146_read(dev, EC1R) & 0x3fff );
2445#endif
2446 }
2447
2448 /* prepare the av7110 device struct */
Panagiotis Issaris74081872006-01-11 19:40:56 -02002449 av7110 = kzalloc(sizeof(struct av7110), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002450 if (!av7110) {
2451 dprintk(1, "out of memory\n");
2452 return -ENOMEM;
2453 }
2454
Linus Torvalds1da177e2005-04-16 15:20:36 -07002455 av7110->card_name = (char*) pci_ext->ext_priv;
2456 av7110->dev = dev;
2457 dev->ext_priv = av7110;
2458
2459 ret = get_firmware(av7110);
2460 if (ret < 0)
2461 goto err_kfree_0;
2462
2463 ret = dvb_register_adapter(&av7110->dvb_adapter, av7110->card_name,
Andrew de Quinceyd09dbf92006-04-10 09:27:37 -03002464 THIS_MODULE, &dev->pci->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002465 if (ret < 0)
2466 goto err_put_firmware_1;
2467
2468 /* the Siemens DVB needs this if you want to have the i2c chips
2469 get recognized before the main driver is fully loaded */
2470 saa7146_write(dev, GPIO_CTRL, 0x500000);
2471
2472#ifdef I2C_ADAP_CLASS_TV_DIGITAL
2473 av7110->i2c_adap.class = I2C_ADAP_CLASS_TV_DIGITAL;
2474#else
2475 av7110->i2c_adap.class = I2C_CLASS_TV_DIGITAL;
2476#endif
2477 strlcpy(av7110->i2c_adap.name, pci_ext->ext_priv, sizeof(av7110->i2c_adap.name));
2478
2479 saa7146_i2c_adapter_prepare(dev, &av7110->i2c_adap, SAA7146_I2C_BUS_BIT_RATE_120); /* 275 kHz */
2480
2481 ret = i2c_add_adapter(&av7110->i2c_adap);
2482 if (ret < 0)
2483 goto err_dvb_unregister_adapter_2;
2484
2485 ttpci_eeprom_parse_mac(&av7110->i2c_adap,
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07002486 av7110->dvb_adapter.proposed_mac);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002487 ret = -ENOMEM;
2488
2489 if (budgetpatch) {
2490 spin_lock_init(&av7110->feedlock1);
2491 av7110->grabbing = saa7146_vmalloc_build_pgtable(pdev, length,
2492 &av7110->pt);
2493 if (!av7110->grabbing)
2494 goto err_i2c_del_3;
2495
2496 saa7146_write(dev, PCI_BT_V1, 0x1c1f101f);
2497 saa7146_write(dev, BCS_CTRL, 0x80400040);
2498 /* set dd1 stream a & b */
2499 saa7146_write(dev, DD1_STREAM_B, 0x00000000);
2500 saa7146_write(dev, DD1_INIT, 0x03000200);
2501 saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
2502 saa7146_write(dev, BRS_CTRL, 0x60000000);
2503 saa7146_write(dev, BASE_ODD3, 0);
2504 saa7146_write(dev, BASE_EVEN3, 0);
2505 saa7146_write(dev, PROT_ADDR3, TS_WIDTH * TS_HEIGHT);
2506 saa7146_write(dev, BASE_PAGE3, av7110->pt.dma | ME1 | 0x90);
2507
2508 saa7146_write(dev, PITCH3, TS_WIDTH);
2509 saa7146_write(dev, NUM_LINE_BYTE3, (TS_HEIGHT << 16) | TS_WIDTH);
2510
2511 /* upload all */
2512 saa7146_write(dev, MC2, 0x077c077c);
2513 saa7146_write(dev, GPIO_CTRL, 0x000000);
2514#if RPS_IRQ
2515 /* set event counter 1 source as RPS1 interrupt (0x03) (rE4 p53)
2516 * use 0x03 to track RPS1 interrupts - increase by 1 every gpio3 is toggled
2517 * use 0x15 to track VPE interrupts - increase by 1 every vpeirq() is called
2518 */
2519 saa7146_write(dev, EC1SSR, (0x03<<2) | 3 );
2520 /* set event counter 1 treshold to maximum allowed value (rEC p55) */
2521 saa7146_write(dev, ECT1R, 0x3fff );
2522#endif
2523 /* Setup BUDGETPATCH MAIN RPS1 "program" (p35) */
2524 count = 0;
2525
2526 /* Wait Source Line Counter Threshold (p36) */
2527 WRITE_RPS1(cpu_to_le32(CMD_PAUSE | EVT_HS));
2528 /* Set GPIO3=1 (p42) */
2529 WRITE_RPS1(cpu_to_le32(CMD_WR_REG_MASK | (GPIO_CTRL>>2)));
2530 WRITE_RPS1(cpu_to_le32(GPIO3_MSK));
2531 WRITE_RPS1(cpu_to_le32(SAA7146_GPIO_OUTHI<<24));
2532#if RPS_IRQ
2533 /* issue RPS1 interrupt */
2534 WRITE_RPS1(cpu_to_le32(CMD_INTERRUPT));
2535#endif
2536 /* Wait reset Source Line Counter Threshold (p36) */
2537 WRITE_RPS1(cpu_to_le32(CMD_PAUSE | RPS_INV | EVT_HS));
2538 /* Set GPIO3=0 (p42) */
2539 WRITE_RPS1(cpu_to_le32(CMD_WR_REG_MASK | (GPIO_CTRL>>2)));
2540 WRITE_RPS1(cpu_to_le32(GPIO3_MSK));
2541 WRITE_RPS1(cpu_to_le32(SAA7146_GPIO_OUTLO<<24));
2542#if RPS_IRQ
2543 /* issue RPS1 interrupt */
2544 WRITE_RPS1(cpu_to_le32(CMD_INTERRUPT));
2545#endif
2546 /* Jump to begin of RPS program (p37) */
2547 WRITE_RPS1(cpu_to_le32(CMD_JUMP));
2548 WRITE_RPS1(cpu_to_le32(dev->d_rps1.dma_handle));
2549
2550 /* Fix VSYNC level */
2551 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
2552 /* Set RPS1 Address register to point to RPS code (r108 p42) */
2553 saa7146_write(dev, RPS_ADDR1, dev->d_rps1.dma_handle);
2554 /* Set Source Line Counter Threshold, using BRS (rCC p43)
2555 * It generates HS event every TS_HEIGHT lines
2556 * this is related to TS_WIDTH set in register
2557 * NUM_LINE_BYTE3. If NUM_LINE_BYTE low 16 bits
2558 * are set to TS_WIDTH bytes (TS_WIDTH=2*188),
2559 * then RPS_THRESH1 should be set to trigger
2560 * every TS_HEIGHT (512) lines.
2561 */
2562 saa7146_write(dev, RPS_THRESH1, (TS_HEIGHT*1) | MASK_12 );
2563
2564 /* Enable RPS1 (rFC p33) */
2565 saa7146_write(dev, MC1, (MASK_13 | MASK_29));
2566
2567 /* end of budgetpatch register initialization */
2568 tasklet_init (&av7110->vpe_tasklet, vpeirq, (unsigned long) av7110);
2569 } else {
2570 saa7146_write(dev, PCI_BT_V1, 0x1c00101f);
2571 saa7146_write(dev, BCS_CTRL, 0x80400040);
2572
2573 /* set dd1 stream a & b */
2574 saa7146_write(dev, DD1_STREAM_B, 0x00000000);
2575 saa7146_write(dev, DD1_INIT, 0x03000000);
2576 saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
2577
2578 /* upload all */
2579 saa7146_write(dev, MC2, 0x077c077c);
2580 saa7146_write(dev, GPIO_CTRL, 0x000000);
2581 }
2582
2583 tasklet_init (&av7110->debi_tasklet, debiirq, (unsigned long) av7110);
2584 tasklet_init (&av7110->gpio_tasklet, gpioirq, (unsigned long) av7110);
2585
Ingo Molnar3593cab2006-02-07 06:49:14 -02002586 mutex_init(&av7110->pid_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002587
2588 /* locks for data transfers from/to AV7110 */
2589 spin_lock_init(&av7110->debilock);
Ingo Molnar3593cab2006-02-07 06:49:14 -02002590 mutex_init(&av7110->dcomlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002591 av7110->debitype = -1;
2592
2593 /* default OSD window */
2594 av7110->osdwin = 1;
Ingo Molnar3593cab2006-02-07 06:49:14 -02002595 mutex_init(&av7110->osd_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002596
C.Y.M2f03ee82006-03-30 04:31:48 -03002597 /* TV standard */
Marco Schluessler58a44042007-10-31 01:20:42 -03002598 av7110->vidmode = tv_standard == 1 ? AV7110_VIDEO_MODE_NTSC
2599 : AV7110_VIDEO_MODE_PAL;
C.Y.M2f03ee82006-03-30 04:31:48 -03002600
Linus Torvalds1da177e2005-04-16 15:20:36 -07002601 /* ARM "watchdog" */
2602 init_waitqueue_head(&av7110->arm_wait);
2603 av7110->arm_thread = NULL;
2604
2605 /* allocate and init buffers */
2606 av7110->debi_virt = pci_alloc_consistent(pdev, 8192, &av7110->debi_bus);
2607 if (!av7110->debi_virt)
2608 goto err_saa71466_vfree_4;
2609
2610
2611 av7110->iobuf = vmalloc(AVOUTLEN+AOUTLEN+BMPLEN+4*IPACKS);
2612 if (!av7110->iobuf)
2613 goto err_pci_free_5;
2614
2615 ret = av7110_av_init(av7110);
2616 if (ret < 0)
2617 goto err_iobuf_vfree_6;
2618
2619 /* init BMP buffer */
2620 av7110->bmpbuf = av7110->iobuf+AVOUTLEN+AOUTLEN;
2621 init_waitqueue_head(&av7110->bmpq);
2622
2623 ret = av7110_ca_init(av7110);
2624 if (ret < 0)
2625 goto err_av7110_av_exit_7;
2626
2627 /* load firmware into AV7110 cards */
2628 ret = av7110_bootarm(av7110);
2629 if (ret < 0)
2630 goto err_av7110_ca_exit_8;
2631
2632 ret = av7110_firmversion(av7110);
2633 if (ret < 0)
2634 goto err_stop_arm_9;
2635
2636 if (FW_VERSION(av7110->arm_app)<0x2501)
2637 printk ("dvb-ttpci: Warning, firmware version 0x%04x is too old. "
2638 "System might be unstable!\n", FW_VERSION(av7110->arm_app));
2639
Herbert Poetzl8eec1422007-02-08 14:32:43 -03002640 thread = kthread_run(arm_thread, (void *) av7110, "arm_mon");
2641 if (IS_ERR(thread)) {
2642 ret = PTR_ERR(thread);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002643 goto err_stop_arm_9;
Herbert Poetzl8eec1422007-02-08 14:32:43 -03002644 }
2645 av7110->arm_thread = thread;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002646
2647 /* set initial volume in mixer struct */
2648 av7110->mixer.volume_left = volume;
2649 av7110->mixer.volume_right = volume;
2650
Linus Torvalds1da177e2005-04-16 15:20:36 -07002651 ret = av7110_register(av7110);
2652 if (ret < 0)
2653 goto err_arm_thread_stop_10;
2654
Oliver Endrissdefd574e2007-07-12 23:08:07 -03002655 init_av7110_av(av7110);
2656
Linus Torvalds1da177e2005-04-16 15:20:36 -07002657 /* special case DVB-C: these cards have an analog tuner
2658 plus need some special handling, so we have separate
2659 saa7146_ext_vv data for these... */
2660 ret = av7110_init_v4l(av7110);
2661 if (ret < 0)
2662 goto err_av7110_unregister_11;
2663
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07002664 av7110->dvb_adapter.priv = av7110;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002665 ret = frontend_init(av7110);
2666 if (ret < 0)
2667 goto err_av7110_exit_v4l_12;
2668
2669#if defined(CONFIG_INPUT_EVDEV) || defined(CONFIG_INPUT_EVDEV_MODULE)
Oliver Endriss03388ae2005-09-09 13:03:12 -07002670 av7110_ir_init(av7110);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002671#endif
2672 printk(KERN_INFO "dvb-ttpci: found av7110-%d.\n", av7110_num);
2673 av7110_num++;
2674out:
2675 return ret;
2676
2677err_av7110_exit_v4l_12:
2678 av7110_exit_v4l(av7110);
2679err_av7110_unregister_11:
2680 dvb_unregister(av7110);
2681err_arm_thread_stop_10:
2682 av7110_arm_sync(av7110);
2683err_stop_arm_9:
2684 /* Nothing to do. Rejoice. */
2685err_av7110_ca_exit_8:
2686 av7110_ca_exit(av7110);
2687err_av7110_av_exit_7:
2688 av7110_av_exit(av7110);
2689err_iobuf_vfree_6:
2690 vfree(av7110->iobuf);
2691err_pci_free_5:
2692 pci_free_consistent(pdev, 8192, av7110->debi_virt, av7110->debi_bus);
2693err_saa71466_vfree_4:
Jon Burgess87c30192007-05-03 12:23:44 -03002694 if (av7110->grabbing)
2695 saa7146_vfree_destroy_pgtable(pdev, av7110->grabbing, &av7110->pt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002696err_i2c_del_3:
2697 i2c_del_adapter(&av7110->i2c_adap);
2698err_dvb_unregister_adapter_2:
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07002699 dvb_unregister_adapter(&av7110->dvb_adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002700err_put_firmware_1:
2701 put_firmware(av7110);
2702err_kfree_0:
2703 kfree(av7110);
2704 goto out;
2705}
2706
Johannes Stezenbach1be11e32006-02-27 00:09:20 -03002707static int __devexit av7110_detach(struct saa7146_dev* saa)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002708{
2709 struct av7110 *av7110 = saa->ext_priv;
2710 dprintk(4, "%p\n", av7110);
2711
Oliver Endriss03388ae2005-09-09 13:03:12 -07002712#if defined(CONFIG_INPUT_EVDEV) || defined(CONFIG_INPUT_EVDEV_MODULE)
2713 av7110_ir_exit(av7110);
2714#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07002715 if (budgetpatch) {
2716 /* Disable RPS1 */
2717 saa7146_write(saa, MC1, MASK_29);
2718 /* VSYNC LOW (inactive) */
2719 saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);
2720 saa7146_write(saa, MC1, MASK_20); /* DMA3 off */
2721 SAA7146_IER_DISABLE(saa, MASK_10);
2722 SAA7146_ISR_CLEAR(saa, MASK_10);
2723 msleep(50);
2724 tasklet_kill(&av7110->vpe_tasklet);
Jon Burgess87c30192007-05-03 12:23:44 -03002725 saa7146_vfree_destroy_pgtable(saa->pci, av7110->grabbing, &av7110->pt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002726 }
2727 av7110_exit_v4l(av7110);
2728
2729 av7110_arm_sync(av7110);
2730
2731 tasklet_kill(&av7110->debi_tasklet);
2732 tasklet_kill(&av7110->gpio_tasklet);
2733
2734 dvb_unregister(av7110);
2735
2736 SAA7146_IER_DISABLE(saa, MASK_19 | MASK_03);
2737 SAA7146_ISR_CLEAR(saa, MASK_19 | MASK_03);
2738
2739 av7110_ca_exit(av7110);
2740 av7110_av_exit(av7110);
2741
2742 vfree(av7110->iobuf);
2743 pci_free_consistent(saa->pci, 8192, av7110->debi_virt,
2744 av7110->debi_bus);
2745
2746 i2c_del_adapter(&av7110->i2c_adap);
2747
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07002748 dvb_unregister_adapter (&av7110->dvb_adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002749
2750 av7110_num--;
2751
2752 put_firmware(av7110);
2753
2754 kfree(av7110);
2755
2756 saa->ext_priv = NULL;
2757
2758 return 0;
2759}
2760
2761
2762static void av7110_irq(struct saa7146_dev* dev, u32 *isr)
2763{
2764 struct av7110 *av7110 = dev->ext_priv;
2765
2766 //print_time("av7110_irq");
2767
2768 /* Note: Don't try to handle the DEBI error irq (MASK_18), in
2769 * intel mode the timeout is asserted all the time...
2770 */
2771
2772 if (*isr & MASK_19) {
2773 //printk("av7110_irq: DEBI\n");
2774 /* Note 1: The DEBI irq is level triggered: We must enable it
2775 * only after we started a DMA xfer, and disable it here
2776 * immediately, or it will be signalled all the time while
2777 * DEBI is idle.
2778 * Note 2: You would think that an irq which is masked is
2779 * not signalled by the hardware. Not so for the SAA7146:
2780 * An irq is signalled as long as the corresponding bit
2781 * in the ISR is set, and disabling irqs just prevents the
2782 * hardware from setting the ISR bit. This means a) that we
2783 * must clear the ISR *after* disabling the irq (which is why
2784 * we must do it here even though saa7146_core did it already),
2785 * and b) that if we were to disable an edge triggered irq
2786 * (like the gpio irqs sadly are) temporarily we would likely
2787 * loose some. This sucks :-(
2788 */
2789 SAA7146_IER_DISABLE(av7110->dev, MASK_19);
2790 SAA7146_ISR_CLEAR(av7110->dev, MASK_19);
2791 tasklet_schedule(&av7110->debi_tasklet);
2792 }
2793
2794 if (*isr & MASK_03) {
2795 //printk("av7110_irq: GPIO\n");
2796 tasklet_schedule(&av7110->gpio_tasklet);
2797 }
2798
2799 if ((*isr & MASK_10) && budgetpatch)
2800 tasklet_schedule(&av7110->vpe_tasklet);
2801}
2802
2803
Randy Dunlapda517162008-01-10 19:31:47 -03002804static struct saa7146_extension av7110_extension_driver;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002805
2806#define MAKE_AV7110_INFO(x_var,x_name) \
2807static struct saa7146_pci_extension_data x_var = { \
2808 .ext_priv = x_name, \
Randy Dunlapda517162008-01-10 19:31:47 -03002809 .ext = &av7110_extension_driver }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002810
Karl Herz6af4ee12005-09-09 13:03:13 -07002811MAKE_AV7110_INFO(tts_1_X_fsc,"Technotrend/Hauppauge WinTV DVB-S rev1.X or Fujitsu Siemens DVB-C");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002812MAKE_AV7110_INFO(ttt_1_X, "Technotrend/Hauppauge WinTV DVB-T rev1.X");
2813MAKE_AV7110_INFO(ttc_1_X, "Technotrend/Hauppauge WinTV Nexus-CA rev1.X");
2814MAKE_AV7110_INFO(ttc_2_X, "Technotrend/Hauppauge WinTV DVB-C rev2.X");
2815MAKE_AV7110_INFO(tts_2_X, "Technotrend/Hauppauge WinTV Nexus-S rev2.X");
Johannes Stezenbach3dfaebd2005-05-16 21:54:19 -07002816MAKE_AV7110_INFO(tts_2_3, "Technotrend/Hauppauge WinTV Nexus-S rev2.3");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002817MAKE_AV7110_INFO(tts_1_3se, "Technotrend/Hauppauge WinTV DVB-S rev1.3 SE");
2818MAKE_AV7110_INFO(ttt, "Technotrend/Hauppauge DVB-T");
2819MAKE_AV7110_INFO(fsc, "Fujitsu Siemens DVB-C");
2820MAKE_AV7110_INFO(fss, "Fujitsu Siemens DVB-S rev1.6");
Oliver Endriss8bd63012006-02-07 06:49:11 -02002821MAKE_AV7110_INFO(gxs_1_3, "Galaxis DVB-S rev1.3");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002822
2823static struct pci_device_id pci_tbl[] = {
Karl Herz6af4ee12005-09-09 13:03:13 -07002824 MAKE_EXTENSION_PCI(fsc, 0x110a, 0x0000),
2825 MAKE_EXTENSION_PCI(tts_1_X_fsc, 0x13c2, 0x0000),
2826 MAKE_EXTENSION_PCI(ttt_1_X, 0x13c2, 0x0001),
2827 MAKE_EXTENSION_PCI(ttc_2_X, 0x13c2, 0x0002),
2828 MAKE_EXTENSION_PCI(tts_2_X, 0x13c2, 0x0003),
Oliver Endriss8bd63012006-02-07 06:49:11 -02002829 MAKE_EXTENSION_PCI(gxs_1_3, 0x13c2, 0x0004),
Karl Herz6af4ee12005-09-09 13:03:13 -07002830 MAKE_EXTENSION_PCI(fss, 0x13c2, 0x0006),
2831 MAKE_EXTENSION_PCI(ttt, 0x13c2, 0x0008),
2832 MAKE_EXTENSION_PCI(ttc_1_X, 0x13c2, 0x000a),
2833 MAKE_EXTENSION_PCI(tts_2_3, 0x13c2, 0x000e),
2834 MAKE_EXTENSION_PCI(tts_1_3se, 0x13c2, 0x1002),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002835
Linus Torvalds1da177e2005-04-16 15:20:36 -07002836/* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0005), UNDEFINED CARD */ // Technisat SkyStar1
2837/* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0009), UNDEFINED CARD */ // TT/Hauppauge WinTV Nexus-CA v????
2838
2839 {
2840 .vendor = 0,
2841 }
2842};
2843
2844MODULE_DEVICE_TABLE(pci, pci_tbl);
2845
2846
Randy Dunlapda517162008-01-10 19:31:47 -03002847static struct saa7146_extension av7110_extension_driver = {
Dave Jones0e367a12006-08-07 13:18:56 -03002848 .name = "dvb",
Oliver Endriss00c4cc62006-11-01 13:09:51 -03002849 .flags = SAA7146_USE_I2C_IRQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002850
2851 .module = THIS_MODULE,
2852 .pci_tbl = &pci_tbl[0],
2853 .attach = av7110_attach,
Johannes Stezenbach1be11e32006-02-27 00:09:20 -03002854 .detach = __devexit_p(av7110_detach),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002855
2856 .irq_mask = MASK_19 | MASK_03 | MASK_10,
2857 .irq_func = av7110_irq,
2858};
2859
2860
2861static int __init av7110_init(void)
2862{
2863 int retval;
Randy Dunlapda517162008-01-10 19:31:47 -03002864 retval = saa7146_register_extension(&av7110_extension_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002865 return retval;
2866}
2867
2868
2869static void __exit av7110_exit(void)
2870{
Randy Dunlapda517162008-01-10 19:31:47 -03002871 saa7146_unregister_extension(&av7110_extension_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002872}
2873
2874module_init(av7110_init);
2875module_exit(av7110_exit);
2876
2877MODULE_DESCRIPTION("driver for the SAA7146 based AV110 PCI DVB cards by "
2878 "Siemens, Technotrend, Hauppauge");
2879MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, others");
2880MODULE_LICENSE("GPL");