blob: 6ecbcf614878fa186be24be1a39f8a07365b3cc9 [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 *
Justin P. Mattock631dd1a2010-10-18 11:03:14 +020029 * the project's page is at http://www.linuxtv.org/
Linus Torvalds1da177e2005-04-16 15:20:36 -070030 */
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,
Arnd Bergmann6038f372010-08-15 18:52:59 +0200733 .llseek = noop_llseek,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734};
735
736static struct dvb_device dvbdev_osd = {
737 .priv = NULL,
738 .users = 1,
739 .writers = 1,
740 .fops = &dvb_osd_fops,
741 .kernel_ioctl = dvb_osd_ioctl,
742};
743#endif /* CONFIG_DVB_AV7110_OSD */
744
745
746static inline int SetPIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid,
747 u16 subpid, u16 pcrpid)
748{
Dr. Werner Fink47f36922006-01-09 15:25:07 -0200749 u16 aflags = 0;
750
Linus Torvalds1da177e2005-04-16 15:20:36 -0700751 dprintk(4, "%p\n", av7110);
752
753 if (vpid == 0x1fff || apid == 0x1fff ||
754 ttpid == 0x1fff || subpid == 0x1fff || pcrpid == 0x1fff) {
755 vpid = apid = ttpid = subpid = pcrpid = 0;
756 av7110->pids[DMX_PES_VIDEO] = 0;
757 av7110->pids[DMX_PES_AUDIO] = 0;
758 av7110->pids[DMX_PES_TELETEXT] = 0;
759 av7110->pids[DMX_PES_PCR] = 0;
760 }
761
Dr. Werner Fink47f36922006-01-09 15:25:07 -0200762 if (av7110->audiostate.bypass_mode)
763 aflags |= 0x8000;
764
765 return av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, MultiPID, 6,
766 pcrpid, vpid, apid, ttpid, subpid, aflags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700767}
768
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700769int ChangePIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700770 u16 subpid, u16 pcrpid)
771{
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700772 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700773 dprintk(4, "%p\n", av7110);
774
Ingo Molnar3593cab2006-02-07 06:49:14 -0200775 if (mutex_lock_interruptible(&av7110->pid_mutex))
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700776 return -ERESTARTSYS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700777
778 if (!(vpid & 0x8000))
779 av7110->pids[DMX_PES_VIDEO] = vpid;
780 if (!(apid & 0x8000))
781 av7110->pids[DMX_PES_AUDIO] = apid;
782 if (!(ttpid & 0x8000))
783 av7110->pids[DMX_PES_TELETEXT] = ttpid;
784 if (!(pcrpid & 0x8000))
785 av7110->pids[DMX_PES_PCR] = pcrpid;
786
787 av7110->pids[DMX_PES_SUBTITLE] = 0;
788
789 if (av7110->fe_synced) {
790 pcrpid = av7110->pids[DMX_PES_PCR];
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700791 ret = SetPIDs(av7110, vpid, apid, ttpid, subpid, pcrpid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792 }
793
Ingo Molnar3593cab2006-02-07 06:49:14 -0200794 mutex_unlock(&av7110->pid_mutex);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700795 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700796}
797
798
799/******************************************************************************
800 * hardware filter functions
801 ******************************************************************************/
802
803static int StartHWFilter(struct dvb_demux_filter *dvbdmxfilter)
804{
805 struct dvb_demux_feed *dvbdmxfeed = dvbdmxfilter->feed;
Tobias Klauserd9bdf772006-12-26 07:33:48 -0300806 struct av7110 *av7110 = dvbdmxfeed->demux->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700807 u16 buf[20];
808 int ret, i;
809 u16 handle;
810// u16 mode = 0x0320;
811 u16 mode = 0xb96a;
812
813 dprintk(4, "%p\n", av7110);
814
Oliver Endriss9e615ea2008-09-03 19:15:27 -0300815 if (av7110->full_ts)
816 return 0;
817
Linus Torvalds1da177e2005-04-16 15:20:36 -0700818 if (dvbdmxfilter->type == DMX_TYPE_SEC) {
819 if (hw_sections) {
820 buf[4] = (dvbdmxfilter->filter.filter_value[0] << 8) |
821 dvbdmxfilter->maskandmode[0];
822 for (i = 3; i < 18; i++)
823 buf[i + 4 - 2] =
824 (dvbdmxfilter->filter.filter_value[i] << 8) |
825 dvbdmxfilter->maskandmode[i];
826 mode = 4;
827 }
828 } else if ((dvbdmxfeed->ts_type & TS_PACKET) &&
829 !(dvbdmxfeed->ts_type & TS_PAYLOAD_ONLY)) {
830 av7110_p2t_init(&av7110->p2t_filter[dvbdmxfilter->index], dvbdmxfeed);
831 }
832
833 buf[0] = (COMTYPE_PID_FILTER << 8) + AddPIDFilter;
834 buf[1] = 16;
835 buf[2] = dvbdmxfeed->pid;
836 buf[3] = mode;
837
838 ret = av7110_fw_request(av7110, buf, 20, &handle, 1);
839 if (ret != 0 || handle >= 32) {
840 printk("dvb-ttpci: %s error buf %04x %04x %04x %04x "
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700841 "ret %d handle %04x\n",
Harvey Harrison3ca7fc82008-04-08 23:20:00 -0300842 __func__, buf[0], buf[1], buf[2], buf[3],
Linus Torvalds1da177e2005-04-16 15:20:36 -0700843 ret, handle);
844 dvbdmxfilter->hw_handle = 0xffff;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700845 if (!ret)
846 ret = -1;
847 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700848 }
849
850 av7110->handle2filter[handle] = dvbdmxfilter;
851 dvbdmxfilter->hw_handle = handle;
852
853 return ret;
854}
855
856static int StopHWFilter(struct dvb_demux_filter *dvbdmxfilter)
857{
Tobias Klauserd9bdf772006-12-26 07:33:48 -0300858 struct av7110 *av7110 = dvbdmxfilter->feed->demux->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700859 u16 buf[3];
860 u16 answ[2];
861 int ret;
862 u16 handle;
863
864 dprintk(4, "%p\n", av7110);
865
Oliver Endriss9e615ea2008-09-03 19:15:27 -0300866 if (av7110->full_ts)
867 return 0;
868
Linus Torvalds1da177e2005-04-16 15:20:36 -0700869 handle = dvbdmxfilter->hw_handle;
870 if (handle >= 32) {
871 printk("%s tried to stop invalid filter %04x, filter type = %x\n",
Harvey Harrison3ca7fc82008-04-08 23:20:00 -0300872 __func__, handle, dvbdmxfilter->type);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700873 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700874 }
875
876 av7110->handle2filter[handle] = NULL;
877
878 buf[0] = (COMTYPE_PID_FILTER << 8) + DelPIDFilter;
879 buf[1] = 1;
880 buf[2] = handle;
881 ret = av7110_fw_request(av7110, buf, 3, answ, 2);
882 if (ret != 0 || answ[1] != handle) {
883 printk("dvb-ttpci: %s error cmd %04x %04x %04x ret %x "
884 "resp %04x %04x pid %d\n",
Harvey Harrison3ca7fc82008-04-08 23:20:00 -0300885 __func__, buf[0], buf[1], buf[2], ret,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886 answ[0], answ[1], dvbdmxfilter->feed->pid);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700887 if (!ret)
888 ret = -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700889 }
890 return ret;
891}
892
893
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700894static int dvb_feed_start_pid(struct dvb_demux_feed *dvbdmxfeed)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700895{
896 struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
Tobias Klauserd9bdf772006-12-26 07:33:48 -0300897 struct av7110 *av7110 = dvbdmx->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700898 u16 *pid = dvbdmx->pids, npids[5];
899 int i;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700900 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901
902 dprintk(4, "%p\n", av7110);
903
904 npids[0] = npids[1] = npids[2] = npids[3] = npids[4] = 0xffff;
905 i = dvbdmxfeed->pes_type;
906 npids[i] = (pid[i]&0x8000) ? 0 : pid[i];
907 if ((i == 2) && npids[i] && (dvbdmxfeed->ts_type & TS_PACKET)) {
908 npids[i] = 0;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700909 ret = ChangePIDs(av7110, npids[1], npids[0], npids[2], npids[3], npids[4]);
910 if (!ret)
911 ret = StartHWFilter(dvbdmxfeed->filter);
912 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700914 if (dvbdmxfeed->pes_type <= 2 || dvbdmxfeed->pes_type == 4) {
915 ret = ChangePIDs(av7110, npids[1], npids[0], npids[2], npids[3], npids[4]);
916 if (ret)
917 return ret;
918 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919
920 if (dvbdmxfeed->pes_type < 2 && npids[0])
921 if (av7110->fe_synced)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700922 {
923 ret = av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, Scan, 0);
924 if (ret)
925 return ret;
926 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700927
Oliver Endriss9e615ea2008-09-03 19:15:27 -0300928 if ((dvbdmxfeed->ts_type & TS_PACKET) && !av7110->full_ts) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700929 if (dvbdmxfeed->pes_type == 0 && !(dvbdmx->pids[0] & 0x8000))
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700930 ret = av7110_av_start_record(av7110, RP_AUDIO, dvbdmxfeed);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931 if (dvbdmxfeed->pes_type == 1 && !(dvbdmx->pids[1] & 0x8000))
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700932 ret = av7110_av_start_record(av7110, RP_VIDEO, dvbdmxfeed);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700933 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700934 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700935}
936
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700937static int dvb_feed_stop_pid(struct dvb_demux_feed *dvbdmxfeed)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700938{
939 struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
Tobias Klauserd9bdf772006-12-26 07:33:48 -0300940 struct av7110 *av7110 = dvbdmx->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700941 u16 *pid = dvbdmx->pids, npids[5];
942 int i;
943
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700944 int ret = 0;
945
Linus Torvalds1da177e2005-04-16 15:20:36 -0700946 dprintk(4, "%p\n", av7110);
947
948 if (dvbdmxfeed->pes_type <= 1) {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700949 ret = av7110_av_stop(av7110, dvbdmxfeed->pes_type ? RP_VIDEO : RP_AUDIO);
950 if (ret)
951 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700952 if (!av7110->rec_mode)
953 dvbdmx->recording = 0;
954 if (!av7110->playing)
955 dvbdmx->playing = 0;
956 }
957 npids[0] = npids[1] = npids[2] = npids[3] = npids[4] = 0xffff;
958 i = dvbdmxfeed->pes_type;
959 switch (i) {
960 case 2: //teletext
961 if (dvbdmxfeed->ts_type & TS_PACKET)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700962 ret = StopHWFilter(dvbdmxfeed->filter);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700963 npids[2] = 0;
964 break;
965 case 0:
966 case 1:
967 case 4:
968 if (!pids_off)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700969 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700970 npids[i] = (pid[i]&0x8000) ? 0 : pid[i];
971 break;
972 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700973 if (!ret)
974 ret = ChangePIDs(av7110, npids[1], npids[0], npids[2], npids[3], npids[4]);
975 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700976}
977
978static int av7110_start_feed(struct dvb_demux_feed *feed)
979{
980 struct dvb_demux *demux = feed->demux;
981 struct av7110 *av7110 = demux->priv;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700982 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700983
984 dprintk(4, "%p\n", av7110);
985
986 if (!demux->dmx.frontend)
987 return -EINVAL;
988
Oliver Endriss9e615ea2008-09-03 19:15:27 -0300989 if (!av7110->full_ts && feed->pid > 0x1fff)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700990 return -EINVAL;
991
992 if (feed->type == DMX_TYPE_TS) {
993 if ((feed->ts_type & TS_DECODER) &&
Dan Carpenter9369cc92011-10-18 02:12:09 -0300994 (feed->pes_type <= DMX_TS_PES_PCR)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700995 switch (demux->dmx.frontend->source) {
996 case DMX_MEMORY_FE:
997 if (feed->ts_type & TS_DECODER)
998 if (feed->pes_type < 2 &&
999 !(demux->pids[0] & 0x8000) &&
1000 !(demux->pids[1] & 0x8000)) {
1001 dvb_ringbuffer_flush_spinlock_wakeup(&av7110->avout);
1002 dvb_ringbuffer_flush_spinlock_wakeup(&av7110->aout);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001003 ret = av7110_av_start_play(av7110,RP_AV);
1004 if (!ret)
1005 demux->playing = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001006 }
1007 break;
1008 default:
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001009 ret = dvb_feed_start_pid(feed);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001010 break;
1011 }
1012 } else if ((feed->ts_type & TS_PACKET) &&
1013 (demux->dmx.frontend->source != DMX_MEMORY_FE)) {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001014 ret = StartHWFilter(feed->filter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001015 }
1016 }
1017
Oliver Endriss9e615ea2008-09-03 19:15:27 -03001018 if (av7110->full_ts) {
1019 budget_start_feed(feed);
1020 return ret;
1021 }
1022
1023 if (feed->type == DMX_TYPE_SEC) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001024 int i;
1025
1026 for (i = 0; i < demux->filternum; i++) {
1027 if (demux->filter[i].state != DMX_STATE_READY)
1028 continue;
1029 if (demux->filter[i].type != DMX_TYPE_SEC)
1030 continue;
1031 if (demux->filter[i].filter.parent != &feed->feed.sec)
1032 continue;
1033 demux->filter[i].state = DMX_STATE_GO;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001034 if (demux->dmx.frontend->source != DMX_MEMORY_FE) {
1035 ret = StartHWFilter(&demux->filter[i]);
1036 if (ret)
1037 break;
1038 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001039 }
1040 }
1041
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001042 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001043}
1044
1045
1046static int av7110_stop_feed(struct dvb_demux_feed *feed)
1047{
1048 struct dvb_demux *demux = feed->demux;
1049 struct av7110 *av7110 = demux->priv;
Johannes Stezenbach12ba0502005-07-07 17:58:00 -07001050 int i, rc, ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051 dprintk(4, "%p\n", av7110);
1052
1053 if (feed->type == DMX_TYPE_TS) {
1054 if (feed->ts_type & TS_DECODER) {
1055 if (feed->pes_type >= DMX_TS_PES_OTHER ||
1056 !demux->pesfilter[feed->pes_type])
1057 return -EINVAL;
1058 demux->pids[feed->pes_type] |= 0x8000;
1059 demux->pesfilter[feed->pes_type] = NULL;
1060 }
1061 if (feed->ts_type & TS_DECODER &&
1062 feed->pes_type < DMX_TS_PES_OTHER) {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001063 ret = dvb_feed_stop_pid(feed);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001064 } else
1065 if ((feed->ts_type & TS_PACKET) &&
1066 (demux->dmx.frontend->source != DMX_MEMORY_FE))
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001067 ret = StopHWFilter(feed->filter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068 }
1069
Oliver Endriss9e615ea2008-09-03 19:15:27 -03001070 if (av7110->full_ts) {
1071 budget_stop_feed(feed);
1072 return ret;
1073 }
1074
1075 if (feed->type == DMX_TYPE_SEC) {
Johannes Stezenbach12ba0502005-07-07 17:58:00 -07001076 for (i = 0; i<demux->filternum; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001077 if (demux->filter[i].state == DMX_STATE_GO &&
1078 demux->filter[i].filter.parent == &feed->feed.sec) {
1079 demux->filter[i].state = DMX_STATE_READY;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001080 if (demux->dmx.frontend->source != DMX_MEMORY_FE) {
Johannes Stezenbach12ba0502005-07-07 17:58:00 -07001081 rc = StopHWFilter(&demux->filter[i]);
1082 if (!ret)
1083 ret = rc;
1084 /* keep going, stop as many filters as possible */
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001085 }
Johannes Stezenbach12ba0502005-07-07 17:58:00 -07001086 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001087 }
1088 }
1089
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001090 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001091}
1092
1093
1094static void restart_feeds(struct av7110 *av7110)
1095{
1096 struct dvb_demux *dvbdmx = &av7110->demux;
1097 struct dvb_demux_feed *feed;
1098 int mode;
Oliver Endriss9e615ea2008-09-03 19:15:27 -03001099 int feeding;
Oliver Endriss66190a22006-01-09 15:32:42 -02001100 int i, j;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001101
1102 dprintk(4, "%p\n", av7110);
1103
1104 mode = av7110->playing;
1105 av7110->playing = 0;
1106 av7110->rec_mode = 0;
1107
Oliver Endriss9e615ea2008-09-03 19:15:27 -03001108 feeding = av7110->feeding1; /* full_ts mod */
1109
Oliver Endriss66190a22006-01-09 15:32:42 -02001110 for (i = 0; i < dvbdmx->feednum; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001111 feed = &dvbdmx->feed[i];
Oliver Endriss66190a22006-01-09 15:32:42 -02001112 if (feed->state == DMX_STATE_GO) {
1113 if (feed->type == DMX_TYPE_SEC) {
1114 for (j = 0; j < dvbdmx->filternum; j++) {
1115 if (dvbdmx->filter[j].type != DMX_TYPE_SEC)
1116 continue;
1117 if (dvbdmx->filter[j].filter.parent != &feed->feed.sec)
1118 continue;
1119 if (dvbdmx->filter[j].state == DMX_STATE_GO)
1120 dvbdmx->filter[j].state = DMX_STATE_READY;
1121 }
1122 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001123 av7110_start_feed(feed);
Oliver Endriss66190a22006-01-09 15:32:42 -02001124 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001125 }
1126
Oliver Endriss9e615ea2008-09-03 19:15:27 -03001127 av7110->feeding1 = feeding; /* full_ts mod */
1128
Linus Torvalds1da177e2005-04-16 15:20:36 -07001129 if (mode)
1130 av7110_av_start_play(av7110, mode);
1131}
1132
1133static int dvb_get_stc(struct dmx_demux *demux, unsigned int num,
1134 uint64_t *stc, unsigned int *base)
1135{
1136 int ret;
1137 u16 fwstc[4];
1138 u16 tag = ((COMTYPE_REQUEST << 8) + ReqSTC);
1139 struct dvb_demux *dvbdemux;
1140 struct av7110 *av7110;
1141
1142 /* pointer casting paranoia... */
Eric Sesterhennae246012006-03-13 13:17:11 -03001143 BUG_ON(!demux);
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001144 dvbdemux = demux->priv;
Eric Sesterhennae246012006-03-13 13:17:11 -03001145 BUG_ON(!dvbdemux);
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001146 av7110 = dvbdemux->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001147
1148 dprintk(4, "%p\n", av7110);
1149
1150 if (num != 0)
1151 return -EINVAL;
1152
1153 ret = av7110_fw_request(av7110, &tag, 0, fwstc, 4);
1154 if (ret) {
Harvey Harrison3ca7fc82008-04-08 23:20:00 -03001155 printk(KERN_ERR "%s: av7110_fw_request error\n", __func__);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001156 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001157 }
1158 dprintk(2, "fwstc = %04hx %04hx %04hx %04hx\n",
1159 fwstc[0], fwstc[1], fwstc[2], fwstc[3]);
1160
1161 *stc = (((uint64_t) ((fwstc[3] & 0x8000) >> 15)) << 32) |
1162 (((uint64_t) fwstc[1]) << 16) | ((uint64_t) fwstc[0]);
1163 *base = 1;
1164
1165 dprintk(4, "stc = %lu\n", (unsigned long)*stc);
1166
1167 return 0;
1168}
1169
1170
1171/******************************************************************************
1172 * SEC device file operations
1173 ******************************************************************************/
1174
1175
1176static int av7110_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
1177{
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001178 struct av7110* av7110 = fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001179
1180 switch (tone) {
1181 case SEC_TONE_ON:
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001182 return Set22K(av7110, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001183
1184 case SEC_TONE_OFF:
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001185 return Set22K(av7110, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001186
1187 default:
1188 return -EINVAL;
1189 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001190}
1191
1192static int av7110_diseqc_send_master_cmd(struct dvb_frontend* fe,
1193 struct dvb_diseqc_master_cmd* cmd)
1194{
1195 struct av7110* av7110 = fe->dvb->priv;
1196
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001197 return av7110_diseqc_send(av7110, cmd->msg_len, cmd->msg, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001198}
1199
1200static int av7110_diseqc_send_burst(struct dvb_frontend* fe,
1201 fe_sec_mini_cmd_t minicmd)
1202{
1203 struct av7110* av7110 = fe->dvb->priv;
1204
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001205 return av7110_diseqc_send(av7110, 0, NULL, minicmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206}
1207
1208/* simplified code from budget-core.c */
1209static int stop_ts_capture(struct av7110 *budget)
1210{
1211 dprintk(2, "budget: %p\n", budget);
1212
1213 if (--budget->feeding1)
1214 return budget->feeding1;
1215 saa7146_write(budget->dev, MC1, MASK_20); /* DMA3 off */
1216 SAA7146_IER_DISABLE(budget->dev, MASK_10);
1217 SAA7146_ISR_CLEAR(budget->dev, MASK_10);
1218 return 0;
1219}
1220
1221static int start_ts_capture(struct av7110 *budget)
1222{
1223 dprintk(2, "budget: %p\n", budget);
1224
1225 if (budget->feeding1)
1226 return ++budget->feeding1;
Oliver Endriss9e615ea2008-09-03 19:15:27 -03001227 memset(budget->grabbing, 0x00, TS_BUFLEN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001228 budget->ttbp = 0;
Oliver Endriss9e615ea2008-09-03 19:15:27 -03001229 SAA7146_ISR_CLEAR(budget->dev, MASK_10); /* VPE */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001230 SAA7146_IER_ENABLE(budget->dev, MASK_10); /* VPE */
1231 saa7146_write(budget->dev, MC1, (MASK_04 | MASK_20)); /* DMA3 on */
1232 return ++budget->feeding1;
1233}
1234
1235static int budget_start_feed(struct dvb_demux_feed *feed)
1236{
1237 struct dvb_demux *demux = feed->demux;
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001238 struct av7110 *budget = demux->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001239 int status;
1240
1241 dprintk(2, "av7110: %p\n", budget);
1242
1243 spin_lock(&budget->feedlock1);
1244 feed->pusi_seen = 0; /* have a clean section start */
1245 status = start_ts_capture(budget);
1246 spin_unlock(&budget->feedlock1);
1247 return status;
1248}
1249
1250static int budget_stop_feed(struct dvb_demux_feed *feed)
1251{
1252 struct dvb_demux *demux = feed->demux;
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001253 struct av7110 *budget = demux->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001254 int status;
1255
1256 dprintk(2, "budget: %p\n", budget);
1257
1258 spin_lock(&budget->feedlock1);
1259 status = stop_ts_capture(budget);
1260 spin_unlock(&budget->feedlock1);
1261 return status;
1262}
1263
Hans Verkuild45b9b82008-09-04 03:33:43 -03001264static void vpeirq(unsigned long cookie)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001265{
Hans Verkuild45b9b82008-09-04 03:33:43 -03001266 struct av7110 *budget = (struct av7110 *)cookie;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001267 u8 *mem = (u8 *) (budget->grabbing);
1268 u32 olddma = budget->ttbp;
1269 u32 newdma = saa7146_read(budget->dev, PCI_VDP3);
Oliver Endriss9e615ea2008-09-03 19:15:27 -03001270 struct dvb_demux *demux = budget->full_ts ? &budget->demux : &budget->demux1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001271
Linus Torvalds1da177e2005-04-16 15:20:36 -07001272 /* nearest lower position divisible by 188 */
1273 newdma -= newdma % 188;
1274
1275 if (newdma >= TS_BUFLEN)
1276 return;
1277
1278 budget->ttbp = newdma;
1279
1280 if (!budget->feeding1 || (newdma == olddma))
1281 return;
1282
Jon Burgess87c30192007-05-03 12:23:44 -03001283 /* Ensure streamed PCI data is synced to CPU */
1284 pci_dma_sync_sg_for_cpu(budget->dev->pci, budget->pt.slist, budget->pt.nents, PCI_DMA_FROMDEVICE);
1285
Linus Torvalds1da177e2005-04-16 15:20:36 -07001286#if 0
1287 /* track rps1 activity */
1288 printk("vpeirq: %02x Event Counter 1 0x%04x\n",
1289 mem[olddma],
1290 saa7146_read(budget->dev, EC1R) & 0x3fff);
1291#endif
1292
1293 if (newdma > olddma)
1294 /* no wraparound, dump olddma..newdma */
Oliver Endriss9e615ea2008-09-03 19:15:27 -03001295 dvb_dmx_swfilter_packets(demux, mem + olddma, (newdma - olddma) / 188);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001296 else {
1297 /* wraparound, dump olddma..buflen and 0..newdma */
Oliver Endriss9e615ea2008-09-03 19:15:27 -03001298 dvb_dmx_swfilter_packets(demux, mem + olddma, (TS_BUFLEN - olddma) / 188);
1299 dvb_dmx_swfilter_packets(demux, mem, newdma / 188);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001300 }
1301}
1302
1303static int av7110_register(struct av7110 *av7110)
1304{
1305 int ret, i;
1306 struct dvb_demux *dvbdemux = &av7110->demux;
1307 struct dvb_demux *dvbdemux1 = &av7110->demux1;
1308
1309 dprintk(4, "%p\n", av7110);
1310
1311 if (av7110->registered)
1312 return -1;
1313
1314 av7110->registered = 1;
1315
1316 dvbdemux->priv = (void *) av7110;
1317
1318 for (i = 0; i < 32; i++)
1319 av7110->handle2filter[i] = NULL;
1320
Oliver Endriss9e615ea2008-09-03 19:15:27 -03001321 dvbdemux->filternum = (av7110->full_ts) ? 256 : 32;
1322 dvbdemux->feednum = (av7110->full_ts) ? 256 : 32;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001323 dvbdemux->start_feed = av7110_start_feed;
1324 dvbdemux->stop_feed = av7110_stop_feed;
1325 dvbdemux->write_to_decoder = av7110_write_to_decoder;
1326 dvbdemux->dmx.capabilities = (DMX_TS_FILTERING | DMX_SECTION_FILTERING |
1327 DMX_MEMORY_BASED_FILTERING);
1328
1329 dvb_dmx_init(&av7110->demux);
1330 av7110->demux.dmx.get_stc = dvb_get_stc;
1331
Oliver Endriss9e615ea2008-09-03 19:15:27 -03001332 av7110->dmxdev.filternum = (av7110->full_ts) ? 256 : 32;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001333 av7110->dmxdev.demux = &dvbdemux->dmx;
1334 av7110->dmxdev.capabilities = 0;
1335
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001336 dvb_dmxdev_init(&av7110->dmxdev, &av7110->dvb_adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001337
1338 av7110->hw_frontend.source = DMX_FRONTEND_0;
1339
1340 ret = dvbdemux->dmx.add_frontend(&dvbdemux->dmx, &av7110->hw_frontend);
1341
1342 if (ret < 0)
1343 return ret;
1344
1345 av7110->mem_frontend.source = DMX_MEMORY_FE;
1346
1347 ret = dvbdemux->dmx.add_frontend(&dvbdemux->dmx, &av7110->mem_frontend);
1348
1349 if (ret < 0)
1350 return ret;
1351
1352 ret = dvbdemux->dmx.connect_frontend(&dvbdemux->dmx,
1353 &av7110->hw_frontend);
1354 if (ret < 0)
1355 return ret;
1356
1357 av7110_av_register(av7110);
1358 av7110_ca_register(av7110);
1359
1360#ifdef CONFIG_DVB_AV7110_OSD
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001361 dvb_register_device(&av7110->dvb_adapter, &av7110->osd_dev,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001362 &dvbdev_osd, av7110, DVB_DEVICE_OSD);
1363#endif
1364
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001365 dvb_net_init(&av7110->dvb_adapter, &av7110->dvb_net, &dvbdemux->dmx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001366
1367 if (budgetpatch) {
1368 /* initialize software demux1 without its own frontend
1369 * demux1 hardware is connected to frontend0 of demux0
1370 */
1371 dvbdemux1->priv = (void *) av7110;
1372
1373 dvbdemux1->filternum = 256;
1374 dvbdemux1->feednum = 256;
1375 dvbdemux1->start_feed = budget_start_feed;
1376 dvbdemux1->stop_feed = budget_stop_feed;
1377 dvbdemux1->write_to_decoder = NULL;
1378
1379 dvbdemux1->dmx.capabilities = (DMX_TS_FILTERING | DMX_SECTION_FILTERING |
1380 DMX_MEMORY_BASED_FILTERING);
1381
1382 dvb_dmx_init(&av7110->demux1);
1383
1384 av7110->dmxdev1.filternum = 256;
1385 av7110->dmxdev1.demux = &dvbdemux1->dmx;
1386 av7110->dmxdev1.capabilities = 0;
1387
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001388 dvb_dmxdev_init(&av7110->dmxdev1, &av7110->dvb_adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001389
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001390 dvb_net_init(&av7110->dvb_adapter, &av7110->dvb_net1, &dvbdemux1->dmx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001391 printk("dvb-ttpci: additional demux1 for budget-patch registered\n");
1392 }
1393 return 0;
1394}
1395
1396
1397static void dvb_unregister(struct av7110 *av7110)
1398{
1399 struct dvb_demux *dvbdemux = &av7110->demux;
1400 struct dvb_demux *dvbdemux1 = &av7110->demux1;
1401
1402 dprintk(4, "%p\n", av7110);
1403
1404 if (!av7110->registered)
1405 return;
1406
1407 if (budgetpatch) {
1408 dvb_net_release(&av7110->dvb_net1);
1409 dvbdemux->dmx.close(&dvbdemux1->dmx);
1410 dvb_dmxdev_release(&av7110->dmxdev1);
1411 dvb_dmx_release(&av7110->demux1);
1412 }
1413
1414 dvb_net_release(&av7110->dvb_net);
1415
1416 dvbdemux->dmx.close(&dvbdemux->dmx);
1417 dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &av7110->hw_frontend);
1418 dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &av7110->mem_frontend);
1419
1420 dvb_dmxdev_release(&av7110->dmxdev);
1421 dvb_dmx_release(&av7110->demux);
1422
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001423 if (av7110->fe != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001424 dvb_unregister_frontend(av7110->fe);
Andrew de Quinceyf52a8382006-08-08 09:10:09 -03001425 dvb_frontend_detach(av7110->fe);
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001426 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001427 dvb_unregister_device(av7110->osd_dev);
1428 av7110_av_unregister(av7110);
1429 av7110_ca_unregister(av7110);
1430}
1431
1432
1433/****************************************************************************
1434 * I2C client commands
1435 ****************************************************************************/
1436
1437int i2c_writereg(struct av7110 *av7110, u8 id, u8 reg, u8 val)
1438{
1439 u8 msg[2] = { reg, val };
1440 struct i2c_msg msgs;
1441
1442 msgs.flags = 0;
1443 msgs.addr = id / 2;
1444 msgs.len = 2;
1445 msgs.buf = msg;
1446 return i2c_transfer(&av7110->i2c_adap, &msgs, 1);
1447}
1448
Linus Torvalds1da177e2005-04-16 15:20:36 -07001449u8 i2c_readreg(struct av7110 *av7110, u8 id, u8 reg)
1450{
1451 u8 mm1[] = {0x00};
1452 u8 mm2[] = {0x00};
1453 struct i2c_msg msgs[2];
1454
1455 msgs[0].flags = 0;
1456 msgs[1].flags = I2C_M_RD;
1457 msgs[0].addr = msgs[1].addr = id / 2;
1458 mm1[0] = reg;
1459 msgs[0].len = 1; msgs[1].len = 1;
1460 msgs[0].buf = mm1; msgs[1].buf = mm2;
1461 i2c_transfer(&av7110->i2c_adap, msgs, 2);
1462
1463 return mm2[0];
1464}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001465
1466/****************************************************************************
1467 * INITIALIZATION
1468 ****************************************************************************/
1469
1470
1471static int check_firmware(struct av7110* av7110)
1472{
1473 u32 crc = 0, len = 0;
1474 unsigned char *ptr;
1475
1476 /* check for firmware magic */
1477 ptr = av7110->bin_fw;
1478 if (ptr[0] != 'A' || ptr[1] != 'V' ||
1479 ptr[2] != 'F' || ptr[3] != 'W') {
1480 printk("dvb-ttpci: this is not an av7110 firmware\n");
1481 return -EINVAL;
1482 }
1483 ptr += 4;
1484
1485 /* check dpram file */
Al Viro3e085622008-05-21 00:30:51 -03001486 crc = get_unaligned_be32(ptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001487 ptr += 4;
Al Viro3e085622008-05-21 00:30:51 -03001488 len = get_unaligned_be32(ptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001489 ptr += 4;
1490 if (len >= 512) {
Alexey Dobriyanbe787ac2006-03-07 22:20:23 -03001491 printk("dvb-ttpci: dpram file is way too big.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001492 return -EINVAL;
1493 }
1494 if (crc != crc32_le(0, ptr, len)) {
1495 printk("dvb-ttpci: crc32 of dpram file does not match.\n");
1496 return -EINVAL;
1497 }
1498 av7110->bin_dpram = ptr;
1499 av7110->size_dpram = len;
1500 ptr += len;
1501
1502 /* check root file */
Al Viro3e085622008-05-21 00:30:51 -03001503 crc = get_unaligned_be32(ptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001504 ptr += 4;
Al Viro3e085622008-05-21 00:30:51 -03001505 len = get_unaligned_be32(ptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001506 ptr += 4;
1507
1508 if (len <= 200000 || len >= 300000 ||
1509 len > ((av7110->bin_fw + av7110->size_fw) - ptr)) {
1510 printk("dvb-ttpci: root file has strange size (%d). aborting.\n", len);
1511 return -EINVAL;
1512 }
1513 if( crc != crc32_le(0, ptr, len)) {
1514 printk("dvb-ttpci: crc32 of root file does not match.\n");
1515 return -EINVAL;
1516 }
1517 av7110->bin_root = ptr;
1518 av7110->size_root = len;
1519 return 0;
1520}
1521
Linus Torvalds1da177e2005-04-16 15:20:36 -07001522static void put_firmware(struct av7110* av7110)
1523{
1524 vfree(av7110->bin_fw);
1525}
1526
1527static int get_firmware(struct av7110* av7110)
1528{
1529 int ret;
1530 const struct firmware *fw;
1531
1532 /* request the av7110 firmware, this will block until someone uploads it */
1533 ret = request_firmware(&fw, "dvb-ttpci-01.fw", &av7110->dev->pci->dev);
1534 if (ret) {
1535 if (ret == -ENOENT) {
1536 printk(KERN_ERR "dvb-ttpci: could not load firmware,"
1537 " file not found: dvb-ttpci-01.fw\n");
Ville Skytt\ä12e66f62006-01-09 15:25:38 -02001538 printk(KERN_ERR "dvb-ttpci: usually this should be in "
1539 "/usr/lib/hotplug/firmware or /lib/firmware\n");
1540 printk(KERN_ERR "dvb-ttpci: and can be downloaded from"
Linus Torvalds1da177e2005-04-16 15:20:36 -07001541 " http://www.linuxtv.org/download/dvb/firmware/\n");
1542 } else
1543 printk(KERN_ERR "dvb-ttpci: cannot request firmware"
1544 " (error %i)\n", ret);
1545 return -EINVAL;
1546 }
1547
1548 if (fw->size <= 200000) {
1549 printk("dvb-ttpci: this firmware is way too small.\n");
1550 release_firmware(fw);
1551 return -EINVAL;
1552 }
1553
1554 /* check if the firmware is available */
Jesper Juhld9bf2c02007-08-25 11:23:54 -03001555 av7110->bin_fw = vmalloc(fw->size);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001556 if (NULL == av7110->bin_fw) {
1557 dprintk(1, "out of memory\n");
1558 release_firmware(fw);
1559 return -ENOMEM;
1560 }
1561
1562 memcpy(av7110->bin_fw, fw->data, fw->size);
1563 av7110->size_fw = fw->size;
1564 if ((ret = check_firmware(av7110)))
1565 vfree(av7110->bin_fw);
1566
1567 release_firmware(fw);
1568 return ret;
1569}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001570
Mauro Carvalho Chehab14d24d12011-12-24 12:24:33 -03001571static int alps_bsrv2_tuner_set_params(struct dvb_frontend *fe)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001572{
Mauro Carvalho Chehabe439aed2011-12-23 08:01:05 -03001573 struct dtv_frontend_properties *p = &fe->dtv_property_cache;
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001574 struct av7110* av7110 = fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001575 u8 pwr = 0;
1576 u8 buf[4];
1577 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
Mauro Carvalho Chehabe439aed2011-12-23 08:01:05 -03001578 u32 div = (p->frequency + 479500) / 125;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001579
Mauro Carvalho Chehabe439aed2011-12-23 08:01:05 -03001580 if (p->frequency > 2000000)
1581 pwr = 3;
1582 else if (p->frequency > 1800000)
1583 pwr = 2;
1584 else if (p->frequency > 1600000)
1585 pwr = 1;
1586 else if (p->frequency > 1200000)
1587 pwr = 0;
1588 else if (p->frequency >= 1100000)
1589 pwr = 1;
1590 else
1591 pwr = 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001592
1593 buf[0] = (div >> 8) & 0x7f;
1594 buf[1] = div & 0xff;
1595 buf[2] = ((div & 0x18000) >> 10) | 0x95;
1596 buf[3] = (pwr << 6) | 0x30;
1597
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -08001598 // NOTE: since we're using a prescaler of 2, we set the
Linus Torvalds1da177e2005-04-16 15:20:36 -07001599 // divisor frequency to 62.5kHz and divide by 125 above
1600
Patrick Boettcherdea74862006-05-14 05:01:31 -03001601 if (fe->ops.i2c_gate_ctrl)
1602 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001603 if (i2c_transfer (&av7110->i2c_adap, &msg, 1) != 1)
1604 return -EIO;
1605 return 0;
1606}
1607
1608static struct ves1x93_config alps_bsrv2_config = {
1609 .demod_address = 0x08,
1610 .xin = 90100000UL,
1611 .invert_pwm = 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001612};
1613
Mauro Carvalho Chehab14d24d12011-12-24 12:24:33 -03001614static int alps_tdbe2_tuner_set_params(struct dvb_frontend *fe)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001615{
Mauro Carvalho Chehabe439aed2011-12-23 08:01:05 -03001616 struct dtv_frontend_properties *p = &fe->dtv_property_cache;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001617 struct av7110* av7110 = fe->dvb->priv;
1618 u32 div;
1619 u8 data[4];
1620 struct i2c_msg msg = { .addr = 0x62, .flags = 0, .buf = data, .len = sizeof(data) };
1621
Mauro Carvalho Chehabe439aed2011-12-23 08:01:05 -03001622 div = (p->frequency + 35937500 + 31250) / 62500;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001623
1624 data[0] = (div >> 8) & 0x7f;
1625 data[1] = div & 0xff;
1626 data[2] = 0x85 | ((div >> 10) & 0x60);
Mauro Carvalho Chehabe439aed2011-12-23 08:01:05 -03001627 data[3] = (p->frequency < 174000000 ? 0x88 : p->frequency < 470000000 ? 0x84 : 0x81);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001628
Patrick Boettcherdea74862006-05-14 05:01:31 -03001629 if (fe->ops.i2c_gate_ctrl)
1630 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001631 if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
1632 return -EIO;
1633 return 0;
1634}
1635
1636static struct ves1820_config alps_tdbe2_config = {
1637 .demod_address = 0x09,
1638 .xin = 57840000UL,
1639 .invert = 1,
1640 .selagc = VES1820_SELAGC_SIGNAMPERR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001641};
1642
1643
1644
1645
Mauro Carvalho Chehab14d24d12011-12-24 12:24:33 -03001646static int grundig_29504_451_tuner_set_params(struct dvb_frontend *fe)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001647{
Mauro Carvalho Chehabe439aed2011-12-23 08:01:05 -03001648 struct dtv_frontend_properties *p = &fe->dtv_property_cache;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001649 struct av7110* av7110 = fe->dvb->priv;
1650 u32 div;
1651 u8 data[4];
1652 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
1653
Mauro Carvalho Chehabe439aed2011-12-23 08:01:05 -03001654 div = p->frequency / 125;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001655 data[0] = (div >> 8) & 0x7f;
1656 data[1] = div & 0xff;
1657 data[2] = 0x8e;
1658 data[3] = 0x00;
1659
Patrick Boettcherdea74862006-05-14 05:01:31 -03001660 if (fe->ops.i2c_gate_ctrl)
1661 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001662 if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
1663 return -EIO;
1664 return 0;
1665}
1666
1667static struct tda8083_config grundig_29504_451_config = {
1668 .demod_address = 0x68,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001669};
1670
1671
1672
Mauro Carvalho Chehab14d24d12011-12-24 12:24:33 -03001673static int philips_cd1516_tuner_set_params(struct dvb_frontend *fe)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001674{
Mauro Carvalho Chehabe439aed2011-12-23 08:01:05 -03001675 struct dtv_frontend_properties *p = &fe->dtv_property_cache;
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -08001676 struct av7110* av7110 = fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001677 u32 div;
Mauro Carvalho Chehabe439aed2011-12-23 08:01:05 -03001678 u32 f = p->frequency;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001679 u8 data[4];
1680 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
1681
1682 div = (f + 36125000 + 31250) / 62500;
1683
1684 data[0] = (div >> 8) & 0x7f;
1685 data[1] = div & 0xff;
1686 data[2] = 0x8e;
1687 data[3] = (f < 174000000 ? 0xa1 : f < 470000000 ? 0x92 : 0x34);
1688
Patrick Boettcherdea74862006-05-14 05:01:31 -03001689 if (fe->ops.i2c_gate_ctrl)
1690 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001691 if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
1692 return -EIO;
1693 return 0;
1694}
1695
1696static struct ves1820_config philips_cd1516_config = {
1697 .demod_address = 0x09,
1698 .xin = 57840000UL,
1699 .invert = 1,
1700 .selagc = VES1820_SELAGC_SIGNAMPERR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001701};
1702
1703
1704
Mauro Carvalho Chehab14d24d12011-12-24 12:24:33 -03001705static int alps_tdlb7_tuner_set_params(struct dvb_frontend *fe)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001706{
Mauro Carvalho Chehabe439aed2011-12-23 08:01:05 -03001707 struct dtv_frontend_properties *p = &fe->dtv_property_cache;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001708 struct av7110* av7110 = fe->dvb->priv;
1709 u32 div, pwr;
1710 u8 data[4];
1711 struct i2c_msg msg = { .addr = 0x60, .flags = 0, .buf = data, .len = sizeof(data) };
1712
Mauro Carvalho Chehabe439aed2011-12-23 08:01:05 -03001713 div = (p->frequency + 36200000) / 166666;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001714
Mauro Carvalho Chehabe439aed2011-12-23 08:01:05 -03001715 if (p->frequency <= 782000000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001716 pwr = 1;
1717 else
1718 pwr = 2;
1719
1720 data[0] = (div >> 8) & 0x7f;
1721 data[1] = div & 0xff;
1722 data[2] = 0x85;
1723 data[3] = pwr << 6;
1724
Patrick Boettcherdea74862006-05-14 05:01:31 -03001725 if (fe->ops.i2c_gate_ctrl)
1726 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001727 if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
1728 return -EIO;
1729 return 0;
1730}
1731
1732static int alps_tdlb7_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name)
1733{
Oliver Endrissd98821e2006-09-14 00:15:13 -03001734#if defined(CONFIG_DVB_SP8870) || defined(CONFIG_DVB_SP8870_MODULE)
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001735 struct av7110* av7110 = fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001736
1737 return request_firmware(fw, name, &av7110->dev->pci->dev);
Oliver Endrissd98821e2006-09-14 00:15:13 -03001738#else
1739 return -EINVAL;
1740#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001741}
1742
1743static struct sp8870_config alps_tdlb7_config = {
1744
1745 .demod_address = 0x71,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001746 .request_firmware = alps_tdlb7_request_firmware,
1747};
1748
1749
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001750static u8 nexusca_stv0297_inittab[] = {
1751 0x80, 0x01,
1752 0x80, 0x00,
1753 0x81, 0x01,
1754 0x81, 0x00,
1755 0x00, 0x09,
1756 0x01, 0x69,
1757 0x03, 0x00,
1758 0x04, 0x00,
1759 0x07, 0x00,
1760 0x08, 0x00,
1761 0x20, 0x00,
1762 0x21, 0x40,
1763 0x22, 0x00,
1764 0x23, 0x00,
1765 0x24, 0x40,
1766 0x25, 0x88,
1767 0x30, 0xff,
1768 0x31, 0x00,
1769 0x32, 0xff,
1770 0x33, 0x00,
1771 0x34, 0x50,
1772 0x35, 0x7f,
1773 0x36, 0x00,
1774 0x37, 0x20,
1775 0x38, 0x00,
1776 0x40, 0x1c,
1777 0x41, 0xff,
1778 0x42, 0x29,
1779 0x43, 0x00,
1780 0x44, 0xff,
1781 0x45, 0x00,
1782 0x46, 0x00,
1783 0x49, 0x04,
1784 0x4a, 0x00,
1785 0x4b, 0x7b,
1786 0x52, 0x30,
1787 0x55, 0xae,
1788 0x56, 0x47,
1789 0x57, 0xe1,
1790 0x58, 0x3a,
1791 0x5a, 0x1e,
1792 0x5b, 0x34,
1793 0x60, 0x00,
1794 0x63, 0x00,
1795 0x64, 0x00,
1796 0x65, 0x00,
1797 0x66, 0x00,
1798 0x67, 0x00,
1799 0x68, 0x00,
1800 0x69, 0x00,
1801 0x6a, 0x02,
1802 0x6b, 0x00,
1803 0x70, 0xff,
1804 0x71, 0x00,
1805 0x72, 0x00,
1806 0x73, 0x00,
1807 0x74, 0x0c,
1808 0x80, 0x00,
1809 0x81, 0x00,
1810 0x82, 0x00,
1811 0x83, 0x00,
1812 0x84, 0x04,
1813 0x85, 0x80,
1814 0x86, 0x24,
1815 0x87, 0x78,
1816 0x88, 0x10,
1817 0x89, 0x00,
1818 0x90, 0x01,
1819 0x91, 0x01,
1820 0xa0, 0x04,
1821 0xa1, 0x00,
1822 0xa2, 0x00,
1823 0xb0, 0x91,
1824 0xb1, 0x0b,
1825 0xc0, 0x53,
1826 0xc1, 0x70,
1827 0xc2, 0x12,
1828 0xd0, 0x00,
1829 0xd1, 0x00,
1830 0xd2, 0x00,
1831 0xd3, 0x00,
1832 0xd4, 0x00,
1833 0xd5, 0x00,
1834 0xde, 0x00,
1835 0xdf, 0x00,
1836 0x61, 0x49,
1837 0x62, 0x0b,
1838 0x53, 0x08,
1839 0x59, 0x08,
1840 0xff, 0xff,
1841};
Linus Torvalds1da177e2005-04-16 15:20:36 -07001842
Mauro Carvalho Chehab14d24d12011-12-24 12:24:33 -03001843static int nexusca_stv0297_tuner_set_params(struct dvb_frontend *fe)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001844{
Mauro Carvalho Chehabe439aed2011-12-23 08:01:05 -03001845 struct dtv_frontend_properties *p = &fe->dtv_property_cache;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001846 struct av7110* av7110 = fe->dvb->priv;
1847 u32 div;
1848 u8 data[4];
1849 struct i2c_msg msg = { .addr = 0x63, .flags = 0, .buf = data, .len = sizeof(data) };
1850 struct i2c_msg readmsg = { .addr = 0x63, .flags = I2C_M_RD, .buf = data, .len = 1 };
1851 int i;
1852
Mauro Carvalho Chehabe439aed2011-12-23 08:01:05 -03001853 div = (p->frequency + 36150000 + 31250) / 62500;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001854
1855 data[0] = (div >> 8) & 0x7f;
1856 data[1] = div & 0xff;
1857 data[2] = 0xce;
1858
Mauro Carvalho Chehabe439aed2011-12-23 08:01:05 -03001859 if (p->frequency < 45000000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001860 return -EINVAL;
Mauro Carvalho Chehabe439aed2011-12-23 08:01:05 -03001861 else if (p->frequency < 137000000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001862 data[3] = 0x01;
Mauro Carvalho Chehabe439aed2011-12-23 08:01:05 -03001863 else if (p->frequency < 403000000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001864 data[3] = 0x02;
Mauro Carvalho Chehabe439aed2011-12-23 08:01:05 -03001865 else if (p->frequency < 860000000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001866 data[3] = 0x04;
1867 else
1868 return -EINVAL;
1869
Patrick Boettcherdea74862006-05-14 05:01:31 -03001870 if (fe->ops.i2c_gate_ctrl)
1871 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001872 if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1) {
1873 printk("nexusca: pll transfer failed!\n");
1874 return -EIO;
1875 }
1876
1877 // wait for PLL lock
1878 for(i = 0; i < 20; i++) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001879 if (fe->ops.i2c_gate_ctrl)
1880 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001881 if (i2c_transfer(&av7110->i2c_adap, &readmsg, 1) == 1)
1882 if (data[0] & 0x40) break;
1883 msleep(10);
1884 }
1885
1886 return 0;
1887}
1888
1889static struct stv0297_config nexusca_stv0297_config = {
1890
1891 .demod_address = 0x1C,
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001892 .inittab = nexusca_stv0297_inittab,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001893 .invert = 1,
Thomas Kaiserb8d4c232006-04-27 21:45:20 -03001894 .stop_during_read = 1,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001895};
1896
1897
1898
Mauro Carvalho Chehab14d24d12011-12-24 12:24:33 -03001899static int grundig_29504_401_tuner_set_params(struct dvb_frontend *fe)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001900{
Mauro Carvalho Chehabe439aed2011-12-23 08:01:05 -03001901 struct dtv_frontend_properties *p = &fe->dtv_property_cache;
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001902 struct av7110* av7110 = fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001903 u32 div;
1904 u8 cfg, cpump, band_select;
1905 u8 data[4];
1906 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
1907
Mauro Carvalho Chehabe439aed2011-12-23 08:01:05 -03001908 div = (36125000 + p->frequency) / 166666;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001909
1910 cfg = 0x88;
1911
Mauro Carvalho Chehabe439aed2011-12-23 08:01:05 -03001912 if (p->frequency < 175000000)
1913 cpump = 2;
1914 else if (p->frequency < 390000000)
1915 cpump = 1;
1916 else if (p->frequency < 470000000)
1917 cpump = 2;
1918 else if (p->frequency < 750000000)
1919 cpump = 1;
1920 else
1921 cpump = 3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001922
Mauro Carvalho Chehabe439aed2011-12-23 08:01:05 -03001923 if (p->frequency < 175000000)
1924 band_select = 0x0e;
1925 else if (p->frequency < 470000000)
1926 band_select = 0x05;
1927 else
1928 band_select = 0x03;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001929
1930 data[0] = (div >> 8) & 0x7f;
1931 data[1] = div & 0xff;
1932 data[2] = ((div >> 10) & 0x60) | cfg;
1933 data[3] = (cpump << 6) | band_select;
1934
Patrick Boettcherdea74862006-05-14 05:01:31 -03001935 if (fe->ops.i2c_gate_ctrl)
1936 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001937 if (i2c_transfer (&av7110->i2c_adap, &msg, 1) != 1) return -EIO;
1938 return 0;
1939}
1940
1941static struct l64781_config grundig_29504_401_config = {
1942 .demod_address = 0x55,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001943};
1944
1945
1946
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001947static int av7110_fe_lock_fix(struct av7110* av7110, fe_status_t status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001948{
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001949 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001950 int synced = (status & FE_HAS_LOCK) ? 1 : 0;
1951
1952 av7110->fe_status = status;
1953
1954 if (av7110->fe_synced == synced)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001955 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001956
Oliver Endriss14500d42007-03-03 14:45:48 -03001957 if (av7110->playing) {
1958 av7110->fe_synced = synced;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001959 return 0;
Oliver Endriss14500d42007-03-03 14:45:48 -03001960 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001961
Ingo Molnar3593cab2006-02-07 06:49:14 -02001962 if (mutex_lock_interruptible(&av7110->pid_mutex))
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001963 return -ERESTARTSYS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001964
Oliver Endriss34612152005-07-07 17:58:02 -07001965 if (synced) {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001966 ret = SetPIDs(av7110, av7110->pids[DMX_PES_VIDEO],
Linus Torvalds1da177e2005-04-16 15:20:36 -07001967 av7110->pids[DMX_PES_AUDIO],
1968 av7110->pids[DMX_PES_TELETEXT], 0,
1969 av7110->pids[DMX_PES_PCR]);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001970 if (!ret)
1971 ret = av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, Scan, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001972 } else {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001973 ret = SetPIDs(av7110, 0, 0, 0, 0, 0);
1974 if (!ret) {
1975 ret = av7110_fw_cmd(av7110, COMTYPE_PID_FILTER, FlushTSQueue, 0);
1976 if (!ret)
1977 ret = av7110_wait_msgstate(av7110, GPMQBusy);
1978 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001979 }
1980
Oliver Endriss34612152005-07-07 17:58:02 -07001981 if (!ret)
1982 av7110->fe_synced = synced;
1983
Ingo Molnar3593cab2006-02-07 06:49:14 -02001984 mutex_unlock(&av7110->pid_mutex);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001985 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001986}
1987
Mauro Carvalho Chehabb5c7cfd2011-12-23 18:19:24 -03001988static int av7110_fe_set_frontend(struct dvb_frontend *fe)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001989{
1990 struct av7110* av7110 = fe->dvb->priv;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001991
1992 int ret = av7110_fe_lock_fix(av7110, 0);
Mauro Carvalho Chehabb5c7cfd2011-12-23 18:19:24 -03001993 if (!ret)
1994 ret = av7110->fe_set_frontend(fe);
1995
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001996 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001997}
1998
1999static int av7110_fe_init(struct dvb_frontend* fe)
2000{
2001 struct av7110* av7110 = fe->dvb->priv;
2002
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002003 int ret = av7110_fe_lock_fix(av7110, 0);
2004 if (!ret)
2005 ret = av7110->fe_init(fe);
2006 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002007}
2008
2009static int av7110_fe_read_status(struct dvb_frontend* fe, fe_status_t* status)
2010{
2011 struct av7110* av7110 = fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002012
2013 /* call the real implementation */
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002014 int ret = av7110->fe_read_status(fe, status);
2015 if (!ret)
2016 if (((*status ^ av7110->fe_status) & FE_HAS_LOCK) && (*status & FE_HAS_LOCK))
2017 ret = av7110_fe_lock_fix(av7110, *status);
2018 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002019}
2020
2021static int av7110_fe_diseqc_reset_overload(struct dvb_frontend* fe)
2022{
2023 struct av7110* av7110 = fe->dvb->priv;
2024
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002025 int ret = av7110_fe_lock_fix(av7110, 0);
2026 if (!ret)
2027 ret = av7110->fe_diseqc_reset_overload(fe);
2028 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002029}
2030
2031static int av7110_fe_diseqc_send_master_cmd(struct dvb_frontend* fe,
2032 struct dvb_diseqc_master_cmd* cmd)
2033{
2034 struct av7110* av7110 = fe->dvb->priv;
2035
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002036 int ret = av7110_fe_lock_fix(av7110, 0);
Oliver Endriss66190a22006-01-09 15:32:42 -02002037 if (!ret) {
2038 av7110->saved_master_cmd = *cmd;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002039 ret = av7110->fe_diseqc_send_master_cmd(fe, cmd);
Oliver Endriss66190a22006-01-09 15:32:42 -02002040 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002041 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002042}
2043
2044static int av7110_fe_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd)
2045{
2046 struct av7110* av7110 = fe->dvb->priv;
2047
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002048 int ret = av7110_fe_lock_fix(av7110, 0);
Oliver Endriss66190a22006-01-09 15:32:42 -02002049 if (!ret) {
2050 av7110->saved_minicmd = minicmd;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002051 ret = av7110->fe_diseqc_send_burst(fe, minicmd);
Oliver Endriss66190a22006-01-09 15:32:42 -02002052 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002053 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002054}
2055
2056static int av7110_fe_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
2057{
2058 struct av7110* av7110 = fe->dvb->priv;
2059
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002060 int ret = av7110_fe_lock_fix(av7110, 0);
Oliver Endriss66190a22006-01-09 15:32:42 -02002061 if (!ret) {
2062 av7110->saved_tone = tone;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002063 ret = av7110->fe_set_tone(fe, tone);
Oliver Endriss66190a22006-01-09 15:32:42 -02002064 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002065 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002066}
2067
2068static int av7110_fe_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
2069{
2070 struct av7110* av7110 = fe->dvb->priv;
2071
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002072 int ret = av7110_fe_lock_fix(av7110, 0);
Oliver Endriss66190a22006-01-09 15:32:42 -02002073 if (!ret) {
2074 av7110->saved_voltage = voltage;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002075 ret = av7110->fe_set_voltage(fe, voltage);
Oliver Endriss66190a22006-01-09 15:32:42 -02002076 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002077 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002078}
2079
Peter Beutner400b7082006-01-09 15:32:43 -02002080static int av7110_fe_dishnetwork_send_legacy_command(struct dvb_frontend* fe, unsigned long cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002081{
2082 struct av7110* av7110 = fe->dvb->priv;
2083
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002084 int ret = av7110_fe_lock_fix(av7110, 0);
2085 if (!ret)
2086 ret = av7110->fe_dishnetwork_send_legacy_command(fe, cmd);
2087 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002088}
2089
Oliver Endriss66190a22006-01-09 15:32:42 -02002090static void dvb_s_recover(struct av7110* av7110)
2091{
2092 av7110_fe_init(av7110->fe);
2093
2094 av7110_fe_set_voltage(av7110->fe, av7110->saved_voltage);
2095 if (av7110->saved_master_cmd.msg_len) {
2096 msleep(20);
2097 av7110_fe_diseqc_send_master_cmd(av7110->fe, &av7110->saved_master_cmd);
2098 }
2099 msleep(20);
2100 av7110_fe_diseqc_send_burst(av7110->fe, av7110->saved_minicmd);
2101 msleep(20);
2102 av7110_fe_set_tone(av7110->fe, av7110->saved_tone);
2103
Mauro Carvalho Chehabb5c7cfd2011-12-23 18:19:24 -03002104 av7110_fe_set_frontend(av7110->fe);
Oliver Endriss66190a22006-01-09 15:32:42 -02002105}
2106
Linus Torvalds1da177e2005-04-16 15:20:36 -07002107static u8 read_pwm(struct av7110* av7110)
2108{
2109 u8 b = 0xff;
2110 u8 pwm;
2111 struct i2c_msg msg[] = { { .addr = 0x50,.flags = 0,.buf = &b,.len = 1 },
2112 { .addr = 0x50,.flags = I2C_M_RD,.buf = &pwm,.len = 1} };
2113
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -08002114 if ((i2c_transfer(&av7110->i2c_adap, msg, 2) != 2) || (pwm == 0xff))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002115 pwm = 0x48;
2116
2117 return pwm;
2118}
2119
2120static int frontend_init(struct av7110 *av7110)
2121{
2122 int ret;
2123
2124 if (av7110->dev->pci->subsystem_vendor == 0x110a) {
2125 switch(av7110->dev->pci->subsystem_device) {
2126 case 0x0000: // Fujitsu/Siemens DVB-Cable (ves1820/Philips CD1516(??))
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002127 av7110->fe = dvb_attach(ves1820_attach, &philips_cd1516_config,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002128 &av7110->i2c_adap, read_pwm(av7110));
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002129 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002130 av7110->fe->ops.tuner_ops.set_params = philips_cd1516_tuner_set_params;
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002131 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002132 break;
2133 }
2134
2135 } else if (av7110->dev->pci->subsystem_vendor == 0x13c2) {
2136 switch(av7110->dev->pci->subsystem_device) {
2137 case 0x0000: // Hauppauge/TT WinTV DVB-S rev1.X
2138 case 0x0003: // Hauppauge/TT WinTV Nexus-S Rev 2.X
2139 case 0x1002: // Hauppauge/TT WinTV DVB-S rev1.3SE
2140
2141 // try the ALPS BSRV2 first of all
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002142 av7110->fe = dvb_attach(ves1x93_attach, &alps_bsrv2_config, &av7110->i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002143 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002144 av7110->fe->ops.tuner_ops.set_params = alps_bsrv2_tuner_set_params;
2145 av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
2146 av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
2147 av7110->fe->ops.set_tone = av7110_set_tone;
Oliver Endriss66190a22006-01-09 15:32:42 -02002148 av7110->recover = dvb_s_recover;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002149 break;
2150 }
2151
2152 // try the ALPS BSRU6 now
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002153 av7110->fe = dvb_attach(stv0299_attach, &alps_bsru6_config, &av7110->i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002154 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002155 av7110->fe->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03002156 av7110->fe->tuner_priv = &av7110->i2c_adap;
2157
Patrick Boettcherdea74862006-05-14 05:01:31 -03002158 av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
2159 av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
2160 av7110->fe->ops.set_tone = av7110_set_tone;
Oliver Endriss66190a22006-01-09 15:32:42 -02002161 av7110->recover = dvb_s_recover;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002162 break;
2163 }
2164
2165 // Try the grundig 29504-451
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002166 av7110->fe = dvb_attach(tda8083_attach, &grundig_29504_451_config, &av7110->i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002167 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002168 av7110->fe->ops.tuner_ops.set_params = grundig_29504_451_tuner_set_params;
2169 av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
2170 av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
2171 av7110->fe->ops.set_tone = av7110_set_tone;
Oliver Endriss66190a22006-01-09 15:32:42 -02002172 av7110->recover = dvb_s_recover;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002173 break;
2174 }
2175
2176 /* Try DVB-C cards */
2177 switch(av7110->dev->pci->subsystem_device) {
2178 case 0x0000:
2179 /* Siemens DVB-C (full-length card) VES1820/Philips CD1516 */
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002180 av7110->fe = dvb_attach(ves1820_attach, &philips_cd1516_config, &av7110->i2c_adap,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002181 read_pwm(av7110));
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002182 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002183 av7110->fe->ops.tuner_ops.set_params = philips_cd1516_tuner_set_params;
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002184 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002185 break;
2186 case 0x0003:
Adrian Bunkf3688fc2006-03-29 22:46:12 -03002187 /* Hauppauge DVB-C 2.1 VES1820/ALPS TDBE2 */
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002188 av7110->fe = dvb_attach(ves1820_attach, &alps_tdbe2_config, &av7110->i2c_adap,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002189 read_pwm(av7110));
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002190 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002191 av7110->fe->ops.tuner_ops.set_params = alps_tdbe2_tuner_set_params;
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002192 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002193 break;
2194 }
2195 break;
2196
2197 case 0x0001: // Hauppauge/TT Nexus-T premium rev1.X
Oliver Endriss8d90ee52006-08-07 02:04:26 -03002198 // try ALPS TDLB7 first, then Grundig 29504-401
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002199 av7110->fe = dvb_attach(sp8870_attach, &alps_tdlb7_config, &av7110->i2c_adap);
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002200 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002201 av7110->fe->ops.tuner_ops.set_params = alps_tdlb7_tuner_set_params;
Oliver Endriss8d90ee52006-08-07 02:04:26 -03002202 break;
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002203 }
Oliver Endriss8d90ee52006-08-07 02:04:26 -03002204 /* fall-thru */
2205
2206 case 0x0008: // Hauppauge/TT DVB-T
2207 // Grundig 29504-401
2208 av7110->fe = dvb_attach(l64781_attach, &grundig_29504_401_config, &av7110->i2c_adap);
2209 if (av7110->fe)
2210 av7110->fe->ops.tuner_ops.set_params = grundig_29504_401_tuner_set_params;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002211 break;
2212
2213 case 0x0002: // Hauppauge/TT DVB-C premium rev2.X
2214
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002215 av7110->fe = dvb_attach(ves1820_attach, &alps_tdbe2_config, &av7110->i2c_adap, read_pwm(av7110));
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002216 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002217 av7110->fe->ops.tuner_ops.set_params = alps_tdbe2_tuner_set_params;
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002218 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002219 break;
2220
Oliver Endriss8bd63012006-02-07 06:49:11 -02002221 case 0x0004: // Galaxis DVB-S rev1.3
2222 /* ALPS BSRV2 */
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002223 av7110->fe = dvb_attach(ves1x93_attach, &alps_bsrv2_config, &av7110->i2c_adap);
Oliver Endriss8bd63012006-02-07 06:49:11 -02002224 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002225 av7110->fe->ops.tuner_ops.set_params = alps_bsrv2_tuner_set_params;
2226 av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
2227 av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
2228 av7110->fe->ops.set_tone = av7110_set_tone;
Oliver Endriss8bd63012006-02-07 06:49:11 -02002229 av7110->recover = dvb_s_recover;
2230 }
2231 break;
2232
Linus Torvalds1da177e2005-04-16 15:20:36 -07002233 case 0x0006: /* Fujitsu-Siemens DVB-S rev 1.6 */
2234 /* Grundig 29504-451 */
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002235 av7110->fe = dvb_attach(tda8083_attach, &grundig_29504_451_config, &av7110->i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002236 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002237 av7110->fe->ops.tuner_ops.set_params = grundig_29504_451_tuner_set_params;
2238 av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
2239 av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
2240 av7110->fe->ops.set_tone = av7110_set_tone;
Oliver Endriss66190a22006-01-09 15:32:42 -02002241 av7110->recover = dvb_s_recover;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002242 }
2243 break;
2244
Linus Torvalds1da177e2005-04-16 15:20:36 -07002245 case 0x000A: // Hauppauge/TT Nexus-CA rev1.X
2246
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002247 av7110->fe = dvb_attach(stv0297_attach, &nexusca_stv0297_config, &av7110->i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002248 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002249 av7110->fe->ops.tuner_ops.set_params = nexusca_stv0297_tuner_set_params;
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03002250
Linus Torvalds1da177e2005-04-16 15:20:36 -07002251 /* set TDA9819 into DVB mode */
Marco Schluessler6a857742006-07-10 03:34:16 -03002252 saa7146_setgpio(av7110->dev, 1, SAA7146_GPIO_OUTLO); // TDA9819 pin9(STD)
2253 saa7146_setgpio(av7110->dev, 3, SAA7146_GPIO_OUTLO); // TDA9819 pin30(VIF)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002254
2255 /* tuner on this needs a slower i2c bus speed */
2256 av7110->dev->i2c_bitrate = SAA7146_I2C_BUS_BIT_RATE_240;
2257 break;
2258 }
Johannes Stezenbach3dfaebd2005-05-16 21:54:19 -07002259 break;
2260
2261 case 0x000E: /* Hauppauge/TT Nexus-S rev 2.3 */
2262 /* ALPS BSBE1 */
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002263 av7110->fe = dvb_attach(stv0299_attach, &alps_bsbe1_config, &av7110->i2c_adap);
Oliver Endrisseb3daf32006-01-09 15:25:05 -02002264 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002265 av7110->fe->ops.tuner_ops.set_params = alps_bsbe1_tuner_set_params;
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03002266 av7110->fe->tuner_priv = &av7110->i2c_adap;
2267
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002268 if (dvb_attach(lnbp21_attach, av7110->fe, &av7110->i2c_adap, 0, 0) == NULL) {
Oliver Endrissdb5d91e2006-02-28 10:32:25 -03002269 printk("dvb-ttpci: LNBP21 not found!\n");
Patrick Boettcherdea74862006-05-14 05:01:31 -03002270 if (av7110->fe->ops.release)
2271 av7110->fe->ops.release(av7110->fe);
Oliver Endrissdb5d91e2006-02-28 10:32:25 -03002272 av7110->fe = NULL;
2273 } else {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002274 av7110->fe->ops.dishnetwork_send_legacy_command = NULL;
Oliver Endrissdb5d91e2006-02-28 10:32:25 -03002275 av7110->recover = dvb_s_recover;
2276 }
Oliver Endrisseb3daf32006-01-09 15:25:05 -02002277 }
Johannes Stezenbach3dfaebd2005-05-16 21:54:19 -07002278 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002279 }
2280 }
2281
2282 if (!av7110->fe) {
2283 /* FIXME: propagate the failure code from the lower layers */
2284 ret = -ENOMEM;
Bjorn Helgaas29e66a62008-09-04 17:24:51 -03002285 printk("dvb-ttpci: A frontend driver was not found for device [%04x:%04x] subsystem [%04x:%04x]\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002286 av7110->dev->pci->vendor,
2287 av7110->dev->pci->device,
2288 av7110->dev->pci->subsystem_vendor,
2289 av7110->dev->pci->subsystem_device);
2290 } else {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002291 FE_FUNC_OVERRIDE(av7110->fe->ops.init, av7110->fe_init, av7110_fe_init);
2292 FE_FUNC_OVERRIDE(av7110->fe->ops.read_status, av7110->fe_read_status, av7110_fe_read_status);
2293 FE_FUNC_OVERRIDE(av7110->fe->ops.diseqc_reset_overload, av7110->fe_diseqc_reset_overload, av7110_fe_diseqc_reset_overload);
2294 FE_FUNC_OVERRIDE(av7110->fe->ops.diseqc_send_master_cmd, av7110->fe_diseqc_send_master_cmd, av7110_fe_diseqc_send_master_cmd);
2295 FE_FUNC_OVERRIDE(av7110->fe->ops.diseqc_send_burst, av7110->fe_diseqc_send_burst, av7110_fe_diseqc_send_burst);
2296 FE_FUNC_OVERRIDE(av7110->fe->ops.set_tone, av7110->fe_set_tone, av7110_fe_set_tone);
Yoann Padioleau8f40a9f2007-07-16 16:54:49 -03002297 FE_FUNC_OVERRIDE(av7110->fe->ops.set_voltage, av7110->fe_set_voltage, av7110_fe_set_voltage);
Patrick Boettcherdea74862006-05-14 05:01:31 -03002298 FE_FUNC_OVERRIDE(av7110->fe->ops.dishnetwork_send_legacy_command, av7110->fe_dishnetwork_send_legacy_command, av7110_fe_dishnetwork_send_legacy_command);
Mauro Carvalho Chehabb5c7cfd2011-12-23 18:19:24 -03002299 FE_FUNC_OVERRIDE(av7110->fe->ops.set_frontend, av7110->fe_set_frontend, av7110_fe_set_frontend);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002300
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07002301 ret = dvb_register_frontend(&av7110->dvb_adapter, av7110->fe);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002302 if (ret < 0) {
2303 printk("av7110: Frontend registration failed!\n");
Andrew de Quinceyf52a8382006-08-08 09:10:09 -03002304 dvb_frontend_detach(av7110->fe);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002305 av7110->fe = NULL;
2306 }
2307 }
2308 return ret;
2309}
2310
2311/* Budgetpatch note:
2312 * Original hardware design by Roberto Deza:
2313 * There is a DVB_Wiki at
Justin P. Mattock631dd1a2010-10-18 11:03:14 +02002314 * http://www.linuxtv.org/
Linus Torvalds1da177e2005-04-16 15:20:36 -07002315 *
2316 * New software triggering design by Emard that works on
2317 * original Roberto Deza's hardware:
2318 *
2319 * rps1 code for budgetpatch will copy internal HS event to GPIO3 pin.
2320 * GPIO3 is in budget-patch hardware connectd to port B VSYNC
2321 * HS is an internal event of 7146, accessible with RPS
2322 * and temporarily raised high every n lines
2323 * (n in defined in the RPS_THRESH1 counter threshold)
2324 * I think HS is raised high on the beginning of the n-th line
2325 * and remains high until this n-th line that triggered
2326 * it is completely received. When the receiption of n-th line
2327 * ends, HS is lowered.
2328 *
2329 * To transmit data over DMA, 7146 needs changing state at
2330 * port B VSYNC pin. Any changing of port B VSYNC will
2331 * cause some DMA data transfer, with more or less packets loss.
2332 * It depends on the phase and frequency of VSYNC and
2333 * the way of 7146 is instructed to trigger on port B (defined
2334 * in DD1_INIT register, 3rd nibble from the right valid
2335 * numbers are 0-7, see datasheet)
2336 *
2337 * The correct triggering can minimize packet loss,
2338 * dvbtraffic should give this stable bandwidths:
2339 * 22k transponder = 33814 kbit/s
2340 * 27.5k transponder = 38045 kbit/s
2341 * by experiment it is found that the best results
2342 * (stable bandwidths and almost no packet loss)
2343 * are obtained using DD1_INIT triggering number 2
2344 * (Va at rising edge of VS Fa = HS x VS-failing forced toggle)
2345 * and a VSYNC phase that occurs in the middle of DMA transfer
2346 * (about byte 188*512=96256 in the DMA window).
2347 *
2348 * Phase of HS is still not clear to me how to control,
2349 * It just happens to be so. It can be seen if one enables
2350 * RPS_IRQ and print Event Counter 1 in vpeirq(). Every
2351 * time RPS_INTERRUPT is called, the Event Counter 1 will
2352 * increment. That's how the 7146 is programmed to do event
2353 * counting in this budget-patch.c
2354 * I *think* HPS setting has something to do with the phase
Lucas De Marchi25985ed2011-03-30 22:57:33 -03002355 * of HS but I can't be 100% sure in that.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002356 *
2357 * hardware debug note: a working budget card (including budget patch)
2358 * with vpeirq() interrupt setup in mode "0x90" (every 64K) will
2359 * generate 3 interrupts per 25-Hz DMA frame of 2*188*512 bytes
2360 * and that means 3*25=75 Hz of interrupt freqency, as seen by
2361 * watch cat /proc/interrupts
2362 *
2363 * If this frequency is 3x lower (and data received in the DMA
2364 * buffer don't start with 0x47, but in the middle of packets,
2365 * whose lengths appear to be like 188 292 188 104 etc.
2366 * this means VSYNC line is not connected in the hardware.
2367 * (check soldering pcb and pins)
2368 * The same behaviour of missing VSYNC can be duplicated on budget
2369 * cards, by seting DD1_INIT trigger mode 7 in 3rd nibble.
2370 */
Johannes Stezenbach1be11e32006-02-27 00:09:20 -03002371static int __devinit av7110_attach(struct saa7146_dev* dev,
2372 struct saa7146_pci_extension_data *pci_ext)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002373{
2374 const int length = TS_WIDTH * TS_HEIGHT;
2375 struct pci_dev *pdev = dev->pci;
2376 struct av7110 *av7110;
Herbert Poetzl8eec1422007-02-08 14:32:43 -03002377 struct task_struct *thread;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002378 int ret, count = 0;
2379
2380 dprintk(4, "dev: %p\n", dev);
2381
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -08002382 /* Set RPS_IRQ to 1 to track rps1 activity.
2383 * Enabling this won't send any interrupt to PC CPU.
2384 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002385#define RPS_IRQ 0
2386
2387 if (budgetpatch == 1) {
2388 budgetpatch = 0;
2389 /* autodetect the presence of budget patch
2390 * this only works if saa7146 has been recently
2391 * reset with with MASK_31 to MC1
2392 *
2393 * will wait for VBI_B event (vertical blank at port B)
2394 * and will reset GPIO3 after VBI_B is detected.
2395 * (GPIO3 should be raised high by CPU to
2396 * test if GPIO3 will generate vertical blank signal
2397 * in budget patch GPIO3 is connected to VSYNC_B
2398 */
2399
2400 /* RESET SAA7146 */
2401 saa7146_write(dev, MC1, MASK_31);
2402 /* autodetection success seems to be time-dependend after reset */
2403
2404 /* Fix VSYNC level */
2405 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
2406 /* set vsync_b triggering */
2407 saa7146_write(dev, DD1_STREAM_B, 0);
2408 /* port B VSYNC at rising edge */
2409 saa7146_write(dev, DD1_INIT, 0x00000200);
2410 saa7146_write(dev, BRS_CTRL, 0x00000000); // VBI
2411 saa7146_write(dev, MC2,
2412 1 * (MASK_08 | MASK_24) | // BRS control
2413 0 * (MASK_09 | MASK_25) | // a
2414 1 * (MASK_10 | MASK_26) | // b
2415 0 * (MASK_06 | MASK_22) | // HPS_CTRL1
2416 0 * (MASK_05 | MASK_21) | // HPS_CTRL2
2417 0 * (MASK_01 | MASK_15) // DEBI
2418 );
2419
2420 /* start writing RPS1 code from beginning */
2421 count = 0;
2422 /* Disable RPS1 */
2423 saa7146_write(dev, MC1, MASK_29);
2424 /* RPS1 timeout disable */
2425 saa7146_write(dev, RPS_TOV1, 0);
Al Viro153755a2008-06-22 14:19:39 -03002426 WRITE_RPS1(CMD_PAUSE | EVT_VBI_B);
2427 WRITE_RPS1(CMD_WR_REG_MASK | (GPIO_CTRL>>2));
2428 WRITE_RPS1(GPIO3_MSK);
2429 WRITE_RPS1(SAA7146_GPIO_OUTLO<<24);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002430#if RPS_IRQ
2431 /* issue RPS1 interrupt to increment counter */
Al Viro153755a2008-06-22 14:19:39 -03002432 WRITE_RPS1(CMD_INTERRUPT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002433#endif
Al Viro153755a2008-06-22 14:19:39 -03002434 WRITE_RPS1(CMD_STOP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002435 /* Jump to begin of RPS program as safety measure (p37) */
Al Viro153755a2008-06-22 14:19:39 -03002436 WRITE_RPS1(CMD_JUMP);
2437 WRITE_RPS1(dev->d_rps1.dma_handle);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002438
2439#if RPS_IRQ
2440 /* set event counter 1 source as RPS1 interrupt (0x03) (rE4 p53)
2441 * use 0x03 to track RPS1 interrupts - increase by 1 every gpio3 is toggled
2442 * use 0x15 to track VPE interrupts - increase by 1 every vpeirq() is called
2443 */
2444 saa7146_write(dev, EC1SSR, (0x03<<2) | 3 );
André Goddard Rosaaf901ca2009-11-14 13:09:05 -02002445 /* set event counter 1 threshold to maximum allowed value (rEC p55) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002446 saa7146_write(dev, ECT1R, 0x3fff );
2447#endif
2448 /* Set RPS1 Address register to point to RPS code (r108 p42) */
2449 saa7146_write(dev, RPS_ADDR1, dev->d_rps1.dma_handle);
2450 /* Enable RPS1, (rFC p33) */
2451 saa7146_write(dev, MC1, (MASK_13 | MASK_29 ));
2452
2453 mdelay(10);
2454 /* now send VSYNC_B to rps1 by rising GPIO3 */
2455 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI);
2456 mdelay(10);
2457 /* if rps1 responded by lowering the GPIO3,
2458 * then we have budgetpatch hardware
2459 */
2460 if ((saa7146_read(dev, GPIO_CTRL) & 0x10000000) == 0) {
2461 budgetpatch = 1;
2462 printk("dvb-ttpci: BUDGET-PATCH DETECTED.\n");
2463 }
2464 /* Disable RPS1 */
2465 saa7146_write(dev, MC1, ( MASK_29 ));
2466#if RPS_IRQ
2467 printk("dvb-ttpci: Event Counter 1 0x%04x\n", saa7146_read(dev, EC1R) & 0x3fff );
2468#endif
2469 }
2470
2471 /* prepare the av7110 device struct */
Panagiotis Issaris74081872006-01-11 19:40:56 -02002472 av7110 = kzalloc(sizeof(struct av7110), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002473 if (!av7110) {
2474 dprintk(1, "out of memory\n");
2475 return -ENOMEM;
2476 }
2477
Linus Torvalds1da177e2005-04-16 15:20:36 -07002478 av7110->card_name = (char*) pci_ext->ext_priv;
2479 av7110->dev = dev;
2480 dev->ext_priv = av7110;
2481
2482 ret = get_firmware(av7110);
2483 if (ret < 0)
2484 goto err_kfree_0;
2485
2486 ret = dvb_register_adapter(&av7110->dvb_adapter, av7110->card_name,
Janne Grunau78e92002008-04-09 19:13:13 -03002487 THIS_MODULE, &dev->pci->dev, adapter_nr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002488 if (ret < 0)
2489 goto err_put_firmware_1;
2490
2491 /* the Siemens DVB needs this if you want to have the i2c chips
2492 get recognized before the main driver is fully loaded */
2493 saa7146_write(dev, GPIO_CTRL, 0x500000);
2494
Linus Torvalds1da177e2005-04-16 15:20:36 -07002495 strlcpy(av7110->i2c_adap.name, pci_ext->ext_priv, sizeof(av7110->i2c_adap.name));
2496
2497 saa7146_i2c_adapter_prepare(dev, &av7110->i2c_adap, SAA7146_I2C_BUS_BIT_RATE_120); /* 275 kHz */
2498
2499 ret = i2c_add_adapter(&av7110->i2c_adap);
2500 if (ret < 0)
2501 goto err_dvb_unregister_adapter_2;
2502
2503 ttpci_eeprom_parse_mac(&av7110->i2c_adap,
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07002504 av7110->dvb_adapter.proposed_mac);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002505 ret = -ENOMEM;
2506
Oliver Endriss9e615ea2008-09-03 19:15:27 -03002507 /* full-ts mod? */
2508 if (full_ts)
2509 av7110->full_ts = true;
2510
2511 /* check for full-ts flag in eeprom */
2512 if (i2c_readreg(av7110, 0xaa, 0) == 0x4f && i2c_readreg(av7110, 0xaa, 1) == 0x45) {
2513 u8 flags = i2c_readreg(av7110, 0xaa, 2);
2514 if (flags != 0xff && (flags & 0x01))
2515 av7110->full_ts = true;
2516 }
2517
2518 if (av7110->full_ts) {
2519 printk(KERN_INFO "dvb-ttpci: full-ts mode enabled for saa7146 port B\n");
2520 spin_lock_init(&av7110->feedlock1);
2521 av7110->grabbing = saa7146_vmalloc_build_pgtable(pdev, length,
2522 &av7110->pt);
2523 if (!av7110->grabbing)
2524 goto err_i2c_del_3;
2525
2526 saa7146_write(dev, DD1_STREAM_B, 0x00000000);
2527 saa7146_write(dev, MC2, (MASK_10 | MASK_26));
2528
2529 saa7146_write(dev, DD1_INIT, 0x00000600);
2530 saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
2531
2532 saa7146_write(dev, BRS_CTRL, 0x60000000);
2533 saa7146_write(dev, MC2, MASK_08 | MASK_24);
2534
2535 /* dma3 */
2536 saa7146_write(dev, PCI_BT_V1, 0x001c0000 | (saa7146_read(dev, PCI_BT_V1) & ~0x001f0000));
2537 saa7146_write(dev, BASE_ODD3, 0);
2538 saa7146_write(dev, BASE_EVEN3, 0);
2539 saa7146_write(dev, PROT_ADDR3, TS_WIDTH * TS_HEIGHT);
2540 saa7146_write(dev, PITCH3, TS_WIDTH);
2541 saa7146_write(dev, BASE_PAGE3, av7110->pt.dma | ME1 | 0x90);
2542 saa7146_write(dev, NUM_LINE_BYTE3, (TS_HEIGHT << 16) | TS_WIDTH);
2543 saa7146_write(dev, MC2, MASK_04 | MASK_20);
2544
2545 tasklet_init(&av7110->vpe_tasklet, vpeirq, (unsigned long) av7110);
2546
2547 } else if (budgetpatch) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002548 spin_lock_init(&av7110->feedlock1);
2549 av7110->grabbing = saa7146_vmalloc_build_pgtable(pdev, length,
2550 &av7110->pt);
2551 if (!av7110->grabbing)
2552 goto err_i2c_del_3;
2553
2554 saa7146_write(dev, PCI_BT_V1, 0x1c1f101f);
2555 saa7146_write(dev, BCS_CTRL, 0x80400040);
2556 /* set dd1 stream a & b */
2557 saa7146_write(dev, DD1_STREAM_B, 0x00000000);
2558 saa7146_write(dev, DD1_INIT, 0x03000200);
2559 saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
2560 saa7146_write(dev, BRS_CTRL, 0x60000000);
2561 saa7146_write(dev, BASE_ODD3, 0);
2562 saa7146_write(dev, BASE_EVEN3, 0);
2563 saa7146_write(dev, PROT_ADDR3, TS_WIDTH * TS_HEIGHT);
2564 saa7146_write(dev, BASE_PAGE3, av7110->pt.dma | ME1 | 0x90);
2565
2566 saa7146_write(dev, PITCH3, TS_WIDTH);
2567 saa7146_write(dev, NUM_LINE_BYTE3, (TS_HEIGHT << 16) | TS_WIDTH);
2568
2569 /* upload all */
2570 saa7146_write(dev, MC2, 0x077c077c);
2571 saa7146_write(dev, GPIO_CTRL, 0x000000);
2572#if RPS_IRQ
2573 /* set event counter 1 source as RPS1 interrupt (0x03) (rE4 p53)
2574 * use 0x03 to track RPS1 interrupts - increase by 1 every gpio3 is toggled
2575 * use 0x15 to track VPE interrupts - increase by 1 every vpeirq() is called
2576 */
2577 saa7146_write(dev, EC1SSR, (0x03<<2) | 3 );
André Goddard Rosaaf901ca2009-11-14 13:09:05 -02002578 /* set event counter 1 threshold to maximum allowed value (rEC p55) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002579 saa7146_write(dev, ECT1R, 0x3fff );
2580#endif
2581 /* Setup BUDGETPATCH MAIN RPS1 "program" (p35) */
2582 count = 0;
2583
2584 /* Wait Source Line Counter Threshold (p36) */
Al Viro153755a2008-06-22 14:19:39 -03002585 WRITE_RPS1(CMD_PAUSE | EVT_HS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002586 /* Set GPIO3=1 (p42) */
Al Viro153755a2008-06-22 14:19:39 -03002587 WRITE_RPS1(CMD_WR_REG_MASK | (GPIO_CTRL>>2));
2588 WRITE_RPS1(GPIO3_MSK);
2589 WRITE_RPS1(SAA7146_GPIO_OUTHI<<24);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002590#if RPS_IRQ
2591 /* issue RPS1 interrupt */
Al Viro153755a2008-06-22 14:19:39 -03002592 WRITE_RPS1(CMD_INTERRUPT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002593#endif
2594 /* Wait reset Source Line Counter Threshold (p36) */
Al Viro153755a2008-06-22 14:19:39 -03002595 WRITE_RPS1(CMD_PAUSE | RPS_INV | EVT_HS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002596 /* Set GPIO3=0 (p42) */
Al Viro153755a2008-06-22 14:19:39 -03002597 WRITE_RPS1(CMD_WR_REG_MASK | (GPIO_CTRL>>2));
2598 WRITE_RPS1(GPIO3_MSK);
2599 WRITE_RPS1(SAA7146_GPIO_OUTLO<<24);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002600#if RPS_IRQ
2601 /* issue RPS1 interrupt */
Al Viro153755a2008-06-22 14:19:39 -03002602 WRITE_RPS1(CMD_INTERRUPT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002603#endif
2604 /* Jump to begin of RPS program (p37) */
Al Viro153755a2008-06-22 14:19:39 -03002605 WRITE_RPS1(CMD_JUMP);
2606 WRITE_RPS1(dev->d_rps1.dma_handle);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002607
2608 /* Fix VSYNC level */
2609 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
2610 /* Set RPS1 Address register to point to RPS code (r108 p42) */
2611 saa7146_write(dev, RPS_ADDR1, dev->d_rps1.dma_handle);
2612 /* Set Source Line Counter Threshold, using BRS (rCC p43)
2613 * It generates HS event every TS_HEIGHT lines
2614 * this is related to TS_WIDTH set in register
2615 * NUM_LINE_BYTE3. If NUM_LINE_BYTE low 16 bits
2616 * are set to TS_WIDTH bytes (TS_WIDTH=2*188),
2617 * then RPS_THRESH1 should be set to trigger
2618 * every TS_HEIGHT (512) lines.
2619 */
2620 saa7146_write(dev, RPS_THRESH1, (TS_HEIGHT*1) | MASK_12 );
2621
2622 /* Enable RPS1 (rFC p33) */
2623 saa7146_write(dev, MC1, (MASK_13 | MASK_29));
2624
2625 /* end of budgetpatch register initialization */
2626 tasklet_init (&av7110->vpe_tasklet, vpeirq, (unsigned long) av7110);
2627 } else {
2628 saa7146_write(dev, PCI_BT_V1, 0x1c00101f);
2629 saa7146_write(dev, BCS_CTRL, 0x80400040);
2630
2631 /* set dd1 stream a & b */
2632 saa7146_write(dev, DD1_STREAM_B, 0x00000000);
2633 saa7146_write(dev, DD1_INIT, 0x03000000);
2634 saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
2635
2636 /* upload all */
2637 saa7146_write(dev, MC2, 0x077c077c);
2638 saa7146_write(dev, GPIO_CTRL, 0x000000);
2639 }
2640
2641 tasklet_init (&av7110->debi_tasklet, debiirq, (unsigned long) av7110);
2642 tasklet_init (&av7110->gpio_tasklet, gpioirq, (unsigned long) av7110);
2643
Ingo Molnar3593cab2006-02-07 06:49:14 -02002644 mutex_init(&av7110->pid_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002645
2646 /* locks for data transfers from/to AV7110 */
2647 spin_lock_init(&av7110->debilock);
Ingo Molnar3593cab2006-02-07 06:49:14 -02002648 mutex_init(&av7110->dcomlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002649 av7110->debitype = -1;
2650
2651 /* default OSD window */
2652 av7110->osdwin = 1;
Ingo Molnar3593cab2006-02-07 06:49:14 -02002653 mutex_init(&av7110->osd_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002654
C.Y.M2f03ee82006-03-30 04:31:48 -03002655 /* TV standard */
Marco Schluessler58a44042007-10-31 01:20:42 -03002656 av7110->vidmode = tv_standard == 1 ? AV7110_VIDEO_MODE_NTSC
2657 : AV7110_VIDEO_MODE_PAL;
C.Y.M2f03ee82006-03-30 04:31:48 -03002658
Linus Torvalds1da177e2005-04-16 15:20:36 -07002659 /* ARM "watchdog" */
2660 init_waitqueue_head(&av7110->arm_wait);
2661 av7110->arm_thread = NULL;
2662
2663 /* allocate and init buffers */
2664 av7110->debi_virt = pci_alloc_consistent(pdev, 8192, &av7110->debi_bus);
2665 if (!av7110->debi_virt)
2666 goto err_saa71466_vfree_4;
2667
2668
2669 av7110->iobuf = vmalloc(AVOUTLEN+AOUTLEN+BMPLEN+4*IPACKS);
2670 if (!av7110->iobuf)
2671 goto err_pci_free_5;
2672
2673 ret = av7110_av_init(av7110);
2674 if (ret < 0)
2675 goto err_iobuf_vfree_6;
2676
2677 /* init BMP buffer */
2678 av7110->bmpbuf = av7110->iobuf+AVOUTLEN+AOUTLEN;
2679 init_waitqueue_head(&av7110->bmpq);
2680
2681 ret = av7110_ca_init(av7110);
2682 if (ret < 0)
2683 goto err_av7110_av_exit_7;
2684
2685 /* load firmware into AV7110 cards */
2686 ret = av7110_bootarm(av7110);
2687 if (ret < 0)
2688 goto err_av7110_ca_exit_8;
2689
2690 ret = av7110_firmversion(av7110);
2691 if (ret < 0)
2692 goto err_stop_arm_9;
2693
2694 if (FW_VERSION(av7110->arm_app)<0x2501)
2695 printk ("dvb-ttpci: Warning, firmware version 0x%04x is too old. "
2696 "System might be unstable!\n", FW_VERSION(av7110->arm_app));
2697
Herbert Poetzl8eec1422007-02-08 14:32:43 -03002698 thread = kthread_run(arm_thread, (void *) av7110, "arm_mon");
2699 if (IS_ERR(thread)) {
2700 ret = PTR_ERR(thread);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002701 goto err_stop_arm_9;
Herbert Poetzl8eec1422007-02-08 14:32:43 -03002702 }
2703 av7110->arm_thread = thread;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002704
2705 /* set initial volume in mixer struct */
2706 av7110->mixer.volume_left = volume;
2707 av7110->mixer.volume_right = volume;
2708
Linus Torvalds1da177e2005-04-16 15:20:36 -07002709 ret = av7110_register(av7110);
2710 if (ret < 0)
2711 goto err_arm_thread_stop_10;
2712
Oliver Endrissdefd574e2007-07-12 23:08:07 -03002713 init_av7110_av(av7110);
2714
Linus Torvalds1da177e2005-04-16 15:20:36 -07002715 /* special case DVB-C: these cards have an analog tuner
2716 plus need some special handling, so we have separate
2717 saa7146_ext_vv data for these... */
2718 ret = av7110_init_v4l(av7110);
2719 if (ret < 0)
2720 goto err_av7110_unregister_11;
2721
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07002722 av7110->dvb_adapter.priv = av7110;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002723 ret = frontend_init(av7110);
2724 if (ret < 0)
2725 goto err_av7110_exit_v4l_12;
2726
2727#if defined(CONFIG_INPUT_EVDEV) || defined(CONFIG_INPUT_EVDEV_MODULE)
Oliver Endriss03388ae2005-09-09 13:03:12 -07002728 av7110_ir_init(av7110);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002729#endif
2730 printk(KERN_INFO "dvb-ttpci: found av7110-%d.\n", av7110_num);
2731 av7110_num++;
2732out:
2733 return ret;
2734
2735err_av7110_exit_v4l_12:
2736 av7110_exit_v4l(av7110);
2737err_av7110_unregister_11:
2738 dvb_unregister(av7110);
2739err_arm_thread_stop_10:
2740 av7110_arm_sync(av7110);
2741err_stop_arm_9:
2742 /* Nothing to do. Rejoice. */
2743err_av7110_ca_exit_8:
2744 av7110_ca_exit(av7110);
2745err_av7110_av_exit_7:
2746 av7110_av_exit(av7110);
2747err_iobuf_vfree_6:
2748 vfree(av7110->iobuf);
2749err_pci_free_5:
2750 pci_free_consistent(pdev, 8192, av7110->debi_virt, av7110->debi_bus);
2751err_saa71466_vfree_4:
Jon Burgess87c30192007-05-03 12:23:44 -03002752 if (av7110->grabbing)
2753 saa7146_vfree_destroy_pgtable(pdev, av7110->grabbing, &av7110->pt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002754err_i2c_del_3:
2755 i2c_del_adapter(&av7110->i2c_adap);
2756err_dvb_unregister_adapter_2:
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07002757 dvb_unregister_adapter(&av7110->dvb_adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002758err_put_firmware_1:
2759 put_firmware(av7110);
2760err_kfree_0:
2761 kfree(av7110);
2762 goto out;
2763}
2764
Johannes Stezenbach1be11e32006-02-27 00:09:20 -03002765static int __devexit av7110_detach(struct saa7146_dev* saa)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002766{
2767 struct av7110 *av7110 = saa->ext_priv;
2768 dprintk(4, "%p\n", av7110);
2769
Oliver Endriss03388ae2005-09-09 13:03:12 -07002770#if defined(CONFIG_INPUT_EVDEV) || defined(CONFIG_INPUT_EVDEV_MODULE)
2771 av7110_ir_exit(av7110);
2772#endif
Oliver Endriss9e615ea2008-09-03 19:15:27 -03002773 if (budgetpatch || av7110->full_ts) {
2774 if (budgetpatch) {
2775 /* Disable RPS1 */
2776 saa7146_write(saa, MC1, MASK_29);
2777 /* VSYNC LOW (inactive) */
2778 saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);
2779 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002780 saa7146_write(saa, MC1, MASK_20); /* DMA3 off */
2781 SAA7146_IER_DISABLE(saa, MASK_10);
2782 SAA7146_ISR_CLEAR(saa, MASK_10);
2783 msleep(50);
2784 tasklet_kill(&av7110->vpe_tasklet);
Jon Burgess87c30192007-05-03 12:23:44 -03002785 saa7146_vfree_destroy_pgtable(saa->pci, av7110->grabbing, &av7110->pt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002786 }
2787 av7110_exit_v4l(av7110);
2788
2789 av7110_arm_sync(av7110);
2790
2791 tasklet_kill(&av7110->debi_tasklet);
2792 tasklet_kill(&av7110->gpio_tasklet);
2793
2794 dvb_unregister(av7110);
2795
2796 SAA7146_IER_DISABLE(saa, MASK_19 | MASK_03);
2797 SAA7146_ISR_CLEAR(saa, MASK_19 | MASK_03);
2798
2799 av7110_ca_exit(av7110);
2800 av7110_av_exit(av7110);
2801
2802 vfree(av7110->iobuf);
2803 pci_free_consistent(saa->pci, 8192, av7110->debi_virt,
2804 av7110->debi_bus);
2805
2806 i2c_del_adapter(&av7110->i2c_adap);
2807
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07002808 dvb_unregister_adapter (&av7110->dvb_adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002809
2810 av7110_num--;
2811
2812 put_firmware(av7110);
2813
2814 kfree(av7110);
2815
2816 saa->ext_priv = NULL;
2817
2818 return 0;
2819}
2820
2821
2822static void av7110_irq(struct saa7146_dev* dev, u32 *isr)
2823{
2824 struct av7110 *av7110 = dev->ext_priv;
2825
2826 //print_time("av7110_irq");
2827
2828 /* Note: Don't try to handle the DEBI error irq (MASK_18), in
2829 * intel mode the timeout is asserted all the time...
2830 */
2831
2832 if (*isr & MASK_19) {
2833 //printk("av7110_irq: DEBI\n");
2834 /* Note 1: The DEBI irq is level triggered: We must enable it
2835 * only after we started a DMA xfer, and disable it here
2836 * immediately, or it will be signalled all the time while
2837 * DEBI is idle.
2838 * Note 2: You would think that an irq which is masked is
2839 * not signalled by the hardware. Not so for the SAA7146:
2840 * An irq is signalled as long as the corresponding bit
2841 * in the ISR is set, and disabling irqs just prevents the
2842 * hardware from setting the ISR bit. This means a) that we
2843 * must clear the ISR *after* disabling the irq (which is why
2844 * we must do it here even though saa7146_core did it already),
2845 * and b) that if we were to disable an edge triggered irq
2846 * (like the gpio irqs sadly are) temporarily we would likely
2847 * loose some. This sucks :-(
2848 */
2849 SAA7146_IER_DISABLE(av7110->dev, MASK_19);
2850 SAA7146_ISR_CLEAR(av7110->dev, MASK_19);
2851 tasklet_schedule(&av7110->debi_tasklet);
2852 }
2853
2854 if (*isr & MASK_03) {
2855 //printk("av7110_irq: GPIO\n");
2856 tasklet_schedule(&av7110->gpio_tasklet);
2857 }
2858
Oliver Endriss9e615ea2008-09-03 19:15:27 -03002859 if (*isr & MASK_10)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002860 tasklet_schedule(&av7110->vpe_tasklet);
2861}
2862
2863
Randy Dunlapda517162008-01-10 19:31:47 -03002864static struct saa7146_extension av7110_extension_driver;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002865
2866#define MAKE_AV7110_INFO(x_var,x_name) \
2867static struct saa7146_pci_extension_data x_var = { \
2868 .ext_priv = x_name, \
Randy Dunlapda517162008-01-10 19:31:47 -03002869 .ext = &av7110_extension_driver }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002870
Karl Herz6af4ee12005-09-09 13:03:13 -07002871MAKE_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 -07002872MAKE_AV7110_INFO(ttt_1_X, "Technotrend/Hauppauge WinTV DVB-T rev1.X");
2873MAKE_AV7110_INFO(ttc_1_X, "Technotrend/Hauppauge WinTV Nexus-CA rev1.X");
2874MAKE_AV7110_INFO(ttc_2_X, "Technotrend/Hauppauge WinTV DVB-C rev2.X");
2875MAKE_AV7110_INFO(tts_2_X, "Technotrend/Hauppauge WinTV Nexus-S rev2.X");
Johannes Stezenbach3dfaebd2005-05-16 21:54:19 -07002876MAKE_AV7110_INFO(tts_2_3, "Technotrend/Hauppauge WinTV Nexus-S rev2.3");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002877MAKE_AV7110_INFO(tts_1_3se, "Technotrend/Hauppauge WinTV DVB-S rev1.3 SE");
2878MAKE_AV7110_INFO(ttt, "Technotrend/Hauppauge DVB-T");
2879MAKE_AV7110_INFO(fsc, "Fujitsu Siemens DVB-C");
2880MAKE_AV7110_INFO(fss, "Fujitsu Siemens DVB-S rev1.6");
Oliver Endriss8bd63012006-02-07 06:49:11 -02002881MAKE_AV7110_INFO(gxs_1_3, "Galaxis DVB-S rev1.3");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002882
2883static struct pci_device_id pci_tbl[] = {
Karl Herz6af4ee12005-09-09 13:03:13 -07002884 MAKE_EXTENSION_PCI(fsc, 0x110a, 0x0000),
2885 MAKE_EXTENSION_PCI(tts_1_X_fsc, 0x13c2, 0x0000),
2886 MAKE_EXTENSION_PCI(ttt_1_X, 0x13c2, 0x0001),
2887 MAKE_EXTENSION_PCI(ttc_2_X, 0x13c2, 0x0002),
2888 MAKE_EXTENSION_PCI(tts_2_X, 0x13c2, 0x0003),
Oliver Endriss8bd63012006-02-07 06:49:11 -02002889 MAKE_EXTENSION_PCI(gxs_1_3, 0x13c2, 0x0004),
Karl Herz6af4ee12005-09-09 13:03:13 -07002890 MAKE_EXTENSION_PCI(fss, 0x13c2, 0x0006),
2891 MAKE_EXTENSION_PCI(ttt, 0x13c2, 0x0008),
2892 MAKE_EXTENSION_PCI(ttc_1_X, 0x13c2, 0x000a),
2893 MAKE_EXTENSION_PCI(tts_2_3, 0x13c2, 0x000e),
2894 MAKE_EXTENSION_PCI(tts_1_3se, 0x13c2, 0x1002),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002895
Linus Torvalds1da177e2005-04-16 15:20:36 -07002896/* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0005), UNDEFINED CARD */ // Technisat SkyStar1
2897/* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0009), UNDEFINED CARD */ // TT/Hauppauge WinTV Nexus-CA v????
2898
2899 {
2900 .vendor = 0,
2901 }
2902};
2903
2904MODULE_DEVICE_TABLE(pci, pci_tbl);
2905
2906
Randy Dunlapda517162008-01-10 19:31:47 -03002907static struct saa7146_extension av7110_extension_driver = {
Derek Kelly62929252010-10-16 16:33:53 -03002908 .name = "av7110",
Oliver Endriss00c4cc62006-11-01 13:09:51 -03002909 .flags = SAA7146_USE_I2C_IRQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002910
2911 .module = THIS_MODULE,
2912 .pci_tbl = &pci_tbl[0],
2913 .attach = av7110_attach,
Johannes Stezenbach1be11e32006-02-27 00:09:20 -03002914 .detach = __devexit_p(av7110_detach),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002915
2916 .irq_mask = MASK_19 | MASK_03 | MASK_10,
2917 .irq_func = av7110_irq,
2918};
2919
2920
2921static int __init av7110_init(void)
2922{
2923 int retval;
Randy Dunlapda517162008-01-10 19:31:47 -03002924 retval = saa7146_register_extension(&av7110_extension_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002925 return retval;
2926}
2927
2928
2929static void __exit av7110_exit(void)
2930{
Randy Dunlapda517162008-01-10 19:31:47 -03002931 saa7146_unregister_extension(&av7110_extension_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002932}
2933
2934module_init(av7110_init);
2935module_exit(av7110_exit);
2936
2937MODULE_DESCRIPTION("driver for the SAA7146 based AV110 PCI DVB cards by "
2938 "Siemens, Technotrend, Hauppauge");
2939MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, others");
2940MODULE_LICENSE("GPL");