blob: 8d65c652ba5062c5c51765b887ea82ddb616f6f0 [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>
Linus Torvalds1da177e2005-04-16 15:20:36 -070039
40#include <linux/kernel.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070041#include <linux/sched.h>
42#include <linux/types.h>
43#include <linux/fcntl.h>
44#include <linux/interrupt.h>
45#include <linux/string.h>
46#include <linux/pci.h>
47#include <linux/vmalloc.h>
48#include <linux/firmware.h>
49#include <linux/crc32.h>
50#include <linux/i2c.h>
Herbert Poetzl8eec1422007-02-08 14:32:43 -030051#include <linux/kthread.h>
Al Viro3e085622008-05-21 00:30:51 -030052#include <asm/unaligned.h>
Harvey Harrison1a651a02008-10-18 20:28:37 -070053#include <asm/byteorder.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;
Oliver Endriss9e615ea2008-09-03 19:15:27 -030090static int full_ts;
Linus Torvalds1da177e2005-04-16 15:20:36 -070091
92module_param_named(debug, av7110_debug, int, 0644);
93MODULE_PARM_DESC(debug, "debug level (bitmask, default 0)");
94module_param(vidmode, int, 0444);
95MODULE_PARM_DESC(vidmode,"analog video out: 0 off, 1 CVBS+RGB (default), 2 CVBS+YC, 3 YC");
96module_param(pids_off, int, 0444);
97MODULE_PARM_DESC(pids_off,"clear video/audio/PCR PID filters when demux is closed");
98module_param(adac, int, 0444);
99MODULE_PARM_DESC(adac,"audio DAC type: 0 TI, 1 CRYSTAL, 2 MSP (use if autodetection fails)");
100module_param(hw_sections, int, 0444);
101MODULE_PARM_DESC(hw_sections, "0 use software section filter, 1 use hardware");
102module_param(rgb_on, int, 0444);
103MODULE_PARM_DESC(rgb_on, "For Siemens DVB-C cards only: Enable RGB control"
104 " signal on SCART pin 16 to switch SCART video mode from CVBS to RGB");
105module_param(volume, int, 0444);
106MODULE_PARM_DESC(volume, "initial volume: default 255 (range 0-255)");
107module_param(budgetpatch, int, 0444);
108MODULE_PARM_DESC(budgetpatch, "use budget-patch hardware modification: default 0 (0 no, 1 autodetect, 2 always)");
Oliver Endriss9e615ea2008-09-03 19:15:27 -0300109module_param(full_ts, int, 0444);
110MODULE_PARM_DESC(full_ts, "enable code for full-ts hardware modification: 0 disable (default), 1 enable");
Oliver Endriss4caba422006-03-17 05:29:15 -0300111module_param(wss_cfg_4_3, int, 0444);
112MODULE_PARM_DESC(wss_cfg_4_3, "WSS 4:3 - default 0x4008 - bit 15: disable, 14: burst mode, 13..0: wss data");
113module_param(wss_cfg_16_9, int, 0444);
114MODULE_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 -0300115module_param(tv_standard, int, 0444);
116MODULE_PARM_DESC(tv_standard, "TV standard: 0 PAL (default), 1 NTSC");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700117
Janne Grunau78e92002008-04-09 19:13:13 -0300118DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
119
Linus Torvalds1da177e2005-04-16 15:20:36 -0700120static void restart_feeds(struct av7110 *av7110);
Oliver Endriss9e615ea2008-09-03 19:15:27 -0300121static int budget_start_feed(struct dvb_demux_feed *feed);
122static int budget_stop_feed(struct dvb_demux_feed *feed);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700123
Mauro Carvalho Chehaba5ed4252006-01-13 14:10:19 -0200124static int av7110_num;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125
126#define FE_FUNC_OVERRIDE(fe_func, av7110_copy, av7110_func) \
127{\
128 if (fe_func != NULL) { \
129 av7110_copy = fe_func; \
130 fe_func = av7110_func; \
131 } \
132}
133
134
135static void init_av7110_av(struct av7110 *av7110)
136{
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700137 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700138 struct saa7146_dev *dev = av7110->dev;
139
140 /* set internal volume control to maximum */
141 av7110->adac_type = DVB_ADAC_TI;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700142 ret = av7110_set_volume(av7110, av7110->mixer.volume_left, av7110->mixer.volume_right);
Johannes Stezenbach7a2fa902005-07-07 17:58:01 -0700143 if (ret < 0)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700144 printk("dvb-ttpci:cannot set internal volume to maximum:%d\n",ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700145
Oliver Endrissdefd574e2007-07-12 23:08:07 -0300146 ret = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetMonitorType,
147 1, (u16) av7110->display_ar);
148 if (ret < 0)
149 printk("dvb-ttpci: unable to set aspect ratio\n");
150 ret = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetPanScanType,
151 1, av7110->display_panscan);
152 if (ret < 0)
153 printk("dvb-ttpci: unable to set pan scan\n");
154
Oliver Endriss4caba422006-03-17 05:29:15 -0300155 ret = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetWSSConfig, 2, 2, wss_cfg_4_3);
156 if (ret < 0)
157 printk("dvb-ttpci: unable to configure 4:3 wss\n");
158 ret = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetWSSConfig, 2, 3, wss_cfg_16_9);
159 if (ret < 0)
160 printk("dvb-ttpci: unable to configure 16:9 wss\n");
161
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700162 ret = av7710_set_video_mode(av7110, vidmode);
Johannes Stezenbach7a2fa902005-07-07 17:58:01 -0700163 if (ret < 0)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700164 printk("dvb-ttpci:cannot set video mode:%d\n",ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700165
166 /* handle different card types */
167 /* remaining inits according to card and frontend type */
168 av7110->analog_tuner_flags = 0;
169 av7110->current_input = 0;
Tim Kaiser61391e02006-06-25 09:14:07 -0300170 if (dev->pci->subsystem_vendor == 0x13c2 && dev->pci->subsystem_device == 0x000a)
Marco Schluessler1c13b952006-01-09 15:25:06 -0200171 av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, ADSwitch, 1, 0); // SPDIF on
Tim Kaiser61391e02006-06-25 09:14:07 -0300172 if (i2c_writereg(av7110, 0x20, 0x00, 0x00) == 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700173 printk ("dvb-ttpci: Crystal audio DAC @ card %d detected\n",
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -0700174 av7110->dvb_adapter.num);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700175 av7110->adac_type = DVB_ADAC_CRYSTAL;
176 i2c_writereg(av7110, 0x20, 0x01, 0xd2);
177 i2c_writereg(av7110, 0x20, 0x02, 0x49);
178 i2c_writereg(av7110, 0x20, 0x03, 0x00);
179 i2c_writereg(av7110, 0x20, 0x04, 0x00);
180
181 /**
182 * some special handling for the Siemens DVB-C cards...
183 */
184 } else if (0 == av7110_init_analog_module(av7110)) {
185 /* done. */
186 }
187 else if (dev->pci->subsystem_vendor == 0x110a) {
188 printk("dvb-ttpci: DVB-C w/o analog module @ card %d detected\n",
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -0700189 av7110->dvb_adapter.num);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700190 av7110->adac_type = DVB_ADAC_NONE;
191 }
192 else {
193 av7110->adac_type = adac;
194 printk("dvb-ttpci: adac type set to %d @ card %d\n",
Marco Schluessler1c13b952006-01-09 15:25:06 -0200195 av7110->adac_type, av7110->dvb_adapter.num);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700196 }
197
Marco Schluessler1c13b952006-01-09 15:25:06 -0200198 if (av7110->adac_type == DVB_ADAC_NONE || av7110->adac_type == DVB_ADAC_MSP34x0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700199 // switch DVB SCART on
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700200 ret = av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, MainSwitch, 1, 0);
Johannes Stezenbach7a2fa902005-07-07 17:58:01 -0700201 if (ret < 0)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700202 printk("dvb-ttpci:cannot switch on SCART(Main):%d\n",ret);
203 ret = av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, ADSwitch, 1, 1);
Johannes Stezenbach7a2fa902005-07-07 17:58:01 -0700204 if (ret < 0)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700205 printk("dvb-ttpci:cannot switch on SCART(AD):%d\n",ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700206 if (rgb_on &&
Karl Herz6af4ee12005-09-09 13:03:13 -0700207 ((av7110->dev->pci->subsystem_vendor == 0x110a) ||
208 (av7110->dev->pci->subsystem_vendor == 0x13c2)) &&
209 (av7110->dev->pci->subsystem_device == 0x0000)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210 saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); // RGB on, SCART pin 16
211 //saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); // SCARTpin 8
212 }
213 }
214
Oliver Endriss60edb132005-12-19 08:54:11 -0200215 if (dev->pci->subsystem_vendor == 0x13c2 && dev->pci->subsystem_device == 0x000e)
216 av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, SpdifSwitch, 1, 0); // SPDIF on
217
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700218 ret = av7110_set_volume(av7110, av7110->mixer.volume_left, av7110->mixer.volume_right);
Johannes Stezenbach7a2fa902005-07-07 17:58:01 -0700219 if (ret < 0)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700220 printk("dvb-ttpci:cannot set volume :%d\n",ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700221}
222
223static void recover_arm(struct av7110 *av7110)
224{
225 dprintk(4, "%p\n",av7110);
226
227 av7110_bootarm(av7110);
228 msleep(100);
Oliver Endriss66190a22006-01-09 15:32:42 -0200229
230 init_av7110_av(av7110);
231
232 /* card-specific recovery */
233 if (av7110->recover)
234 av7110->recover(av7110);
235
Linus Torvalds1da177e2005-04-16 15:20:36 -0700236 restart_feeds(av7110);
Oliver Endrissee820a62007-04-27 12:31:21 -0300237
238#if defined(CONFIG_INPUT_EVDEV) || defined(CONFIG_INPUT_EVDEV_MODULE)
239 av7110_check_ir_config(av7110, true);
240#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700241}
242
Linus Torvalds1da177e2005-04-16 15:20:36 -0700243static void av7110_arm_sync(struct av7110 *av7110)
244{
Herbert Poetzl8eec1422007-02-08 14:32:43 -0300245 if (av7110->arm_thread)
246 kthread_stop(av7110->arm_thread);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700247
Herbert Poetzl8eec1422007-02-08 14:32:43 -0300248 av7110->arm_thread = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700249}
250
251static int arm_thread(void *data)
252{
253 struct av7110 *av7110 = data;
254 u16 newloops = 0;
255 int timeout;
256
257 dprintk(4, "%p\n",av7110);
258
Linus Torvalds1da177e2005-04-16 15:20:36 -0700259 for (;;) {
260 timeout = wait_event_interruptible_timeout(av7110->arm_wait,
Herbert Poetzl8eec1422007-02-08 14:32:43 -0300261 kthread_should_stop(), 5 * HZ);
262
263 if (-ERESTARTSYS == timeout || kthread_should_stop()) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700264 /* got signal or told to quit*/
265 break;
266 }
267
268 if (!av7110->arm_ready)
269 continue;
270
Oliver Endrissee820a62007-04-27 12:31:21 -0300271#if defined(CONFIG_INPUT_EVDEV) || defined(CONFIG_INPUT_EVDEV_MODULE)
272 av7110_check_ir_config(av7110, false);
273#endif
274
Ingo Molnar3593cab2006-02-07 06:49:14 -0200275 if (mutex_lock_interruptible(&av7110->dcomlock))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700276 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700277 newloops = rdebi(av7110, DEBINOSWAP, STATUS_LOOPS, 0, 2);
Ingo Molnar3593cab2006-02-07 06:49:14 -0200278 mutex_unlock(&av7110->dcomlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279
Oliver Endriss66190a22006-01-09 15:32:42 -0200280 if (newloops == av7110->arm_loops || av7110->arm_errors > 3) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700281 printk(KERN_ERR "dvb-ttpci: ARM crashed @ card %d\n",
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -0700282 av7110->dvb_adapter.num);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283
Oliver Endriss66190a22006-01-09 15:32:42 -0200284 recover_arm(av7110);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285
Ingo Molnar3593cab2006-02-07 06:49:14 -0200286 if (mutex_lock_interruptible(&av7110->dcomlock))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288 newloops = rdebi(av7110, DEBINOSWAP, STATUS_LOOPS, 0, 2) - 1;
Ingo Molnar3593cab2006-02-07 06:49:14 -0200289 mutex_unlock(&av7110->dcomlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700290 }
291 av7110->arm_loops = newloops;
Oliver Endriss66190a22006-01-09 15:32:42 -0200292 av7110->arm_errors = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293 }
294
Linus Torvalds1da177e2005-04-16 15:20:36 -0700295 return 0;
296}
297
298
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299/****************************************************************************
300 * IRQ handling
301 ****************************************************************************/
302
303static int DvbDmxFilterCallback(u8 *buffer1, size_t buffer1_len,
304 u8 *buffer2, size_t buffer2_len,
305 struct dvb_demux_filter *dvbdmxfilter,
306 enum dmx_success success,
307 struct av7110 *av7110)
308{
309 if (!dvbdmxfilter->feed->demux->dmx.frontend)
310 return 0;
311 if (dvbdmxfilter->feed->demux->dmx.frontend->source == DMX_MEMORY_FE)
312 return 0;
313
314 switch (dvbdmxfilter->type) {
315 case DMX_TYPE_SEC:
316 if ((((buffer1[1] << 8) | buffer1[2]) & 0xfff) + 3 != buffer1_len)
317 return 0;
318 if (dvbdmxfilter->doneq) {
319 struct dmx_section_filter *filter = &dvbdmxfilter->filter;
320 int i;
321 u8 xor, neq = 0;
322
323 for (i = 0; i < DVB_DEMUX_MASK_MAX; i++) {
324 xor = filter->filter_value[i] ^ buffer1[i];
325 neq |= dvbdmxfilter->maskandnotmode[i] & xor;
326 }
327 if (!neq)
328 return 0;
329 }
330 return dvbdmxfilter->feed->cb.sec(buffer1, buffer1_len,
331 buffer2, buffer2_len,
332 &dvbdmxfilter->filter,
333 DMX_OK);
334 case DMX_TYPE_TS:
335 if (!(dvbdmxfilter->feed->ts_type & TS_PACKET))
336 return 0;
337 if (dvbdmxfilter->feed->ts_type & TS_PAYLOAD_ONLY)
338 return dvbdmxfilter->feed->cb.ts(buffer1, buffer1_len,
339 buffer2, buffer2_len,
340 &dvbdmxfilter->feed->feed.ts,
341 DMX_OK);
342 else
343 av7110_p2t_write(buffer1, buffer1_len,
344 dvbdmxfilter->feed->pid,
345 &av7110->p2t_filter[dvbdmxfilter->index]);
346 default:
347 return 0;
348 }
349}
350
351
352//#define DEBUG_TIMING
353static inline void print_time(char *s)
354{
355#ifdef DEBUG_TIMING
356 struct timeval tv;
357 do_gettimeofday(&tv);
358 printk("%s: %d.%d\n", s, (int)tv.tv_sec, (int)tv.tv_usec);
359#endif
360}
361
362#define DEBI_READ 0
363#define DEBI_WRITE 1
364static inline void start_debi_dma(struct av7110 *av7110, int dir,
365 unsigned long addr, unsigned int len)
366{
367 dprintk(8, "%c %08lx %u\n", dir == DEBI_READ ? 'R' : 'W', addr, len);
368 if (saa7146_wait_for_debi_done(av7110->dev, 0)) {
Harvey Harrison3ca7fc82008-04-08 23:20:00 -0300369 printk(KERN_ERR "%s: saa7146_wait_for_debi_done timed out\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700370 return;
371 }
372
373 SAA7146_ISR_CLEAR(av7110->dev, MASK_19); /* for good measure */
374 SAA7146_IER_ENABLE(av7110->dev, MASK_19);
375 if (len < 5)
376 len = 5; /* we want a real DEBI DMA */
377 if (dir == DEBI_WRITE)
378 iwdebi(av7110, DEBISWAB, addr, 0, (len + 3) & ~3);
379 else
380 irdebi(av7110, DEBISWAB, addr, 0, len);
381}
382
Hans Verkuild45b9b82008-09-04 03:33:43 -0300383static void debiirq(unsigned long cookie)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384{
Hans Verkuild45b9b82008-09-04 03:33:43 -0300385 struct av7110 *av7110 = (struct av7110 *)cookie;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386 int type = av7110->debitype;
387 int handle = (type >> 8) & 0x1f;
388 unsigned int xfer = 0;
389
390 print_time("debi");
391 dprintk(4, "type 0x%04x\n", type);
392
393 if (type == -1) {
394 printk("DEBI irq oops @ %ld, psr:0x%08x, ssr:0x%08x\n",
395 jiffies, saa7146_read(av7110->dev, PSR),
396 saa7146_read(av7110->dev, SSR));
397 goto debi_done;
398 }
399 av7110->debitype = -1;
400
401 switch (type & 0xff) {
402
403 case DATA_TS_RECORD:
404 dvb_dmx_swfilter_packets(&av7110->demux,
405 (const u8 *) av7110->debi_virt,
406 av7110->debilen / 188);
407 xfer = RX_BUFF;
408 break;
409
410 case DATA_PES_RECORD:
411 if (av7110->demux.recording)
412 av7110_record_cb(&av7110->p2t[handle],
413 (u8 *) av7110->debi_virt,
414 av7110->debilen);
415 xfer = RX_BUFF;
416 break;
417
418 case DATA_IPMPE:
419 case DATA_FSECTION:
420 case DATA_PIPING:
421 if (av7110->handle2filter[handle])
422 DvbDmxFilterCallback((u8 *)av7110->debi_virt,
423 av7110->debilen, NULL, 0,
424 av7110->handle2filter[handle],
425 DMX_OK, av7110);
426 xfer = RX_BUFF;
427 break;
428
429 case DATA_CI_GET:
430 {
431 u8 *data = av7110->debi_virt;
432
433 if ((data[0] < 2) && data[2] == 0xff) {
434 int flags = 0;
435 if (data[5] > 0)
436 flags |= CA_CI_MODULE_PRESENT;
437 if (data[5] > 5)
438 flags |= CA_CI_MODULE_READY;
439 av7110->ci_slot[data[0]].flags = flags;
440 } else
441 ci_get_data(&av7110->ci_rbuffer,
442 av7110->debi_virt,
443 av7110->debilen);
444 xfer = RX_BUFF;
445 break;
446 }
447
448 case DATA_COMMON_INTERFACE:
449 CI_handle(av7110, (u8 *)av7110->debi_virt, av7110->debilen);
450#if 0
451 {
452 int i;
453
454 printk("av7110%d: ", av7110->num);
455 printk("%02x ", *(u8 *)av7110->debi_virt);
456 printk("%02x ", *(1+(u8 *)av7110->debi_virt));
457 for (i = 2; i < av7110->debilen; i++)
458 printk("%02x ", (*(i+(unsigned char *)av7110->debi_virt)));
459 for (i = 2; i < av7110->debilen; i++)
460 printk("%c", chtrans(*(i+(unsigned char *)av7110->debi_virt)));
461
462 printk("\n");
463 }
464#endif
465 xfer = RX_BUFF;
466 break;
467
468 case DATA_DEBUG_MESSAGE:
469 ((s8*)av7110->debi_virt)[Reserved_SIZE - 1] = 0;
470 printk("%s\n", (s8 *) av7110->debi_virt);
471 xfer = RX_BUFF;
472 break;
473
474 case DATA_CI_PUT:
475 dprintk(4, "debi DATA_CI_PUT\n");
476 case DATA_MPEG_PLAY:
477 dprintk(4, "debi DATA_MPEG_PLAY\n");
478 case DATA_BMP_LOAD:
479 dprintk(4, "debi DATA_BMP_LOAD\n");
480 xfer = TX_BUFF;
481 break;
482 default:
483 break;
484 }
485debi_done:
486 spin_lock(&av7110->debilock);
487 if (xfer)
488 iwdebi(av7110, DEBINOSWAP, xfer, 0, 2);
489 ARM_ClearMailBox(av7110);
490 spin_unlock(&av7110->debilock);
491}
492
493/* irq from av7110 firmware writing the mailbox register in the DPRAM */
Hans Verkuild45b9b82008-09-04 03:33:43 -0300494static void gpioirq(unsigned long cookie)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495{
Hans Verkuild45b9b82008-09-04 03:33:43 -0300496 struct av7110 *av7110 = (struct av7110 *)cookie;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497 u32 rxbuf, txbuf;
498 int len;
499
500 if (av7110->debitype != -1)
501 /* we shouldn't get any irq while a debi xfer is running */
502 printk("dvb-ttpci: GPIO0 irq oops @ %ld, psr:0x%08x, ssr:0x%08x\n",
503 jiffies, saa7146_read(av7110->dev, PSR),
504 saa7146_read(av7110->dev, SSR));
505
506 if (saa7146_wait_for_debi_done(av7110->dev, 0)) {
Harvey Harrison3ca7fc82008-04-08 23:20:00 -0300507 printk(KERN_ERR "%s: saa7146_wait_for_debi_done timed out\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700508 BUG(); /* maybe we should try resetting the debi? */
509 }
510
511 spin_lock(&av7110->debilock);
512 ARM_ClearIrq(av7110);
513
514 /* see what the av7110 wants */
515 av7110->debitype = irdebi(av7110, DEBINOSWAP, IRQ_STATE, 0, 2);
516 av7110->debilen = irdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
517 rxbuf = irdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
518 txbuf = irdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
519 len = (av7110->debilen + 3) & ~3;
520
521 print_time("gpio");
522 dprintk(8, "GPIO0 irq 0x%04x %d\n", av7110->debitype, av7110->debilen);
523
524 switch (av7110->debitype & 0xff) {
525
526 case DATA_TS_PLAY:
527 case DATA_PES_PLAY:
528 break;
529
530 case DATA_MPEG_VIDEO_EVENT:
531 {
532 u32 h_ar;
533 struct video_event event;
534
535 av7110->video_size.w = irdebi(av7110, DEBINOSWAP, STATUS_MPEG_WIDTH, 0, 2);
536 h_ar = irdebi(av7110, DEBINOSWAP, STATUS_MPEG_HEIGHT_AR, 0, 2);
537
538 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
539 iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
540
541 av7110->video_size.h = h_ar & 0xfff;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700542
543 event.type = VIDEO_EVENT_SIZE_CHANGED;
544 event.u.size.w = av7110->video_size.w;
545 event.u.size.h = av7110->video_size.h;
546 switch ((h_ar >> 12) & 0xf)
547 {
548 case 3:
549 av7110->video_size.aspect_ratio = VIDEO_FORMAT_16_9;
550 event.u.size.aspect_ratio = VIDEO_FORMAT_16_9;
551 av7110->videostate.video_format = VIDEO_FORMAT_16_9;
552 break;
553 case 4:
554 av7110->video_size.aspect_ratio = VIDEO_FORMAT_221_1;
555 event.u.size.aspect_ratio = VIDEO_FORMAT_221_1;
556 av7110->videostate.video_format = VIDEO_FORMAT_221_1;
557 break;
558 default:
559 av7110->video_size.aspect_ratio = VIDEO_FORMAT_4_3;
560 event.u.size.aspect_ratio = VIDEO_FORMAT_4_3;
561 av7110->videostate.video_format = VIDEO_FORMAT_4_3;
562 }
Oliver Endriss66190a22006-01-09 15:32:42 -0200563
564 dprintk(8, "GPIO0 irq: DATA_MPEG_VIDEO_EVENT: w/h/ar = %u/%u/%u\n",
565 av7110->video_size.w, av7110->video_size.h,
566 av7110->video_size.aspect_ratio);
567
Linus Torvalds1da177e2005-04-16 15:20:36 -0700568 dvb_video_add_event(av7110, &event);
569 break;
570 }
571
572 case DATA_CI_PUT:
573 {
574 int avail;
575 struct dvb_ringbuffer *cibuf = &av7110->ci_wbuffer;
576
577 avail = dvb_ringbuffer_avail(cibuf);
578 if (avail <= 2) {
579 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
580 iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
581 iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
582 break;
583 }
584 len = DVB_RINGBUFFER_PEEK(cibuf, 0) << 8;
585 len |= DVB_RINGBUFFER_PEEK(cibuf, 1);
586 if (avail < len + 2) {
587 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
588 iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
589 iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
590 break;
591 }
592 DVB_RINGBUFFER_SKIP(cibuf, 2);
593
Al Virob0ba0e32008-06-22 14:20:29 -0300594 dvb_ringbuffer_read(cibuf, av7110->debi_virt, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595
596 iwdebi(av7110, DEBINOSWAP, TX_LEN, len, 2);
597 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, len, 2);
598 dprintk(8, "DMA: CI\n");
599 start_debi_dma(av7110, DEBI_WRITE, DPRAM_BASE + txbuf, len);
600 spin_unlock(&av7110->debilock);
601 wake_up(&cibuf->queue);
602 return;
603 }
604
605 case DATA_MPEG_PLAY:
606 if (!av7110->playing) {
607 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
608 iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
609 iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
610 break;
611 }
612 len = 0;
613 if (av7110->debitype & 0x100) {
614 spin_lock(&av7110->aout.lock);
615 len = av7110_pes_play(av7110->debi_virt, &av7110->aout, 2048);
616 spin_unlock(&av7110->aout.lock);
617 }
618 if (len <= 0 && (av7110->debitype & 0x200)
619 &&av7110->videostate.play_state != VIDEO_FREEZED) {
620 spin_lock(&av7110->avout.lock);
621 len = av7110_pes_play(av7110->debi_virt, &av7110->avout, 2048);
622 spin_unlock(&av7110->avout.lock);
623 }
624 if (len <= 0) {
625 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
626 iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
627 iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
628 break;
629 }
630 dprintk(8, "GPIO0 PES_PLAY len=%04x\n", len);
631 iwdebi(av7110, DEBINOSWAP, TX_LEN, len, 2);
632 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, len, 2);
633 dprintk(8, "DMA: MPEG_PLAY\n");
634 start_debi_dma(av7110, DEBI_WRITE, DPRAM_BASE + txbuf, len);
635 spin_unlock(&av7110->debilock);
636 return;
637
638 case DATA_BMP_LOAD:
639 len = av7110->debilen;
640 dprintk(8, "gpio DATA_BMP_LOAD len %d\n", len);
641 if (!len) {
642 av7110->bmp_state = BMP_LOADED;
643 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
644 iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
645 iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
646 wake_up(&av7110->bmpq);
647 dprintk(8, "gpio DATA_BMP_LOAD done\n");
648 break;
649 }
650 if (len > av7110->bmplen)
651 len = av7110->bmplen;
652 if (len > 2 * 1024)
653 len = 2 * 1024;
654 iwdebi(av7110, DEBINOSWAP, TX_LEN, len, 2);
655 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, len, 2);
656 memcpy(av7110->debi_virt, av7110->bmpbuf+av7110->bmpp, len);
657 av7110->bmpp += len;
658 av7110->bmplen -= len;
659 dprintk(8, "gpio DATA_BMP_LOAD DMA len %d\n", len);
660 start_debi_dma(av7110, DEBI_WRITE, DPRAM_BASE+txbuf, len);
661 spin_unlock(&av7110->debilock);
662 return;
663
664 case DATA_CI_GET:
665 case DATA_COMMON_INTERFACE:
666 case DATA_FSECTION:
667 case DATA_IPMPE:
668 case DATA_PIPING:
669 if (!len || len > 4 * 1024) {
670 iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
671 break;
672 }
673 /* fall through */
674
675 case DATA_TS_RECORD:
676 case DATA_PES_RECORD:
677 dprintk(8, "DMA: TS_REC etc.\n");
678 start_debi_dma(av7110, DEBI_READ, DPRAM_BASE+rxbuf, len);
679 spin_unlock(&av7110->debilock);
680 return;
681
682 case DATA_DEBUG_MESSAGE:
683 if (!len || len > 0xff) {
684 iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
685 break;
686 }
687 start_debi_dma(av7110, DEBI_READ, Reserved, len);
688 spin_unlock(&av7110->debilock);
689 return;
690
691 case DATA_IRCOMMAND:
Oliver Endrissee820a62007-04-27 12:31:21 -0300692 if (av7110->ir.ir_handler)
693 av7110->ir.ir_handler(av7110,
Oliver Endriss03388ae2005-09-09 13:03:12 -0700694 swahw32(irdebi(av7110, DEBINOSWAP, Reserved, 0, 4)));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700695 iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
696 break;
697
698 default:
699 printk("dvb-ttpci: gpioirq unknown type=%d len=%d\n",
700 av7110->debitype, av7110->debilen);
701 break;
702 }
703 av7110->debitype = -1;
704 ARM_ClearMailBox(av7110);
705 spin_unlock(&av7110->debilock);
706}
707
708
709#ifdef CONFIG_DVB_AV7110_OSD
710static int dvb_osd_ioctl(struct inode *inode, struct file *file,
711 unsigned int cmd, void *parg)
712{
Tobias Klauserd9bdf772006-12-26 07:33:48 -0300713 struct dvb_device *dvbdev = file->private_data;
714 struct av7110 *av7110 = dvbdev->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700715
716 dprintk(4, "%p\n", av7110);
717
718 if (cmd == OSD_SEND_CMD)
719 return av7110_osd_cmd(av7110, (osd_cmd_t *) parg);
720 if (cmd == OSD_GET_CAPABILITY)
721 return av7110_osd_capability(av7110, (osd_cap_t *) parg);
722
723 return -EINVAL;
724}
725
726
Jan Engelhardt784e29d2009-01-11 06:12:43 -0300727static const struct file_operations dvb_osd_fops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700728 .owner = THIS_MODULE,
729 .ioctl = dvb_generic_ioctl,
730 .open = dvb_generic_open,
731 .release = dvb_generic_release,
732};
733
734static struct dvb_device dvbdev_osd = {
735 .priv = NULL,
736 .users = 1,
737 .writers = 1,
738 .fops = &dvb_osd_fops,
739 .kernel_ioctl = dvb_osd_ioctl,
740};
741#endif /* CONFIG_DVB_AV7110_OSD */
742
743
744static inline int SetPIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid,
745 u16 subpid, u16 pcrpid)
746{
Dr. Werner Fink47f36922006-01-09 15:25:07 -0200747 u16 aflags = 0;
748
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749 dprintk(4, "%p\n", av7110);
750
751 if (vpid == 0x1fff || apid == 0x1fff ||
752 ttpid == 0x1fff || subpid == 0x1fff || pcrpid == 0x1fff) {
753 vpid = apid = ttpid = subpid = pcrpid = 0;
754 av7110->pids[DMX_PES_VIDEO] = 0;
755 av7110->pids[DMX_PES_AUDIO] = 0;
756 av7110->pids[DMX_PES_TELETEXT] = 0;
757 av7110->pids[DMX_PES_PCR] = 0;
758 }
759
Dr. Werner Fink47f36922006-01-09 15:25:07 -0200760 if (av7110->audiostate.bypass_mode)
761 aflags |= 0x8000;
762
763 return av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, MultiPID, 6,
764 pcrpid, vpid, apid, ttpid, subpid, aflags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700765}
766
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700767int ChangePIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700768 u16 subpid, u16 pcrpid)
769{
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700770 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700771 dprintk(4, "%p\n", av7110);
772
Ingo Molnar3593cab2006-02-07 06:49:14 -0200773 if (mutex_lock_interruptible(&av7110->pid_mutex))
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700774 return -ERESTARTSYS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700775
776 if (!(vpid & 0x8000))
777 av7110->pids[DMX_PES_VIDEO] = vpid;
778 if (!(apid & 0x8000))
779 av7110->pids[DMX_PES_AUDIO] = apid;
780 if (!(ttpid & 0x8000))
781 av7110->pids[DMX_PES_TELETEXT] = ttpid;
782 if (!(pcrpid & 0x8000))
783 av7110->pids[DMX_PES_PCR] = pcrpid;
784
785 av7110->pids[DMX_PES_SUBTITLE] = 0;
786
787 if (av7110->fe_synced) {
788 pcrpid = av7110->pids[DMX_PES_PCR];
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700789 ret = SetPIDs(av7110, vpid, apid, ttpid, subpid, pcrpid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790 }
791
Ingo Molnar3593cab2006-02-07 06:49:14 -0200792 mutex_unlock(&av7110->pid_mutex);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700793 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700794}
795
796
797/******************************************************************************
798 * hardware filter functions
799 ******************************************************************************/
800
801static int StartHWFilter(struct dvb_demux_filter *dvbdmxfilter)
802{
803 struct dvb_demux_feed *dvbdmxfeed = dvbdmxfilter->feed;
Tobias Klauserd9bdf772006-12-26 07:33:48 -0300804 struct av7110 *av7110 = dvbdmxfeed->demux->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700805 u16 buf[20];
806 int ret, i;
807 u16 handle;
808// u16 mode = 0x0320;
809 u16 mode = 0xb96a;
810
811 dprintk(4, "%p\n", av7110);
812
Oliver Endriss9e615ea2008-09-03 19:15:27 -0300813 if (av7110->full_ts)
814 return 0;
815
Linus Torvalds1da177e2005-04-16 15:20:36 -0700816 if (dvbdmxfilter->type == DMX_TYPE_SEC) {
817 if (hw_sections) {
818 buf[4] = (dvbdmxfilter->filter.filter_value[0] << 8) |
819 dvbdmxfilter->maskandmode[0];
820 for (i = 3; i < 18; i++)
821 buf[i + 4 - 2] =
822 (dvbdmxfilter->filter.filter_value[i] << 8) |
823 dvbdmxfilter->maskandmode[i];
824 mode = 4;
825 }
826 } else if ((dvbdmxfeed->ts_type & TS_PACKET) &&
827 !(dvbdmxfeed->ts_type & TS_PAYLOAD_ONLY)) {
828 av7110_p2t_init(&av7110->p2t_filter[dvbdmxfilter->index], dvbdmxfeed);
829 }
830
831 buf[0] = (COMTYPE_PID_FILTER << 8) + AddPIDFilter;
832 buf[1] = 16;
833 buf[2] = dvbdmxfeed->pid;
834 buf[3] = mode;
835
836 ret = av7110_fw_request(av7110, buf, 20, &handle, 1);
837 if (ret != 0 || handle >= 32) {
838 printk("dvb-ttpci: %s error buf %04x %04x %04x %04x "
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700839 "ret %d handle %04x\n",
Harvey Harrison3ca7fc82008-04-08 23:20:00 -0300840 __func__, buf[0], buf[1], buf[2], buf[3],
Linus Torvalds1da177e2005-04-16 15:20:36 -0700841 ret, handle);
842 dvbdmxfilter->hw_handle = 0xffff;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700843 if (!ret)
844 ret = -1;
845 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846 }
847
848 av7110->handle2filter[handle] = dvbdmxfilter;
849 dvbdmxfilter->hw_handle = handle;
850
851 return ret;
852}
853
854static int StopHWFilter(struct dvb_demux_filter *dvbdmxfilter)
855{
Tobias Klauserd9bdf772006-12-26 07:33:48 -0300856 struct av7110 *av7110 = dvbdmxfilter->feed->demux->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700857 u16 buf[3];
858 u16 answ[2];
859 int ret;
860 u16 handle;
861
862 dprintk(4, "%p\n", av7110);
863
Oliver Endriss9e615ea2008-09-03 19:15:27 -0300864 if (av7110->full_ts)
865 return 0;
866
Linus Torvalds1da177e2005-04-16 15:20:36 -0700867 handle = dvbdmxfilter->hw_handle;
868 if (handle >= 32) {
869 printk("%s tried to stop invalid filter %04x, filter type = %x\n",
Harvey Harrison3ca7fc82008-04-08 23:20:00 -0300870 __func__, handle, dvbdmxfilter->type);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700871 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700872 }
873
874 av7110->handle2filter[handle] = NULL;
875
876 buf[0] = (COMTYPE_PID_FILTER << 8) + DelPIDFilter;
877 buf[1] = 1;
878 buf[2] = handle;
879 ret = av7110_fw_request(av7110, buf, 3, answ, 2);
880 if (ret != 0 || answ[1] != handle) {
881 printk("dvb-ttpci: %s error cmd %04x %04x %04x ret %x "
882 "resp %04x %04x pid %d\n",
Harvey Harrison3ca7fc82008-04-08 23:20:00 -0300883 __func__, buf[0], buf[1], buf[2], ret,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700884 answ[0], answ[1], dvbdmxfilter->feed->pid);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700885 if (!ret)
886 ret = -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700887 }
888 return ret;
889}
890
891
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700892static int dvb_feed_start_pid(struct dvb_demux_feed *dvbdmxfeed)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700893{
894 struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
Tobias Klauserd9bdf772006-12-26 07:33:48 -0300895 struct av7110 *av7110 = dvbdmx->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700896 u16 *pid = dvbdmx->pids, npids[5];
897 int i;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700898 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700899
900 dprintk(4, "%p\n", av7110);
901
902 npids[0] = npids[1] = npids[2] = npids[3] = npids[4] = 0xffff;
903 i = dvbdmxfeed->pes_type;
904 npids[i] = (pid[i]&0x8000) ? 0 : pid[i];
905 if ((i == 2) && npids[i] && (dvbdmxfeed->ts_type & TS_PACKET)) {
906 npids[i] = 0;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700907 ret = ChangePIDs(av7110, npids[1], npids[0], npids[2], npids[3], npids[4]);
908 if (!ret)
909 ret = StartHWFilter(dvbdmxfeed->filter);
910 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700911 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700912 if (dvbdmxfeed->pes_type <= 2 || dvbdmxfeed->pes_type == 4) {
913 ret = ChangePIDs(av7110, npids[1], npids[0], npids[2], npids[3], npids[4]);
914 if (ret)
915 return ret;
916 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700917
918 if (dvbdmxfeed->pes_type < 2 && npids[0])
919 if (av7110->fe_synced)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700920 {
921 ret = av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, Scan, 0);
922 if (ret)
923 return ret;
924 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700925
Oliver Endriss9e615ea2008-09-03 19:15:27 -0300926 if ((dvbdmxfeed->ts_type & TS_PACKET) && !av7110->full_ts) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700927 if (dvbdmxfeed->pes_type == 0 && !(dvbdmx->pids[0] & 0x8000))
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700928 ret = av7110_av_start_record(av7110, RP_AUDIO, dvbdmxfeed);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700929 if (dvbdmxfeed->pes_type == 1 && !(dvbdmx->pids[1] & 0x8000))
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700930 ret = av7110_av_start_record(av7110, RP_VIDEO, dvbdmxfeed);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700932 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700933}
934
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700935static int dvb_feed_stop_pid(struct dvb_demux_feed *dvbdmxfeed)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700936{
937 struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
Tobias Klauserd9bdf772006-12-26 07:33:48 -0300938 struct av7110 *av7110 = dvbdmx->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700939 u16 *pid = dvbdmx->pids, npids[5];
940 int i;
941
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700942 int ret = 0;
943
Linus Torvalds1da177e2005-04-16 15:20:36 -0700944 dprintk(4, "%p\n", av7110);
945
946 if (dvbdmxfeed->pes_type <= 1) {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700947 ret = av7110_av_stop(av7110, dvbdmxfeed->pes_type ? RP_VIDEO : RP_AUDIO);
948 if (ret)
949 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700950 if (!av7110->rec_mode)
951 dvbdmx->recording = 0;
952 if (!av7110->playing)
953 dvbdmx->playing = 0;
954 }
955 npids[0] = npids[1] = npids[2] = npids[3] = npids[4] = 0xffff;
956 i = dvbdmxfeed->pes_type;
957 switch (i) {
958 case 2: //teletext
959 if (dvbdmxfeed->ts_type & TS_PACKET)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700960 ret = StopHWFilter(dvbdmxfeed->filter);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700961 npids[2] = 0;
962 break;
963 case 0:
964 case 1:
965 case 4:
966 if (!pids_off)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700967 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700968 npids[i] = (pid[i]&0x8000) ? 0 : pid[i];
969 break;
970 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700971 if (!ret)
972 ret = ChangePIDs(av7110, npids[1], npids[0], npids[2], npids[3], npids[4]);
973 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700974}
975
976static int av7110_start_feed(struct dvb_demux_feed *feed)
977{
978 struct dvb_demux *demux = feed->demux;
979 struct av7110 *av7110 = demux->priv;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700980 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700981
982 dprintk(4, "%p\n", av7110);
983
984 if (!demux->dmx.frontend)
985 return -EINVAL;
986
Oliver Endriss9e615ea2008-09-03 19:15:27 -0300987 if (!av7110->full_ts && feed->pid > 0x1fff)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700988 return -EINVAL;
989
990 if (feed->type == DMX_TYPE_TS) {
991 if ((feed->ts_type & TS_DECODER) &&
992 (feed->pes_type < DMX_TS_PES_OTHER)) {
993 switch (demux->dmx.frontend->source) {
994 case DMX_MEMORY_FE:
995 if (feed->ts_type & TS_DECODER)
996 if (feed->pes_type < 2 &&
997 !(demux->pids[0] & 0x8000) &&
998 !(demux->pids[1] & 0x8000)) {
999 dvb_ringbuffer_flush_spinlock_wakeup(&av7110->avout);
1000 dvb_ringbuffer_flush_spinlock_wakeup(&av7110->aout);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001001 ret = av7110_av_start_play(av7110,RP_AV);
1002 if (!ret)
1003 demux->playing = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001004 }
1005 break;
1006 default:
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001007 ret = dvb_feed_start_pid(feed);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001008 break;
1009 }
1010 } else if ((feed->ts_type & TS_PACKET) &&
1011 (demux->dmx.frontend->source != DMX_MEMORY_FE)) {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001012 ret = StartHWFilter(feed->filter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001013 }
1014 }
1015
Oliver Endriss9e615ea2008-09-03 19:15:27 -03001016 if (av7110->full_ts) {
1017 budget_start_feed(feed);
1018 return ret;
1019 }
1020
1021 if (feed->type == DMX_TYPE_SEC) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022 int i;
1023
1024 for (i = 0; i < demux->filternum; i++) {
1025 if (demux->filter[i].state != DMX_STATE_READY)
1026 continue;
1027 if (demux->filter[i].type != DMX_TYPE_SEC)
1028 continue;
1029 if (demux->filter[i].filter.parent != &feed->feed.sec)
1030 continue;
1031 demux->filter[i].state = DMX_STATE_GO;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001032 if (demux->dmx.frontend->source != DMX_MEMORY_FE) {
1033 ret = StartHWFilter(&demux->filter[i]);
1034 if (ret)
1035 break;
1036 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001037 }
1038 }
1039
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001040 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001041}
1042
1043
1044static int av7110_stop_feed(struct dvb_demux_feed *feed)
1045{
1046 struct dvb_demux *demux = feed->demux;
1047 struct av7110 *av7110 = demux->priv;
Johannes Stezenbach12ba0502005-07-07 17:58:00 -07001048 int i, rc, ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049 dprintk(4, "%p\n", av7110);
1050
1051 if (feed->type == DMX_TYPE_TS) {
1052 if (feed->ts_type & TS_DECODER) {
1053 if (feed->pes_type >= DMX_TS_PES_OTHER ||
1054 !demux->pesfilter[feed->pes_type])
1055 return -EINVAL;
1056 demux->pids[feed->pes_type] |= 0x8000;
1057 demux->pesfilter[feed->pes_type] = NULL;
1058 }
1059 if (feed->ts_type & TS_DECODER &&
1060 feed->pes_type < DMX_TS_PES_OTHER) {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001061 ret = dvb_feed_stop_pid(feed);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062 } else
1063 if ((feed->ts_type & TS_PACKET) &&
1064 (demux->dmx.frontend->source != DMX_MEMORY_FE))
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001065 ret = StopHWFilter(feed->filter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066 }
1067
Oliver Endriss9e615ea2008-09-03 19:15:27 -03001068 if (av7110->full_ts) {
1069 budget_stop_feed(feed);
1070 return ret;
1071 }
1072
1073 if (feed->type == DMX_TYPE_SEC) {
Johannes Stezenbach12ba0502005-07-07 17:58:00 -07001074 for (i = 0; i<demux->filternum; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001075 if (demux->filter[i].state == DMX_STATE_GO &&
1076 demux->filter[i].filter.parent == &feed->feed.sec) {
1077 demux->filter[i].state = DMX_STATE_READY;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001078 if (demux->dmx.frontend->source != DMX_MEMORY_FE) {
Johannes Stezenbach12ba0502005-07-07 17:58:00 -07001079 rc = StopHWFilter(&demux->filter[i]);
1080 if (!ret)
1081 ret = rc;
1082 /* keep going, stop as many filters as possible */
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001083 }
Johannes Stezenbach12ba0502005-07-07 17:58:00 -07001084 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001085 }
1086 }
1087
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001088 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089}
1090
1091
1092static void restart_feeds(struct av7110 *av7110)
1093{
1094 struct dvb_demux *dvbdmx = &av7110->demux;
1095 struct dvb_demux_feed *feed;
1096 int mode;
Oliver Endriss9e615ea2008-09-03 19:15:27 -03001097 int feeding;
Oliver Endriss66190a22006-01-09 15:32:42 -02001098 int i, j;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001099
1100 dprintk(4, "%p\n", av7110);
1101
1102 mode = av7110->playing;
1103 av7110->playing = 0;
1104 av7110->rec_mode = 0;
1105
Oliver Endriss9e615ea2008-09-03 19:15:27 -03001106 feeding = av7110->feeding1; /* full_ts mod */
1107
Oliver Endriss66190a22006-01-09 15:32:42 -02001108 for (i = 0; i < dvbdmx->feednum; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109 feed = &dvbdmx->feed[i];
Oliver Endriss66190a22006-01-09 15:32:42 -02001110 if (feed->state == DMX_STATE_GO) {
1111 if (feed->type == DMX_TYPE_SEC) {
1112 for (j = 0; j < dvbdmx->filternum; j++) {
1113 if (dvbdmx->filter[j].type != DMX_TYPE_SEC)
1114 continue;
1115 if (dvbdmx->filter[j].filter.parent != &feed->feed.sec)
1116 continue;
1117 if (dvbdmx->filter[j].state == DMX_STATE_GO)
1118 dvbdmx->filter[j].state = DMX_STATE_READY;
1119 }
1120 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001121 av7110_start_feed(feed);
Oliver Endriss66190a22006-01-09 15:32:42 -02001122 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001123 }
1124
Oliver Endriss9e615ea2008-09-03 19:15:27 -03001125 av7110->feeding1 = feeding; /* full_ts mod */
1126
Linus Torvalds1da177e2005-04-16 15:20:36 -07001127 if (mode)
1128 av7110_av_start_play(av7110, mode);
1129}
1130
1131static int dvb_get_stc(struct dmx_demux *demux, unsigned int num,
1132 uint64_t *stc, unsigned int *base)
1133{
1134 int ret;
1135 u16 fwstc[4];
1136 u16 tag = ((COMTYPE_REQUEST << 8) + ReqSTC);
1137 struct dvb_demux *dvbdemux;
1138 struct av7110 *av7110;
1139
1140 /* pointer casting paranoia... */
Eric Sesterhennae246012006-03-13 13:17:11 -03001141 BUG_ON(!demux);
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001142 dvbdemux = demux->priv;
Eric Sesterhennae246012006-03-13 13:17:11 -03001143 BUG_ON(!dvbdemux);
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001144 av7110 = dvbdemux->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001145
1146 dprintk(4, "%p\n", av7110);
1147
1148 if (num != 0)
1149 return -EINVAL;
1150
1151 ret = av7110_fw_request(av7110, &tag, 0, fwstc, 4);
1152 if (ret) {
Harvey Harrison3ca7fc82008-04-08 23:20:00 -03001153 printk(KERN_ERR "%s: av7110_fw_request error\n", __func__);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001154 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001155 }
1156 dprintk(2, "fwstc = %04hx %04hx %04hx %04hx\n",
1157 fwstc[0], fwstc[1], fwstc[2], fwstc[3]);
1158
1159 *stc = (((uint64_t) ((fwstc[3] & 0x8000) >> 15)) << 32) |
1160 (((uint64_t) fwstc[1]) << 16) | ((uint64_t) fwstc[0]);
1161 *base = 1;
1162
1163 dprintk(4, "stc = %lu\n", (unsigned long)*stc);
1164
1165 return 0;
1166}
1167
1168
1169/******************************************************************************
1170 * SEC device file operations
1171 ******************************************************************************/
1172
1173
1174static int av7110_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
1175{
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001176 struct av7110* av7110 = fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001177
1178 switch (tone) {
1179 case SEC_TONE_ON:
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001180 return Set22K(av7110, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001181
1182 case SEC_TONE_OFF:
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001183 return Set22K(av7110, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001184
1185 default:
1186 return -EINVAL;
1187 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188}
1189
1190static int av7110_diseqc_send_master_cmd(struct dvb_frontend* fe,
1191 struct dvb_diseqc_master_cmd* cmd)
1192{
1193 struct av7110* av7110 = fe->dvb->priv;
1194
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001195 return av7110_diseqc_send(av7110, cmd->msg_len, cmd->msg, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001196}
1197
1198static int av7110_diseqc_send_burst(struct dvb_frontend* fe,
1199 fe_sec_mini_cmd_t minicmd)
1200{
1201 struct av7110* av7110 = fe->dvb->priv;
1202
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001203 return av7110_diseqc_send(av7110, 0, NULL, minicmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001204}
1205
1206/* simplified code from budget-core.c */
1207static int stop_ts_capture(struct av7110 *budget)
1208{
1209 dprintk(2, "budget: %p\n", budget);
1210
1211 if (--budget->feeding1)
1212 return budget->feeding1;
1213 saa7146_write(budget->dev, MC1, MASK_20); /* DMA3 off */
1214 SAA7146_IER_DISABLE(budget->dev, MASK_10);
1215 SAA7146_ISR_CLEAR(budget->dev, MASK_10);
1216 return 0;
1217}
1218
1219static int start_ts_capture(struct av7110 *budget)
1220{
1221 dprintk(2, "budget: %p\n", budget);
1222
1223 if (budget->feeding1)
1224 return ++budget->feeding1;
Oliver Endriss9e615ea2008-09-03 19:15:27 -03001225 memset(budget->grabbing, 0x00, TS_BUFLEN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001226 budget->ttbp = 0;
Oliver Endriss9e615ea2008-09-03 19:15:27 -03001227 SAA7146_ISR_CLEAR(budget->dev, MASK_10); /* VPE */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001228 SAA7146_IER_ENABLE(budget->dev, MASK_10); /* VPE */
1229 saa7146_write(budget->dev, MC1, (MASK_04 | MASK_20)); /* DMA3 on */
1230 return ++budget->feeding1;
1231}
1232
1233static int budget_start_feed(struct dvb_demux_feed *feed)
1234{
1235 struct dvb_demux *demux = feed->demux;
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001236 struct av7110 *budget = demux->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001237 int status;
1238
1239 dprintk(2, "av7110: %p\n", budget);
1240
1241 spin_lock(&budget->feedlock1);
1242 feed->pusi_seen = 0; /* have a clean section start */
1243 status = start_ts_capture(budget);
1244 spin_unlock(&budget->feedlock1);
1245 return status;
1246}
1247
1248static int budget_stop_feed(struct dvb_demux_feed *feed)
1249{
1250 struct dvb_demux *demux = feed->demux;
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001251 struct av7110 *budget = demux->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001252 int status;
1253
1254 dprintk(2, "budget: %p\n", budget);
1255
1256 spin_lock(&budget->feedlock1);
1257 status = stop_ts_capture(budget);
1258 spin_unlock(&budget->feedlock1);
1259 return status;
1260}
1261
Hans Verkuild45b9b82008-09-04 03:33:43 -03001262static void vpeirq(unsigned long cookie)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001263{
Hans Verkuild45b9b82008-09-04 03:33:43 -03001264 struct av7110 *budget = (struct av7110 *)cookie;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001265 u8 *mem = (u8 *) (budget->grabbing);
1266 u32 olddma = budget->ttbp;
1267 u32 newdma = saa7146_read(budget->dev, PCI_VDP3);
Oliver Endriss9e615ea2008-09-03 19:15:27 -03001268 struct dvb_demux *demux = budget->full_ts ? &budget->demux : &budget->demux1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001269
Linus Torvalds1da177e2005-04-16 15:20:36 -07001270 /* nearest lower position divisible by 188 */
1271 newdma -= newdma % 188;
1272
1273 if (newdma >= TS_BUFLEN)
1274 return;
1275
1276 budget->ttbp = newdma;
1277
1278 if (!budget->feeding1 || (newdma == olddma))
1279 return;
1280
Jon Burgess87c30192007-05-03 12:23:44 -03001281 /* Ensure streamed PCI data is synced to CPU */
1282 pci_dma_sync_sg_for_cpu(budget->dev->pci, budget->pt.slist, budget->pt.nents, PCI_DMA_FROMDEVICE);
1283
Linus Torvalds1da177e2005-04-16 15:20:36 -07001284#if 0
1285 /* track rps1 activity */
1286 printk("vpeirq: %02x Event Counter 1 0x%04x\n",
1287 mem[olddma],
1288 saa7146_read(budget->dev, EC1R) & 0x3fff);
1289#endif
1290
1291 if (newdma > olddma)
1292 /* no wraparound, dump olddma..newdma */
Oliver Endriss9e615ea2008-09-03 19:15:27 -03001293 dvb_dmx_swfilter_packets(demux, mem + olddma, (newdma - olddma) / 188);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001294 else {
1295 /* wraparound, dump olddma..buflen and 0..newdma */
Oliver Endriss9e615ea2008-09-03 19:15:27 -03001296 dvb_dmx_swfilter_packets(demux, mem + olddma, (TS_BUFLEN - olddma) / 188);
1297 dvb_dmx_swfilter_packets(demux, mem, newdma / 188);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001298 }
1299}
1300
1301static int av7110_register(struct av7110 *av7110)
1302{
1303 int ret, i;
1304 struct dvb_demux *dvbdemux = &av7110->demux;
1305 struct dvb_demux *dvbdemux1 = &av7110->demux1;
1306
1307 dprintk(4, "%p\n", av7110);
1308
1309 if (av7110->registered)
1310 return -1;
1311
1312 av7110->registered = 1;
1313
1314 dvbdemux->priv = (void *) av7110;
1315
1316 for (i = 0; i < 32; i++)
1317 av7110->handle2filter[i] = NULL;
1318
Oliver Endriss9e615ea2008-09-03 19:15:27 -03001319 dvbdemux->filternum = (av7110->full_ts) ? 256 : 32;
1320 dvbdemux->feednum = (av7110->full_ts) ? 256 : 32;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001321 dvbdemux->start_feed = av7110_start_feed;
1322 dvbdemux->stop_feed = av7110_stop_feed;
1323 dvbdemux->write_to_decoder = av7110_write_to_decoder;
1324 dvbdemux->dmx.capabilities = (DMX_TS_FILTERING | DMX_SECTION_FILTERING |
1325 DMX_MEMORY_BASED_FILTERING);
1326
1327 dvb_dmx_init(&av7110->demux);
1328 av7110->demux.dmx.get_stc = dvb_get_stc;
1329
Oliver Endriss9e615ea2008-09-03 19:15:27 -03001330 av7110->dmxdev.filternum = (av7110->full_ts) ? 256 : 32;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001331 av7110->dmxdev.demux = &dvbdemux->dmx;
1332 av7110->dmxdev.capabilities = 0;
1333
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001334 dvb_dmxdev_init(&av7110->dmxdev, &av7110->dvb_adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001335
1336 av7110->hw_frontend.source = DMX_FRONTEND_0;
1337
1338 ret = dvbdemux->dmx.add_frontend(&dvbdemux->dmx, &av7110->hw_frontend);
1339
1340 if (ret < 0)
1341 return ret;
1342
1343 av7110->mem_frontend.source = DMX_MEMORY_FE;
1344
1345 ret = dvbdemux->dmx.add_frontend(&dvbdemux->dmx, &av7110->mem_frontend);
1346
1347 if (ret < 0)
1348 return ret;
1349
1350 ret = dvbdemux->dmx.connect_frontend(&dvbdemux->dmx,
1351 &av7110->hw_frontend);
1352 if (ret < 0)
1353 return ret;
1354
1355 av7110_av_register(av7110);
1356 av7110_ca_register(av7110);
1357
1358#ifdef CONFIG_DVB_AV7110_OSD
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001359 dvb_register_device(&av7110->dvb_adapter, &av7110->osd_dev,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001360 &dvbdev_osd, av7110, DVB_DEVICE_OSD);
1361#endif
1362
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001363 dvb_net_init(&av7110->dvb_adapter, &av7110->dvb_net, &dvbdemux->dmx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001364
1365 if (budgetpatch) {
1366 /* initialize software demux1 without its own frontend
1367 * demux1 hardware is connected to frontend0 of demux0
1368 */
1369 dvbdemux1->priv = (void *) av7110;
1370
1371 dvbdemux1->filternum = 256;
1372 dvbdemux1->feednum = 256;
1373 dvbdemux1->start_feed = budget_start_feed;
1374 dvbdemux1->stop_feed = budget_stop_feed;
1375 dvbdemux1->write_to_decoder = NULL;
1376
1377 dvbdemux1->dmx.capabilities = (DMX_TS_FILTERING | DMX_SECTION_FILTERING |
1378 DMX_MEMORY_BASED_FILTERING);
1379
1380 dvb_dmx_init(&av7110->demux1);
1381
1382 av7110->dmxdev1.filternum = 256;
1383 av7110->dmxdev1.demux = &dvbdemux1->dmx;
1384 av7110->dmxdev1.capabilities = 0;
1385
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001386 dvb_dmxdev_init(&av7110->dmxdev1, &av7110->dvb_adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001387
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001388 dvb_net_init(&av7110->dvb_adapter, &av7110->dvb_net1, &dvbdemux1->dmx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001389 printk("dvb-ttpci: additional demux1 for budget-patch registered\n");
1390 }
1391 return 0;
1392}
1393
1394
1395static void dvb_unregister(struct av7110 *av7110)
1396{
1397 struct dvb_demux *dvbdemux = &av7110->demux;
1398 struct dvb_demux *dvbdemux1 = &av7110->demux1;
1399
1400 dprintk(4, "%p\n", av7110);
1401
1402 if (!av7110->registered)
1403 return;
1404
1405 if (budgetpatch) {
1406 dvb_net_release(&av7110->dvb_net1);
1407 dvbdemux->dmx.close(&dvbdemux1->dmx);
1408 dvb_dmxdev_release(&av7110->dmxdev1);
1409 dvb_dmx_release(&av7110->demux1);
1410 }
1411
1412 dvb_net_release(&av7110->dvb_net);
1413
1414 dvbdemux->dmx.close(&dvbdemux->dmx);
1415 dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &av7110->hw_frontend);
1416 dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &av7110->mem_frontend);
1417
1418 dvb_dmxdev_release(&av7110->dmxdev);
1419 dvb_dmx_release(&av7110->demux);
1420
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001421 if (av7110->fe != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001422 dvb_unregister_frontend(av7110->fe);
Andrew de Quinceyf52a8382006-08-08 09:10:09 -03001423 dvb_frontend_detach(av7110->fe);
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001424 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001425 dvb_unregister_device(av7110->osd_dev);
1426 av7110_av_unregister(av7110);
1427 av7110_ca_unregister(av7110);
1428}
1429
1430
1431/****************************************************************************
1432 * I2C client commands
1433 ****************************************************************************/
1434
1435int i2c_writereg(struct av7110 *av7110, u8 id, u8 reg, u8 val)
1436{
1437 u8 msg[2] = { reg, val };
1438 struct i2c_msg msgs;
1439
1440 msgs.flags = 0;
1441 msgs.addr = id / 2;
1442 msgs.len = 2;
1443 msgs.buf = msg;
1444 return i2c_transfer(&av7110->i2c_adap, &msgs, 1);
1445}
1446
Linus Torvalds1da177e2005-04-16 15:20:36 -07001447u8 i2c_readreg(struct av7110 *av7110, u8 id, u8 reg)
1448{
1449 u8 mm1[] = {0x00};
1450 u8 mm2[] = {0x00};
1451 struct i2c_msg msgs[2];
1452
1453 msgs[0].flags = 0;
1454 msgs[1].flags = I2C_M_RD;
1455 msgs[0].addr = msgs[1].addr = id / 2;
1456 mm1[0] = reg;
1457 msgs[0].len = 1; msgs[1].len = 1;
1458 msgs[0].buf = mm1; msgs[1].buf = mm2;
1459 i2c_transfer(&av7110->i2c_adap, msgs, 2);
1460
1461 return mm2[0];
1462}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001463
1464/****************************************************************************
1465 * INITIALIZATION
1466 ****************************************************************************/
1467
1468
1469static int check_firmware(struct av7110* av7110)
1470{
1471 u32 crc = 0, len = 0;
1472 unsigned char *ptr;
1473
1474 /* check for firmware magic */
1475 ptr = av7110->bin_fw;
1476 if (ptr[0] != 'A' || ptr[1] != 'V' ||
1477 ptr[2] != 'F' || ptr[3] != 'W') {
1478 printk("dvb-ttpci: this is not an av7110 firmware\n");
1479 return -EINVAL;
1480 }
1481 ptr += 4;
1482
1483 /* check dpram file */
Al Viro3e085622008-05-21 00:30:51 -03001484 crc = get_unaligned_be32(ptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001485 ptr += 4;
Al Viro3e085622008-05-21 00:30:51 -03001486 len = get_unaligned_be32(ptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001487 ptr += 4;
1488 if (len >= 512) {
Alexey Dobriyanbe787ac2006-03-07 22:20:23 -03001489 printk("dvb-ttpci: dpram file is way too big.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001490 return -EINVAL;
1491 }
1492 if (crc != crc32_le(0, ptr, len)) {
1493 printk("dvb-ttpci: crc32 of dpram file does not match.\n");
1494 return -EINVAL;
1495 }
1496 av7110->bin_dpram = ptr;
1497 av7110->size_dpram = len;
1498 ptr += len;
1499
1500 /* check root file */
Al Viro3e085622008-05-21 00:30:51 -03001501 crc = get_unaligned_be32(ptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001502 ptr += 4;
Al Viro3e085622008-05-21 00:30:51 -03001503 len = get_unaligned_be32(ptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001504 ptr += 4;
1505
1506 if (len <= 200000 || len >= 300000 ||
1507 len > ((av7110->bin_fw + av7110->size_fw) - ptr)) {
1508 printk("dvb-ttpci: root file has strange size (%d). aborting.\n", len);
1509 return -EINVAL;
1510 }
1511 if( crc != crc32_le(0, ptr, len)) {
1512 printk("dvb-ttpci: crc32 of root file does not match.\n");
1513 return -EINVAL;
1514 }
1515 av7110->bin_root = ptr;
1516 av7110->size_root = len;
1517 return 0;
1518}
1519
Linus Torvalds1da177e2005-04-16 15:20:36 -07001520static void put_firmware(struct av7110* av7110)
1521{
1522 vfree(av7110->bin_fw);
1523}
1524
1525static int get_firmware(struct av7110* av7110)
1526{
1527 int ret;
1528 const struct firmware *fw;
1529
1530 /* request the av7110 firmware, this will block until someone uploads it */
1531 ret = request_firmware(&fw, "dvb-ttpci-01.fw", &av7110->dev->pci->dev);
1532 if (ret) {
1533 if (ret == -ENOENT) {
1534 printk(KERN_ERR "dvb-ttpci: could not load firmware,"
1535 " file not found: dvb-ttpci-01.fw\n");
Ville Skytt\ä12e66f62006-01-09 15:25:38 -02001536 printk(KERN_ERR "dvb-ttpci: usually this should be in "
1537 "/usr/lib/hotplug/firmware or /lib/firmware\n");
1538 printk(KERN_ERR "dvb-ttpci: and can be downloaded from"
Linus Torvalds1da177e2005-04-16 15:20:36 -07001539 " http://www.linuxtv.org/download/dvb/firmware/\n");
1540 } else
1541 printk(KERN_ERR "dvb-ttpci: cannot request firmware"
1542 " (error %i)\n", ret);
1543 return -EINVAL;
1544 }
1545
1546 if (fw->size <= 200000) {
1547 printk("dvb-ttpci: this firmware is way too small.\n");
1548 release_firmware(fw);
1549 return -EINVAL;
1550 }
1551
1552 /* check if the firmware is available */
Jesper Juhld9bf2c02007-08-25 11:23:54 -03001553 av7110->bin_fw = vmalloc(fw->size);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001554 if (NULL == av7110->bin_fw) {
1555 dprintk(1, "out of memory\n");
1556 release_firmware(fw);
1557 return -ENOMEM;
1558 }
1559
1560 memcpy(av7110->bin_fw, fw->data, fw->size);
1561 av7110->size_fw = fw->size;
1562 if ((ret = check_firmware(av7110)))
1563 vfree(av7110->bin_fw);
1564
1565 release_firmware(fw);
1566 return ret;
1567}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001568
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001569static int alps_bsrv2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001570{
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001571 struct av7110* av7110 = fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001572 u8 pwr = 0;
1573 u8 buf[4];
1574 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
1575 u32 div = (params->frequency + 479500) / 125;
1576
1577 if (params->frequency > 2000000) pwr = 3;
1578 else if (params->frequency > 1800000) pwr = 2;
1579 else if (params->frequency > 1600000) pwr = 1;
1580 else if (params->frequency > 1200000) pwr = 0;
1581 else if (params->frequency >= 1100000) pwr = 1;
1582 else pwr = 2;
1583
1584 buf[0] = (div >> 8) & 0x7f;
1585 buf[1] = div & 0xff;
1586 buf[2] = ((div & 0x18000) >> 10) | 0x95;
1587 buf[3] = (pwr << 6) | 0x30;
1588
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -08001589 // NOTE: since we're using a prescaler of 2, we set the
Linus Torvalds1da177e2005-04-16 15:20:36 -07001590 // divisor frequency to 62.5kHz and divide by 125 above
1591
Patrick Boettcherdea74862006-05-14 05:01:31 -03001592 if (fe->ops.i2c_gate_ctrl)
1593 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001594 if (i2c_transfer (&av7110->i2c_adap, &msg, 1) != 1)
1595 return -EIO;
1596 return 0;
1597}
1598
1599static struct ves1x93_config alps_bsrv2_config = {
1600 .demod_address = 0x08,
1601 .xin = 90100000UL,
1602 .invert_pwm = 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001603};
1604
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001605static int alps_tdbe2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001606{
1607 struct av7110* av7110 = fe->dvb->priv;
1608 u32 div;
1609 u8 data[4];
1610 struct i2c_msg msg = { .addr = 0x62, .flags = 0, .buf = data, .len = sizeof(data) };
1611
1612 div = (params->frequency + 35937500 + 31250) / 62500;
1613
1614 data[0] = (div >> 8) & 0x7f;
1615 data[1] = div & 0xff;
1616 data[2] = 0x85 | ((div >> 10) & 0x60);
1617 data[3] = (params->frequency < 174000000 ? 0x88 : params->frequency < 470000000 ? 0x84 : 0x81);
1618
Patrick Boettcherdea74862006-05-14 05:01:31 -03001619 if (fe->ops.i2c_gate_ctrl)
1620 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001621 if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
1622 return -EIO;
1623 return 0;
1624}
1625
1626static struct ves1820_config alps_tdbe2_config = {
1627 .demod_address = 0x09,
1628 .xin = 57840000UL,
1629 .invert = 1,
1630 .selagc = VES1820_SELAGC_SIGNAMPERR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001631};
1632
1633
1634
1635
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001636static int grundig_29504_451_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001637{
1638 struct av7110* av7110 = fe->dvb->priv;
1639 u32 div;
1640 u8 data[4];
1641 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
1642
1643 div = params->frequency / 125;
1644 data[0] = (div >> 8) & 0x7f;
1645 data[1] = div & 0xff;
1646 data[2] = 0x8e;
1647 data[3] = 0x00;
1648
Patrick Boettcherdea74862006-05-14 05:01:31 -03001649 if (fe->ops.i2c_gate_ctrl)
1650 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001651 if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
1652 return -EIO;
1653 return 0;
1654}
1655
1656static struct tda8083_config grundig_29504_451_config = {
1657 .demod_address = 0x68,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001658};
1659
1660
1661
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001662static int philips_cd1516_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001663{
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -08001664 struct av7110* av7110 = fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001665 u32 div;
1666 u32 f = params->frequency;
1667 u8 data[4];
1668 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
1669
1670 div = (f + 36125000 + 31250) / 62500;
1671
1672 data[0] = (div >> 8) & 0x7f;
1673 data[1] = div & 0xff;
1674 data[2] = 0x8e;
1675 data[3] = (f < 174000000 ? 0xa1 : f < 470000000 ? 0x92 : 0x34);
1676
Patrick Boettcherdea74862006-05-14 05:01:31 -03001677 if (fe->ops.i2c_gate_ctrl)
1678 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001679 if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
1680 return -EIO;
1681 return 0;
1682}
1683
1684static struct ves1820_config philips_cd1516_config = {
1685 .demod_address = 0x09,
1686 .xin = 57840000UL,
1687 .invert = 1,
1688 .selagc = VES1820_SELAGC_SIGNAMPERR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001689};
1690
1691
1692
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001693static int alps_tdlb7_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001694{
1695 struct av7110* av7110 = fe->dvb->priv;
1696 u32 div, pwr;
1697 u8 data[4];
1698 struct i2c_msg msg = { .addr = 0x60, .flags = 0, .buf = data, .len = sizeof(data) };
1699
1700 div = (params->frequency + 36200000) / 166666;
1701
1702 if (params->frequency <= 782000000)
1703 pwr = 1;
1704 else
1705 pwr = 2;
1706
1707 data[0] = (div >> 8) & 0x7f;
1708 data[1] = div & 0xff;
1709 data[2] = 0x85;
1710 data[3] = pwr << 6;
1711
Patrick Boettcherdea74862006-05-14 05:01:31 -03001712 if (fe->ops.i2c_gate_ctrl)
1713 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001714 if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
1715 return -EIO;
1716 return 0;
1717}
1718
1719static int alps_tdlb7_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name)
1720{
Oliver Endrissd98821e2006-09-14 00:15:13 -03001721#if defined(CONFIG_DVB_SP8870) || defined(CONFIG_DVB_SP8870_MODULE)
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001722 struct av7110* av7110 = fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001723
1724 return request_firmware(fw, name, &av7110->dev->pci->dev);
Oliver Endrissd98821e2006-09-14 00:15:13 -03001725#else
1726 return -EINVAL;
1727#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001728}
1729
1730static struct sp8870_config alps_tdlb7_config = {
1731
1732 .demod_address = 0x71,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001733 .request_firmware = alps_tdlb7_request_firmware,
1734};
1735
1736
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001737static u8 nexusca_stv0297_inittab[] = {
1738 0x80, 0x01,
1739 0x80, 0x00,
1740 0x81, 0x01,
1741 0x81, 0x00,
1742 0x00, 0x09,
1743 0x01, 0x69,
1744 0x03, 0x00,
1745 0x04, 0x00,
1746 0x07, 0x00,
1747 0x08, 0x00,
1748 0x20, 0x00,
1749 0x21, 0x40,
1750 0x22, 0x00,
1751 0x23, 0x00,
1752 0x24, 0x40,
1753 0x25, 0x88,
1754 0x30, 0xff,
1755 0x31, 0x00,
1756 0x32, 0xff,
1757 0x33, 0x00,
1758 0x34, 0x50,
1759 0x35, 0x7f,
1760 0x36, 0x00,
1761 0x37, 0x20,
1762 0x38, 0x00,
1763 0x40, 0x1c,
1764 0x41, 0xff,
1765 0x42, 0x29,
1766 0x43, 0x00,
1767 0x44, 0xff,
1768 0x45, 0x00,
1769 0x46, 0x00,
1770 0x49, 0x04,
1771 0x4a, 0x00,
1772 0x4b, 0x7b,
1773 0x52, 0x30,
1774 0x55, 0xae,
1775 0x56, 0x47,
1776 0x57, 0xe1,
1777 0x58, 0x3a,
1778 0x5a, 0x1e,
1779 0x5b, 0x34,
1780 0x60, 0x00,
1781 0x63, 0x00,
1782 0x64, 0x00,
1783 0x65, 0x00,
1784 0x66, 0x00,
1785 0x67, 0x00,
1786 0x68, 0x00,
1787 0x69, 0x00,
1788 0x6a, 0x02,
1789 0x6b, 0x00,
1790 0x70, 0xff,
1791 0x71, 0x00,
1792 0x72, 0x00,
1793 0x73, 0x00,
1794 0x74, 0x0c,
1795 0x80, 0x00,
1796 0x81, 0x00,
1797 0x82, 0x00,
1798 0x83, 0x00,
1799 0x84, 0x04,
1800 0x85, 0x80,
1801 0x86, 0x24,
1802 0x87, 0x78,
1803 0x88, 0x10,
1804 0x89, 0x00,
1805 0x90, 0x01,
1806 0x91, 0x01,
1807 0xa0, 0x04,
1808 0xa1, 0x00,
1809 0xa2, 0x00,
1810 0xb0, 0x91,
1811 0xb1, 0x0b,
1812 0xc0, 0x53,
1813 0xc1, 0x70,
1814 0xc2, 0x12,
1815 0xd0, 0x00,
1816 0xd1, 0x00,
1817 0xd2, 0x00,
1818 0xd3, 0x00,
1819 0xd4, 0x00,
1820 0xd5, 0x00,
1821 0xde, 0x00,
1822 0xdf, 0x00,
1823 0x61, 0x49,
1824 0x62, 0x0b,
1825 0x53, 0x08,
1826 0x59, 0x08,
1827 0xff, 0xff,
1828};
Linus Torvalds1da177e2005-04-16 15:20:36 -07001829
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001830static int nexusca_stv0297_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001831{
1832 struct av7110* av7110 = fe->dvb->priv;
1833 u32 div;
1834 u8 data[4];
1835 struct i2c_msg msg = { .addr = 0x63, .flags = 0, .buf = data, .len = sizeof(data) };
1836 struct i2c_msg readmsg = { .addr = 0x63, .flags = I2C_M_RD, .buf = data, .len = 1 };
1837 int i;
1838
1839 div = (params->frequency + 36150000 + 31250) / 62500;
1840
1841 data[0] = (div >> 8) & 0x7f;
1842 data[1] = div & 0xff;
1843 data[2] = 0xce;
1844
1845 if (params->frequency < 45000000)
1846 return -EINVAL;
1847 else if (params->frequency < 137000000)
1848 data[3] = 0x01;
1849 else if (params->frequency < 403000000)
1850 data[3] = 0x02;
1851 else if (params->frequency < 860000000)
1852 data[3] = 0x04;
1853 else
1854 return -EINVAL;
1855
Patrick Boettcherdea74862006-05-14 05:01:31 -03001856 if (fe->ops.i2c_gate_ctrl)
1857 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001858 if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1) {
1859 printk("nexusca: pll transfer failed!\n");
1860 return -EIO;
1861 }
1862
1863 // wait for PLL lock
1864 for(i = 0; i < 20; i++) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001865 if (fe->ops.i2c_gate_ctrl)
1866 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001867 if (i2c_transfer(&av7110->i2c_adap, &readmsg, 1) == 1)
1868 if (data[0] & 0x40) break;
1869 msleep(10);
1870 }
1871
1872 return 0;
1873}
1874
1875static struct stv0297_config nexusca_stv0297_config = {
1876
1877 .demod_address = 0x1C,
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001878 .inittab = nexusca_stv0297_inittab,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001879 .invert = 1,
Thomas Kaiserb8d4c232006-04-27 21:45:20 -03001880 .stop_during_read = 1,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001881};
1882
1883
1884
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001885static int grundig_29504_401_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001886{
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001887 struct av7110* av7110 = fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001888 u32 div;
1889 u8 cfg, cpump, band_select;
1890 u8 data[4];
1891 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
1892
1893 div = (36125000 + params->frequency) / 166666;
1894
1895 cfg = 0x88;
1896
1897 if (params->frequency < 175000000) cpump = 2;
1898 else if (params->frequency < 390000000) cpump = 1;
1899 else if (params->frequency < 470000000) cpump = 2;
1900 else if (params->frequency < 750000000) cpump = 1;
1901 else cpump = 3;
1902
1903 if (params->frequency < 175000000) band_select = 0x0e;
1904 else if (params->frequency < 470000000) band_select = 0x05;
1905 else band_select = 0x03;
1906
1907 data[0] = (div >> 8) & 0x7f;
1908 data[1] = div & 0xff;
1909 data[2] = ((div >> 10) & 0x60) | cfg;
1910 data[3] = (cpump << 6) | band_select;
1911
Patrick Boettcherdea74862006-05-14 05:01:31 -03001912 if (fe->ops.i2c_gate_ctrl)
1913 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001914 if (i2c_transfer (&av7110->i2c_adap, &msg, 1) != 1) return -EIO;
1915 return 0;
1916}
1917
1918static struct l64781_config grundig_29504_401_config = {
1919 .demod_address = 0x55,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001920};
1921
1922
1923
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001924static int av7110_fe_lock_fix(struct av7110* av7110, fe_status_t status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001925{
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001926 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001927 int synced = (status & FE_HAS_LOCK) ? 1 : 0;
1928
1929 av7110->fe_status = status;
1930
1931 if (av7110->fe_synced == synced)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001932 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001933
Oliver Endriss14500d42007-03-03 14:45:48 -03001934 if (av7110->playing) {
1935 av7110->fe_synced = synced;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001936 return 0;
Oliver Endriss14500d42007-03-03 14:45:48 -03001937 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001938
Ingo Molnar3593cab2006-02-07 06:49:14 -02001939 if (mutex_lock_interruptible(&av7110->pid_mutex))
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001940 return -ERESTARTSYS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001941
Oliver Endriss34612152005-07-07 17:58:02 -07001942 if (synced) {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001943 ret = SetPIDs(av7110, av7110->pids[DMX_PES_VIDEO],
Linus Torvalds1da177e2005-04-16 15:20:36 -07001944 av7110->pids[DMX_PES_AUDIO],
1945 av7110->pids[DMX_PES_TELETEXT], 0,
1946 av7110->pids[DMX_PES_PCR]);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001947 if (!ret)
1948 ret = av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, Scan, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001949 } else {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001950 ret = SetPIDs(av7110, 0, 0, 0, 0, 0);
1951 if (!ret) {
1952 ret = av7110_fw_cmd(av7110, COMTYPE_PID_FILTER, FlushTSQueue, 0);
1953 if (!ret)
1954 ret = av7110_wait_msgstate(av7110, GPMQBusy);
1955 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001956 }
1957
Oliver Endriss34612152005-07-07 17:58:02 -07001958 if (!ret)
1959 av7110->fe_synced = synced;
1960
Ingo Molnar3593cab2006-02-07 06:49:14 -02001961 mutex_unlock(&av7110->pid_mutex);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001962 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001963}
1964
1965static int av7110_fe_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
1966{
1967 struct av7110* av7110 = fe->dvb->priv;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001968
1969 int ret = av7110_fe_lock_fix(av7110, 0);
Oliver Endriss66190a22006-01-09 15:32:42 -02001970 if (!ret) {
1971 av7110->saved_fe_params = *params;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001972 ret = av7110->fe_set_frontend(fe, params);
Oliver Endriss66190a22006-01-09 15:32:42 -02001973 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001974 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001975}
1976
1977static int av7110_fe_init(struct dvb_frontend* fe)
1978{
1979 struct av7110* av7110 = fe->dvb->priv;
1980
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001981 int ret = av7110_fe_lock_fix(av7110, 0);
1982 if (!ret)
1983 ret = av7110->fe_init(fe);
1984 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001985}
1986
1987static int av7110_fe_read_status(struct dvb_frontend* fe, fe_status_t* status)
1988{
1989 struct av7110* av7110 = fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001990
1991 /* call the real implementation */
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001992 int ret = av7110->fe_read_status(fe, status);
1993 if (!ret)
1994 if (((*status ^ av7110->fe_status) & FE_HAS_LOCK) && (*status & FE_HAS_LOCK))
1995 ret = av7110_fe_lock_fix(av7110, *status);
1996 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001997}
1998
1999static int av7110_fe_diseqc_reset_overload(struct dvb_frontend* fe)
2000{
2001 struct av7110* av7110 = fe->dvb->priv;
2002
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002003 int ret = av7110_fe_lock_fix(av7110, 0);
2004 if (!ret)
2005 ret = av7110->fe_diseqc_reset_overload(fe);
2006 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002007}
2008
2009static int av7110_fe_diseqc_send_master_cmd(struct dvb_frontend* fe,
2010 struct dvb_diseqc_master_cmd* cmd)
2011{
2012 struct av7110* av7110 = fe->dvb->priv;
2013
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002014 int ret = av7110_fe_lock_fix(av7110, 0);
Oliver Endriss66190a22006-01-09 15:32:42 -02002015 if (!ret) {
2016 av7110->saved_master_cmd = *cmd;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002017 ret = av7110->fe_diseqc_send_master_cmd(fe, cmd);
Oliver Endriss66190a22006-01-09 15:32:42 -02002018 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002019 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002020}
2021
2022static int av7110_fe_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd)
2023{
2024 struct av7110* av7110 = fe->dvb->priv;
2025
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002026 int ret = av7110_fe_lock_fix(av7110, 0);
Oliver Endriss66190a22006-01-09 15:32:42 -02002027 if (!ret) {
2028 av7110->saved_minicmd = minicmd;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002029 ret = av7110->fe_diseqc_send_burst(fe, minicmd);
Oliver Endriss66190a22006-01-09 15:32:42 -02002030 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002031 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002032}
2033
2034static int av7110_fe_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
2035{
2036 struct av7110* av7110 = fe->dvb->priv;
2037
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002038 int ret = av7110_fe_lock_fix(av7110, 0);
Oliver Endriss66190a22006-01-09 15:32:42 -02002039 if (!ret) {
2040 av7110->saved_tone = tone;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002041 ret = av7110->fe_set_tone(fe, tone);
Oliver Endriss66190a22006-01-09 15:32:42 -02002042 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002043 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002044}
2045
2046static int av7110_fe_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
2047{
2048 struct av7110* av7110 = fe->dvb->priv;
2049
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002050 int ret = av7110_fe_lock_fix(av7110, 0);
Oliver Endriss66190a22006-01-09 15:32:42 -02002051 if (!ret) {
2052 av7110->saved_voltage = voltage;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002053 ret = av7110->fe_set_voltage(fe, voltage);
Oliver Endriss66190a22006-01-09 15:32:42 -02002054 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002055 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002056}
2057
Peter Beutner400b7082006-01-09 15:32:43 -02002058static int av7110_fe_dishnetwork_send_legacy_command(struct dvb_frontend* fe, unsigned long cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002059{
2060 struct av7110* av7110 = fe->dvb->priv;
2061
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002062 int ret = av7110_fe_lock_fix(av7110, 0);
2063 if (!ret)
2064 ret = av7110->fe_dishnetwork_send_legacy_command(fe, cmd);
2065 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002066}
2067
Oliver Endriss66190a22006-01-09 15:32:42 -02002068static void dvb_s_recover(struct av7110* av7110)
2069{
2070 av7110_fe_init(av7110->fe);
2071
2072 av7110_fe_set_voltage(av7110->fe, av7110->saved_voltage);
2073 if (av7110->saved_master_cmd.msg_len) {
2074 msleep(20);
2075 av7110_fe_diseqc_send_master_cmd(av7110->fe, &av7110->saved_master_cmd);
2076 }
2077 msleep(20);
2078 av7110_fe_diseqc_send_burst(av7110->fe, av7110->saved_minicmd);
2079 msleep(20);
2080 av7110_fe_set_tone(av7110->fe, av7110->saved_tone);
2081
2082 av7110_fe_set_frontend(av7110->fe, &av7110->saved_fe_params);
2083}
2084
Linus Torvalds1da177e2005-04-16 15:20:36 -07002085static u8 read_pwm(struct av7110* av7110)
2086{
2087 u8 b = 0xff;
2088 u8 pwm;
2089 struct i2c_msg msg[] = { { .addr = 0x50,.flags = 0,.buf = &b,.len = 1 },
2090 { .addr = 0x50,.flags = I2C_M_RD,.buf = &pwm,.len = 1} };
2091
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -08002092 if ((i2c_transfer(&av7110->i2c_adap, msg, 2) != 2) || (pwm == 0xff))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002093 pwm = 0x48;
2094
2095 return pwm;
2096}
2097
2098static int frontend_init(struct av7110 *av7110)
2099{
2100 int ret;
2101
2102 if (av7110->dev->pci->subsystem_vendor == 0x110a) {
2103 switch(av7110->dev->pci->subsystem_device) {
2104 case 0x0000: // Fujitsu/Siemens DVB-Cable (ves1820/Philips CD1516(??))
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002105 av7110->fe = dvb_attach(ves1820_attach, &philips_cd1516_config,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002106 &av7110->i2c_adap, read_pwm(av7110));
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002107 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002108 av7110->fe->ops.tuner_ops.set_params = philips_cd1516_tuner_set_params;
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002109 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002110 break;
2111 }
2112
2113 } else if (av7110->dev->pci->subsystem_vendor == 0x13c2) {
2114 switch(av7110->dev->pci->subsystem_device) {
2115 case 0x0000: // Hauppauge/TT WinTV DVB-S rev1.X
2116 case 0x0003: // Hauppauge/TT WinTV Nexus-S Rev 2.X
2117 case 0x1002: // Hauppauge/TT WinTV DVB-S rev1.3SE
2118
2119 // try the ALPS BSRV2 first of all
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002120 av7110->fe = dvb_attach(ves1x93_attach, &alps_bsrv2_config, &av7110->i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002121 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002122 av7110->fe->ops.tuner_ops.set_params = alps_bsrv2_tuner_set_params;
2123 av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
2124 av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
2125 av7110->fe->ops.set_tone = av7110_set_tone;
Oliver Endriss66190a22006-01-09 15:32:42 -02002126 av7110->recover = dvb_s_recover;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002127 break;
2128 }
2129
2130 // try the ALPS BSRU6 now
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002131 av7110->fe = dvb_attach(stv0299_attach, &alps_bsru6_config, &av7110->i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002132 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002133 av7110->fe->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03002134 av7110->fe->tuner_priv = &av7110->i2c_adap;
2135
Patrick Boettcherdea74862006-05-14 05:01:31 -03002136 av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
2137 av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
2138 av7110->fe->ops.set_tone = av7110_set_tone;
Oliver Endriss66190a22006-01-09 15:32:42 -02002139 av7110->recover = dvb_s_recover;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002140 break;
2141 }
2142
2143 // Try the grundig 29504-451
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002144 av7110->fe = dvb_attach(tda8083_attach, &grundig_29504_451_config, &av7110->i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002145 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002146 av7110->fe->ops.tuner_ops.set_params = grundig_29504_451_tuner_set_params;
2147 av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
2148 av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
2149 av7110->fe->ops.set_tone = av7110_set_tone;
Oliver Endriss66190a22006-01-09 15:32:42 -02002150 av7110->recover = dvb_s_recover;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002151 break;
2152 }
2153
2154 /* Try DVB-C cards */
2155 switch(av7110->dev->pci->subsystem_device) {
2156 case 0x0000:
2157 /* Siemens DVB-C (full-length card) VES1820/Philips CD1516 */
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002158 av7110->fe = dvb_attach(ves1820_attach, &philips_cd1516_config, &av7110->i2c_adap,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002159 read_pwm(av7110));
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002160 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002161 av7110->fe->ops.tuner_ops.set_params = philips_cd1516_tuner_set_params;
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002162 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002163 break;
2164 case 0x0003:
Adrian Bunkf3688fc2006-03-29 22:46:12 -03002165 /* Hauppauge DVB-C 2.1 VES1820/ALPS TDBE2 */
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002166 av7110->fe = dvb_attach(ves1820_attach, &alps_tdbe2_config, &av7110->i2c_adap,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002167 read_pwm(av7110));
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002168 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002169 av7110->fe->ops.tuner_ops.set_params = alps_tdbe2_tuner_set_params;
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002170 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002171 break;
2172 }
2173 break;
2174
2175 case 0x0001: // Hauppauge/TT Nexus-T premium rev1.X
Oliver Endriss8d90ee52006-08-07 02:04:26 -03002176 // try ALPS TDLB7 first, then Grundig 29504-401
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002177 av7110->fe = dvb_attach(sp8870_attach, &alps_tdlb7_config, &av7110->i2c_adap);
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002178 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002179 av7110->fe->ops.tuner_ops.set_params = alps_tdlb7_tuner_set_params;
Oliver Endriss8d90ee52006-08-07 02:04:26 -03002180 break;
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002181 }
Oliver Endriss8d90ee52006-08-07 02:04:26 -03002182 /* fall-thru */
2183
2184 case 0x0008: // Hauppauge/TT DVB-T
2185 // Grundig 29504-401
2186 av7110->fe = dvb_attach(l64781_attach, &grundig_29504_401_config, &av7110->i2c_adap);
2187 if (av7110->fe)
2188 av7110->fe->ops.tuner_ops.set_params = grundig_29504_401_tuner_set_params;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002189 break;
2190
2191 case 0x0002: // Hauppauge/TT DVB-C premium rev2.X
2192
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002193 av7110->fe = dvb_attach(ves1820_attach, &alps_tdbe2_config, &av7110->i2c_adap, read_pwm(av7110));
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002194 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002195 av7110->fe->ops.tuner_ops.set_params = alps_tdbe2_tuner_set_params;
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002196 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002197 break;
2198
Oliver Endriss8bd63012006-02-07 06:49:11 -02002199 case 0x0004: // Galaxis DVB-S rev1.3
2200 /* ALPS BSRV2 */
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002201 av7110->fe = dvb_attach(ves1x93_attach, &alps_bsrv2_config, &av7110->i2c_adap);
Oliver Endriss8bd63012006-02-07 06:49:11 -02002202 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002203 av7110->fe->ops.tuner_ops.set_params = alps_bsrv2_tuner_set_params;
2204 av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
2205 av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
2206 av7110->fe->ops.set_tone = av7110_set_tone;
Oliver Endriss8bd63012006-02-07 06:49:11 -02002207 av7110->recover = dvb_s_recover;
2208 }
2209 break;
2210
Linus Torvalds1da177e2005-04-16 15:20:36 -07002211 case 0x0006: /* Fujitsu-Siemens DVB-S rev 1.6 */
2212 /* Grundig 29504-451 */
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002213 av7110->fe = dvb_attach(tda8083_attach, &grundig_29504_451_config, &av7110->i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002214 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002215 av7110->fe->ops.tuner_ops.set_params = grundig_29504_451_tuner_set_params;
2216 av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
2217 av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
2218 av7110->fe->ops.set_tone = av7110_set_tone;
Oliver Endriss66190a22006-01-09 15:32:42 -02002219 av7110->recover = dvb_s_recover;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002220 }
2221 break;
2222
Linus Torvalds1da177e2005-04-16 15:20:36 -07002223 case 0x000A: // Hauppauge/TT Nexus-CA rev1.X
2224
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002225 av7110->fe = dvb_attach(stv0297_attach, &nexusca_stv0297_config, &av7110->i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002226 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002227 av7110->fe->ops.tuner_ops.set_params = nexusca_stv0297_tuner_set_params;
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03002228
Linus Torvalds1da177e2005-04-16 15:20:36 -07002229 /* set TDA9819 into DVB mode */
Marco Schluessler6a857742006-07-10 03:34:16 -03002230 saa7146_setgpio(av7110->dev, 1, SAA7146_GPIO_OUTLO); // TDA9819 pin9(STD)
2231 saa7146_setgpio(av7110->dev, 3, SAA7146_GPIO_OUTLO); // TDA9819 pin30(VIF)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002232
2233 /* tuner on this needs a slower i2c bus speed */
2234 av7110->dev->i2c_bitrate = SAA7146_I2C_BUS_BIT_RATE_240;
2235 break;
2236 }
Johannes Stezenbach3dfaebd2005-05-16 21:54:19 -07002237 break;
2238
2239 case 0x000E: /* Hauppauge/TT Nexus-S rev 2.3 */
2240 /* ALPS BSBE1 */
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002241 av7110->fe = dvb_attach(stv0299_attach, &alps_bsbe1_config, &av7110->i2c_adap);
Oliver Endrisseb3daf32006-01-09 15:25:05 -02002242 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002243 av7110->fe->ops.tuner_ops.set_params = alps_bsbe1_tuner_set_params;
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03002244 av7110->fe->tuner_priv = &av7110->i2c_adap;
2245
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002246 if (dvb_attach(lnbp21_attach, av7110->fe, &av7110->i2c_adap, 0, 0) == NULL) {
Oliver Endrissdb5d91e2006-02-28 10:32:25 -03002247 printk("dvb-ttpci: LNBP21 not found!\n");
Patrick Boettcherdea74862006-05-14 05:01:31 -03002248 if (av7110->fe->ops.release)
2249 av7110->fe->ops.release(av7110->fe);
Oliver Endrissdb5d91e2006-02-28 10:32:25 -03002250 av7110->fe = NULL;
2251 } else {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002252 av7110->fe->ops.dishnetwork_send_legacy_command = NULL;
Oliver Endrissdb5d91e2006-02-28 10:32:25 -03002253 av7110->recover = dvb_s_recover;
2254 }
Oliver Endrisseb3daf32006-01-09 15:25:05 -02002255 }
Johannes Stezenbach3dfaebd2005-05-16 21:54:19 -07002256 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002257 }
2258 }
2259
2260 if (!av7110->fe) {
2261 /* FIXME: propagate the failure code from the lower layers */
2262 ret = -ENOMEM;
Bjorn Helgaas29e66a62008-09-04 17:24:51 -03002263 printk("dvb-ttpci: A frontend driver was not found for device [%04x:%04x] subsystem [%04x:%04x]\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002264 av7110->dev->pci->vendor,
2265 av7110->dev->pci->device,
2266 av7110->dev->pci->subsystem_vendor,
2267 av7110->dev->pci->subsystem_device);
2268 } else {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002269 FE_FUNC_OVERRIDE(av7110->fe->ops.init, av7110->fe_init, av7110_fe_init);
2270 FE_FUNC_OVERRIDE(av7110->fe->ops.read_status, av7110->fe_read_status, av7110_fe_read_status);
2271 FE_FUNC_OVERRIDE(av7110->fe->ops.diseqc_reset_overload, av7110->fe_diseqc_reset_overload, av7110_fe_diseqc_reset_overload);
2272 FE_FUNC_OVERRIDE(av7110->fe->ops.diseqc_send_master_cmd, av7110->fe_diseqc_send_master_cmd, av7110_fe_diseqc_send_master_cmd);
2273 FE_FUNC_OVERRIDE(av7110->fe->ops.diseqc_send_burst, av7110->fe_diseqc_send_burst, av7110_fe_diseqc_send_burst);
2274 FE_FUNC_OVERRIDE(av7110->fe->ops.set_tone, av7110->fe_set_tone, av7110_fe_set_tone);
Yoann Padioleau8f40a9f2007-07-16 16:54:49 -03002275 FE_FUNC_OVERRIDE(av7110->fe->ops.set_voltage, av7110->fe_set_voltage, av7110_fe_set_voltage);
Patrick Boettcherdea74862006-05-14 05:01:31 -03002276 FE_FUNC_OVERRIDE(av7110->fe->ops.dishnetwork_send_legacy_command, av7110->fe_dishnetwork_send_legacy_command, av7110_fe_dishnetwork_send_legacy_command);
2277 FE_FUNC_OVERRIDE(av7110->fe->ops.set_frontend, av7110->fe_set_frontend, av7110_fe_set_frontend);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002278
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07002279 ret = dvb_register_frontend(&av7110->dvb_adapter, av7110->fe);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002280 if (ret < 0) {
2281 printk("av7110: Frontend registration failed!\n");
Andrew de Quinceyf52a8382006-08-08 09:10:09 -03002282 dvb_frontend_detach(av7110->fe);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002283 av7110->fe = NULL;
2284 }
2285 }
2286 return ret;
2287}
2288
2289/* Budgetpatch note:
2290 * Original hardware design by Roberto Deza:
2291 * There is a DVB_Wiki at
2292 * http://212.227.36.83/linuxtv/wiki/index.php/Main_Page
2293 * where is described this 'DVB TT Budget Patch', on Card Modding:
2294 * http://212.227.36.83/linuxtv/wiki/index.php/DVB_TT_Budget_Patch
2295 * On the short description there is also a link to a external file,
2296 * with more details:
2297 * http://perso.wanadoo.es/jesussolano/Ttf_tsc1.zip
2298 *
2299 * New software triggering design by Emard that works on
2300 * original Roberto Deza's hardware:
2301 *
2302 * rps1 code for budgetpatch will copy internal HS event to GPIO3 pin.
2303 * GPIO3 is in budget-patch hardware connectd to port B VSYNC
2304 * HS is an internal event of 7146, accessible with RPS
2305 * and temporarily raised high every n lines
2306 * (n in defined in the RPS_THRESH1 counter threshold)
2307 * I think HS is raised high on the beginning of the n-th line
2308 * and remains high until this n-th line that triggered
2309 * it is completely received. When the receiption of n-th line
2310 * ends, HS is lowered.
2311 *
2312 * To transmit data over DMA, 7146 needs changing state at
2313 * port B VSYNC pin. Any changing of port B VSYNC will
2314 * cause some DMA data transfer, with more or less packets loss.
2315 * It depends on the phase and frequency of VSYNC and
2316 * the way of 7146 is instructed to trigger on port B (defined
2317 * in DD1_INIT register, 3rd nibble from the right valid
2318 * numbers are 0-7, see datasheet)
2319 *
2320 * The correct triggering can minimize packet loss,
2321 * dvbtraffic should give this stable bandwidths:
2322 * 22k transponder = 33814 kbit/s
2323 * 27.5k transponder = 38045 kbit/s
2324 * by experiment it is found that the best results
2325 * (stable bandwidths and almost no packet loss)
2326 * are obtained using DD1_INIT triggering number 2
2327 * (Va at rising edge of VS Fa = HS x VS-failing forced toggle)
2328 * and a VSYNC phase that occurs in the middle of DMA transfer
2329 * (about byte 188*512=96256 in the DMA window).
2330 *
2331 * Phase of HS is still not clear to me how to control,
2332 * It just happens to be so. It can be seen if one enables
2333 * RPS_IRQ and print Event Counter 1 in vpeirq(). Every
2334 * time RPS_INTERRUPT is called, the Event Counter 1 will
2335 * increment. That's how the 7146 is programmed to do event
2336 * counting in this budget-patch.c
2337 * I *think* HPS setting has something to do with the phase
2338 * of HS but I cant be 100% sure in that.
2339 *
2340 * hardware debug note: a working budget card (including budget patch)
2341 * with vpeirq() interrupt setup in mode "0x90" (every 64K) will
2342 * generate 3 interrupts per 25-Hz DMA frame of 2*188*512 bytes
2343 * and that means 3*25=75 Hz of interrupt freqency, as seen by
2344 * watch cat /proc/interrupts
2345 *
2346 * If this frequency is 3x lower (and data received in the DMA
2347 * buffer don't start with 0x47, but in the middle of packets,
2348 * whose lengths appear to be like 188 292 188 104 etc.
2349 * this means VSYNC line is not connected in the hardware.
2350 * (check soldering pcb and pins)
2351 * The same behaviour of missing VSYNC can be duplicated on budget
2352 * cards, by seting DD1_INIT trigger mode 7 in 3rd nibble.
2353 */
Johannes Stezenbach1be11e32006-02-27 00:09:20 -03002354static int __devinit av7110_attach(struct saa7146_dev* dev,
2355 struct saa7146_pci_extension_data *pci_ext)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002356{
2357 const int length = TS_WIDTH * TS_HEIGHT;
2358 struct pci_dev *pdev = dev->pci;
2359 struct av7110 *av7110;
Herbert Poetzl8eec1422007-02-08 14:32:43 -03002360 struct task_struct *thread;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002361 int ret, count = 0;
2362
2363 dprintk(4, "dev: %p\n", dev);
2364
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -08002365 /* Set RPS_IRQ to 1 to track rps1 activity.
2366 * Enabling this won't send any interrupt to PC CPU.
2367 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002368#define RPS_IRQ 0
2369
2370 if (budgetpatch == 1) {
2371 budgetpatch = 0;
2372 /* autodetect the presence of budget patch
2373 * this only works if saa7146 has been recently
2374 * reset with with MASK_31 to MC1
2375 *
2376 * will wait for VBI_B event (vertical blank at port B)
2377 * and will reset GPIO3 after VBI_B is detected.
2378 * (GPIO3 should be raised high by CPU to
2379 * test if GPIO3 will generate vertical blank signal
2380 * in budget patch GPIO3 is connected to VSYNC_B
2381 */
2382
2383 /* RESET SAA7146 */
2384 saa7146_write(dev, MC1, MASK_31);
2385 /* autodetection success seems to be time-dependend after reset */
2386
2387 /* Fix VSYNC level */
2388 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
2389 /* set vsync_b triggering */
2390 saa7146_write(dev, DD1_STREAM_B, 0);
2391 /* port B VSYNC at rising edge */
2392 saa7146_write(dev, DD1_INIT, 0x00000200);
2393 saa7146_write(dev, BRS_CTRL, 0x00000000); // VBI
2394 saa7146_write(dev, MC2,
2395 1 * (MASK_08 | MASK_24) | // BRS control
2396 0 * (MASK_09 | MASK_25) | // a
2397 1 * (MASK_10 | MASK_26) | // b
2398 0 * (MASK_06 | MASK_22) | // HPS_CTRL1
2399 0 * (MASK_05 | MASK_21) | // HPS_CTRL2
2400 0 * (MASK_01 | MASK_15) // DEBI
2401 );
2402
2403 /* start writing RPS1 code from beginning */
2404 count = 0;
2405 /* Disable RPS1 */
2406 saa7146_write(dev, MC1, MASK_29);
2407 /* RPS1 timeout disable */
2408 saa7146_write(dev, RPS_TOV1, 0);
Al Viro153755a2008-06-22 14:19:39 -03002409 WRITE_RPS1(CMD_PAUSE | EVT_VBI_B);
2410 WRITE_RPS1(CMD_WR_REG_MASK | (GPIO_CTRL>>2));
2411 WRITE_RPS1(GPIO3_MSK);
2412 WRITE_RPS1(SAA7146_GPIO_OUTLO<<24);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002413#if RPS_IRQ
2414 /* issue RPS1 interrupt to increment counter */
Al Viro153755a2008-06-22 14:19:39 -03002415 WRITE_RPS1(CMD_INTERRUPT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002416#endif
Al Viro153755a2008-06-22 14:19:39 -03002417 WRITE_RPS1(CMD_STOP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002418 /* Jump to begin of RPS program as safety measure (p37) */
Al Viro153755a2008-06-22 14:19:39 -03002419 WRITE_RPS1(CMD_JUMP);
2420 WRITE_RPS1(dev->d_rps1.dma_handle);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002421
2422#if RPS_IRQ
2423 /* set event counter 1 source as RPS1 interrupt (0x03) (rE4 p53)
2424 * use 0x03 to track RPS1 interrupts - increase by 1 every gpio3 is toggled
2425 * use 0x15 to track VPE interrupts - increase by 1 every vpeirq() is called
2426 */
2427 saa7146_write(dev, EC1SSR, (0x03<<2) | 3 );
2428 /* set event counter 1 treshold to maximum allowed value (rEC p55) */
2429 saa7146_write(dev, ECT1R, 0x3fff );
2430#endif
2431 /* Set RPS1 Address register to point to RPS code (r108 p42) */
2432 saa7146_write(dev, RPS_ADDR1, dev->d_rps1.dma_handle);
2433 /* Enable RPS1, (rFC p33) */
2434 saa7146_write(dev, MC1, (MASK_13 | MASK_29 ));
2435
2436 mdelay(10);
2437 /* now send VSYNC_B to rps1 by rising GPIO3 */
2438 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI);
2439 mdelay(10);
2440 /* if rps1 responded by lowering the GPIO3,
2441 * then we have budgetpatch hardware
2442 */
2443 if ((saa7146_read(dev, GPIO_CTRL) & 0x10000000) == 0) {
2444 budgetpatch = 1;
2445 printk("dvb-ttpci: BUDGET-PATCH DETECTED.\n");
2446 }
2447 /* Disable RPS1 */
2448 saa7146_write(dev, MC1, ( MASK_29 ));
2449#if RPS_IRQ
2450 printk("dvb-ttpci: Event Counter 1 0x%04x\n", saa7146_read(dev, EC1R) & 0x3fff );
2451#endif
2452 }
2453
2454 /* prepare the av7110 device struct */
Panagiotis Issaris74081872006-01-11 19:40:56 -02002455 av7110 = kzalloc(sizeof(struct av7110), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002456 if (!av7110) {
2457 dprintk(1, "out of memory\n");
2458 return -ENOMEM;
2459 }
2460
Linus Torvalds1da177e2005-04-16 15:20:36 -07002461 av7110->card_name = (char*) pci_ext->ext_priv;
2462 av7110->dev = dev;
2463 dev->ext_priv = av7110;
2464
2465 ret = get_firmware(av7110);
2466 if (ret < 0)
2467 goto err_kfree_0;
2468
2469 ret = dvb_register_adapter(&av7110->dvb_adapter, av7110->card_name,
Janne Grunau78e92002008-04-09 19:13:13 -03002470 THIS_MODULE, &dev->pci->dev, adapter_nr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002471 if (ret < 0)
2472 goto err_put_firmware_1;
2473
2474 /* the Siemens DVB needs this if you want to have the i2c chips
2475 get recognized before the main driver is fully loaded */
2476 saa7146_write(dev, GPIO_CTRL, 0x500000);
2477
Linus Torvalds1da177e2005-04-16 15:20:36 -07002478 av7110->i2c_adap.class = I2C_CLASS_TV_DIGITAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002479 strlcpy(av7110->i2c_adap.name, pci_ext->ext_priv, sizeof(av7110->i2c_adap.name));
2480
2481 saa7146_i2c_adapter_prepare(dev, &av7110->i2c_adap, SAA7146_I2C_BUS_BIT_RATE_120); /* 275 kHz */
2482
2483 ret = i2c_add_adapter(&av7110->i2c_adap);
2484 if (ret < 0)
2485 goto err_dvb_unregister_adapter_2;
2486
2487 ttpci_eeprom_parse_mac(&av7110->i2c_adap,
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07002488 av7110->dvb_adapter.proposed_mac);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002489 ret = -ENOMEM;
2490
Oliver Endriss9e615ea2008-09-03 19:15:27 -03002491 /* full-ts mod? */
2492 if (full_ts)
2493 av7110->full_ts = true;
2494
2495 /* check for full-ts flag in eeprom */
2496 if (i2c_readreg(av7110, 0xaa, 0) == 0x4f && i2c_readreg(av7110, 0xaa, 1) == 0x45) {
2497 u8 flags = i2c_readreg(av7110, 0xaa, 2);
2498 if (flags != 0xff && (flags & 0x01))
2499 av7110->full_ts = true;
2500 }
2501
2502 if (av7110->full_ts) {
2503 printk(KERN_INFO "dvb-ttpci: full-ts mode enabled for saa7146 port B\n");
2504 spin_lock_init(&av7110->feedlock1);
2505 av7110->grabbing = saa7146_vmalloc_build_pgtable(pdev, length,
2506 &av7110->pt);
2507 if (!av7110->grabbing)
2508 goto err_i2c_del_3;
2509
2510 saa7146_write(dev, DD1_STREAM_B, 0x00000000);
2511 saa7146_write(dev, MC2, (MASK_10 | MASK_26));
2512
2513 saa7146_write(dev, DD1_INIT, 0x00000600);
2514 saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
2515
2516 saa7146_write(dev, BRS_CTRL, 0x60000000);
2517 saa7146_write(dev, MC2, MASK_08 | MASK_24);
2518
2519 /* dma3 */
2520 saa7146_write(dev, PCI_BT_V1, 0x001c0000 | (saa7146_read(dev, PCI_BT_V1) & ~0x001f0000));
2521 saa7146_write(dev, BASE_ODD3, 0);
2522 saa7146_write(dev, BASE_EVEN3, 0);
2523 saa7146_write(dev, PROT_ADDR3, TS_WIDTH * TS_HEIGHT);
2524 saa7146_write(dev, PITCH3, TS_WIDTH);
2525 saa7146_write(dev, BASE_PAGE3, av7110->pt.dma | ME1 | 0x90);
2526 saa7146_write(dev, NUM_LINE_BYTE3, (TS_HEIGHT << 16) | TS_WIDTH);
2527 saa7146_write(dev, MC2, MASK_04 | MASK_20);
2528
2529 tasklet_init(&av7110->vpe_tasklet, vpeirq, (unsigned long) av7110);
2530
2531 } else if (budgetpatch) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002532 spin_lock_init(&av7110->feedlock1);
2533 av7110->grabbing = saa7146_vmalloc_build_pgtable(pdev, length,
2534 &av7110->pt);
2535 if (!av7110->grabbing)
2536 goto err_i2c_del_3;
2537
2538 saa7146_write(dev, PCI_BT_V1, 0x1c1f101f);
2539 saa7146_write(dev, BCS_CTRL, 0x80400040);
2540 /* set dd1 stream a & b */
2541 saa7146_write(dev, DD1_STREAM_B, 0x00000000);
2542 saa7146_write(dev, DD1_INIT, 0x03000200);
2543 saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
2544 saa7146_write(dev, BRS_CTRL, 0x60000000);
2545 saa7146_write(dev, BASE_ODD3, 0);
2546 saa7146_write(dev, BASE_EVEN3, 0);
2547 saa7146_write(dev, PROT_ADDR3, TS_WIDTH * TS_HEIGHT);
2548 saa7146_write(dev, BASE_PAGE3, av7110->pt.dma | ME1 | 0x90);
2549
2550 saa7146_write(dev, PITCH3, TS_WIDTH);
2551 saa7146_write(dev, NUM_LINE_BYTE3, (TS_HEIGHT << 16) | TS_WIDTH);
2552
2553 /* upload all */
2554 saa7146_write(dev, MC2, 0x077c077c);
2555 saa7146_write(dev, GPIO_CTRL, 0x000000);
2556#if RPS_IRQ
2557 /* set event counter 1 source as RPS1 interrupt (0x03) (rE4 p53)
2558 * use 0x03 to track RPS1 interrupts - increase by 1 every gpio3 is toggled
2559 * use 0x15 to track VPE interrupts - increase by 1 every vpeirq() is called
2560 */
2561 saa7146_write(dev, EC1SSR, (0x03<<2) | 3 );
2562 /* set event counter 1 treshold to maximum allowed value (rEC p55) */
2563 saa7146_write(dev, ECT1R, 0x3fff );
2564#endif
2565 /* Setup BUDGETPATCH MAIN RPS1 "program" (p35) */
2566 count = 0;
2567
2568 /* Wait Source Line Counter Threshold (p36) */
Al Viro153755a2008-06-22 14:19:39 -03002569 WRITE_RPS1(CMD_PAUSE | EVT_HS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002570 /* Set GPIO3=1 (p42) */
Al Viro153755a2008-06-22 14:19:39 -03002571 WRITE_RPS1(CMD_WR_REG_MASK | (GPIO_CTRL>>2));
2572 WRITE_RPS1(GPIO3_MSK);
2573 WRITE_RPS1(SAA7146_GPIO_OUTHI<<24);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002574#if RPS_IRQ
2575 /* issue RPS1 interrupt */
Al Viro153755a2008-06-22 14:19:39 -03002576 WRITE_RPS1(CMD_INTERRUPT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002577#endif
2578 /* Wait reset Source Line Counter Threshold (p36) */
Al Viro153755a2008-06-22 14:19:39 -03002579 WRITE_RPS1(CMD_PAUSE | RPS_INV | EVT_HS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002580 /* Set GPIO3=0 (p42) */
Al Viro153755a2008-06-22 14:19:39 -03002581 WRITE_RPS1(CMD_WR_REG_MASK | (GPIO_CTRL>>2));
2582 WRITE_RPS1(GPIO3_MSK);
2583 WRITE_RPS1(SAA7146_GPIO_OUTLO<<24);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002584#if RPS_IRQ
2585 /* issue RPS1 interrupt */
Al Viro153755a2008-06-22 14:19:39 -03002586 WRITE_RPS1(CMD_INTERRUPT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002587#endif
2588 /* Jump to begin of RPS program (p37) */
Al Viro153755a2008-06-22 14:19:39 -03002589 WRITE_RPS1(CMD_JUMP);
2590 WRITE_RPS1(dev->d_rps1.dma_handle);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002591
2592 /* Fix VSYNC level */
2593 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
2594 /* Set RPS1 Address register to point to RPS code (r108 p42) */
2595 saa7146_write(dev, RPS_ADDR1, dev->d_rps1.dma_handle);
2596 /* Set Source Line Counter Threshold, using BRS (rCC p43)
2597 * It generates HS event every TS_HEIGHT lines
2598 * this is related to TS_WIDTH set in register
2599 * NUM_LINE_BYTE3. If NUM_LINE_BYTE low 16 bits
2600 * are set to TS_WIDTH bytes (TS_WIDTH=2*188),
2601 * then RPS_THRESH1 should be set to trigger
2602 * every TS_HEIGHT (512) lines.
2603 */
2604 saa7146_write(dev, RPS_THRESH1, (TS_HEIGHT*1) | MASK_12 );
2605
2606 /* Enable RPS1 (rFC p33) */
2607 saa7146_write(dev, MC1, (MASK_13 | MASK_29));
2608
2609 /* end of budgetpatch register initialization */
2610 tasklet_init (&av7110->vpe_tasklet, vpeirq, (unsigned long) av7110);
2611 } else {
2612 saa7146_write(dev, PCI_BT_V1, 0x1c00101f);
2613 saa7146_write(dev, BCS_CTRL, 0x80400040);
2614
2615 /* set dd1 stream a & b */
2616 saa7146_write(dev, DD1_STREAM_B, 0x00000000);
2617 saa7146_write(dev, DD1_INIT, 0x03000000);
2618 saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
2619
2620 /* upload all */
2621 saa7146_write(dev, MC2, 0x077c077c);
2622 saa7146_write(dev, GPIO_CTRL, 0x000000);
2623 }
2624
2625 tasklet_init (&av7110->debi_tasklet, debiirq, (unsigned long) av7110);
2626 tasklet_init (&av7110->gpio_tasklet, gpioirq, (unsigned long) av7110);
2627
Ingo Molnar3593cab2006-02-07 06:49:14 -02002628 mutex_init(&av7110->pid_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002629
2630 /* locks for data transfers from/to AV7110 */
2631 spin_lock_init(&av7110->debilock);
Ingo Molnar3593cab2006-02-07 06:49:14 -02002632 mutex_init(&av7110->dcomlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002633 av7110->debitype = -1;
2634
2635 /* default OSD window */
2636 av7110->osdwin = 1;
Ingo Molnar3593cab2006-02-07 06:49:14 -02002637 mutex_init(&av7110->osd_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002638
C.Y.M2f03ee82006-03-30 04:31:48 -03002639 /* TV standard */
Marco Schluessler58a44042007-10-31 01:20:42 -03002640 av7110->vidmode = tv_standard == 1 ? AV7110_VIDEO_MODE_NTSC
2641 : AV7110_VIDEO_MODE_PAL;
C.Y.M2f03ee82006-03-30 04:31:48 -03002642
Linus Torvalds1da177e2005-04-16 15:20:36 -07002643 /* ARM "watchdog" */
2644 init_waitqueue_head(&av7110->arm_wait);
2645 av7110->arm_thread = NULL;
2646
2647 /* allocate and init buffers */
2648 av7110->debi_virt = pci_alloc_consistent(pdev, 8192, &av7110->debi_bus);
2649 if (!av7110->debi_virt)
2650 goto err_saa71466_vfree_4;
2651
2652
2653 av7110->iobuf = vmalloc(AVOUTLEN+AOUTLEN+BMPLEN+4*IPACKS);
2654 if (!av7110->iobuf)
2655 goto err_pci_free_5;
2656
2657 ret = av7110_av_init(av7110);
2658 if (ret < 0)
2659 goto err_iobuf_vfree_6;
2660
2661 /* init BMP buffer */
2662 av7110->bmpbuf = av7110->iobuf+AVOUTLEN+AOUTLEN;
2663 init_waitqueue_head(&av7110->bmpq);
2664
2665 ret = av7110_ca_init(av7110);
2666 if (ret < 0)
2667 goto err_av7110_av_exit_7;
2668
2669 /* load firmware into AV7110 cards */
2670 ret = av7110_bootarm(av7110);
2671 if (ret < 0)
2672 goto err_av7110_ca_exit_8;
2673
2674 ret = av7110_firmversion(av7110);
2675 if (ret < 0)
2676 goto err_stop_arm_9;
2677
2678 if (FW_VERSION(av7110->arm_app)<0x2501)
2679 printk ("dvb-ttpci: Warning, firmware version 0x%04x is too old. "
2680 "System might be unstable!\n", FW_VERSION(av7110->arm_app));
2681
Herbert Poetzl8eec1422007-02-08 14:32:43 -03002682 thread = kthread_run(arm_thread, (void *) av7110, "arm_mon");
2683 if (IS_ERR(thread)) {
2684 ret = PTR_ERR(thread);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002685 goto err_stop_arm_9;
Herbert Poetzl8eec1422007-02-08 14:32:43 -03002686 }
2687 av7110->arm_thread = thread;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002688
2689 /* set initial volume in mixer struct */
2690 av7110->mixer.volume_left = volume;
2691 av7110->mixer.volume_right = volume;
2692
Linus Torvalds1da177e2005-04-16 15:20:36 -07002693 ret = av7110_register(av7110);
2694 if (ret < 0)
2695 goto err_arm_thread_stop_10;
2696
Oliver Endrissdefd574e2007-07-12 23:08:07 -03002697 init_av7110_av(av7110);
2698
Linus Torvalds1da177e2005-04-16 15:20:36 -07002699 /* special case DVB-C: these cards have an analog tuner
2700 plus need some special handling, so we have separate
2701 saa7146_ext_vv data for these... */
2702 ret = av7110_init_v4l(av7110);
2703 if (ret < 0)
2704 goto err_av7110_unregister_11;
2705
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07002706 av7110->dvb_adapter.priv = av7110;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002707 ret = frontend_init(av7110);
2708 if (ret < 0)
2709 goto err_av7110_exit_v4l_12;
2710
2711#if defined(CONFIG_INPUT_EVDEV) || defined(CONFIG_INPUT_EVDEV_MODULE)
Oliver Endriss03388ae2005-09-09 13:03:12 -07002712 av7110_ir_init(av7110);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002713#endif
2714 printk(KERN_INFO "dvb-ttpci: found av7110-%d.\n", av7110_num);
2715 av7110_num++;
2716out:
2717 return ret;
2718
2719err_av7110_exit_v4l_12:
2720 av7110_exit_v4l(av7110);
2721err_av7110_unregister_11:
2722 dvb_unregister(av7110);
2723err_arm_thread_stop_10:
2724 av7110_arm_sync(av7110);
2725err_stop_arm_9:
2726 /* Nothing to do. Rejoice. */
2727err_av7110_ca_exit_8:
2728 av7110_ca_exit(av7110);
2729err_av7110_av_exit_7:
2730 av7110_av_exit(av7110);
2731err_iobuf_vfree_6:
2732 vfree(av7110->iobuf);
2733err_pci_free_5:
2734 pci_free_consistent(pdev, 8192, av7110->debi_virt, av7110->debi_bus);
2735err_saa71466_vfree_4:
Jon Burgess87c30192007-05-03 12:23:44 -03002736 if (av7110->grabbing)
2737 saa7146_vfree_destroy_pgtable(pdev, av7110->grabbing, &av7110->pt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002738err_i2c_del_3:
2739 i2c_del_adapter(&av7110->i2c_adap);
2740err_dvb_unregister_adapter_2:
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07002741 dvb_unregister_adapter(&av7110->dvb_adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002742err_put_firmware_1:
2743 put_firmware(av7110);
2744err_kfree_0:
2745 kfree(av7110);
2746 goto out;
2747}
2748
Johannes Stezenbach1be11e32006-02-27 00:09:20 -03002749static int __devexit av7110_detach(struct saa7146_dev* saa)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002750{
2751 struct av7110 *av7110 = saa->ext_priv;
2752 dprintk(4, "%p\n", av7110);
2753
Oliver Endriss03388ae2005-09-09 13:03:12 -07002754#if defined(CONFIG_INPUT_EVDEV) || defined(CONFIG_INPUT_EVDEV_MODULE)
2755 av7110_ir_exit(av7110);
2756#endif
Oliver Endriss9e615ea2008-09-03 19:15:27 -03002757 if (budgetpatch || av7110->full_ts) {
2758 if (budgetpatch) {
2759 /* Disable RPS1 */
2760 saa7146_write(saa, MC1, MASK_29);
2761 /* VSYNC LOW (inactive) */
2762 saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);
2763 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002764 saa7146_write(saa, MC1, MASK_20); /* DMA3 off */
2765 SAA7146_IER_DISABLE(saa, MASK_10);
2766 SAA7146_ISR_CLEAR(saa, MASK_10);
2767 msleep(50);
2768 tasklet_kill(&av7110->vpe_tasklet);
Jon Burgess87c30192007-05-03 12:23:44 -03002769 saa7146_vfree_destroy_pgtable(saa->pci, av7110->grabbing, &av7110->pt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002770 }
2771 av7110_exit_v4l(av7110);
2772
2773 av7110_arm_sync(av7110);
2774
2775 tasklet_kill(&av7110->debi_tasklet);
2776 tasklet_kill(&av7110->gpio_tasklet);
2777
2778 dvb_unregister(av7110);
2779
2780 SAA7146_IER_DISABLE(saa, MASK_19 | MASK_03);
2781 SAA7146_ISR_CLEAR(saa, MASK_19 | MASK_03);
2782
2783 av7110_ca_exit(av7110);
2784 av7110_av_exit(av7110);
2785
2786 vfree(av7110->iobuf);
2787 pci_free_consistent(saa->pci, 8192, av7110->debi_virt,
2788 av7110->debi_bus);
2789
2790 i2c_del_adapter(&av7110->i2c_adap);
2791
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07002792 dvb_unregister_adapter (&av7110->dvb_adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002793
2794 av7110_num--;
2795
2796 put_firmware(av7110);
2797
2798 kfree(av7110);
2799
2800 saa->ext_priv = NULL;
2801
2802 return 0;
2803}
2804
2805
2806static void av7110_irq(struct saa7146_dev* dev, u32 *isr)
2807{
2808 struct av7110 *av7110 = dev->ext_priv;
2809
2810 //print_time("av7110_irq");
2811
2812 /* Note: Don't try to handle the DEBI error irq (MASK_18), in
2813 * intel mode the timeout is asserted all the time...
2814 */
2815
2816 if (*isr & MASK_19) {
2817 //printk("av7110_irq: DEBI\n");
2818 /* Note 1: The DEBI irq is level triggered: We must enable it
2819 * only after we started a DMA xfer, and disable it here
2820 * immediately, or it will be signalled all the time while
2821 * DEBI is idle.
2822 * Note 2: You would think that an irq which is masked is
2823 * not signalled by the hardware. Not so for the SAA7146:
2824 * An irq is signalled as long as the corresponding bit
2825 * in the ISR is set, and disabling irqs just prevents the
2826 * hardware from setting the ISR bit. This means a) that we
2827 * must clear the ISR *after* disabling the irq (which is why
2828 * we must do it here even though saa7146_core did it already),
2829 * and b) that if we were to disable an edge triggered irq
2830 * (like the gpio irqs sadly are) temporarily we would likely
2831 * loose some. This sucks :-(
2832 */
2833 SAA7146_IER_DISABLE(av7110->dev, MASK_19);
2834 SAA7146_ISR_CLEAR(av7110->dev, MASK_19);
2835 tasklet_schedule(&av7110->debi_tasklet);
2836 }
2837
2838 if (*isr & MASK_03) {
2839 //printk("av7110_irq: GPIO\n");
2840 tasklet_schedule(&av7110->gpio_tasklet);
2841 }
2842
Oliver Endriss9e615ea2008-09-03 19:15:27 -03002843 if (*isr & MASK_10)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002844 tasklet_schedule(&av7110->vpe_tasklet);
2845}
2846
2847
Randy Dunlapda517162008-01-10 19:31:47 -03002848static struct saa7146_extension av7110_extension_driver;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002849
2850#define MAKE_AV7110_INFO(x_var,x_name) \
2851static struct saa7146_pci_extension_data x_var = { \
2852 .ext_priv = x_name, \
Randy Dunlapda517162008-01-10 19:31:47 -03002853 .ext = &av7110_extension_driver }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002854
Karl Herz6af4ee12005-09-09 13:03:13 -07002855MAKE_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 -07002856MAKE_AV7110_INFO(ttt_1_X, "Technotrend/Hauppauge WinTV DVB-T rev1.X");
2857MAKE_AV7110_INFO(ttc_1_X, "Technotrend/Hauppauge WinTV Nexus-CA rev1.X");
2858MAKE_AV7110_INFO(ttc_2_X, "Technotrend/Hauppauge WinTV DVB-C rev2.X");
2859MAKE_AV7110_INFO(tts_2_X, "Technotrend/Hauppauge WinTV Nexus-S rev2.X");
Johannes Stezenbach3dfaebd2005-05-16 21:54:19 -07002860MAKE_AV7110_INFO(tts_2_3, "Technotrend/Hauppauge WinTV Nexus-S rev2.3");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002861MAKE_AV7110_INFO(tts_1_3se, "Technotrend/Hauppauge WinTV DVB-S rev1.3 SE");
2862MAKE_AV7110_INFO(ttt, "Technotrend/Hauppauge DVB-T");
2863MAKE_AV7110_INFO(fsc, "Fujitsu Siemens DVB-C");
2864MAKE_AV7110_INFO(fss, "Fujitsu Siemens DVB-S rev1.6");
Oliver Endriss8bd63012006-02-07 06:49:11 -02002865MAKE_AV7110_INFO(gxs_1_3, "Galaxis DVB-S rev1.3");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002866
2867static struct pci_device_id pci_tbl[] = {
Karl Herz6af4ee12005-09-09 13:03:13 -07002868 MAKE_EXTENSION_PCI(fsc, 0x110a, 0x0000),
2869 MAKE_EXTENSION_PCI(tts_1_X_fsc, 0x13c2, 0x0000),
2870 MAKE_EXTENSION_PCI(ttt_1_X, 0x13c2, 0x0001),
2871 MAKE_EXTENSION_PCI(ttc_2_X, 0x13c2, 0x0002),
2872 MAKE_EXTENSION_PCI(tts_2_X, 0x13c2, 0x0003),
Oliver Endriss8bd63012006-02-07 06:49:11 -02002873 MAKE_EXTENSION_PCI(gxs_1_3, 0x13c2, 0x0004),
Karl Herz6af4ee12005-09-09 13:03:13 -07002874 MAKE_EXTENSION_PCI(fss, 0x13c2, 0x0006),
2875 MAKE_EXTENSION_PCI(ttt, 0x13c2, 0x0008),
2876 MAKE_EXTENSION_PCI(ttc_1_X, 0x13c2, 0x000a),
2877 MAKE_EXTENSION_PCI(tts_2_3, 0x13c2, 0x000e),
2878 MAKE_EXTENSION_PCI(tts_1_3se, 0x13c2, 0x1002),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002879
Linus Torvalds1da177e2005-04-16 15:20:36 -07002880/* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0005), UNDEFINED CARD */ // Technisat SkyStar1
2881/* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0009), UNDEFINED CARD */ // TT/Hauppauge WinTV Nexus-CA v????
2882
2883 {
2884 .vendor = 0,
2885 }
2886};
2887
2888MODULE_DEVICE_TABLE(pci, pci_tbl);
2889
2890
Randy Dunlapda517162008-01-10 19:31:47 -03002891static struct saa7146_extension av7110_extension_driver = {
Dave Jones0e367a12006-08-07 13:18:56 -03002892 .name = "dvb",
Oliver Endriss00c4cc62006-11-01 13:09:51 -03002893 .flags = SAA7146_USE_I2C_IRQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002894
2895 .module = THIS_MODULE,
2896 .pci_tbl = &pci_tbl[0],
2897 .attach = av7110_attach,
Johannes Stezenbach1be11e32006-02-27 00:09:20 -03002898 .detach = __devexit_p(av7110_detach),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002899
2900 .irq_mask = MASK_19 | MASK_03 | MASK_10,
2901 .irq_func = av7110_irq,
2902};
2903
2904
2905static int __init av7110_init(void)
2906{
2907 int retval;
Randy Dunlapda517162008-01-10 19:31:47 -03002908 retval = saa7146_register_extension(&av7110_extension_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002909 return retval;
2910}
2911
2912
2913static void __exit av7110_exit(void)
2914{
Randy Dunlapda517162008-01-10 19:31:47 -03002915 saa7146_unregister_extension(&av7110_extension_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002916}
2917
2918module_init(av7110_init);
2919module_exit(av7110_exit);
2920
2921MODULE_DESCRIPTION("driver for the SAA7146 based AV110 PCI DVB cards by "
2922 "Siemens, Technotrend, Hauppauge");
2923MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, others");
2924MODULE_LICENSE("GPL");