blob: a6be529eec5ca72e3dd8f965e334b956b4911557 [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>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090052#include <linux/slab.h>
Al Viro3e085622008-05-21 00:30:51 -030053#include <asm/unaligned.h>
Harvey Harrison1a651a02008-10-18 20:28:37 -070054#include <asm/byteorder.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070055
56#include <asm/system.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070057
58#include <linux/dvb/frontend.h>
59
60#include "dvb_frontend.h"
61
62#include "ttpci-eeprom.h"
63#include "av7110.h"
64#include "av7110_hw.h"
65#include "av7110_av.h"
66#include "av7110_ca.h"
67#include "av7110_ipack.h"
68
Oliver Endrissdb5d91e2006-02-28 10:32:25 -030069#include "bsbe1.h"
70#include "lnbp21.h"
Perceval Anichini265366e2006-03-16 11:22:47 -030071#include "bsru6.h"
Oliver Endrissdb5d91e2006-02-28 10:32:25 -030072
Linus Torvalds1da177e2005-04-16 15:20:36 -070073#define TS_WIDTH 376
74#define TS_HEIGHT 512
75#define TS_BUFLEN (TS_WIDTH*TS_HEIGHT)
76#define TS_MAX_PACKETS (TS_BUFLEN/TS_SIZE)
77
78
79int av7110_debug;
80
81static int vidmode = CVBS_RGB_OUT;
82static int pids_off;
83static int adac = DVB_ADAC_TI;
84static int hw_sections;
85static int rgb_on;
86static int volume = 255;
Mauro Carvalho Chehaba5ed4252006-01-13 14:10:19 -020087static int budgetpatch;
Oliver Endriss4caba422006-03-17 05:29:15 -030088static int wss_cfg_4_3 = 0x4008;
89static int wss_cfg_16_9 = 0x0007;
C.Y.M2f03ee82006-03-30 04:31:48 -030090static int tv_standard;
Oliver Endriss9e615ea2008-09-03 19:15:27 -030091static int full_ts;
Linus Torvalds1da177e2005-04-16 15:20:36 -070092
93module_param_named(debug, av7110_debug, int, 0644);
94MODULE_PARM_DESC(debug, "debug level (bitmask, default 0)");
95module_param(vidmode, int, 0444);
96MODULE_PARM_DESC(vidmode,"analog video out: 0 off, 1 CVBS+RGB (default), 2 CVBS+YC, 3 YC");
97module_param(pids_off, int, 0444);
98MODULE_PARM_DESC(pids_off,"clear video/audio/PCR PID filters when demux is closed");
99module_param(adac, int, 0444);
100MODULE_PARM_DESC(adac,"audio DAC type: 0 TI, 1 CRYSTAL, 2 MSP (use if autodetection fails)");
101module_param(hw_sections, int, 0444);
102MODULE_PARM_DESC(hw_sections, "0 use software section filter, 1 use hardware");
103module_param(rgb_on, int, 0444);
104MODULE_PARM_DESC(rgb_on, "For Siemens DVB-C cards only: Enable RGB control"
105 " signal on SCART pin 16 to switch SCART video mode from CVBS to RGB");
106module_param(volume, int, 0444);
107MODULE_PARM_DESC(volume, "initial volume: default 255 (range 0-255)");
108module_param(budgetpatch, int, 0444);
109MODULE_PARM_DESC(budgetpatch, "use budget-patch hardware modification: default 0 (0 no, 1 autodetect, 2 always)");
Oliver Endriss9e615ea2008-09-03 19:15:27 -0300110module_param(full_ts, int, 0444);
111MODULE_PARM_DESC(full_ts, "enable code for full-ts hardware modification: 0 disable (default), 1 enable");
Oliver Endriss4caba422006-03-17 05:29:15 -0300112module_param(wss_cfg_4_3, int, 0444);
113MODULE_PARM_DESC(wss_cfg_4_3, "WSS 4:3 - default 0x4008 - bit 15: disable, 14: burst mode, 13..0: wss data");
114module_param(wss_cfg_16_9, int, 0444);
115MODULE_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 -0300116module_param(tv_standard, int, 0444);
117MODULE_PARM_DESC(tv_standard, "TV standard: 0 PAL (default), 1 NTSC");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118
Janne Grunau78e92002008-04-09 19:13:13 -0300119DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
120
Linus Torvalds1da177e2005-04-16 15:20:36 -0700121static void restart_feeds(struct av7110 *av7110);
Oliver Endriss9e615ea2008-09-03 19:15:27 -0300122static int budget_start_feed(struct dvb_demux_feed *feed);
123static int budget_stop_feed(struct dvb_demux_feed *feed);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700124
Mauro Carvalho Chehaba5ed4252006-01-13 14:10:19 -0200125static int av7110_num;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126
127#define FE_FUNC_OVERRIDE(fe_func, av7110_copy, av7110_func) \
128{\
129 if (fe_func != NULL) { \
130 av7110_copy = fe_func; \
131 fe_func = av7110_func; \
132 } \
133}
134
135
136static void init_av7110_av(struct av7110 *av7110)
137{
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700138 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139 struct saa7146_dev *dev = av7110->dev;
140
141 /* set internal volume control to maximum */
142 av7110->adac_type = DVB_ADAC_TI;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700143 ret = av7110_set_volume(av7110, av7110->mixer.volume_left, av7110->mixer.volume_right);
Johannes Stezenbach7a2fa902005-07-07 17:58:01 -0700144 if (ret < 0)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700145 printk("dvb-ttpci:cannot set internal volume to maximum:%d\n",ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700146
Oliver Endrissdefd574e2007-07-12 23:08:07 -0300147 ret = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetMonitorType,
148 1, (u16) av7110->display_ar);
149 if (ret < 0)
150 printk("dvb-ttpci: unable to set aspect ratio\n");
151 ret = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetPanScanType,
152 1, av7110->display_panscan);
153 if (ret < 0)
154 printk("dvb-ttpci: unable to set pan scan\n");
155
Oliver Endriss4caba422006-03-17 05:29:15 -0300156 ret = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetWSSConfig, 2, 2, wss_cfg_4_3);
157 if (ret < 0)
158 printk("dvb-ttpci: unable to configure 4:3 wss\n");
159 ret = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetWSSConfig, 2, 3, wss_cfg_16_9);
160 if (ret < 0)
161 printk("dvb-ttpci: unable to configure 16:9 wss\n");
162
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700163 ret = av7710_set_video_mode(av7110, vidmode);
Johannes Stezenbach7a2fa902005-07-07 17:58:01 -0700164 if (ret < 0)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700165 printk("dvb-ttpci:cannot set video mode:%d\n",ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700166
167 /* handle different card types */
168 /* remaining inits according to card and frontend type */
169 av7110->analog_tuner_flags = 0;
170 av7110->current_input = 0;
Tim Kaiser61391e02006-06-25 09:14:07 -0300171 if (dev->pci->subsystem_vendor == 0x13c2 && dev->pci->subsystem_device == 0x000a)
Marco Schluessler1c13b952006-01-09 15:25:06 -0200172 av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, ADSwitch, 1, 0); // SPDIF on
Tim Kaiser61391e02006-06-25 09:14:07 -0300173 if (i2c_writereg(av7110, 0x20, 0x00, 0x00) == 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700174 printk ("dvb-ttpci: Crystal audio DAC @ card %d detected\n",
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -0700175 av7110->dvb_adapter.num);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700176 av7110->adac_type = DVB_ADAC_CRYSTAL;
177 i2c_writereg(av7110, 0x20, 0x01, 0xd2);
178 i2c_writereg(av7110, 0x20, 0x02, 0x49);
179 i2c_writereg(av7110, 0x20, 0x03, 0x00);
180 i2c_writereg(av7110, 0x20, 0x04, 0x00);
181
182 /**
183 * some special handling for the Siemens DVB-C cards...
184 */
185 } else if (0 == av7110_init_analog_module(av7110)) {
186 /* done. */
187 }
188 else if (dev->pci->subsystem_vendor == 0x110a) {
189 printk("dvb-ttpci: DVB-C w/o analog module @ card %d detected\n",
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -0700190 av7110->dvb_adapter.num);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700191 av7110->adac_type = DVB_ADAC_NONE;
192 }
193 else {
194 av7110->adac_type = adac;
195 printk("dvb-ttpci: adac type set to %d @ card %d\n",
Marco Schluessler1c13b952006-01-09 15:25:06 -0200196 av7110->adac_type, av7110->dvb_adapter.num);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700197 }
198
Marco Schluessler1c13b952006-01-09 15:25:06 -0200199 if (av7110->adac_type == DVB_ADAC_NONE || av7110->adac_type == DVB_ADAC_MSP34x0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200 // switch DVB SCART on
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700201 ret = av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, MainSwitch, 1, 0);
Johannes Stezenbach7a2fa902005-07-07 17:58:01 -0700202 if (ret < 0)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700203 printk("dvb-ttpci:cannot switch on SCART(Main):%d\n",ret);
204 ret = av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, ADSwitch, 1, 1);
Johannes Stezenbach7a2fa902005-07-07 17:58:01 -0700205 if (ret < 0)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700206 printk("dvb-ttpci:cannot switch on SCART(AD):%d\n",ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700207 if (rgb_on &&
Karl Herz6af4ee12005-09-09 13:03:13 -0700208 ((av7110->dev->pci->subsystem_vendor == 0x110a) ||
209 (av7110->dev->pci->subsystem_vendor == 0x13c2)) &&
210 (av7110->dev->pci->subsystem_device == 0x0000)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700211 saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); // RGB on, SCART pin 16
212 //saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); // SCARTpin 8
213 }
214 }
215
Oliver Endriss60edb132005-12-19 08:54:11 -0200216 if (dev->pci->subsystem_vendor == 0x13c2 && dev->pci->subsystem_device == 0x000e)
217 av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, SpdifSwitch, 1, 0); // SPDIF on
218
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700219 ret = av7110_set_volume(av7110, av7110->mixer.volume_left, av7110->mixer.volume_right);
Johannes Stezenbach7a2fa902005-07-07 17:58:01 -0700220 if (ret < 0)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700221 printk("dvb-ttpci:cannot set volume :%d\n",ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700222}
223
224static void recover_arm(struct av7110 *av7110)
225{
226 dprintk(4, "%p\n",av7110);
227
228 av7110_bootarm(av7110);
229 msleep(100);
Oliver Endriss66190a22006-01-09 15:32:42 -0200230
231 init_av7110_av(av7110);
232
233 /* card-specific recovery */
234 if (av7110->recover)
235 av7110->recover(av7110);
236
Linus Torvalds1da177e2005-04-16 15:20:36 -0700237 restart_feeds(av7110);
Oliver Endrissee820a62007-04-27 12:31:21 -0300238
239#if defined(CONFIG_INPUT_EVDEV) || defined(CONFIG_INPUT_EVDEV_MODULE)
240 av7110_check_ir_config(av7110, true);
241#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700242}
243
Linus Torvalds1da177e2005-04-16 15:20:36 -0700244static void av7110_arm_sync(struct av7110 *av7110)
245{
Herbert Poetzl8eec1422007-02-08 14:32:43 -0300246 if (av7110->arm_thread)
247 kthread_stop(av7110->arm_thread);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700248
Herbert Poetzl8eec1422007-02-08 14:32:43 -0300249 av7110->arm_thread = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700250}
251
252static int arm_thread(void *data)
253{
254 struct av7110 *av7110 = data;
255 u16 newloops = 0;
256 int timeout;
257
258 dprintk(4, "%p\n",av7110);
259
Linus Torvalds1da177e2005-04-16 15:20:36 -0700260 for (;;) {
261 timeout = wait_event_interruptible_timeout(av7110->arm_wait,
Herbert Poetzl8eec1422007-02-08 14:32:43 -0300262 kthread_should_stop(), 5 * HZ);
263
264 if (-ERESTARTSYS == timeout || kthread_should_stop()) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700265 /* got signal or told to quit*/
266 break;
267 }
268
269 if (!av7110->arm_ready)
270 continue;
271
Oliver Endrissee820a62007-04-27 12:31:21 -0300272#if defined(CONFIG_INPUT_EVDEV) || defined(CONFIG_INPUT_EVDEV_MODULE)
273 av7110_check_ir_config(av7110, false);
274#endif
275
Ingo Molnar3593cab2006-02-07 06:49:14 -0200276 if (mutex_lock_interruptible(&av7110->dcomlock))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700277 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278 newloops = rdebi(av7110, DEBINOSWAP, STATUS_LOOPS, 0, 2);
Ingo Molnar3593cab2006-02-07 06:49:14 -0200279 mutex_unlock(&av7110->dcomlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700280
Oliver Endriss66190a22006-01-09 15:32:42 -0200281 if (newloops == av7110->arm_loops || av7110->arm_errors > 3) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700282 printk(KERN_ERR "dvb-ttpci: ARM crashed @ card %d\n",
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -0700283 av7110->dvb_adapter.num);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284
Oliver Endriss66190a22006-01-09 15:32:42 -0200285 recover_arm(av7110);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286
Ingo Molnar3593cab2006-02-07 06:49:14 -0200287 if (mutex_lock_interruptible(&av7110->dcomlock))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700289 newloops = rdebi(av7110, DEBINOSWAP, STATUS_LOOPS, 0, 2) - 1;
Ingo Molnar3593cab2006-02-07 06:49:14 -0200290 mutex_unlock(&av7110->dcomlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291 }
292 av7110->arm_loops = newloops;
Oliver Endriss66190a22006-01-09 15:32:42 -0200293 av7110->arm_errors = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294 }
295
Linus Torvalds1da177e2005-04-16 15:20:36 -0700296 return 0;
297}
298
299
Linus Torvalds1da177e2005-04-16 15:20:36 -0700300/****************************************************************************
301 * IRQ handling
302 ****************************************************************************/
303
304static int DvbDmxFilterCallback(u8 *buffer1, size_t buffer1_len,
305 u8 *buffer2, size_t buffer2_len,
306 struct dvb_demux_filter *dvbdmxfilter,
307 enum dmx_success success,
308 struct av7110 *av7110)
309{
310 if (!dvbdmxfilter->feed->demux->dmx.frontend)
311 return 0;
312 if (dvbdmxfilter->feed->demux->dmx.frontend->source == DMX_MEMORY_FE)
313 return 0;
314
315 switch (dvbdmxfilter->type) {
316 case DMX_TYPE_SEC:
317 if ((((buffer1[1] << 8) | buffer1[2]) & 0xfff) + 3 != buffer1_len)
318 return 0;
319 if (dvbdmxfilter->doneq) {
320 struct dmx_section_filter *filter = &dvbdmxfilter->filter;
321 int i;
322 u8 xor, neq = 0;
323
324 for (i = 0; i < DVB_DEMUX_MASK_MAX; i++) {
325 xor = filter->filter_value[i] ^ buffer1[i];
326 neq |= dvbdmxfilter->maskandnotmode[i] & xor;
327 }
328 if (!neq)
329 return 0;
330 }
331 return dvbdmxfilter->feed->cb.sec(buffer1, buffer1_len,
332 buffer2, buffer2_len,
333 &dvbdmxfilter->filter,
334 DMX_OK);
335 case DMX_TYPE_TS:
336 if (!(dvbdmxfilter->feed->ts_type & TS_PACKET))
337 return 0;
338 if (dvbdmxfilter->feed->ts_type & TS_PAYLOAD_ONLY)
339 return dvbdmxfilter->feed->cb.ts(buffer1, buffer1_len,
340 buffer2, buffer2_len,
341 &dvbdmxfilter->feed->feed.ts,
342 DMX_OK);
343 else
344 av7110_p2t_write(buffer1, buffer1_len,
345 dvbdmxfilter->feed->pid,
346 &av7110->p2t_filter[dvbdmxfilter->index]);
347 default:
348 return 0;
349 }
350}
351
352
353//#define DEBUG_TIMING
354static inline void print_time(char *s)
355{
356#ifdef DEBUG_TIMING
357 struct timeval tv;
358 do_gettimeofday(&tv);
359 printk("%s: %d.%d\n", s, (int)tv.tv_sec, (int)tv.tv_usec);
360#endif
361}
362
363#define DEBI_READ 0
364#define DEBI_WRITE 1
365static inline void start_debi_dma(struct av7110 *av7110, int dir,
366 unsigned long addr, unsigned int len)
367{
368 dprintk(8, "%c %08lx %u\n", dir == DEBI_READ ? 'R' : 'W', addr, len);
369 if (saa7146_wait_for_debi_done(av7110->dev, 0)) {
Harvey Harrison3ca7fc82008-04-08 23:20:00 -0300370 printk(KERN_ERR "%s: saa7146_wait_for_debi_done timed out\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371 return;
372 }
373
374 SAA7146_ISR_CLEAR(av7110->dev, MASK_19); /* for good measure */
375 SAA7146_IER_ENABLE(av7110->dev, MASK_19);
376 if (len < 5)
377 len = 5; /* we want a real DEBI DMA */
378 if (dir == DEBI_WRITE)
379 iwdebi(av7110, DEBISWAB, addr, 0, (len + 3) & ~3);
380 else
381 irdebi(av7110, DEBISWAB, addr, 0, len);
382}
383
Hans Verkuild45b9b82008-09-04 03:33:43 -0300384static void debiirq(unsigned long cookie)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385{
Hans Verkuild45b9b82008-09-04 03:33:43 -0300386 struct av7110 *av7110 = (struct av7110 *)cookie;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387 int type = av7110->debitype;
388 int handle = (type >> 8) & 0x1f;
389 unsigned int xfer = 0;
390
391 print_time("debi");
392 dprintk(4, "type 0x%04x\n", type);
393
394 if (type == -1) {
395 printk("DEBI irq oops @ %ld, psr:0x%08x, ssr:0x%08x\n",
396 jiffies, saa7146_read(av7110->dev, PSR),
397 saa7146_read(av7110->dev, SSR));
398 goto debi_done;
399 }
400 av7110->debitype = -1;
401
402 switch (type & 0xff) {
403
404 case DATA_TS_RECORD:
405 dvb_dmx_swfilter_packets(&av7110->demux,
406 (const u8 *) av7110->debi_virt,
407 av7110->debilen / 188);
408 xfer = RX_BUFF;
409 break;
410
411 case DATA_PES_RECORD:
412 if (av7110->demux.recording)
413 av7110_record_cb(&av7110->p2t[handle],
414 (u8 *) av7110->debi_virt,
415 av7110->debilen);
416 xfer = RX_BUFF;
417 break;
418
419 case DATA_IPMPE:
420 case DATA_FSECTION:
421 case DATA_PIPING:
422 if (av7110->handle2filter[handle])
423 DvbDmxFilterCallback((u8 *)av7110->debi_virt,
424 av7110->debilen, NULL, 0,
425 av7110->handle2filter[handle],
426 DMX_OK, av7110);
427 xfer = RX_BUFF;
428 break;
429
430 case DATA_CI_GET:
431 {
432 u8 *data = av7110->debi_virt;
433
434 if ((data[0] < 2) && data[2] == 0xff) {
435 int flags = 0;
436 if (data[5] > 0)
437 flags |= CA_CI_MODULE_PRESENT;
438 if (data[5] > 5)
439 flags |= CA_CI_MODULE_READY;
440 av7110->ci_slot[data[0]].flags = flags;
441 } else
442 ci_get_data(&av7110->ci_rbuffer,
443 av7110->debi_virt,
444 av7110->debilen);
445 xfer = RX_BUFF;
446 break;
447 }
448
449 case DATA_COMMON_INTERFACE:
450 CI_handle(av7110, (u8 *)av7110->debi_virt, av7110->debilen);
451#if 0
452 {
453 int i;
454
455 printk("av7110%d: ", av7110->num);
456 printk("%02x ", *(u8 *)av7110->debi_virt);
457 printk("%02x ", *(1+(u8 *)av7110->debi_virt));
458 for (i = 2; i < av7110->debilen; i++)
459 printk("%02x ", (*(i+(unsigned char *)av7110->debi_virt)));
460 for (i = 2; i < av7110->debilen; i++)
461 printk("%c", chtrans(*(i+(unsigned char *)av7110->debi_virt)));
462
463 printk("\n");
464 }
465#endif
466 xfer = RX_BUFF;
467 break;
468
469 case DATA_DEBUG_MESSAGE:
470 ((s8*)av7110->debi_virt)[Reserved_SIZE - 1] = 0;
471 printk("%s\n", (s8 *) av7110->debi_virt);
472 xfer = RX_BUFF;
473 break;
474
475 case DATA_CI_PUT:
476 dprintk(4, "debi DATA_CI_PUT\n");
477 case DATA_MPEG_PLAY:
478 dprintk(4, "debi DATA_MPEG_PLAY\n");
479 case DATA_BMP_LOAD:
480 dprintk(4, "debi DATA_BMP_LOAD\n");
481 xfer = TX_BUFF;
482 break;
483 default:
484 break;
485 }
486debi_done:
487 spin_lock(&av7110->debilock);
488 if (xfer)
489 iwdebi(av7110, DEBINOSWAP, xfer, 0, 2);
490 ARM_ClearMailBox(av7110);
491 spin_unlock(&av7110->debilock);
492}
493
494/* irq from av7110 firmware writing the mailbox register in the DPRAM */
Hans Verkuild45b9b82008-09-04 03:33:43 -0300495static void gpioirq(unsigned long cookie)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496{
Hans Verkuild45b9b82008-09-04 03:33:43 -0300497 struct av7110 *av7110 = (struct av7110 *)cookie;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498 u32 rxbuf, txbuf;
499 int len;
500
501 if (av7110->debitype != -1)
502 /* we shouldn't get any irq while a debi xfer is running */
503 printk("dvb-ttpci: GPIO0 irq oops @ %ld, psr:0x%08x, ssr:0x%08x\n",
504 jiffies, saa7146_read(av7110->dev, PSR),
505 saa7146_read(av7110->dev, SSR));
506
507 if (saa7146_wait_for_debi_done(av7110->dev, 0)) {
Harvey Harrison3ca7fc82008-04-08 23:20:00 -0300508 printk(KERN_ERR "%s: saa7146_wait_for_debi_done timed out\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700509 BUG(); /* maybe we should try resetting the debi? */
510 }
511
512 spin_lock(&av7110->debilock);
513 ARM_ClearIrq(av7110);
514
515 /* see what the av7110 wants */
516 av7110->debitype = irdebi(av7110, DEBINOSWAP, IRQ_STATE, 0, 2);
517 av7110->debilen = irdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
518 rxbuf = irdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
519 txbuf = irdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
520 len = (av7110->debilen + 3) & ~3;
521
522 print_time("gpio");
523 dprintk(8, "GPIO0 irq 0x%04x %d\n", av7110->debitype, av7110->debilen);
524
525 switch (av7110->debitype & 0xff) {
526
527 case DATA_TS_PLAY:
528 case DATA_PES_PLAY:
529 break;
530
531 case DATA_MPEG_VIDEO_EVENT:
532 {
533 u32 h_ar;
534 struct video_event event;
535
536 av7110->video_size.w = irdebi(av7110, DEBINOSWAP, STATUS_MPEG_WIDTH, 0, 2);
537 h_ar = irdebi(av7110, DEBINOSWAP, STATUS_MPEG_HEIGHT_AR, 0, 2);
538
539 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
540 iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
541
542 av7110->video_size.h = h_ar & 0xfff;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543
544 event.type = VIDEO_EVENT_SIZE_CHANGED;
545 event.u.size.w = av7110->video_size.w;
546 event.u.size.h = av7110->video_size.h;
547 switch ((h_ar >> 12) & 0xf)
548 {
549 case 3:
550 av7110->video_size.aspect_ratio = VIDEO_FORMAT_16_9;
551 event.u.size.aspect_ratio = VIDEO_FORMAT_16_9;
552 av7110->videostate.video_format = VIDEO_FORMAT_16_9;
553 break;
554 case 4:
555 av7110->video_size.aspect_ratio = VIDEO_FORMAT_221_1;
556 event.u.size.aspect_ratio = VIDEO_FORMAT_221_1;
557 av7110->videostate.video_format = VIDEO_FORMAT_221_1;
558 break;
559 default:
560 av7110->video_size.aspect_ratio = VIDEO_FORMAT_4_3;
561 event.u.size.aspect_ratio = VIDEO_FORMAT_4_3;
562 av7110->videostate.video_format = VIDEO_FORMAT_4_3;
563 }
Oliver Endriss66190a22006-01-09 15:32:42 -0200564
565 dprintk(8, "GPIO0 irq: DATA_MPEG_VIDEO_EVENT: w/h/ar = %u/%u/%u\n",
566 av7110->video_size.w, av7110->video_size.h,
567 av7110->video_size.aspect_ratio);
568
Linus Torvalds1da177e2005-04-16 15:20:36 -0700569 dvb_video_add_event(av7110, &event);
570 break;
571 }
572
573 case DATA_CI_PUT:
574 {
575 int avail;
576 struct dvb_ringbuffer *cibuf = &av7110->ci_wbuffer;
577
578 avail = dvb_ringbuffer_avail(cibuf);
579 if (avail <= 2) {
580 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
581 iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
582 iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
583 break;
584 }
585 len = DVB_RINGBUFFER_PEEK(cibuf, 0) << 8;
586 len |= DVB_RINGBUFFER_PEEK(cibuf, 1);
587 if (avail < len + 2) {
588 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
589 iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
590 iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
591 break;
592 }
593 DVB_RINGBUFFER_SKIP(cibuf, 2);
594
Al Virob0ba0e32008-06-22 14:20:29 -0300595 dvb_ringbuffer_read(cibuf, av7110->debi_virt, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700596
597 iwdebi(av7110, DEBINOSWAP, TX_LEN, len, 2);
598 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, len, 2);
599 dprintk(8, "DMA: CI\n");
600 start_debi_dma(av7110, DEBI_WRITE, DPRAM_BASE + txbuf, len);
601 spin_unlock(&av7110->debilock);
602 wake_up(&cibuf->queue);
603 return;
604 }
605
606 case DATA_MPEG_PLAY:
607 if (!av7110->playing) {
608 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
609 iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
610 iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
611 break;
612 }
613 len = 0;
614 if (av7110->debitype & 0x100) {
615 spin_lock(&av7110->aout.lock);
616 len = av7110_pes_play(av7110->debi_virt, &av7110->aout, 2048);
617 spin_unlock(&av7110->aout.lock);
618 }
619 if (len <= 0 && (av7110->debitype & 0x200)
620 &&av7110->videostate.play_state != VIDEO_FREEZED) {
621 spin_lock(&av7110->avout.lock);
622 len = av7110_pes_play(av7110->debi_virt, &av7110->avout, 2048);
623 spin_unlock(&av7110->avout.lock);
624 }
625 if (len <= 0) {
626 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
627 iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
628 iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
629 break;
630 }
631 dprintk(8, "GPIO0 PES_PLAY len=%04x\n", len);
632 iwdebi(av7110, DEBINOSWAP, TX_LEN, len, 2);
633 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, len, 2);
634 dprintk(8, "DMA: MPEG_PLAY\n");
635 start_debi_dma(av7110, DEBI_WRITE, DPRAM_BASE + txbuf, len);
636 spin_unlock(&av7110->debilock);
637 return;
638
639 case DATA_BMP_LOAD:
640 len = av7110->debilen;
641 dprintk(8, "gpio DATA_BMP_LOAD len %d\n", len);
642 if (!len) {
643 av7110->bmp_state = BMP_LOADED;
644 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
645 iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
646 iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
647 wake_up(&av7110->bmpq);
648 dprintk(8, "gpio DATA_BMP_LOAD done\n");
649 break;
650 }
651 if (len > av7110->bmplen)
652 len = av7110->bmplen;
653 if (len > 2 * 1024)
654 len = 2 * 1024;
655 iwdebi(av7110, DEBINOSWAP, TX_LEN, len, 2);
656 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, len, 2);
657 memcpy(av7110->debi_virt, av7110->bmpbuf+av7110->bmpp, len);
658 av7110->bmpp += len;
659 av7110->bmplen -= len;
660 dprintk(8, "gpio DATA_BMP_LOAD DMA len %d\n", len);
661 start_debi_dma(av7110, DEBI_WRITE, DPRAM_BASE+txbuf, len);
662 spin_unlock(&av7110->debilock);
663 return;
664
665 case DATA_CI_GET:
666 case DATA_COMMON_INTERFACE:
667 case DATA_FSECTION:
668 case DATA_IPMPE:
669 case DATA_PIPING:
670 if (!len || len > 4 * 1024) {
671 iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
672 break;
673 }
674 /* fall through */
675
676 case DATA_TS_RECORD:
677 case DATA_PES_RECORD:
678 dprintk(8, "DMA: TS_REC etc.\n");
679 start_debi_dma(av7110, DEBI_READ, DPRAM_BASE+rxbuf, len);
680 spin_unlock(&av7110->debilock);
681 return;
682
683 case DATA_DEBUG_MESSAGE:
684 if (!len || len > 0xff) {
685 iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
686 break;
687 }
688 start_debi_dma(av7110, DEBI_READ, Reserved, len);
689 spin_unlock(&av7110->debilock);
690 return;
691
692 case DATA_IRCOMMAND:
Oliver Endrissee820a62007-04-27 12:31:21 -0300693 if (av7110->ir.ir_handler)
694 av7110->ir.ir_handler(av7110,
Oliver Endriss03388ae2005-09-09 13:03:12 -0700695 swahw32(irdebi(av7110, DEBINOSWAP, Reserved, 0, 4)));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696 iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
697 break;
698
699 default:
700 printk("dvb-ttpci: gpioirq unknown type=%d len=%d\n",
701 av7110->debitype, av7110->debilen);
702 break;
703 }
704 av7110->debitype = -1;
705 ARM_ClearMailBox(av7110);
706 spin_unlock(&av7110->debilock);
707}
708
709
710#ifdef CONFIG_DVB_AV7110_OSD
Arnd Bergmann16ef8de2010-04-27 00:24:00 +0200711static int dvb_osd_ioctl(struct file *file,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700712 unsigned int cmd, void *parg)
713{
Tobias Klauserd9bdf772006-12-26 07:33:48 -0300714 struct dvb_device *dvbdev = file->private_data;
715 struct av7110 *av7110 = dvbdev->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700716
717 dprintk(4, "%p\n", av7110);
718
719 if (cmd == OSD_SEND_CMD)
720 return av7110_osd_cmd(av7110, (osd_cmd_t *) parg);
721 if (cmd == OSD_GET_CAPABILITY)
722 return av7110_osd_capability(av7110, (osd_cap_t *) parg);
723
724 return -EINVAL;
725}
726
727
Jan Engelhardt784e29d2009-01-11 06:12:43 -0300728static const struct file_operations dvb_osd_fops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700729 .owner = THIS_MODULE,
Arnd Bergmann16ef8de2010-04-27 00:24:00 +0200730 .unlocked_ioctl = dvb_generic_ioctl,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700731 .open = dvb_generic_open,
732 .release = dvb_generic_release,
733};
734
735static struct dvb_device dvbdev_osd = {
736 .priv = NULL,
737 .users = 1,
738 .writers = 1,
739 .fops = &dvb_osd_fops,
740 .kernel_ioctl = dvb_osd_ioctl,
741};
742#endif /* CONFIG_DVB_AV7110_OSD */
743
744
745static inline int SetPIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid,
746 u16 subpid, u16 pcrpid)
747{
Dr. Werner Fink47f36922006-01-09 15:25:07 -0200748 u16 aflags = 0;
749
Linus Torvalds1da177e2005-04-16 15:20:36 -0700750 dprintk(4, "%p\n", av7110);
751
752 if (vpid == 0x1fff || apid == 0x1fff ||
753 ttpid == 0x1fff || subpid == 0x1fff || pcrpid == 0x1fff) {
754 vpid = apid = ttpid = subpid = pcrpid = 0;
755 av7110->pids[DMX_PES_VIDEO] = 0;
756 av7110->pids[DMX_PES_AUDIO] = 0;
757 av7110->pids[DMX_PES_TELETEXT] = 0;
758 av7110->pids[DMX_PES_PCR] = 0;
759 }
760
Dr. Werner Fink47f36922006-01-09 15:25:07 -0200761 if (av7110->audiostate.bypass_mode)
762 aflags |= 0x8000;
763
764 return av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, MultiPID, 6,
765 pcrpid, vpid, apid, ttpid, subpid, aflags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700766}
767
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700768int ChangePIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700769 u16 subpid, u16 pcrpid)
770{
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700771 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772 dprintk(4, "%p\n", av7110);
773
Ingo Molnar3593cab2006-02-07 06:49:14 -0200774 if (mutex_lock_interruptible(&av7110->pid_mutex))
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700775 return -ERESTARTSYS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700776
777 if (!(vpid & 0x8000))
778 av7110->pids[DMX_PES_VIDEO] = vpid;
779 if (!(apid & 0x8000))
780 av7110->pids[DMX_PES_AUDIO] = apid;
781 if (!(ttpid & 0x8000))
782 av7110->pids[DMX_PES_TELETEXT] = ttpid;
783 if (!(pcrpid & 0x8000))
784 av7110->pids[DMX_PES_PCR] = pcrpid;
785
786 av7110->pids[DMX_PES_SUBTITLE] = 0;
787
788 if (av7110->fe_synced) {
789 pcrpid = av7110->pids[DMX_PES_PCR];
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700790 ret = SetPIDs(av7110, vpid, apid, ttpid, subpid, pcrpid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700791 }
792
Ingo Molnar3593cab2006-02-07 06:49:14 -0200793 mutex_unlock(&av7110->pid_mutex);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700794 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700795}
796
797
798/******************************************************************************
799 * hardware filter functions
800 ******************************************************************************/
801
802static int StartHWFilter(struct dvb_demux_filter *dvbdmxfilter)
803{
804 struct dvb_demux_feed *dvbdmxfeed = dvbdmxfilter->feed;
Tobias Klauserd9bdf772006-12-26 07:33:48 -0300805 struct av7110 *av7110 = dvbdmxfeed->demux->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700806 u16 buf[20];
807 int ret, i;
808 u16 handle;
809// u16 mode = 0x0320;
810 u16 mode = 0xb96a;
811
812 dprintk(4, "%p\n", av7110);
813
Oliver Endriss9e615ea2008-09-03 19:15:27 -0300814 if (av7110->full_ts)
815 return 0;
816
Linus Torvalds1da177e2005-04-16 15:20:36 -0700817 if (dvbdmxfilter->type == DMX_TYPE_SEC) {
818 if (hw_sections) {
819 buf[4] = (dvbdmxfilter->filter.filter_value[0] << 8) |
820 dvbdmxfilter->maskandmode[0];
821 for (i = 3; i < 18; i++)
822 buf[i + 4 - 2] =
823 (dvbdmxfilter->filter.filter_value[i] << 8) |
824 dvbdmxfilter->maskandmode[i];
825 mode = 4;
826 }
827 } else if ((dvbdmxfeed->ts_type & TS_PACKET) &&
828 !(dvbdmxfeed->ts_type & TS_PAYLOAD_ONLY)) {
829 av7110_p2t_init(&av7110->p2t_filter[dvbdmxfilter->index], dvbdmxfeed);
830 }
831
832 buf[0] = (COMTYPE_PID_FILTER << 8) + AddPIDFilter;
833 buf[1] = 16;
834 buf[2] = dvbdmxfeed->pid;
835 buf[3] = mode;
836
837 ret = av7110_fw_request(av7110, buf, 20, &handle, 1);
838 if (ret != 0 || handle >= 32) {
839 printk("dvb-ttpci: %s error buf %04x %04x %04x %04x "
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700840 "ret %d handle %04x\n",
Harvey Harrison3ca7fc82008-04-08 23:20:00 -0300841 __func__, buf[0], buf[1], buf[2], buf[3],
Linus Torvalds1da177e2005-04-16 15:20:36 -0700842 ret, handle);
843 dvbdmxfilter->hw_handle = 0xffff;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700844 if (!ret)
845 ret = -1;
846 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700847 }
848
849 av7110->handle2filter[handle] = dvbdmxfilter;
850 dvbdmxfilter->hw_handle = handle;
851
852 return ret;
853}
854
855static int StopHWFilter(struct dvb_demux_filter *dvbdmxfilter)
856{
Tobias Klauserd9bdf772006-12-26 07:33:48 -0300857 struct av7110 *av7110 = dvbdmxfilter->feed->demux->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700858 u16 buf[3];
859 u16 answ[2];
860 int ret;
861 u16 handle;
862
863 dprintk(4, "%p\n", av7110);
864
Oliver Endriss9e615ea2008-09-03 19:15:27 -0300865 if (av7110->full_ts)
866 return 0;
867
Linus Torvalds1da177e2005-04-16 15:20:36 -0700868 handle = dvbdmxfilter->hw_handle;
869 if (handle >= 32) {
870 printk("%s tried to stop invalid filter %04x, filter type = %x\n",
Harvey Harrison3ca7fc82008-04-08 23:20:00 -0300871 __func__, handle, dvbdmxfilter->type);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700872 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700873 }
874
875 av7110->handle2filter[handle] = NULL;
876
877 buf[0] = (COMTYPE_PID_FILTER << 8) + DelPIDFilter;
878 buf[1] = 1;
879 buf[2] = handle;
880 ret = av7110_fw_request(av7110, buf, 3, answ, 2);
881 if (ret != 0 || answ[1] != handle) {
882 printk("dvb-ttpci: %s error cmd %04x %04x %04x ret %x "
883 "resp %04x %04x pid %d\n",
Harvey Harrison3ca7fc82008-04-08 23:20:00 -0300884 __func__, buf[0], buf[1], buf[2], ret,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700885 answ[0], answ[1], dvbdmxfilter->feed->pid);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700886 if (!ret)
887 ret = -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700888 }
889 return ret;
890}
891
892
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700893static int dvb_feed_start_pid(struct dvb_demux_feed *dvbdmxfeed)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700894{
895 struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
Tobias Klauserd9bdf772006-12-26 07:33:48 -0300896 struct av7110 *av7110 = dvbdmx->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700897 u16 *pid = dvbdmx->pids, npids[5];
898 int i;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700899 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700900
901 dprintk(4, "%p\n", av7110);
902
903 npids[0] = npids[1] = npids[2] = npids[3] = npids[4] = 0xffff;
904 i = dvbdmxfeed->pes_type;
905 npids[i] = (pid[i]&0x8000) ? 0 : pid[i];
906 if ((i == 2) && npids[i] && (dvbdmxfeed->ts_type & TS_PACKET)) {
907 npids[i] = 0;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700908 ret = ChangePIDs(av7110, npids[1], npids[0], npids[2], npids[3], npids[4]);
909 if (!ret)
910 ret = StartHWFilter(dvbdmxfeed->filter);
911 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700913 if (dvbdmxfeed->pes_type <= 2 || dvbdmxfeed->pes_type == 4) {
914 ret = ChangePIDs(av7110, npids[1], npids[0], npids[2], npids[3], npids[4]);
915 if (ret)
916 return ret;
917 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918
919 if (dvbdmxfeed->pes_type < 2 && npids[0])
920 if (av7110->fe_synced)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700921 {
922 ret = av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, Scan, 0);
923 if (ret)
924 return ret;
925 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700926
Oliver Endriss9e615ea2008-09-03 19:15:27 -0300927 if ((dvbdmxfeed->ts_type & TS_PACKET) && !av7110->full_ts) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700928 if (dvbdmxfeed->pes_type == 0 && !(dvbdmx->pids[0] & 0x8000))
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700929 ret = av7110_av_start_record(av7110, RP_AUDIO, dvbdmxfeed);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700930 if (dvbdmxfeed->pes_type == 1 && !(dvbdmx->pids[1] & 0x8000))
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700931 ret = av7110_av_start_record(av7110, RP_VIDEO, dvbdmxfeed);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700932 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700933 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700934}
935
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700936static int dvb_feed_stop_pid(struct dvb_demux_feed *dvbdmxfeed)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700937{
938 struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
Tobias Klauserd9bdf772006-12-26 07:33:48 -0300939 struct av7110 *av7110 = dvbdmx->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700940 u16 *pid = dvbdmx->pids, npids[5];
941 int i;
942
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700943 int ret = 0;
944
Linus Torvalds1da177e2005-04-16 15:20:36 -0700945 dprintk(4, "%p\n", av7110);
946
947 if (dvbdmxfeed->pes_type <= 1) {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700948 ret = av7110_av_stop(av7110, dvbdmxfeed->pes_type ? RP_VIDEO : RP_AUDIO);
949 if (ret)
950 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700951 if (!av7110->rec_mode)
952 dvbdmx->recording = 0;
953 if (!av7110->playing)
954 dvbdmx->playing = 0;
955 }
956 npids[0] = npids[1] = npids[2] = npids[3] = npids[4] = 0xffff;
957 i = dvbdmxfeed->pes_type;
958 switch (i) {
959 case 2: //teletext
960 if (dvbdmxfeed->ts_type & TS_PACKET)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700961 ret = StopHWFilter(dvbdmxfeed->filter);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700962 npids[2] = 0;
963 break;
964 case 0:
965 case 1:
966 case 4:
967 if (!pids_off)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700968 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700969 npids[i] = (pid[i]&0x8000) ? 0 : pid[i];
970 break;
971 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700972 if (!ret)
973 ret = ChangePIDs(av7110, npids[1], npids[0], npids[2], npids[3], npids[4]);
974 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975}
976
977static int av7110_start_feed(struct dvb_demux_feed *feed)
978{
979 struct dvb_demux *demux = feed->demux;
980 struct av7110 *av7110 = demux->priv;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700981 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700982
983 dprintk(4, "%p\n", av7110);
984
985 if (!demux->dmx.frontend)
986 return -EINVAL;
987
Oliver Endriss9e615ea2008-09-03 19:15:27 -0300988 if (!av7110->full_ts && feed->pid > 0x1fff)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989 return -EINVAL;
990
991 if (feed->type == DMX_TYPE_TS) {
992 if ((feed->ts_type & TS_DECODER) &&
993 (feed->pes_type < DMX_TS_PES_OTHER)) {
994 switch (demux->dmx.frontend->source) {
995 case DMX_MEMORY_FE:
996 if (feed->ts_type & TS_DECODER)
997 if (feed->pes_type < 2 &&
998 !(demux->pids[0] & 0x8000) &&
999 !(demux->pids[1] & 0x8000)) {
1000 dvb_ringbuffer_flush_spinlock_wakeup(&av7110->avout);
1001 dvb_ringbuffer_flush_spinlock_wakeup(&av7110->aout);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001002 ret = av7110_av_start_play(av7110,RP_AV);
1003 if (!ret)
1004 demux->playing = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001005 }
1006 break;
1007 default:
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001008 ret = dvb_feed_start_pid(feed);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001009 break;
1010 }
1011 } else if ((feed->ts_type & TS_PACKET) &&
1012 (demux->dmx.frontend->source != DMX_MEMORY_FE)) {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001013 ret = StartHWFilter(feed->filter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001014 }
1015 }
1016
Oliver Endriss9e615ea2008-09-03 19:15:27 -03001017 if (av7110->full_ts) {
1018 budget_start_feed(feed);
1019 return ret;
1020 }
1021
1022 if (feed->type == DMX_TYPE_SEC) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001023 int i;
1024
1025 for (i = 0; i < demux->filternum; i++) {
1026 if (demux->filter[i].state != DMX_STATE_READY)
1027 continue;
1028 if (demux->filter[i].type != DMX_TYPE_SEC)
1029 continue;
1030 if (demux->filter[i].filter.parent != &feed->feed.sec)
1031 continue;
1032 demux->filter[i].state = DMX_STATE_GO;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001033 if (demux->dmx.frontend->source != DMX_MEMORY_FE) {
1034 ret = StartHWFilter(&demux->filter[i]);
1035 if (ret)
1036 break;
1037 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001038 }
1039 }
1040
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001041 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001042}
1043
1044
1045static int av7110_stop_feed(struct dvb_demux_feed *feed)
1046{
1047 struct dvb_demux *demux = feed->demux;
1048 struct av7110 *av7110 = demux->priv;
Johannes Stezenbach12ba0502005-07-07 17:58:00 -07001049 int i, rc, ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001050 dprintk(4, "%p\n", av7110);
1051
1052 if (feed->type == DMX_TYPE_TS) {
1053 if (feed->ts_type & TS_DECODER) {
1054 if (feed->pes_type >= DMX_TS_PES_OTHER ||
1055 !demux->pesfilter[feed->pes_type])
1056 return -EINVAL;
1057 demux->pids[feed->pes_type] |= 0x8000;
1058 demux->pesfilter[feed->pes_type] = NULL;
1059 }
1060 if (feed->ts_type & TS_DECODER &&
1061 feed->pes_type < DMX_TS_PES_OTHER) {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001062 ret = dvb_feed_stop_pid(feed);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001063 } else
1064 if ((feed->ts_type & TS_PACKET) &&
1065 (demux->dmx.frontend->source != DMX_MEMORY_FE))
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001066 ret = StopHWFilter(feed->filter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067 }
1068
Oliver Endriss9e615ea2008-09-03 19:15:27 -03001069 if (av7110->full_ts) {
1070 budget_stop_feed(feed);
1071 return ret;
1072 }
1073
1074 if (feed->type == DMX_TYPE_SEC) {
Johannes Stezenbach12ba0502005-07-07 17:58:00 -07001075 for (i = 0; i<demux->filternum; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076 if (demux->filter[i].state == DMX_STATE_GO &&
1077 demux->filter[i].filter.parent == &feed->feed.sec) {
1078 demux->filter[i].state = DMX_STATE_READY;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001079 if (demux->dmx.frontend->source != DMX_MEMORY_FE) {
Johannes Stezenbach12ba0502005-07-07 17:58:00 -07001080 rc = StopHWFilter(&demux->filter[i]);
1081 if (!ret)
1082 ret = rc;
1083 /* keep going, stop as many filters as possible */
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001084 }
Johannes Stezenbach12ba0502005-07-07 17:58:00 -07001085 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001086 }
1087 }
1088
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001089 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001090}
1091
1092
1093static void restart_feeds(struct av7110 *av7110)
1094{
1095 struct dvb_demux *dvbdmx = &av7110->demux;
1096 struct dvb_demux_feed *feed;
1097 int mode;
Oliver Endriss9e615ea2008-09-03 19:15:27 -03001098 int feeding;
Oliver Endriss66190a22006-01-09 15:32:42 -02001099 int i, j;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001100
1101 dprintk(4, "%p\n", av7110);
1102
1103 mode = av7110->playing;
1104 av7110->playing = 0;
1105 av7110->rec_mode = 0;
1106
Oliver Endriss9e615ea2008-09-03 19:15:27 -03001107 feeding = av7110->feeding1; /* full_ts mod */
1108
Oliver Endriss66190a22006-01-09 15:32:42 -02001109 for (i = 0; i < dvbdmx->feednum; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001110 feed = &dvbdmx->feed[i];
Oliver Endriss66190a22006-01-09 15:32:42 -02001111 if (feed->state == DMX_STATE_GO) {
1112 if (feed->type == DMX_TYPE_SEC) {
1113 for (j = 0; j < dvbdmx->filternum; j++) {
1114 if (dvbdmx->filter[j].type != DMX_TYPE_SEC)
1115 continue;
1116 if (dvbdmx->filter[j].filter.parent != &feed->feed.sec)
1117 continue;
1118 if (dvbdmx->filter[j].state == DMX_STATE_GO)
1119 dvbdmx->filter[j].state = DMX_STATE_READY;
1120 }
1121 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001122 av7110_start_feed(feed);
Oliver Endriss66190a22006-01-09 15:32:42 -02001123 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001124 }
1125
Oliver Endriss9e615ea2008-09-03 19:15:27 -03001126 av7110->feeding1 = feeding; /* full_ts mod */
1127
Linus Torvalds1da177e2005-04-16 15:20:36 -07001128 if (mode)
1129 av7110_av_start_play(av7110, mode);
1130}
1131
1132static int dvb_get_stc(struct dmx_demux *demux, unsigned int num,
1133 uint64_t *stc, unsigned int *base)
1134{
1135 int ret;
1136 u16 fwstc[4];
1137 u16 tag = ((COMTYPE_REQUEST << 8) + ReqSTC);
1138 struct dvb_demux *dvbdemux;
1139 struct av7110 *av7110;
1140
1141 /* pointer casting paranoia... */
Eric Sesterhennae246012006-03-13 13:17:11 -03001142 BUG_ON(!demux);
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001143 dvbdemux = demux->priv;
Eric Sesterhennae246012006-03-13 13:17:11 -03001144 BUG_ON(!dvbdemux);
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001145 av7110 = dvbdemux->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001146
1147 dprintk(4, "%p\n", av7110);
1148
1149 if (num != 0)
1150 return -EINVAL;
1151
1152 ret = av7110_fw_request(av7110, &tag, 0, fwstc, 4);
1153 if (ret) {
Harvey Harrison3ca7fc82008-04-08 23:20:00 -03001154 printk(KERN_ERR "%s: av7110_fw_request error\n", __func__);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001155 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001156 }
1157 dprintk(2, "fwstc = %04hx %04hx %04hx %04hx\n",
1158 fwstc[0], fwstc[1], fwstc[2], fwstc[3]);
1159
1160 *stc = (((uint64_t) ((fwstc[3] & 0x8000) >> 15)) << 32) |
1161 (((uint64_t) fwstc[1]) << 16) | ((uint64_t) fwstc[0]);
1162 *base = 1;
1163
1164 dprintk(4, "stc = %lu\n", (unsigned long)*stc);
1165
1166 return 0;
1167}
1168
1169
1170/******************************************************************************
1171 * SEC device file operations
1172 ******************************************************************************/
1173
1174
1175static int av7110_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
1176{
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001177 struct av7110* av7110 = fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001178
1179 switch (tone) {
1180 case SEC_TONE_ON:
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001181 return Set22K(av7110, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001182
1183 case SEC_TONE_OFF:
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001184 return Set22K(av7110, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001185
1186 default:
1187 return -EINVAL;
1188 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001189}
1190
1191static int av7110_diseqc_send_master_cmd(struct dvb_frontend* fe,
1192 struct dvb_diseqc_master_cmd* cmd)
1193{
1194 struct av7110* av7110 = fe->dvb->priv;
1195
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001196 return av7110_diseqc_send(av7110, cmd->msg_len, cmd->msg, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001197}
1198
1199static int av7110_diseqc_send_burst(struct dvb_frontend* fe,
1200 fe_sec_mini_cmd_t minicmd)
1201{
1202 struct av7110* av7110 = fe->dvb->priv;
1203
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001204 return av7110_diseqc_send(av7110, 0, NULL, minicmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001205}
1206
1207/* simplified code from budget-core.c */
1208static int stop_ts_capture(struct av7110 *budget)
1209{
1210 dprintk(2, "budget: %p\n", budget);
1211
1212 if (--budget->feeding1)
1213 return budget->feeding1;
1214 saa7146_write(budget->dev, MC1, MASK_20); /* DMA3 off */
1215 SAA7146_IER_DISABLE(budget->dev, MASK_10);
1216 SAA7146_ISR_CLEAR(budget->dev, MASK_10);
1217 return 0;
1218}
1219
1220static int start_ts_capture(struct av7110 *budget)
1221{
1222 dprintk(2, "budget: %p\n", budget);
1223
1224 if (budget->feeding1)
1225 return ++budget->feeding1;
Oliver Endriss9e615ea2008-09-03 19:15:27 -03001226 memset(budget->grabbing, 0x00, TS_BUFLEN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001227 budget->ttbp = 0;
Oliver Endriss9e615ea2008-09-03 19:15:27 -03001228 SAA7146_ISR_CLEAR(budget->dev, MASK_10); /* VPE */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001229 SAA7146_IER_ENABLE(budget->dev, MASK_10); /* VPE */
1230 saa7146_write(budget->dev, MC1, (MASK_04 | MASK_20)); /* DMA3 on */
1231 return ++budget->feeding1;
1232}
1233
1234static int budget_start_feed(struct dvb_demux_feed *feed)
1235{
1236 struct dvb_demux *demux = feed->demux;
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001237 struct av7110 *budget = demux->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001238 int status;
1239
1240 dprintk(2, "av7110: %p\n", budget);
1241
1242 spin_lock(&budget->feedlock1);
1243 feed->pusi_seen = 0; /* have a clean section start */
1244 status = start_ts_capture(budget);
1245 spin_unlock(&budget->feedlock1);
1246 return status;
1247}
1248
1249static int budget_stop_feed(struct dvb_demux_feed *feed)
1250{
1251 struct dvb_demux *demux = feed->demux;
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001252 struct av7110 *budget = demux->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001253 int status;
1254
1255 dprintk(2, "budget: %p\n", budget);
1256
1257 spin_lock(&budget->feedlock1);
1258 status = stop_ts_capture(budget);
1259 spin_unlock(&budget->feedlock1);
1260 return status;
1261}
1262
Hans Verkuild45b9b82008-09-04 03:33:43 -03001263static void vpeirq(unsigned long cookie)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001264{
Hans Verkuild45b9b82008-09-04 03:33:43 -03001265 struct av7110 *budget = (struct av7110 *)cookie;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001266 u8 *mem = (u8 *) (budget->grabbing);
1267 u32 olddma = budget->ttbp;
1268 u32 newdma = saa7146_read(budget->dev, PCI_VDP3);
Oliver Endriss9e615ea2008-09-03 19:15:27 -03001269 struct dvb_demux *demux = budget->full_ts ? &budget->demux : &budget->demux1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001270
Linus Torvalds1da177e2005-04-16 15:20:36 -07001271 /* nearest lower position divisible by 188 */
1272 newdma -= newdma % 188;
1273
1274 if (newdma >= TS_BUFLEN)
1275 return;
1276
1277 budget->ttbp = newdma;
1278
1279 if (!budget->feeding1 || (newdma == olddma))
1280 return;
1281
Jon Burgess87c30192007-05-03 12:23:44 -03001282 /* Ensure streamed PCI data is synced to CPU */
1283 pci_dma_sync_sg_for_cpu(budget->dev->pci, budget->pt.slist, budget->pt.nents, PCI_DMA_FROMDEVICE);
1284
Linus Torvalds1da177e2005-04-16 15:20:36 -07001285#if 0
1286 /* track rps1 activity */
1287 printk("vpeirq: %02x Event Counter 1 0x%04x\n",
1288 mem[olddma],
1289 saa7146_read(budget->dev, EC1R) & 0x3fff);
1290#endif
1291
1292 if (newdma > olddma)
1293 /* no wraparound, dump olddma..newdma */
Oliver Endriss9e615ea2008-09-03 19:15:27 -03001294 dvb_dmx_swfilter_packets(demux, mem + olddma, (newdma - olddma) / 188);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001295 else {
1296 /* wraparound, dump olddma..buflen and 0..newdma */
Oliver Endriss9e615ea2008-09-03 19:15:27 -03001297 dvb_dmx_swfilter_packets(demux, mem + olddma, (TS_BUFLEN - olddma) / 188);
1298 dvb_dmx_swfilter_packets(demux, mem, newdma / 188);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001299 }
1300}
1301
1302static int av7110_register(struct av7110 *av7110)
1303{
1304 int ret, i;
1305 struct dvb_demux *dvbdemux = &av7110->demux;
1306 struct dvb_demux *dvbdemux1 = &av7110->demux1;
1307
1308 dprintk(4, "%p\n", av7110);
1309
1310 if (av7110->registered)
1311 return -1;
1312
1313 av7110->registered = 1;
1314
1315 dvbdemux->priv = (void *) av7110;
1316
1317 for (i = 0; i < 32; i++)
1318 av7110->handle2filter[i] = NULL;
1319
Oliver Endriss9e615ea2008-09-03 19:15:27 -03001320 dvbdemux->filternum = (av7110->full_ts) ? 256 : 32;
1321 dvbdemux->feednum = (av7110->full_ts) ? 256 : 32;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001322 dvbdemux->start_feed = av7110_start_feed;
1323 dvbdemux->stop_feed = av7110_stop_feed;
1324 dvbdemux->write_to_decoder = av7110_write_to_decoder;
1325 dvbdemux->dmx.capabilities = (DMX_TS_FILTERING | DMX_SECTION_FILTERING |
1326 DMX_MEMORY_BASED_FILTERING);
1327
1328 dvb_dmx_init(&av7110->demux);
1329 av7110->demux.dmx.get_stc = dvb_get_stc;
1330
Oliver Endriss9e615ea2008-09-03 19:15:27 -03001331 av7110->dmxdev.filternum = (av7110->full_ts) ? 256 : 32;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001332 av7110->dmxdev.demux = &dvbdemux->dmx;
1333 av7110->dmxdev.capabilities = 0;
1334
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001335 dvb_dmxdev_init(&av7110->dmxdev, &av7110->dvb_adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001336
1337 av7110->hw_frontend.source = DMX_FRONTEND_0;
1338
1339 ret = dvbdemux->dmx.add_frontend(&dvbdemux->dmx, &av7110->hw_frontend);
1340
1341 if (ret < 0)
1342 return ret;
1343
1344 av7110->mem_frontend.source = DMX_MEMORY_FE;
1345
1346 ret = dvbdemux->dmx.add_frontend(&dvbdemux->dmx, &av7110->mem_frontend);
1347
1348 if (ret < 0)
1349 return ret;
1350
1351 ret = dvbdemux->dmx.connect_frontend(&dvbdemux->dmx,
1352 &av7110->hw_frontend);
1353 if (ret < 0)
1354 return ret;
1355
1356 av7110_av_register(av7110);
1357 av7110_ca_register(av7110);
1358
1359#ifdef CONFIG_DVB_AV7110_OSD
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001360 dvb_register_device(&av7110->dvb_adapter, &av7110->osd_dev,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001361 &dvbdev_osd, av7110, DVB_DEVICE_OSD);
1362#endif
1363
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001364 dvb_net_init(&av7110->dvb_adapter, &av7110->dvb_net, &dvbdemux->dmx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001365
1366 if (budgetpatch) {
1367 /* initialize software demux1 without its own frontend
1368 * demux1 hardware is connected to frontend0 of demux0
1369 */
1370 dvbdemux1->priv = (void *) av7110;
1371
1372 dvbdemux1->filternum = 256;
1373 dvbdemux1->feednum = 256;
1374 dvbdemux1->start_feed = budget_start_feed;
1375 dvbdemux1->stop_feed = budget_stop_feed;
1376 dvbdemux1->write_to_decoder = NULL;
1377
1378 dvbdemux1->dmx.capabilities = (DMX_TS_FILTERING | DMX_SECTION_FILTERING |
1379 DMX_MEMORY_BASED_FILTERING);
1380
1381 dvb_dmx_init(&av7110->demux1);
1382
1383 av7110->dmxdev1.filternum = 256;
1384 av7110->dmxdev1.demux = &dvbdemux1->dmx;
1385 av7110->dmxdev1.capabilities = 0;
1386
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001387 dvb_dmxdev_init(&av7110->dmxdev1, &av7110->dvb_adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001388
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001389 dvb_net_init(&av7110->dvb_adapter, &av7110->dvb_net1, &dvbdemux1->dmx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001390 printk("dvb-ttpci: additional demux1 for budget-patch registered\n");
1391 }
1392 return 0;
1393}
1394
1395
1396static void dvb_unregister(struct av7110 *av7110)
1397{
1398 struct dvb_demux *dvbdemux = &av7110->demux;
1399 struct dvb_demux *dvbdemux1 = &av7110->demux1;
1400
1401 dprintk(4, "%p\n", av7110);
1402
1403 if (!av7110->registered)
1404 return;
1405
1406 if (budgetpatch) {
1407 dvb_net_release(&av7110->dvb_net1);
1408 dvbdemux->dmx.close(&dvbdemux1->dmx);
1409 dvb_dmxdev_release(&av7110->dmxdev1);
1410 dvb_dmx_release(&av7110->demux1);
1411 }
1412
1413 dvb_net_release(&av7110->dvb_net);
1414
1415 dvbdemux->dmx.close(&dvbdemux->dmx);
1416 dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &av7110->hw_frontend);
1417 dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &av7110->mem_frontend);
1418
1419 dvb_dmxdev_release(&av7110->dmxdev);
1420 dvb_dmx_release(&av7110->demux);
1421
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001422 if (av7110->fe != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001423 dvb_unregister_frontend(av7110->fe);
Andrew de Quinceyf52a8382006-08-08 09:10:09 -03001424 dvb_frontend_detach(av7110->fe);
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001425 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001426 dvb_unregister_device(av7110->osd_dev);
1427 av7110_av_unregister(av7110);
1428 av7110_ca_unregister(av7110);
1429}
1430
1431
1432/****************************************************************************
1433 * I2C client commands
1434 ****************************************************************************/
1435
1436int i2c_writereg(struct av7110 *av7110, u8 id, u8 reg, u8 val)
1437{
1438 u8 msg[2] = { reg, val };
1439 struct i2c_msg msgs;
1440
1441 msgs.flags = 0;
1442 msgs.addr = id / 2;
1443 msgs.len = 2;
1444 msgs.buf = msg;
1445 return i2c_transfer(&av7110->i2c_adap, &msgs, 1);
1446}
1447
Linus Torvalds1da177e2005-04-16 15:20:36 -07001448u8 i2c_readreg(struct av7110 *av7110, u8 id, u8 reg)
1449{
1450 u8 mm1[] = {0x00};
1451 u8 mm2[] = {0x00};
1452 struct i2c_msg msgs[2];
1453
1454 msgs[0].flags = 0;
1455 msgs[1].flags = I2C_M_RD;
1456 msgs[0].addr = msgs[1].addr = id / 2;
1457 mm1[0] = reg;
1458 msgs[0].len = 1; msgs[1].len = 1;
1459 msgs[0].buf = mm1; msgs[1].buf = mm2;
1460 i2c_transfer(&av7110->i2c_adap, msgs, 2);
1461
1462 return mm2[0];
1463}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001464
1465/****************************************************************************
1466 * INITIALIZATION
1467 ****************************************************************************/
1468
1469
1470static int check_firmware(struct av7110* av7110)
1471{
1472 u32 crc = 0, len = 0;
1473 unsigned char *ptr;
1474
1475 /* check for firmware magic */
1476 ptr = av7110->bin_fw;
1477 if (ptr[0] != 'A' || ptr[1] != 'V' ||
1478 ptr[2] != 'F' || ptr[3] != 'W') {
1479 printk("dvb-ttpci: this is not an av7110 firmware\n");
1480 return -EINVAL;
1481 }
1482 ptr += 4;
1483
1484 /* check dpram file */
Al Viro3e085622008-05-21 00:30:51 -03001485 crc = get_unaligned_be32(ptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001486 ptr += 4;
Al Viro3e085622008-05-21 00:30:51 -03001487 len = get_unaligned_be32(ptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001488 ptr += 4;
1489 if (len >= 512) {
Alexey Dobriyanbe787ac2006-03-07 22:20:23 -03001490 printk("dvb-ttpci: dpram file is way too big.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001491 return -EINVAL;
1492 }
1493 if (crc != crc32_le(0, ptr, len)) {
1494 printk("dvb-ttpci: crc32 of dpram file does not match.\n");
1495 return -EINVAL;
1496 }
1497 av7110->bin_dpram = ptr;
1498 av7110->size_dpram = len;
1499 ptr += len;
1500
1501 /* check root file */
Al Viro3e085622008-05-21 00:30:51 -03001502 crc = get_unaligned_be32(ptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001503 ptr += 4;
Al Viro3e085622008-05-21 00:30:51 -03001504 len = get_unaligned_be32(ptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001505 ptr += 4;
1506
1507 if (len <= 200000 || len >= 300000 ||
1508 len > ((av7110->bin_fw + av7110->size_fw) - ptr)) {
1509 printk("dvb-ttpci: root file has strange size (%d). aborting.\n", len);
1510 return -EINVAL;
1511 }
1512 if( crc != crc32_le(0, ptr, len)) {
1513 printk("dvb-ttpci: crc32 of root file does not match.\n");
1514 return -EINVAL;
1515 }
1516 av7110->bin_root = ptr;
1517 av7110->size_root = len;
1518 return 0;
1519}
1520
Linus Torvalds1da177e2005-04-16 15:20:36 -07001521static void put_firmware(struct av7110* av7110)
1522{
1523 vfree(av7110->bin_fw);
1524}
1525
1526static int get_firmware(struct av7110* av7110)
1527{
1528 int ret;
1529 const struct firmware *fw;
1530
1531 /* request the av7110 firmware, this will block until someone uploads it */
1532 ret = request_firmware(&fw, "dvb-ttpci-01.fw", &av7110->dev->pci->dev);
1533 if (ret) {
1534 if (ret == -ENOENT) {
1535 printk(KERN_ERR "dvb-ttpci: could not load firmware,"
1536 " file not found: dvb-ttpci-01.fw\n");
Ville Skytt\ä12e66f62006-01-09 15:25:38 -02001537 printk(KERN_ERR "dvb-ttpci: usually this should be in "
1538 "/usr/lib/hotplug/firmware or /lib/firmware\n");
1539 printk(KERN_ERR "dvb-ttpci: and can be downloaded from"
Linus Torvalds1da177e2005-04-16 15:20:36 -07001540 " http://www.linuxtv.org/download/dvb/firmware/\n");
1541 } else
1542 printk(KERN_ERR "dvb-ttpci: cannot request firmware"
1543 " (error %i)\n", ret);
1544 return -EINVAL;
1545 }
1546
1547 if (fw->size <= 200000) {
1548 printk("dvb-ttpci: this firmware is way too small.\n");
1549 release_firmware(fw);
1550 return -EINVAL;
1551 }
1552
1553 /* check if the firmware is available */
Jesper Juhld9bf2c02007-08-25 11:23:54 -03001554 av7110->bin_fw = vmalloc(fw->size);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001555 if (NULL == av7110->bin_fw) {
1556 dprintk(1, "out of memory\n");
1557 release_firmware(fw);
1558 return -ENOMEM;
1559 }
1560
1561 memcpy(av7110->bin_fw, fw->data, fw->size);
1562 av7110->size_fw = fw->size;
1563 if ((ret = check_firmware(av7110)))
1564 vfree(av7110->bin_fw);
1565
1566 release_firmware(fw);
1567 return ret;
1568}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001569
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001570static int alps_bsrv2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001571{
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001572 struct av7110* av7110 = fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001573 u8 pwr = 0;
1574 u8 buf[4];
1575 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
1576 u32 div = (params->frequency + 479500) / 125;
1577
1578 if (params->frequency > 2000000) pwr = 3;
1579 else if (params->frequency > 1800000) pwr = 2;
1580 else if (params->frequency > 1600000) pwr = 1;
1581 else if (params->frequency > 1200000) pwr = 0;
1582 else if (params->frequency >= 1100000) pwr = 1;
1583 else pwr = 2;
1584
1585 buf[0] = (div >> 8) & 0x7f;
1586 buf[1] = div & 0xff;
1587 buf[2] = ((div & 0x18000) >> 10) | 0x95;
1588 buf[3] = (pwr << 6) | 0x30;
1589
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -08001590 // NOTE: since we're using a prescaler of 2, we set the
Linus Torvalds1da177e2005-04-16 15:20:36 -07001591 // divisor frequency to 62.5kHz and divide by 125 above
1592
Patrick Boettcherdea74862006-05-14 05:01:31 -03001593 if (fe->ops.i2c_gate_ctrl)
1594 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001595 if (i2c_transfer (&av7110->i2c_adap, &msg, 1) != 1)
1596 return -EIO;
1597 return 0;
1598}
1599
1600static struct ves1x93_config alps_bsrv2_config = {
1601 .demod_address = 0x08,
1602 .xin = 90100000UL,
1603 .invert_pwm = 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001604};
1605
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001606static int alps_tdbe2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001607{
1608 struct av7110* av7110 = fe->dvb->priv;
1609 u32 div;
1610 u8 data[4];
1611 struct i2c_msg msg = { .addr = 0x62, .flags = 0, .buf = data, .len = sizeof(data) };
1612
1613 div = (params->frequency + 35937500 + 31250) / 62500;
1614
1615 data[0] = (div >> 8) & 0x7f;
1616 data[1] = div & 0xff;
1617 data[2] = 0x85 | ((div >> 10) & 0x60);
1618 data[3] = (params->frequency < 174000000 ? 0x88 : params->frequency < 470000000 ? 0x84 : 0x81);
1619
Patrick Boettcherdea74862006-05-14 05:01:31 -03001620 if (fe->ops.i2c_gate_ctrl)
1621 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001622 if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
1623 return -EIO;
1624 return 0;
1625}
1626
1627static struct ves1820_config alps_tdbe2_config = {
1628 .demod_address = 0x09,
1629 .xin = 57840000UL,
1630 .invert = 1,
1631 .selagc = VES1820_SELAGC_SIGNAMPERR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001632};
1633
1634
1635
1636
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001637static int grundig_29504_451_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001638{
1639 struct av7110* av7110 = fe->dvb->priv;
1640 u32 div;
1641 u8 data[4];
1642 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
1643
1644 div = params->frequency / 125;
1645 data[0] = (div >> 8) & 0x7f;
1646 data[1] = div & 0xff;
1647 data[2] = 0x8e;
1648 data[3] = 0x00;
1649
Patrick Boettcherdea74862006-05-14 05:01:31 -03001650 if (fe->ops.i2c_gate_ctrl)
1651 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001652 if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
1653 return -EIO;
1654 return 0;
1655}
1656
1657static struct tda8083_config grundig_29504_451_config = {
1658 .demod_address = 0x68,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001659};
1660
1661
1662
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001663static int philips_cd1516_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001664{
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -08001665 struct av7110* av7110 = fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001666 u32 div;
1667 u32 f = params->frequency;
1668 u8 data[4];
1669 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
1670
1671 div = (f + 36125000 + 31250) / 62500;
1672
1673 data[0] = (div >> 8) & 0x7f;
1674 data[1] = div & 0xff;
1675 data[2] = 0x8e;
1676 data[3] = (f < 174000000 ? 0xa1 : f < 470000000 ? 0x92 : 0x34);
1677
Patrick Boettcherdea74862006-05-14 05:01:31 -03001678 if (fe->ops.i2c_gate_ctrl)
1679 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001680 if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
1681 return -EIO;
1682 return 0;
1683}
1684
1685static struct ves1820_config philips_cd1516_config = {
1686 .demod_address = 0x09,
1687 .xin = 57840000UL,
1688 .invert = 1,
1689 .selagc = VES1820_SELAGC_SIGNAMPERR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001690};
1691
1692
1693
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001694static int alps_tdlb7_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001695{
1696 struct av7110* av7110 = fe->dvb->priv;
1697 u32 div, pwr;
1698 u8 data[4];
1699 struct i2c_msg msg = { .addr = 0x60, .flags = 0, .buf = data, .len = sizeof(data) };
1700
1701 div = (params->frequency + 36200000) / 166666;
1702
1703 if (params->frequency <= 782000000)
1704 pwr = 1;
1705 else
1706 pwr = 2;
1707
1708 data[0] = (div >> 8) & 0x7f;
1709 data[1] = div & 0xff;
1710 data[2] = 0x85;
1711 data[3] = pwr << 6;
1712
Patrick Boettcherdea74862006-05-14 05:01:31 -03001713 if (fe->ops.i2c_gate_ctrl)
1714 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001715 if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
1716 return -EIO;
1717 return 0;
1718}
1719
1720static int alps_tdlb7_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name)
1721{
Oliver Endrissd98821e2006-09-14 00:15:13 -03001722#if defined(CONFIG_DVB_SP8870) || defined(CONFIG_DVB_SP8870_MODULE)
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001723 struct av7110* av7110 = fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001724
1725 return request_firmware(fw, name, &av7110->dev->pci->dev);
Oliver Endrissd98821e2006-09-14 00:15:13 -03001726#else
1727 return -EINVAL;
1728#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001729}
1730
1731static struct sp8870_config alps_tdlb7_config = {
1732
1733 .demod_address = 0x71,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001734 .request_firmware = alps_tdlb7_request_firmware,
1735};
1736
1737
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001738static u8 nexusca_stv0297_inittab[] = {
1739 0x80, 0x01,
1740 0x80, 0x00,
1741 0x81, 0x01,
1742 0x81, 0x00,
1743 0x00, 0x09,
1744 0x01, 0x69,
1745 0x03, 0x00,
1746 0x04, 0x00,
1747 0x07, 0x00,
1748 0x08, 0x00,
1749 0x20, 0x00,
1750 0x21, 0x40,
1751 0x22, 0x00,
1752 0x23, 0x00,
1753 0x24, 0x40,
1754 0x25, 0x88,
1755 0x30, 0xff,
1756 0x31, 0x00,
1757 0x32, 0xff,
1758 0x33, 0x00,
1759 0x34, 0x50,
1760 0x35, 0x7f,
1761 0x36, 0x00,
1762 0x37, 0x20,
1763 0x38, 0x00,
1764 0x40, 0x1c,
1765 0x41, 0xff,
1766 0x42, 0x29,
1767 0x43, 0x00,
1768 0x44, 0xff,
1769 0x45, 0x00,
1770 0x46, 0x00,
1771 0x49, 0x04,
1772 0x4a, 0x00,
1773 0x4b, 0x7b,
1774 0x52, 0x30,
1775 0x55, 0xae,
1776 0x56, 0x47,
1777 0x57, 0xe1,
1778 0x58, 0x3a,
1779 0x5a, 0x1e,
1780 0x5b, 0x34,
1781 0x60, 0x00,
1782 0x63, 0x00,
1783 0x64, 0x00,
1784 0x65, 0x00,
1785 0x66, 0x00,
1786 0x67, 0x00,
1787 0x68, 0x00,
1788 0x69, 0x00,
1789 0x6a, 0x02,
1790 0x6b, 0x00,
1791 0x70, 0xff,
1792 0x71, 0x00,
1793 0x72, 0x00,
1794 0x73, 0x00,
1795 0x74, 0x0c,
1796 0x80, 0x00,
1797 0x81, 0x00,
1798 0x82, 0x00,
1799 0x83, 0x00,
1800 0x84, 0x04,
1801 0x85, 0x80,
1802 0x86, 0x24,
1803 0x87, 0x78,
1804 0x88, 0x10,
1805 0x89, 0x00,
1806 0x90, 0x01,
1807 0x91, 0x01,
1808 0xa0, 0x04,
1809 0xa1, 0x00,
1810 0xa2, 0x00,
1811 0xb0, 0x91,
1812 0xb1, 0x0b,
1813 0xc0, 0x53,
1814 0xc1, 0x70,
1815 0xc2, 0x12,
1816 0xd0, 0x00,
1817 0xd1, 0x00,
1818 0xd2, 0x00,
1819 0xd3, 0x00,
1820 0xd4, 0x00,
1821 0xd5, 0x00,
1822 0xde, 0x00,
1823 0xdf, 0x00,
1824 0x61, 0x49,
1825 0x62, 0x0b,
1826 0x53, 0x08,
1827 0x59, 0x08,
1828 0xff, 0xff,
1829};
Linus Torvalds1da177e2005-04-16 15:20:36 -07001830
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001831static int nexusca_stv0297_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001832{
1833 struct av7110* av7110 = fe->dvb->priv;
1834 u32 div;
1835 u8 data[4];
1836 struct i2c_msg msg = { .addr = 0x63, .flags = 0, .buf = data, .len = sizeof(data) };
1837 struct i2c_msg readmsg = { .addr = 0x63, .flags = I2C_M_RD, .buf = data, .len = 1 };
1838 int i;
1839
1840 div = (params->frequency + 36150000 + 31250) / 62500;
1841
1842 data[0] = (div >> 8) & 0x7f;
1843 data[1] = div & 0xff;
1844 data[2] = 0xce;
1845
1846 if (params->frequency < 45000000)
1847 return -EINVAL;
1848 else if (params->frequency < 137000000)
1849 data[3] = 0x01;
1850 else if (params->frequency < 403000000)
1851 data[3] = 0x02;
1852 else if (params->frequency < 860000000)
1853 data[3] = 0x04;
1854 else
1855 return -EINVAL;
1856
Patrick Boettcherdea74862006-05-14 05:01:31 -03001857 if (fe->ops.i2c_gate_ctrl)
1858 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001859 if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1) {
1860 printk("nexusca: pll transfer failed!\n");
1861 return -EIO;
1862 }
1863
1864 // wait for PLL lock
1865 for(i = 0; i < 20; i++) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001866 if (fe->ops.i2c_gate_ctrl)
1867 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001868 if (i2c_transfer(&av7110->i2c_adap, &readmsg, 1) == 1)
1869 if (data[0] & 0x40) break;
1870 msleep(10);
1871 }
1872
1873 return 0;
1874}
1875
1876static struct stv0297_config nexusca_stv0297_config = {
1877
1878 .demod_address = 0x1C,
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001879 .inittab = nexusca_stv0297_inittab,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001880 .invert = 1,
Thomas Kaiserb8d4c232006-04-27 21:45:20 -03001881 .stop_during_read = 1,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001882};
1883
1884
1885
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03001886static int grundig_29504_401_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001887{
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001888 struct av7110* av7110 = fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001889 u32 div;
1890 u8 cfg, cpump, band_select;
1891 u8 data[4];
1892 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
1893
1894 div = (36125000 + params->frequency) / 166666;
1895
1896 cfg = 0x88;
1897
1898 if (params->frequency < 175000000) cpump = 2;
1899 else if (params->frequency < 390000000) cpump = 1;
1900 else if (params->frequency < 470000000) cpump = 2;
1901 else if (params->frequency < 750000000) cpump = 1;
1902 else cpump = 3;
1903
1904 if (params->frequency < 175000000) band_select = 0x0e;
1905 else if (params->frequency < 470000000) band_select = 0x05;
1906 else band_select = 0x03;
1907
1908 data[0] = (div >> 8) & 0x7f;
1909 data[1] = div & 0xff;
1910 data[2] = ((div >> 10) & 0x60) | cfg;
1911 data[3] = (cpump << 6) | band_select;
1912
Patrick Boettcherdea74862006-05-14 05:01:31 -03001913 if (fe->ops.i2c_gate_ctrl)
1914 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001915 if (i2c_transfer (&av7110->i2c_adap, &msg, 1) != 1) return -EIO;
1916 return 0;
1917}
1918
1919static struct l64781_config grundig_29504_401_config = {
1920 .demod_address = 0x55,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001921};
1922
1923
1924
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001925static int av7110_fe_lock_fix(struct av7110* av7110, fe_status_t status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001926{
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001927 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001928 int synced = (status & FE_HAS_LOCK) ? 1 : 0;
1929
1930 av7110->fe_status = status;
1931
1932 if (av7110->fe_synced == synced)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001933 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001934
Oliver Endriss14500d42007-03-03 14:45:48 -03001935 if (av7110->playing) {
1936 av7110->fe_synced = synced;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001937 return 0;
Oliver Endriss14500d42007-03-03 14:45:48 -03001938 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001939
Ingo Molnar3593cab2006-02-07 06:49:14 -02001940 if (mutex_lock_interruptible(&av7110->pid_mutex))
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001941 return -ERESTARTSYS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001942
Oliver Endriss34612152005-07-07 17:58:02 -07001943 if (synced) {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001944 ret = SetPIDs(av7110, av7110->pids[DMX_PES_VIDEO],
Linus Torvalds1da177e2005-04-16 15:20:36 -07001945 av7110->pids[DMX_PES_AUDIO],
1946 av7110->pids[DMX_PES_TELETEXT], 0,
1947 av7110->pids[DMX_PES_PCR]);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001948 if (!ret)
1949 ret = av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, Scan, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001950 } else {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001951 ret = SetPIDs(av7110, 0, 0, 0, 0, 0);
1952 if (!ret) {
1953 ret = av7110_fw_cmd(av7110, COMTYPE_PID_FILTER, FlushTSQueue, 0);
1954 if (!ret)
1955 ret = av7110_wait_msgstate(av7110, GPMQBusy);
1956 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001957 }
1958
Oliver Endriss34612152005-07-07 17:58:02 -07001959 if (!ret)
1960 av7110->fe_synced = synced;
1961
Ingo Molnar3593cab2006-02-07 06:49:14 -02001962 mutex_unlock(&av7110->pid_mutex);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001963 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001964}
1965
1966static int av7110_fe_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
1967{
1968 struct av7110* av7110 = fe->dvb->priv;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001969
1970 int ret = av7110_fe_lock_fix(av7110, 0);
Oliver Endriss66190a22006-01-09 15:32:42 -02001971 if (!ret) {
1972 av7110->saved_fe_params = *params;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001973 ret = av7110->fe_set_frontend(fe, params);
Oliver Endriss66190a22006-01-09 15:32:42 -02001974 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001975 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001976}
1977
1978static int av7110_fe_init(struct dvb_frontend* fe)
1979{
1980 struct av7110* av7110 = fe->dvb->priv;
1981
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001982 int ret = av7110_fe_lock_fix(av7110, 0);
1983 if (!ret)
1984 ret = av7110->fe_init(fe);
1985 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001986}
1987
1988static int av7110_fe_read_status(struct dvb_frontend* fe, fe_status_t* status)
1989{
1990 struct av7110* av7110 = fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001991
1992 /* call the real implementation */
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001993 int ret = av7110->fe_read_status(fe, status);
1994 if (!ret)
1995 if (((*status ^ av7110->fe_status) & FE_HAS_LOCK) && (*status & FE_HAS_LOCK))
1996 ret = av7110_fe_lock_fix(av7110, *status);
1997 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001998}
1999
2000static int av7110_fe_diseqc_reset_overload(struct dvb_frontend* fe)
2001{
2002 struct av7110* av7110 = fe->dvb->priv;
2003
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002004 int ret = av7110_fe_lock_fix(av7110, 0);
2005 if (!ret)
2006 ret = av7110->fe_diseqc_reset_overload(fe);
2007 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002008}
2009
2010static int av7110_fe_diseqc_send_master_cmd(struct dvb_frontend* fe,
2011 struct dvb_diseqc_master_cmd* cmd)
2012{
2013 struct av7110* av7110 = fe->dvb->priv;
2014
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002015 int ret = av7110_fe_lock_fix(av7110, 0);
Oliver Endriss66190a22006-01-09 15:32:42 -02002016 if (!ret) {
2017 av7110->saved_master_cmd = *cmd;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002018 ret = av7110->fe_diseqc_send_master_cmd(fe, cmd);
Oliver Endriss66190a22006-01-09 15:32:42 -02002019 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002020 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002021}
2022
2023static int av7110_fe_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd)
2024{
2025 struct av7110* av7110 = fe->dvb->priv;
2026
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002027 int ret = av7110_fe_lock_fix(av7110, 0);
Oliver Endriss66190a22006-01-09 15:32:42 -02002028 if (!ret) {
2029 av7110->saved_minicmd = minicmd;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002030 ret = av7110->fe_diseqc_send_burst(fe, minicmd);
Oliver Endriss66190a22006-01-09 15:32:42 -02002031 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002032 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002033}
2034
2035static int av7110_fe_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
2036{
2037 struct av7110* av7110 = fe->dvb->priv;
2038
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002039 int ret = av7110_fe_lock_fix(av7110, 0);
Oliver Endriss66190a22006-01-09 15:32:42 -02002040 if (!ret) {
2041 av7110->saved_tone = tone;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002042 ret = av7110->fe_set_tone(fe, tone);
Oliver Endriss66190a22006-01-09 15:32:42 -02002043 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002044 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002045}
2046
2047static int av7110_fe_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
2048{
2049 struct av7110* av7110 = fe->dvb->priv;
2050
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002051 int ret = av7110_fe_lock_fix(av7110, 0);
Oliver Endriss66190a22006-01-09 15:32:42 -02002052 if (!ret) {
2053 av7110->saved_voltage = voltage;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002054 ret = av7110->fe_set_voltage(fe, voltage);
Oliver Endriss66190a22006-01-09 15:32:42 -02002055 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002056 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002057}
2058
Peter Beutner400b7082006-01-09 15:32:43 -02002059static int av7110_fe_dishnetwork_send_legacy_command(struct dvb_frontend* fe, unsigned long cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002060{
2061 struct av7110* av7110 = fe->dvb->priv;
2062
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002063 int ret = av7110_fe_lock_fix(av7110, 0);
2064 if (!ret)
2065 ret = av7110->fe_dishnetwork_send_legacy_command(fe, cmd);
2066 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002067}
2068
Oliver Endriss66190a22006-01-09 15:32:42 -02002069static void dvb_s_recover(struct av7110* av7110)
2070{
2071 av7110_fe_init(av7110->fe);
2072
2073 av7110_fe_set_voltage(av7110->fe, av7110->saved_voltage);
2074 if (av7110->saved_master_cmd.msg_len) {
2075 msleep(20);
2076 av7110_fe_diseqc_send_master_cmd(av7110->fe, &av7110->saved_master_cmd);
2077 }
2078 msleep(20);
2079 av7110_fe_diseqc_send_burst(av7110->fe, av7110->saved_minicmd);
2080 msleep(20);
2081 av7110_fe_set_tone(av7110->fe, av7110->saved_tone);
2082
2083 av7110_fe_set_frontend(av7110->fe, &av7110->saved_fe_params);
2084}
2085
Linus Torvalds1da177e2005-04-16 15:20:36 -07002086static u8 read_pwm(struct av7110* av7110)
2087{
2088 u8 b = 0xff;
2089 u8 pwm;
2090 struct i2c_msg msg[] = { { .addr = 0x50,.flags = 0,.buf = &b,.len = 1 },
2091 { .addr = 0x50,.flags = I2C_M_RD,.buf = &pwm,.len = 1} };
2092
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -08002093 if ((i2c_transfer(&av7110->i2c_adap, msg, 2) != 2) || (pwm == 0xff))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002094 pwm = 0x48;
2095
2096 return pwm;
2097}
2098
2099static int frontend_init(struct av7110 *av7110)
2100{
2101 int ret;
2102
2103 if (av7110->dev->pci->subsystem_vendor == 0x110a) {
2104 switch(av7110->dev->pci->subsystem_device) {
2105 case 0x0000: // Fujitsu/Siemens DVB-Cable (ves1820/Philips CD1516(??))
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002106 av7110->fe = dvb_attach(ves1820_attach, &philips_cd1516_config,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002107 &av7110->i2c_adap, read_pwm(av7110));
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002108 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002109 av7110->fe->ops.tuner_ops.set_params = philips_cd1516_tuner_set_params;
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002110 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002111 break;
2112 }
2113
2114 } else if (av7110->dev->pci->subsystem_vendor == 0x13c2) {
2115 switch(av7110->dev->pci->subsystem_device) {
2116 case 0x0000: // Hauppauge/TT WinTV DVB-S rev1.X
2117 case 0x0003: // Hauppauge/TT WinTV Nexus-S Rev 2.X
2118 case 0x1002: // Hauppauge/TT WinTV DVB-S rev1.3SE
2119
2120 // try the ALPS BSRV2 first of all
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002121 av7110->fe = dvb_attach(ves1x93_attach, &alps_bsrv2_config, &av7110->i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002122 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002123 av7110->fe->ops.tuner_ops.set_params = alps_bsrv2_tuner_set_params;
2124 av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
2125 av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
2126 av7110->fe->ops.set_tone = av7110_set_tone;
Oliver Endriss66190a22006-01-09 15:32:42 -02002127 av7110->recover = dvb_s_recover;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002128 break;
2129 }
2130
2131 // try the ALPS BSRU6 now
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002132 av7110->fe = dvb_attach(stv0299_attach, &alps_bsru6_config, &av7110->i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002133 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002134 av7110->fe->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03002135 av7110->fe->tuner_priv = &av7110->i2c_adap;
2136
Patrick Boettcherdea74862006-05-14 05:01:31 -03002137 av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
2138 av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
2139 av7110->fe->ops.set_tone = av7110_set_tone;
Oliver Endriss66190a22006-01-09 15:32:42 -02002140 av7110->recover = dvb_s_recover;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002141 break;
2142 }
2143
2144 // Try the grundig 29504-451
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002145 av7110->fe = dvb_attach(tda8083_attach, &grundig_29504_451_config, &av7110->i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002146 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002147 av7110->fe->ops.tuner_ops.set_params = grundig_29504_451_tuner_set_params;
2148 av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
2149 av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
2150 av7110->fe->ops.set_tone = av7110_set_tone;
Oliver Endriss66190a22006-01-09 15:32:42 -02002151 av7110->recover = dvb_s_recover;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002152 break;
2153 }
2154
2155 /* Try DVB-C cards */
2156 switch(av7110->dev->pci->subsystem_device) {
2157 case 0x0000:
2158 /* Siemens DVB-C (full-length card) VES1820/Philips CD1516 */
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002159 av7110->fe = dvb_attach(ves1820_attach, &philips_cd1516_config, &av7110->i2c_adap,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002160 read_pwm(av7110));
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002161 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002162 av7110->fe->ops.tuner_ops.set_params = philips_cd1516_tuner_set_params;
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002163 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002164 break;
2165 case 0x0003:
Adrian Bunkf3688fc2006-03-29 22:46:12 -03002166 /* Hauppauge DVB-C 2.1 VES1820/ALPS TDBE2 */
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002167 av7110->fe = dvb_attach(ves1820_attach, &alps_tdbe2_config, &av7110->i2c_adap,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002168 read_pwm(av7110));
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002169 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002170 av7110->fe->ops.tuner_ops.set_params = alps_tdbe2_tuner_set_params;
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002171 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002172 break;
2173 }
2174 break;
2175
2176 case 0x0001: // Hauppauge/TT Nexus-T premium rev1.X
Oliver Endriss8d90ee52006-08-07 02:04:26 -03002177 // try ALPS TDLB7 first, then Grundig 29504-401
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002178 av7110->fe = dvb_attach(sp8870_attach, &alps_tdlb7_config, &av7110->i2c_adap);
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002179 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002180 av7110->fe->ops.tuner_ops.set_params = alps_tdlb7_tuner_set_params;
Oliver Endriss8d90ee52006-08-07 02:04:26 -03002181 break;
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002182 }
Oliver Endriss8d90ee52006-08-07 02:04:26 -03002183 /* fall-thru */
2184
2185 case 0x0008: // Hauppauge/TT DVB-T
2186 // Grundig 29504-401
2187 av7110->fe = dvb_attach(l64781_attach, &grundig_29504_401_config, &av7110->i2c_adap);
2188 if (av7110->fe)
2189 av7110->fe->ops.tuner_ops.set_params = grundig_29504_401_tuner_set_params;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002190 break;
2191
2192 case 0x0002: // Hauppauge/TT DVB-C premium rev2.X
2193
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002194 av7110->fe = dvb_attach(ves1820_attach, &alps_tdbe2_config, &av7110->i2c_adap, read_pwm(av7110));
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002195 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002196 av7110->fe->ops.tuner_ops.set_params = alps_tdbe2_tuner_set_params;
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002197 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002198 break;
2199
Oliver Endriss8bd63012006-02-07 06:49:11 -02002200 case 0x0004: // Galaxis DVB-S rev1.3
2201 /* ALPS BSRV2 */
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002202 av7110->fe = dvb_attach(ves1x93_attach, &alps_bsrv2_config, &av7110->i2c_adap);
Oliver Endriss8bd63012006-02-07 06:49:11 -02002203 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002204 av7110->fe->ops.tuner_ops.set_params = alps_bsrv2_tuner_set_params;
2205 av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
2206 av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
2207 av7110->fe->ops.set_tone = av7110_set_tone;
Oliver Endriss8bd63012006-02-07 06:49:11 -02002208 av7110->recover = dvb_s_recover;
2209 }
2210 break;
2211
Linus Torvalds1da177e2005-04-16 15:20:36 -07002212 case 0x0006: /* Fujitsu-Siemens DVB-S rev 1.6 */
2213 /* Grundig 29504-451 */
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002214 av7110->fe = dvb_attach(tda8083_attach, &grundig_29504_451_config, &av7110->i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002215 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002216 av7110->fe->ops.tuner_ops.set_params = grundig_29504_451_tuner_set_params;
2217 av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
2218 av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
2219 av7110->fe->ops.set_tone = av7110_set_tone;
Oliver Endriss66190a22006-01-09 15:32:42 -02002220 av7110->recover = dvb_s_recover;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002221 }
2222 break;
2223
Linus Torvalds1da177e2005-04-16 15:20:36 -07002224 case 0x000A: // Hauppauge/TT Nexus-CA rev1.X
2225
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002226 av7110->fe = dvb_attach(stv0297_attach, &nexusca_stv0297_config, &av7110->i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002227 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002228 av7110->fe->ops.tuner_ops.set_params = nexusca_stv0297_tuner_set_params;
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03002229
Linus Torvalds1da177e2005-04-16 15:20:36 -07002230 /* set TDA9819 into DVB mode */
Marco Schluessler6a857742006-07-10 03:34:16 -03002231 saa7146_setgpio(av7110->dev, 1, SAA7146_GPIO_OUTLO); // TDA9819 pin9(STD)
2232 saa7146_setgpio(av7110->dev, 3, SAA7146_GPIO_OUTLO); // TDA9819 pin30(VIF)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002233
2234 /* tuner on this needs a slower i2c bus speed */
2235 av7110->dev->i2c_bitrate = SAA7146_I2C_BUS_BIT_RATE_240;
2236 break;
2237 }
Johannes Stezenbach3dfaebd2005-05-16 21:54:19 -07002238 break;
2239
2240 case 0x000E: /* Hauppauge/TT Nexus-S rev 2.3 */
2241 /* ALPS BSBE1 */
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002242 av7110->fe = dvb_attach(stv0299_attach, &alps_bsbe1_config, &av7110->i2c_adap);
Oliver Endrisseb3daf32006-01-09 15:25:05 -02002243 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002244 av7110->fe->ops.tuner_ops.set_params = alps_bsbe1_tuner_set_params;
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03002245 av7110->fe->tuner_priv = &av7110->i2c_adap;
2246
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002247 if (dvb_attach(lnbp21_attach, av7110->fe, &av7110->i2c_adap, 0, 0) == NULL) {
Oliver Endrissdb5d91e2006-02-28 10:32:25 -03002248 printk("dvb-ttpci: LNBP21 not found!\n");
Patrick Boettcherdea74862006-05-14 05:01:31 -03002249 if (av7110->fe->ops.release)
2250 av7110->fe->ops.release(av7110->fe);
Oliver Endrissdb5d91e2006-02-28 10:32:25 -03002251 av7110->fe = NULL;
2252 } else {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002253 av7110->fe->ops.dishnetwork_send_legacy_command = NULL;
Oliver Endrissdb5d91e2006-02-28 10:32:25 -03002254 av7110->recover = dvb_s_recover;
2255 }
Oliver Endrisseb3daf32006-01-09 15:25:05 -02002256 }
Johannes Stezenbach3dfaebd2005-05-16 21:54:19 -07002257 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002258 }
2259 }
2260
2261 if (!av7110->fe) {
2262 /* FIXME: propagate the failure code from the lower layers */
2263 ret = -ENOMEM;
Bjorn Helgaas29e66a62008-09-04 17:24:51 -03002264 printk("dvb-ttpci: A frontend driver was not found for device [%04x:%04x] subsystem [%04x:%04x]\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002265 av7110->dev->pci->vendor,
2266 av7110->dev->pci->device,
2267 av7110->dev->pci->subsystem_vendor,
2268 av7110->dev->pci->subsystem_device);
2269 } else {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002270 FE_FUNC_OVERRIDE(av7110->fe->ops.init, av7110->fe_init, av7110_fe_init);
2271 FE_FUNC_OVERRIDE(av7110->fe->ops.read_status, av7110->fe_read_status, av7110_fe_read_status);
2272 FE_FUNC_OVERRIDE(av7110->fe->ops.diseqc_reset_overload, av7110->fe_diseqc_reset_overload, av7110_fe_diseqc_reset_overload);
2273 FE_FUNC_OVERRIDE(av7110->fe->ops.diseqc_send_master_cmd, av7110->fe_diseqc_send_master_cmd, av7110_fe_diseqc_send_master_cmd);
2274 FE_FUNC_OVERRIDE(av7110->fe->ops.diseqc_send_burst, av7110->fe_diseqc_send_burst, av7110_fe_diseqc_send_burst);
2275 FE_FUNC_OVERRIDE(av7110->fe->ops.set_tone, av7110->fe_set_tone, av7110_fe_set_tone);
Yoann Padioleau8f40a9f2007-07-16 16:54:49 -03002276 FE_FUNC_OVERRIDE(av7110->fe->ops.set_voltage, av7110->fe_set_voltage, av7110_fe_set_voltage);
Patrick Boettcherdea74862006-05-14 05:01:31 -03002277 FE_FUNC_OVERRIDE(av7110->fe->ops.dishnetwork_send_legacy_command, av7110->fe_dishnetwork_send_legacy_command, av7110_fe_dishnetwork_send_legacy_command);
2278 FE_FUNC_OVERRIDE(av7110->fe->ops.set_frontend, av7110->fe_set_frontend, av7110_fe_set_frontend);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002279
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07002280 ret = dvb_register_frontend(&av7110->dvb_adapter, av7110->fe);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002281 if (ret < 0) {
2282 printk("av7110: Frontend registration failed!\n");
Andrew de Quinceyf52a8382006-08-08 09:10:09 -03002283 dvb_frontend_detach(av7110->fe);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002284 av7110->fe = NULL;
2285 }
2286 }
2287 return ret;
2288}
2289
2290/* Budgetpatch note:
2291 * Original hardware design by Roberto Deza:
2292 * There is a DVB_Wiki at
2293 * http://212.227.36.83/linuxtv/wiki/index.php/Main_Page
2294 * where is described this 'DVB TT Budget Patch', on Card Modding:
2295 * http://212.227.36.83/linuxtv/wiki/index.php/DVB_TT_Budget_Patch
2296 * On the short description there is also a link to a external file,
2297 * with more details:
2298 * http://perso.wanadoo.es/jesussolano/Ttf_tsc1.zip
2299 *
2300 * New software triggering design by Emard that works on
2301 * original Roberto Deza's hardware:
2302 *
2303 * rps1 code for budgetpatch will copy internal HS event to GPIO3 pin.
2304 * GPIO3 is in budget-patch hardware connectd to port B VSYNC
2305 * HS is an internal event of 7146, accessible with RPS
2306 * and temporarily raised high every n lines
2307 * (n in defined in the RPS_THRESH1 counter threshold)
2308 * I think HS is raised high on the beginning of the n-th line
2309 * and remains high until this n-th line that triggered
2310 * it is completely received. When the receiption of n-th line
2311 * ends, HS is lowered.
2312 *
2313 * To transmit data over DMA, 7146 needs changing state at
2314 * port B VSYNC pin. Any changing of port B VSYNC will
2315 * cause some DMA data transfer, with more or less packets loss.
2316 * It depends on the phase and frequency of VSYNC and
2317 * the way of 7146 is instructed to trigger on port B (defined
2318 * in DD1_INIT register, 3rd nibble from the right valid
2319 * numbers are 0-7, see datasheet)
2320 *
2321 * The correct triggering can minimize packet loss,
2322 * dvbtraffic should give this stable bandwidths:
2323 * 22k transponder = 33814 kbit/s
2324 * 27.5k transponder = 38045 kbit/s
2325 * by experiment it is found that the best results
2326 * (stable bandwidths and almost no packet loss)
2327 * are obtained using DD1_INIT triggering number 2
2328 * (Va at rising edge of VS Fa = HS x VS-failing forced toggle)
2329 * and a VSYNC phase that occurs in the middle of DMA transfer
2330 * (about byte 188*512=96256 in the DMA window).
2331 *
2332 * Phase of HS is still not clear to me how to control,
2333 * It just happens to be so. It can be seen if one enables
2334 * RPS_IRQ and print Event Counter 1 in vpeirq(). Every
2335 * time RPS_INTERRUPT is called, the Event Counter 1 will
2336 * increment. That's how the 7146 is programmed to do event
2337 * counting in this budget-patch.c
2338 * I *think* HPS setting has something to do with the phase
2339 * of HS but I cant be 100% sure in that.
2340 *
2341 * hardware debug note: a working budget card (including budget patch)
2342 * with vpeirq() interrupt setup in mode "0x90" (every 64K) will
2343 * generate 3 interrupts per 25-Hz DMA frame of 2*188*512 bytes
2344 * and that means 3*25=75 Hz of interrupt freqency, as seen by
2345 * watch cat /proc/interrupts
2346 *
2347 * If this frequency is 3x lower (and data received in the DMA
2348 * buffer don't start with 0x47, but in the middle of packets,
2349 * whose lengths appear to be like 188 292 188 104 etc.
2350 * this means VSYNC line is not connected in the hardware.
2351 * (check soldering pcb and pins)
2352 * The same behaviour of missing VSYNC can be duplicated on budget
2353 * cards, by seting DD1_INIT trigger mode 7 in 3rd nibble.
2354 */
Johannes Stezenbach1be11e32006-02-27 00:09:20 -03002355static int __devinit av7110_attach(struct saa7146_dev* dev,
2356 struct saa7146_pci_extension_data *pci_ext)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002357{
2358 const int length = TS_WIDTH * TS_HEIGHT;
2359 struct pci_dev *pdev = dev->pci;
2360 struct av7110 *av7110;
Herbert Poetzl8eec1422007-02-08 14:32:43 -03002361 struct task_struct *thread;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002362 int ret, count = 0;
2363
2364 dprintk(4, "dev: %p\n", dev);
2365
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -08002366 /* Set RPS_IRQ to 1 to track rps1 activity.
2367 * Enabling this won't send any interrupt to PC CPU.
2368 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002369#define RPS_IRQ 0
2370
2371 if (budgetpatch == 1) {
2372 budgetpatch = 0;
2373 /* autodetect the presence of budget patch
2374 * this only works if saa7146 has been recently
2375 * reset with with MASK_31 to MC1
2376 *
2377 * will wait for VBI_B event (vertical blank at port B)
2378 * and will reset GPIO3 after VBI_B is detected.
2379 * (GPIO3 should be raised high by CPU to
2380 * test if GPIO3 will generate vertical blank signal
2381 * in budget patch GPIO3 is connected to VSYNC_B
2382 */
2383
2384 /* RESET SAA7146 */
2385 saa7146_write(dev, MC1, MASK_31);
2386 /* autodetection success seems to be time-dependend after reset */
2387
2388 /* Fix VSYNC level */
2389 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
2390 /* set vsync_b triggering */
2391 saa7146_write(dev, DD1_STREAM_B, 0);
2392 /* port B VSYNC at rising edge */
2393 saa7146_write(dev, DD1_INIT, 0x00000200);
2394 saa7146_write(dev, BRS_CTRL, 0x00000000); // VBI
2395 saa7146_write(dev, MC2,
2396 1 * (MASK_08 | MASK_24) | // BRS control
2397 0 * (MASK_09 | MASK_25) | // a
2398 1 * (MASK_10 | MASK_26) | // b
2399 0 * (MASK_06 | MASK_22) | // HPS_CTRL1
2400 0 * (MASK_05 | MASK_21) | // HPS_CTRL2
2401 0 * (MASK_01 | MASK_15) // DEBI
2402 );
2403
2404 /* start writing RPS1 code from beginning */
2405 count = 0;
2406 /* Disable RPS1 */
2407 saa7146_write(dev, MC1, MASK_29);
2408 /* RPS1 timeout disable */
2409 saa7146_write(dev, RPS_TOV1, 0);
Al Viro153755a2008-06-22 14:19:39 -03002410 WRITE_RPS1(CMD_PAUSE | EVT_VBI_B);
2411 WRITE_RPS1(CMD_WR_REG_MASK | (GPIO_CTRL>>2));
2412 WRITE_RPS1(GPIO3_MSK);
2413 WRITE_RPS1(SAA7146_GPIO_OUTLO<<24);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002414#if RPS_IRQ
2415 /* issue RPS1 interrupt to increment counter */
Al Viro153755a2008-06-22 14:19:39 -03002416 WRITE_RPS1(CMD_INTERRUPT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002417#endif
Al Viro153755a2008-06-22 14:19:39 -03002418 WRITE_RPS1(CMD_STOP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002419 /* Jump to begin of RPS program as safety measure (p37) */
Al Viro153755a2008-06-22 14:19:39 -03002420 WRITE_RPS1(CMD_JUMP);
2421 WRITE_RPS1(dev->d_rps1.dma_handle);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002422
2423#if RPS_IRQ
2424 /* set event counter 1 source as RPS1 interrupt (0x03) (rE4 p53)
2425 * use 0x03 to track RPS1 interrupts - increase by 1 every gpio3 is toggled
2426 * use 0x15 to track VPE interrupts - increase by 1 every vpeirq() is called
2427 */
2428 saa7146_write(dev, EC1SSR, (0x03<<2) | 3 );
André Goddard Rosaaf901ca2009-11-14 13:09:05 -02002429 /* set event counter 1 threshold to maximum allowed value (rEC p55) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002430 saa7146_write(dev, ECT1R, 0x3fff );
2431#endif
2432 /* Set RPS1 Address register to point to RPS code (r108 p42) */
2433 saa7146_write(dev, RPS_ADDR1, dev->d_rps1.dma_handle);
2434 /* Enable RPS1, (rFC p33) */
2435 saa7146_write(dev, MC1, (MASK_13 | MASK_29 ));
2436
2437 mdelay(10);
2438 /* now send VSYNC_B to rps1 by rising GPIO3 */
2439 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI);
2440 mdelay(10);
2441 /* if rps1 responded by lowering the GPIO3,
2442 * then we have budgetpatch hardware
2443 */
2444 if ((saa7146_read(dev, GPIO_CTRL) & 0x10000000) == 0) {
2445 budgetpatch = 1;
2446 printk("dvb-ttpci: BUDGET-PATCH DETECTED.\n");
2447 }
2448 /* Disable RPS1 */
2449 saa7146_write(dev, MC1, ( MASK_29 ));
2450#if RPS_IRQ
2451 printk("dvb-ttpci: Event Counter 1 0x%04x\n", saa7146_read(dev, EC1R) & 0x3fff );
2452#endif
2453 }
2454
2455 /* prepare the av7110 device struct */
Panagiotis Issaris74081872006-01-11 19:40:56 -02002456 av7110 = kzalloc(sizeof(struct av7110), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002457 if (!av7110) {
2458 dprintk(1, "out of memory\n");
2459 return -ENOMEM;
2460 }
2461
Linus Torvalds1da177e2005-04-16 15:20:36 -07002462 av7110->card_name = (char*) pci_ext->ext_priv;
2463 av7110->dev = dev;
2464 dev->ext_priv = av7110;
2465
2466 ret = get_firmware(av7110);
2467 if (ret < 0)
2468 goto err_kfree_0;
2469
2470 ret = dvb_register_adapter(&av7110->dvb_adapter, av7110->card_name,
Janne Grunau78e92002008-04-09 19:13:13 -03002471 THIS_MODULE, &dev->pci->dev, adapter_nr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002472 if (ret < 0)
2473 goto err_put_firmware_1;
2474
2475 /* the Siemens DVB needs this if you want to have the i2c chips
2476 get recognized before the main driver is fully loaded */
2477 saa7146_write(dev, GPIO_CTRL, 0x500000);
2478
Linus Torvalds1da177e2005-04-16 15:20:36 -07002479 av7110->i2c_adap.class = I2C_CLASS_TV_DIGITAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002480 strlcpy(av7110->i2c_adap.name, pci_ext->ext_priv, sizeof(av7110->i2c_adap.name));
2481
2482 saa7146_i2c_adapter_prepare(dev, &av7110->i2c_adap, SAA7146_I2C_BUS_BIT_RATE_120); /* 275 kHz */
2483
2484 ret = i2c_add_adapter(&av7110->i2c_adap);
2485 if (ret < 0)
2486 goto err_dvb_unregister_adapter_2;
2487
2488 ttpci_eeprom_parse_mac(&av7110->i2c_adap,
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07002489 av7110->dvb_adapter.proposed_mac);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002490 ret = -ENOMEM;
2491
Oliver Endriss9e615ea2008-09-03 19:15:27 -03002492 /* full-ts mod? */
2493 if (full_ts)
2494 av7110->full_ts = true;
2495
2496 /* check for full-ts flag in eeprom */
2497 if (i2c_readreg(av7110, 0xaa, 0) == 0x4f && i2c_readreg(av7110, 0xaa, 1) == 0x45) {
2498 u8 flags = i2c_readreg(av7110, 0xaa, 2);
2499 if (flags != 0xff && (flags & 0x01))
2500 av7110->full_ts = true;
2501 }
2502
2503 if (av7110->full_ts) {
2504 printk(KERN_INFO "dvb-ttpci: full-ts mode enabled for saa7146 port B\n");
2505 spin_lock_init(&av7110->feedlock1);
2506 av7110->grabbing = saa7146_vmalloc_build_pgtable(pdev, length,
2507 &av7110->pt);
2508 if (!av7110->grabbing)
2509 goto err_i2c_del_3;
2510
2511 saa7146_write(dev, DD1_STREAM_B, 0x00000000);
2512 saa7146_write(dev, MC2, (MASK_10 | MASK_26));
2513
2514 saa7146_write(dev, DD1_INIT, 0x00000600);
2515 saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
2516
2517 saa7146_write(dev, BRS_CTRL, 0x60000000);
2518 saa7146_write(dev, MC2, MASK_08 | MASK_24);
2519
2520 /* dma3 */
2521 saa7146_write(dev, PCI_BT_V1, 0x001c0000 | (saa7146_read(dev, PCI_BT_V1) & ~0x001f0000));
2522 saa7146_write(dev, BASE_ODD3, 0);
2523 saa7146_write(dev, BASE_EVEN3, 0);
2524 saa7146_write(dev, PROT_ADDR3, TS_WIDTH * TS_HEIGHT);
2525 saa7146_write(dev, PITCH3, TS_WIDTH);
2526 saa7146_write(dev, BASE_PAGE3, av7110->pt.dma | ME1 | 0x90);
2527 saa7146_write(dev, NUM_LINE_BYTE3, (TS_HEIGHT << 16) | TS_WIDTH);
2528 saa7146_write(dev, MC2, MASK_04 | MASK_20);
2529
2530 tasklet_init(&av7110->vpe_tasklet, vpeirq, (unsigned long) av7110);
2531
2532 } else if (budgetpatch) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002533 spin_lock_init(&av7110->feedlock1);
2534 av7110->grabbing = saa7146_vmalloc_build_pgtable(pdev, length,
2535 &av7110->pt);
2536 if (!av7110->grabbing)
2537 goto err_i2c_del_3;
2538
2539 saa7146_write(dev, PCI_BT_V1, 0x1c1f101f);
2540 saa7146_write(dev, BCS_CTRL, 0x80400040);
2541 /* set dd1 stream a & b */
2542 saa7146_write(dev, DD1_STREAM_B, 0x00000000);
2543 saa7146_write(dev, DD1_INIT, 0x03000200);
2544 saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
2545 saa7146_write(dev, BRS_CTRL, 0x60000000);
2546 saa7146_write(dev, BASE_ODD3, 0);
2547 saa7146_write(dev, BASE_EVEN3, 0);
2548 saa7146_write(dev, PROT_ADDR3, TS_WIDTH * TS_HEIGHT);
2549 saa7146_write(dev, BASE_PAGE3, av7110->pt.dma | ME1 | 0x90);
2550
2551 saa7146_write(dev, PITCH3, TS_WIDTH);
2552 saa7146_write(dev, NUM_LINE_BYTE3, (TS_HEIGHT << 16) | TS_WIDTH);
2553
2554 /* upload all */
2555 saa7146_write(dev, MC2, 0x077c077c);
2556 saa7146_write(dev, GPIO_CTRL, 0x000000);
2557#if RPS_IRQ
2558 /* set event counter 1 source as RPS1 interrupt (0x03) (rE4 p53)
2559 * use 0x03 to track RPS1 interrupts - increase by 1 every gpio3 is toggled
2560 * use 0x15 to track VPE interrupts - increase by 1 every vpeirq() is called
2561 */
2562 saa7146_write(dev, EC1SSR, (0x03<<2) | 3 );
André Goddard Rosaaf901ca2009-11-14 13:09:05 -02002563 /* set event counter 1 threshold to maximum allowed value (rEC p55) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002564 saa7146_write(dev, ECT1R, 0x3fff );
2565#endif
2566 /* Setup BUDGETPATCH MAIN RPS1 "program" (p35) */
2567 count = 0;
2568
2569 /* Wait Source Line Counter Threshold (p36) */
Al Viro153755a2008-06-22 14:19:39 -03002570 WRITE_RPS1(CMD_PAUSE | EVT_HS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002571 /* Set GPIO3=1 (p42) */
Al Viro153755a2008-06-22 14:19:39 -03002572 WRITE_RPS1(CMD_WR_REG_MASK | (GPIO_CTRL>>2));
2573 WRITE_RPS1(GPIO3_MSK);
2574 WRITE_RPS1(SAA7146_GPIO_OUTHI<<24);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002575#if RPS_IRQ
2576 /* issue RPS1 interrupt */
Al Viro153755a2008-06-22 14:19:39 -03002577 WRITE_RPS1(CMD_INTERRUPT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002578#endif
2579 /* Wait reset Source Line Counter Threshold (p36) */
Al Viro153755a2008-06-22 14:19:39 -03002580 WRITE_RPS1(CMD_PAUSE | RPS_INV | EVT_HS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002581 /* Set GPIO3=0 (p42) */
Al Viro153755a2008-06-22 14:19:39 -03002582 WRITE_RPS1(CMD_WR_REG_MASK | (GPIO_CTRL>>2));
2583 WRITE_RPS1(GPIO3_MSK);
2584 WRITE_RPS1(SAA7146_GPIO_OUTLO<<24);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002585#if RPS_IRQ
2586 /* issue RPS1 interrupt */
Al Viro153755a2008-06-22 14:19:39 -03002587 WRITE_RPS1(CMD_INTERRUPT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002588#endif
2589 /* Jump to begin of RPS program (p37) */
Al Viro153755a2008-06-22 14:19:39 -03002590 WRITE_RPS1(CMD_JUMP);
2591 WRITE_RPS1(dev->d_rps1.dma_handle);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002592
2593 /* Fix VSYNC level */
2594 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
2595 /* Set RPS1 Address register to point to RPS code (r108 p42) */
2596 saa7146_write(dev, RPS_ADDR1, dev->d_rps1.dma_handle);
2597 /* Set Source Line Counter Threshold, using BRS (rCC p43)
2598 * It generates HS event every TS_HEIGHT lines
2599 * this is related to TS_WIDTH set in register
2600 * NUM_LINE_BYTE3. If NUM_LINE_BYTE low 16 bits
2601 * are set to TS_WIDTH bytes (TS_WIDTH=2*188),
2602 * then RPS_THRESH1 should be set to trigger
2603 * every TS_HEIGHT (512) lines.
2604 */
2605 saa7146_write(dev, RPS_THRESH1, (TS_HEIGHT*1) | MASK_12 );
2606
2607 /* Enable RPS1 (rFC p33) */
2608 saa7146_write(dev, MC1, (MASK_13 | MASK_29));
2609
2610 /* end of budgetpatch register initialization */
2611 tasklet_init (&av7110->vpe_tasklet, vpeirq, (unsigned long) av7110);
2612 } else {
2613 saa7146_write(dev, PCI_BT_V1, 0x1c00101f);
2614 saa7146_write(dev, BCS_CTRL, 0x80400040);
2615
2616 /* set dd1 stream a & b */
2617 saa7146_write(dev, DD1_STREAM_B, 0x00000000);
2618 saa7146_write(dev, DD1_INIT, 0x03000000);
2619 saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
2620
2621 /* upload all */
2622 saa7146_write(dev, MC2, 0x077c077c);
2623 saa7146_write(dev, GPIO_CTRL, 0x000000);
2624 }
2625
2626 tasklet_init (&av7110->debi_tasklet, debiirq, (unsigned long) av7110);
2627 tasklet_init (&av7110->gpio_tasklet, gpioirq, (unsigned long) av7110);
2628
Ingo Molnar3593cab2006-02-07 06:49:14 -02002629 mutex_init(&av7110->pid_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002630
2631 /* locks for data transfers from/to AV7110 */
2632 spin_lock_init(&av7110->debilock);
Ingo Molnar3593cab2006-02-07 06:49:14 -02002633 mutex_init(&av7110->dcomlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002634 av7110->debitype = -1;
2635
2636 /* default OSD window */
2637 av7110->osdwin = 1;
Ingo Molnar3593cab2006-02-07 06:49:14 -02002638 mutex_init(&av7110->osd_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002639
C.Y.M2f03ee82006-03-30 04:31:48 -03002640 /* TV standard */
Marco Schluessler58a44042007-10-31 01:20:42 -03002641 av7110->vidmode = tv_standard == 1 ? AV7110_VIDEO_MODE_NTSC
2642 : AV7110_VIDEO_MODE_PAL;
C.Y.M2f03ee82006-03-30 04:31:48 -03002643
Linus Torvalds1da177e2005-04-16 15:20:36 -07002644 /* ARM "watchdog" */
2645 init_waitqueue_head(&av7110->arm_wait);
2646 av7110->arm_thread = NULL;
2647
2648 /* allocate and init buffers */
2649 av7110->debi_virt = pci_alloc_consistent(pdev, 8192, &av7110->debi_bus);
2650 if (!av7110->debi_virt)
2651 goto err_saa71466_vfree_4;
2652
2653
2654 av7110->iobuf = vmalloc(AVOUTLEN+AOUTLEN+BMPLEN+4*IPACKS);
2655 if (!av7110->iobuf)
2656 goto err_pci_free_5;
2657
2658 ret = av7110_av_init(av7110);
2659 if (ret < 0)
2660 goto err_iobuf_vfree_6;
2661
2662 /* init BMP buffer */
2663 av7110->bmpbuf = av7110->iobuf+AVOUTLEN+AOUTLEN;
2664 init_waitqueue_head(&av7110->bmpq);
2665
2666 ret = av7110_ca_init(av7110);
2667 if (ret < 0)
2668 goto err_av7110_av_exit_7;
2669
2670 /* load firmware into AV7110 cards */
2671 ret = av7110_bootarm(av7110);
2672 if (ret < 0)
2673 goto err_av7110_ca_exit_8;
2674
2675 ret = av7110_firmversion(av7110);
2676 if (ret < 0)
2677 goto err_stop_arm_9;
2678
2679 if (FW_VERSION(av7110->arm_app)<0x2501)
2680 printk ("dvb-ttpci: Warning, firmware version 0x%04x is too old. "
2681 "System might be unstable!\n", FW_VERSION(av7110->arm_app));
2682
Herbert Poetzl8eec1422007-02-08 14:32:43 -03002683 thread = kthread_run(arm_thread, (void *) av7110, "arm_mon");
2684 if (IS_ERR(thread)) {
2685 ret = PTR_ERR(thread);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002686 goto err_stop_arm_9;
Herbert Poetzl8eec1422007-02-08 14:32:43 -03002687 }
2688 av7110->arm_thread = thread;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002689
2690 /* set initial volume in mixer struct */
2691 av7110->mixer.volume_left = volume;
2692 av7110->mixer.volume_right = volume;
2693
Linus Torvalds1da177e2005-04-16 15:20:36 -07002694 ret = av7110_register(av7110);
2695 if (ret < 0)
2696 goto err_arm_thread_stop_10;
2697
Oliver Endrissdefd574e2007-07-12 23:08:07 -03002698 init_av7110_av(av7110);
2699
Linus Torvalds1da177e2005-04-16 15:20:36 -07002700 /* special case DVB-C: these cards have an analog tuner
2701 plus need some special handling, so we have separate
2702 saa7146_ext_vv data for these... */
2703 ret = av7110_init_v4l(av7110);
2704 if (ret < 0)
2705 goto err_av7110_unregister_11;
2706
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07002707 av7110->dvb_adapter.priv = av7110;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002708 ret = frontend_init(av7110);
2709 if (ret < 0)
2710 goto err_av7110_exit_v4l_12;
2711
2712#if defined(CONFIG_INPUT_EVDEV) || defined(CONFIG_INPUT_EVDEV_MODULE)
Oliver Endriss03388ae2005-09-09 13:03:12 -07002713 av7110_ir_init(av7110);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002714#endif
2715 printk(KERN_INFO "dvb-ttpci: found av7110-%d.\n", av7110_num);
2716 av7110_num++;
2717out:
2718 return ret;
2719
2720err_av7110_exit_v4l_12:
2721 av7110_exit_v4l(av7110);
2722err_av7110_unregister_11:
2723 dvb_unregister(av7110);
2724err_arm_thread_stop_10:
2725 av7110_arm_sync(av7110);
2726err_stop_arm_9:
2727 /* Nothing to do. Rejoice. */
2728err_av7110_ca_exit_8:
2729 av7110_ca_exit(av7110);
2730err_av7110_av_exit_7:
2731 av7110_av_exit(av7110);
2732err_iobuf_vfree_6:
2733 vfree(av7110->iobuf);
2734err_pci_free_5:
2735 pci_free_consistent(pdev, 8192, av7110->debi_virt, av7110->debi_bus);
2736err_saa71466_vfree_4:
Jon Burgess87c30192007-05-03 12:23:44 -03002737 if (av7110->grabbing)
2738 saa7146_vfree_destroy_pgtable(pdev, av7110->grabbing, &av7110->pt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002739err_i2c_del_3:
2740 i2c_del_adapter(&av7110->i2c_adap);
2741err_dvb_unregister_adapter_2:
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07002742 dvb_unregister_adapter(&av7110->dvb_adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002743err_put_firmware_1:
2744 put_firmware(av7110);
2745err_kfree_0:
2746 kfree(av7110);
2747 goto out;
2748}
2749
Johannes Stezenbach1be11e32006-02-27 00:09:20 -03002750static int __devexit av7110_detach(struct saa7146_dev* saa)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002751{
2752 struct av7110 *av7110 = saa->ext_priv;
2753 dprintk(4, "%p\n", av7110);
2754
Oliver Endriss03388ae2005-09-09 13:03:12 -07002755#if defined(CONFIG_INPUT_EVDEV) || defined(CONFIG_INPUT_EVDEV_MODULE)
2756 av7110_ir_exit(av7110);
2757#endif
Oliver Endriss9e615ea2008-09-03 19:15:27 -03002758 if (budgetpatch || av7110->full_ts) {
2759 if (budgetpatch) {
2760 /* Disable RPS1 */
2761 saa7146_write(saa, MC1, MASK_29);
2762 /* VSYNC LOW (inactive) */
2763 saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);
2764 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002765 saa7146_write(saa, MC1, MASK_20); /* DMA3 off */
2766 SAA7146_IER_DISABLE(saa, MASK_10);
2767 SAA7146_ISR_CLEAR(saa, MASK_10);
2768 msleep(50);
2769 tasklet_kill(&av7110->vpe_tasklet);
Jon Burgess87c30192007-05-03 12:23:44 -03002770 saa7146_vfree_destroy_pgtable(saa->pci, av7110->grabbing, &av7110->pt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002771 }
2772 av7110_exit_v4l(av7110);
2773
2774 av7110_arm_sync(av7110);
2775
2776 tasklet_kill(&av7110->debi_tasklet);
2777 tasklet_kill(&av7110->gpio_tasklet);
2778
2779 dvb_unregister(av7110);
2780
2781 SAA7146_IER_DISABLE(saa, MASK_19 | MASK_03);
2782 SAA7146_ISR_CLEAR(saa, MASK_19 | MASK_03);
2783
2784 av7110_ca_exit(av7110);
2785 av7110_av_exit(av7110);
2786
2787 vfree(av7110->iobuf);
2788 pci_free_consistent(saa->pci, 8192, av7110->debi_virt,
2789 av7110->debi_bus);
2790
2791 i2c_del_adapter(&av7110->i2c_adap);
2792
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07002793 dvb_unregister_adapter (&av7110->dvb_adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002794
2795 av7110_num--;
2796
2797 put_firmware(av7110);
2798
2799 kfree(av7110);
2800
2801 saa->ext_priv = NULL;
2802
2803 return 0;
2804}
2805
2806
2807static void av7110_irq(struct saa7146_dev* dev, u32 *isr)
2808{
2809 struct av7110 *av7110 = dev->ext_priv;
2810
2811 //print_time("av7110_irq");
2812
2813 /* Note: Don't try to handle the DEBI error irq (MASK_18), in
2814 * intel mode the timeout is asserted all the time...
2815 */
2816
2817 if (*isr & MASK_19) {
2818 //printk("av7110_irq: DEBI\n");
2819 /* Note 1: The DEBI irq is level triggered: We must enable it
2820 * only after we started a DMA xfer, and disable it here
2821 * immediately, or it will be signalled all the time while
2822 * DEBI is idle.
2823 * Note 2: You would think that an irq which is masked is
2824 * not signalled by the hardware. Not so for the SAA7146:
2825 * An irq is signalled as long as the corresponding bit
2826 * in the ISR is set, and disabling irqs just prevents the
2827 * hardware from setting the ISR bit. This means a) that we
2828 * must clear the ISR *after* disabling the irq (which is why
2829 * we must do it here even though saa7146_core did it already),
2830 * and b) that if we were to disable an edge triggered irq
2831 * (like the gpio irqs sadly are) temporarily we would likely
2832 * loose some. This sucks :-(
2833 */
2834 SAA7146_IER_DISABLE(av7110->dev, MASK_19);
2835 SAA7146_ISR_CLEAR(av7110->dev, MASK_19);
2836 tasklet_schedule(&av7110->debi_tasklet);
2837 }
2838
2839 if (*isr & MASK_03) {
2840 //printk("av7110_irq: GPIO\n");
2841 tasklet_schedule(&av7110->gpio_tasklet);
2842 }
2843
Oliver Endriss9e615ea2008-09-03 19:15:27 -03002844 if (*isr & MASK_10)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002845 tasklet_schedule(&av7110->vpe_tasklet);
2846}
2847
2848
Randy Dunlapda517162008-01-10 19:31:47 -03002849static struct saa7146_extension av7110_extension_driver;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002850
2851#define MAKE_AV7110_INFO(x_var,x_name) \
2852static struct saa7146_pci_extension_data x_var = { \
2853 .ext_priv = x_name, \
Randy Dunlapda517162008-01-10 19:31:47 -03002854 .ext = &av7110_extension_driver }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002855
Karl Herz6af4ee12005-09-09 13:03:13 -07002856MAKE_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 -07002857MAKE_AV7110_INFO(ttt_1_X, "Technotrend/Hauppauge WinTV DVB-T rev1.X");
2858MAKE_AV7110_INFO(ttc_1_X, "Technotrend/Hauppauge WinTV Nexus-CA rev1.X");
2859MAKE_AV7110_INFO(ttc_2_X, "Technotrend/Hauppauge WinTV DVB-C rev2.X");
2860MAKE_AV7110_INFO(tts_2_X, "Technotrend/Hauppauge WinTV Nexus-S rev2.X");
Johannes Stezenbach3dfaebd2005-05-16 21:54:19 -07002861MAKE_AV7110_INFO(tts_2_3, "Technotrend/Hauppauge WinTV Nexus-S rev2.3");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002862MAKE_AV7110_INFO(tts_1_3se, "Technotrend/Hauppauge WinTV DVB-S rev1.3 SE");
2863MAKE_AV7110_INFO(ttt, "Technotrend/Hauppauge DVB-T");
2864MAKE_AV7110_INFO(fsc, "Fujitsu Siemens DVB-C");
2865MAKE_AV7110_INFO(fss, "Fujitsu Siemens DVB-S rev1.6");
Oliver Endriss8bd63012006-02-07 06:49:11 -02002866MAKE_AV7110_INFO(gxs_1_3, "Galaxis DVB-S rev1.3");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002867
2868static struct pci_device_id pci_tbl[] = {
Karl Herz6af4ee12005-09-09 13:03:13 -07002869 MAKE_EXTENSION_PCI(fsc, 0x110a, 0x0000),
2870 MAKE_EXTENSION_PCI(tts_1_X_fsc, 0x13c2, 0x0000),
2871 MAKE_EXTENSION_PCI(ttt_1_X, 0x13c2, 0x0001),
2872 MAKE_EXTENSION_PCI(ttc_2_X, 0x13c2, 0x0002),
2873 MAKE_EXTENSION_PCI(tts_2_X, 0x13c2, 0x0003),
Oliver Endriss8bd63012006-02-07 06:49:11 -02002874 MAKE_EXTENSION_PCI(gxs_1_3, 0x13c2, 0x0004),
Karl Herz6af4ee12005-09-09 13:03:13 -07002875 MAKE_EXTENSION_PCI(fss, 0x13c2, 0x0006),
2876 MAKE_EXTENSION_PCI(ttt, 0x13c2, 0x0008),
2877 MAKE_EXTENSION_PCI(ttc_1_X, 0x13c2, 0x000a),
2878 MAKE_EXTENSION_PCI(tts_2_3, 0x13c2, 0x000e),
2879 MAKE_EXTENSION_PCI(tts_1_3se, 0x13c2, 0x1002),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002880
Linus Torvalds1da177e2005-04-16 15:20:36 -07002881/* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0005), UNDEFINED CARD */ // Technisat SkyStar1
2882/* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0009), UNDEFINED CARD */ // TT/Hauppauge WinTV Nexus-CA v????
2883
2884 {
2885 .vendor = 0,
2886 }
2887};
2888
2889MODULE_DEVICE_TABLE(pci, pci_tbl);
2890
2891
Randy Dunlapda517162008-01-10 19:31:47 -03002892static struct saa7146_extension av7110_extension_driver = {
Dave Jones0e367a12006-08-07 13:18:56 -03002893 .name = "dvb",
Oliver Endriss00c4cc62006-11-01 13:09:51 -03002894 .flags = SAA7146_USE_I2C_IRQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002895
2896 .module = THIS_MODULE,
2897 .pci_tbl = &pci_tbl[0],
2898 .attach = av7110_attach,
Johannes Stezenbach1be11e32006-02-27 00:09:20 -03002899 .detach = __devexit_p(av7110_detach),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002900
2901 .irq_mask = MASK_19 | MASK_03 | MASK_10,
2902 .irq_func = av7110_irq,
2903};
2904
2905
2906static int __init av7110_init(void)
2907{
2908 int retval;
Randy Dunlapda517162008-01-10 19:31:47 -03002909 retval = saa7146_register_extension(&av7110_extension_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002910 return retval;
2911}
2912
2913
2914static void __exit av7110_exit(void)
2915{
Randy Dunlapda517162008-01-10 19:31:47 -03002916 saa7146_unregister_extension(&av7110_extension_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002917}
2918
2919module_init(av7110_init);
2920module_exit(av7110_exit);
2921
2922MODULE_DESCRIPTION("driver for the SAA7146 based AV110 PCI DVB cards by "
2923 "Siemens, Technotrend, Hauppauge");
2924MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, others");
2925MODULE_LICENSE("GPL");