blob: f38329d29daa8c41a83823deb0d2f87de7a079ff [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
Linus Torvalds1da177e2005-04-16 15:20:36 -070056
57#include <linux/dvb/frontend.h>
58
59#include "dvb_frontend.h"
60
61#include "ttpci-eeprom.h"
62#include "av7110.h"
63#include "av7110_hw.h"
64#include "av7110_av.h"
65#include "av7110_ca.h"
66#include "av7110_ipack.h"
67
Oliver Endrissdb5d91e2006-02-28 10:32:25 -030068#include "bsbe1.h"
69#include "lnbp21.h"
Perceval Anichini265366e2006-03-16 11:22:47 -030070#include "bsru6.h"
Oliver Endrissdb5d91e2006-02-28 10:32:25 -030071
Linus Torvalds1da177e2005-04-16 15:20:36 -070072#define TS_WIDTH 376
73#define TS_HEIGHT 512
74#define TS_BUFLEN (TS_WIDTH*TS_HEIGHT)
75#define TS_MAX_PACKETS (TS_BUFLEN/TS_SIZE)
76
77
78int av7110_debug;
79
80static int vidmode = CVBS_RGB_OUT;
81static int pids_off;
82static int adac = DVB_ADAC_TI;
83static int hw_sections;
84static int rgb_on;
85static int volume = 255;
Mauro Carvalho Chehaba5ed4252006-01-13 14:10:19 -020086static int budgetpatch;
Oliver Endriss4caba422006-03-17 05:29:15 -030087static int wss_cfg_4_3 = 0x4008;
88static int wss_cfg_16_9 = 0x0007;
C.Y.M2f03ee82006-03-30 04:31:48 -030089static int tv_standard;
Oliver Endriss9e615ea2008-09-03 19:15:27 -030090static int full_ts;
Linus Torvalds1da177e2005-04-16 15:20:36 -070091
92module_param_named(debug, av7110_debug, int, 0644);
93MODULE_PARM_DESC(debug, "debug level (bitmask, default 0)");
94module_param(vidmode, int, 0444);
95MODULE_PARM_DESC(vidmode,"analog video out: 0 off, 1 CVBS+RGB (default), 2 CVBS+YC, 3 YC");
96module_param(pids_off, int, 0444);
97MODULE_PARM_DESC(pids_off,"clear video/audio/PCR PID filters when demux is closed");
98module_param(adac, int, 0444);
99MODULE_PARM_DESC(adac,"audio DAC type: 0 TI, 1 CRYSTAL, 2 MSP (use if autodetection fails)");
100module_param(hw_sections, int, 0444);
101MODULE_PARM_DESC(hw_sections, "0 use software section filter, 1 use hardware");
102module_param(rgb_on, int, 0444);
103MODULE_PARM_DESC(rgb_on, "For Siemens DVB-C cards only: Enable RGB control"
104 " signal on SCART pin 16 to switch SCART video mode from CVBS to RGB");
105module_param(volume, int, 0444);
106MODULE_PARM_DESC(volume, "initial volume: default 255 (range 0-255)");
107module_param(budgetpatch, int, 0444);
108MODULE_PARM_DESC(budgetpatch, "use budget-patch hardware modification: default 0 (0 no, 1 autodetect, 2 always)");
Oliver Endriss9e615ea2008-09-03 19:15:27 -0300109module_param(full_ts, int, 0444);
110MODULE_PARM_DESC(full_ts, "enable code for full-ts hardware modification: 0 disable (default), 1 enable");
Oliver Endriss4caba422006-03-17 05:29:15 -0300111module_param(wss_cfg_4_3, int, 0444);
112MODULE_PARM_DESC(wss_cfg_4_3, "WSS 4:3 - default 0x4008 - bit 15: disable, 14: burst mode, 13..0: wss data");
113module_param(wss_cfg_16_9, int, 0444);
114MODULE_PARM_DESC(wss_cfg_16_9, "WSS 16:9 - default 0x0007 - bit 15: disable, 14: burst mode, 13..0: wss data");
C.Y.M2f03ee82006-03-30 04:31:48 -0300115module_param(tv_standard, int, 0444);
116MODULE_PARM_DESC(tv_standard, "TV standard: 0 PAL (default), 1 NTSC");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700117
Janne Grunau78e92002008-04-09 19:13:13 -0300118DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
119
Linus Torvalds1da177e2005-04-16 15:20:36 -0700120static void restart_feeds(struct av7110 *av7110);
Oliver Endriss9e615ea2008-09-03 19:15:27 -0300121static int budget_start_feed(struct dvb_demux_feed *feed);
122static int budget_stop_feed(struct dvb_demux_feed *feed);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700123
Mauro Carvalho Chehaba5ed4252006-01-13 14:10:19 -0200124static int av7110_num;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125
126#define FE_FUNC_OVERRIDE(fe_func, av7110_copy, av7110_func) \
127{\
128 if (fe_func != NULL) { \
129 av7110_copy = fe_func; \
130 fe_func = av7110_func; \
131 } \
132}
133
134
135static void init_av7110_av(struct av7110 *av7110)
136{
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700137 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700138 struct saa7146_dev *dev = av7110->dev;
139
140 /* set internal volume control to maximum */
141 av7110->adac_type = DVB_ADAC_TI;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700142 ret = av7110_set_volume(av7110, av7110->mixer.volume_left, av7110->mixer.volume_right);
Johannes Stezenbach7a2fa902005-07-07 17:58:01 -0700143 if (ret < 0)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700144 printk("dvb-ttpci:cannot set internal volume to maximum:%d\n",ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700145
Oliver Endrissdefd574e2007-07-12 23:08:07 -0300146 ret = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetMonitorType,
147 1, (u16) av7110->display_ar);
148 if (ret < 0)
149 printk("dvb-ttpci: unable to set aspect ratio\n");
150 ret = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetPanScanType,
151 1, av7110->display_panscan);
152 if (ret < 0)
153 printk("dvb-ttpci: unable to set pan scan\n");
154
Oliver Endriss4caba422006-03-17 05:29:15 -0300155 ret = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetWSSConfig, 2, 2, wss_cfg_4_3);
156 if (ret < 0)
157 printk("dvb-ttpci: unable to configure 4:3 wss\n");
158 ret = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetWSSConfig, 2, 3, wss_cfg_16_9);
159 if (ret < 0)
160 printk("dvb-ttpci: unable to configure 16:9 wss\n");
161
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700162 ret = av7710_set_video_mode(av7110, vidmode);
Johannes Stezenbach7a2fa902005-07-07 17:58:01 -0700163 if (ret < 0)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700164 printk("dvb-ttpci:cannot set video mode:%d\n",ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700165
166 /* handle different card types */
167 /* remaining inits according to card and frontend type */
168 av7110->analog_tuner_flags = 0;
169 av7110->current_input = 0;
Tim Kaiser61391e02006-06-25 09:14:07 -0300170 if (dev->pci->subsystem_vendor == 0x13c2 && dev->pci->subsystem_device == 0x000a)
Marco Schluessler1c13b952006-01-09 15:25:06 -0200171 av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, ADSwitch, 1, 0); // SPDIF on
Tim Kaiser61391e02006-06-25 09:14:07 -0300172 if (i2c_writereg(av7110, 0x20, 0x00, 0x00) == 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700173 printk ("dvb-ttpci: Crystal audio DAC @ card %d detected\n",
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -0700174 av7110->dvb_adapter.num);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700175 av7110->adac_type = DVB_ADAC_CRYSTAL;
176 i2c_writereg(av7110, 0x20, 0x01, 0xd2);
177 i2c_writereg(av7110, 0x20, 0x02, 0x49);
178 i2c_writereg(av7110, 0x20, 0x03, 0x00);
179 i2c_writereg(av7110, 0x20, 0x04, 0x00);
180
181 /**
182 * some special handling for the Siemens DVB-C cards...
183 */
184 } else if (0 == av7110_init_analog_module(av7110)) {
185 /* done. */
186 }
187 else if (dev->pci->subsystem_vendor == 0x110a) {
188 printk("dvb-ttpci: DVB-C w/o analog module @ card %d detected\n",
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -0700189 av7110->dvb_adapter.num);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700190 av7110->adac_type = DVB_ADAC_NONE;
191 }
192 else {
193 av7110->adac_type = adac;
194 printk("dvb-ttpci: adac type set to %d @ card %d\n",
Marco Schluessler1c13b952006-01-09 15:25:06 -0200195 av7110->adac_type, av7110->dvb_adapter.num);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700196 }
197
Marco Schluessler1c13b952006-01-09 15:25:06 -0200198 if (av7110->adac_type == DVB_ADAC_NONE || av7110->adac_type == DVB_ADAC_MSP34x0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700199 // switch DVB SCART on
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700200 ret = av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, MainSwitch, 1, 0);
Johannes Stezenbach7a2fa902005-07-07 17:58:01 -0700201 if (ret < 0)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700202 printk("dvb-ttpci:cannot switch on SCART(Main):%d\n",ret);
203 ret = av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, ADSwitch, 1, 1);
Johannes Stezenbach7a2fa902005-07-07 17:58:01 -0700204 if (ret < 0)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700205 printk("dvb-ttpci:cannot switch on SCART(AD):%d\n",ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700206 if (rgb_on &&
Karl Herz6af4ee12005-09-09 13:03:13 -0700207 ((av7110->dev->pci->subsystem_vendor == 0x110a) ||
208 (av7110->dev->pci->subsystem_vendor == 0x13c2)) &&
209 (av7110->dev->pci->subsystem_device == 0x0000)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210 saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); // RGB on, SCART pin 16
211 //saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); // SCARTpin 8
212 }
213 }
214
Oliver Endriss60edb132005-12-19 08:54:11 -0200215 if (dev->pci->subsystem_vendor == 0x13c2 && dev->pci->subsystem_device == 0x000e)
216 av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, SpdifSwitch, 1, 0); // SPDIF on
217
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700218 ret = av7110_set_volume(av7110, av7110->mixer.volume_left, av7110->mixer.volume_right);
Johannes Stezenbach7a2fa902005-07-07 17:58:01 -0700219 if (ret < 0)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700220 printk("dvb-ttpci:cannot set volume :%d\n",ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700221}
222
223static void recover_arm(struct av7110 *av7110)
224{
225 dprintk(4, "%p\n",av7110);
226
227 av7110_bootarm(av7110);
228 msleep(100);
Oliver Endriss66190a22006-01-09 15:32:42 -0200229
230 init_av7110_av(av7110);
231
232 /* card-specific recovery */
233 if (av7110->recover)
234 av7110->recover(av7110);
235
Linus Torvalds1da177e2005-04-16 15:20:36 -0700236 restart_feeds(av7110);
Oliver Endrissee820a62007-04-27 12:31:21 -0300237
Peter Senna Tschudinb168e812013-01-19 19:41:10 -0300238#if IS_ENABLED(CONFIG_INPUT_EVDEV)
Oliver Endrissee820a62007-04-27 12:31:21 -0300239 av7110_check_ir_config(av7110, true);
240#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700241}
242
Linus Torvalds1da177e2005-04-16 15:20:36 -0700243static void av7110_arm_sync(struct av7110 *av7110)
244{
Herbert Poetzl8eec1422007-02-08 14:32:43 -0300245 if (av7110->arm_thread)
246 kthread_stop(av7110->arm_thread);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700247
Herbert Poetzl8eec1422007-02-08 14:32:43 -0300248 av7110->arm_thread = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700249}
250
251static int arm_thread(void *data)
252{
253 struct av7110 *av7110 = data;
254 u16 newloops = 0;
255 int timeout;
256
257 dprintk(4, "%p\n",av7110);
258
Linus Torvalds1da177e2005-04-16 15:20:36 -0700259 for (;;) {
260 timeout = wait_event_interruptible_timeout(av7110->arm_wait,
Herbert Poetzl8eec1422007-02-08 14:32:43 -0300261 kthread_should_stop(), 5 * HZ);
262
263 if (-ERESTARTSYS == timeout || kthread_should_stop()) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700264 /* got signal or told to quit*/
265 break;
266 }
267
268 if (!av7110->arm_ready)
269 continue;
270
Peter Senna Tschudinb168e812013-01-19 19:41:10 -0300271#if IS_ENABLED(CONFIG_INPUT_EVDEV)
Oliver Endrissee820a62007-04-27 12:31:21 -0300272 av7110_check_ir_config(av7110, false);
273#endif
274
Ingo Molnar3593cab2006-02-07 06:49:14 -0200275 if (mutex_lock_interruptible(&av7110->dcomlock))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700276 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700277 newloops = rdebi(av7110, DEBINOSWAP, STATUS_LOOPS, 0, 2);
Ingo Molnar3593cab2006-02-07 06:49:14 -0200278 mutex_unlock(&av7110->dcomlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279
Oliver Endriss66190a22006-01-09 15:32:42 -0200280 if (newloops == av7110->arm_loops || av7110->arm_errors > 3) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700281 printk(KERN_ERR "dvb-ttpci: ARM crashed @ card %d\n",
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -0700282 av7110->dvb_adapter.num);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283
Oliver Endriss66190a22006-01-09 15:32:42 -0200284 recover_arm(av7110);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285
Ingo Molnar3593cab2006-02-07 06:49:14 -0200286 if (mutex_lock_interruptible(&av7110->dcomlock))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288 newloops = rdebi(av7110, DEBINOSWAP, STATUS_LOOPS, 0, 2) - 1;
Ingo Molnar3593cab2006-02-07 06:49:14 -0200289 mutex_unlock(&av7110->dcomlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700290 }
291 av7110->arm_loops = newloops;
Oliver Endriss66190a22006-01-09 15:32:42 -0200292 av7110->arm_errors = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293 }
294
Linus Torvalds1da177e2005-04-16 15:20:36 -0700295 return 0;
296}
297
298
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299/****************************************************************************
300 * IRQ handling
301 ****************************************************************************/
302
303static int DvbDmxFilterCallback(u8 *buffer1, size_t buffer1_len,
304 u8 *buffer2, size_t buffer2_len,
305 struct dvb_demux_filter *dvbdmxfilter,
306 enum dmx_success success,
307 struct av7110 *av7110)
308{
309 if (!dvbdmxfilter->feed->demux->dmx.frontend)
310 return 0;
311 if (dvbdmxfilter->feed->demux->dmx.frontend->source == DMX_MEMORY_FE)
312 return 0;
313
314 switch (dvbdmxfilter->type) {
315 case DMX_TYPE_SEC:
316 if ((((buffer1[1] << 8) | buffer1[2]) & 0xfff) + 3 != buffer1_len)
317 return 0;
318 if (dvbdmxfilter->doneq) {
319 struct dmx_section_filter *filter = &dvbdmxfilter->filter;
320 int i;
321 u8 xor, neq = 0;
322
323 for (i = 0; i < DVB_DEMUX_MASK_MAX; i++) {
324 xor = filter->filter_value[i] ^ buffer1[i];
325 neq |= dvbdmxfilter->maskandnotmode[i] & xor;
326 }
327 if (!neq)
328 return 0;
329 }
330 return dvbdmxfilter->feed->cb.sec(buffer1, buffer1_len,
331 buffer2, buffer2_len,
332 &dvbdmxfilter->filter,
333 DMX_OK);
334 case DMX_TYPE_TS:
335 if (!(dvbdmxfilter->feed->ts_type & TS_PACKET))
336 return 0;
337 if (dvbdmxfilter->feed->ts_type & TS_PAYLOAD_ONLY)
338 return dvbdmxfilter->feed->cb.ts(buffer1, buffer1_len,
339 buffer2, buffer2_len,
340 &dvbdmxfilter->feed->feed.ts,
341 DMX_OK);
342 else
343 av7110_p2t_write(buffer1, buffer1_len,
344 dvbdmxfilter->feed->pid,
345 &av7110->p2t_filter[dvbdmxfilter->index]);
346 default:
347 return 0;
348 }
349}
350
351
352//#define DEBUG_TIMING
353static inline void print_time(char *s)
354{
355#ifdef DEBUG_TIMING
356 struct timeval tv;
357 do_gettimeofday(&tv);
358 printk("%s: %d.%d\n", s, (int)tv.tv_sec, (int)tv.tv_usec);
359#endif
360}
361
362#define DEBI_READ 0
363#define DEBI_WRITE 1
364static inline void start_debi_dma(struct av7110 *av7110, int dir,
365 unsigned long addr, unsigned int len)
366{
367 dprintk(8, "%c %08lx %u\n", dir == DEBI_READ ? 'R' : 'W', addr, len);
368 if (saa7146_wait_for_debi_done(av7110->dev, 0)) {
Harvey Harrison3ca7fc82008-04-08 23:20:00 -0300369 printk(KERN_ERR "%s: saa7146_wait_for_debi_done timed out\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700370 return;
371 }
372
373 SAA7146_ISR_CLEAR(av7110->dev, MASK_19); /* for good measure */
374 SAA7146_IER_ENABLE(av7110->dev, MASK_19);
375 if (len < 5)
376 len = 5; /* we want a real DEBI DMA */
377 if (dir == DEBI_WRITE)
378 iwdebi(av7110, DEBISWAB, addr, 0, (len + 3) & ~3);
379 else
380 irdebi(av7110, DEBISWAB, addr, 0, len);
381}
382
Hans Verkuild45b9b82008-09-04 03:33:43 -0300383static void debiirq(unsigned long cookie)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384{
Hans Verkuild45b9b82008-09-04 03:33:43 -0300385 struct av7110 *av7110 = (struct av7110 *)cookie;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386 int type = av7110->debitype;
387 int handle = (type >> 8) & 0x1f;
388 unsigned int xfer = 0;
389
390 print_time("debi");
391 dprintk(4, "type 0x%04x\n", type);
392
393 if (type == -1) {
394 printk("DEBI irq oops @ %ld, psr:0x%08x, ssr:0x%08x\n",
395 jiffies, saa7146_read(av7110->dev, PSR),
396 saa7146_read(av7110->dev, SSR));
397 goto debi_done;
398 }
399 av7110->debitype = -1;
400
401 switch (type & 0xff) {
402
403 case DATA_TS_RECORD:
404 dvb_dmx_swfilter_packets(&av7110->demux,
405 (const u8 *) av7110->debi_virt,
406 av7110->debilen / 188);
407 xfer = RX_BUFF;
408 break;
409
410 case DATA_PES_RECORD:
411 if (av7110->demux.recording)
412 av7110_record_cb(&av7110->p2t[handle],
413 (u8 *) av7110->debi_virt,
414 av7110->debilen);
415 xfer = RX_BUFF;
416 break;
417
418 case DATA_IPMPE:
419 case DATA_FSECTION:
420 case DATA_PIPING:
421 if (av7110->handle2filter[handle])
422 DvbDmxFilterCallback((u8 *)av7110->debi_virt,
423 av7110->debilen, NULL, 0,
424 av7110->handle2filter[handle],
425 DMX_OK, av7110);
426 xfer = RX_BUFF;
427 break;
428
429 case DATA_CI_GET:
430 {
431 u8 *data = av7110->debi_virt;
432
433 if ((data[0] < 2) && data[2] == 0xff) {
434 int flags = 0;
435 if (data[5] > 0)
436 flags |= CA_CI_MODULE_PRESENT;
437 if (data[5] > 5)
438 flags |= CA_CI_MODULE_READY;
439 av7110->ci_slot[data[0]].flags = flags;
440 } else
441 ci_get_data(&av7110->ci_rbuffer,
442 av7110->debi_virt,
443 av7110->debilen);
444 xfer = RX_BUFF;
445 break;
446 }
447
448 case DATA_COMMON_INTERFACE:
449 CI_handle(av7110, (u8 *)av7110->debi_virt, av7110->debilen);
450#if 0
451 {
452 int i;
453
454 printk("av7110%d: ", av7110->num);
455 printk("%02x ", *(u8 *)av7110->debi_virt);
456 printk("%02x ", *(1+(u8 *)av7110->debi_virt));
457 for (i = 2; i < av7110->debilen; i++)
458 printk("%02x ", (*(i+(unsigned char *)av7110->debi_virt)));
459 for (i = 2; i < av7110->debilen; i++)
460 printk("%c", chtrans(*(i+(unsigned char *)av7110->debi_virt)));
461
462 printk("\n");
463 }
464#endif
465 xfer = RX_BUFF;
466 break;
467
468 case DATA_DEBUG_MESSAGE:
469 ((s8*)av7110->debi_virt)[Reserved_SIZE - 1] = 0;
470 printk("%s\n", (s8 *) av7110->debi_virt);
471 xfer = RX_BUFF;
472 break;
473
474 case DATA_CI_PUT:
475 dprintk(4, "debi DATA_CI_PUT\n");
476 case DATA_MPEG_PLAY:
477 dprintk(4, "debi DATA_MPEG_PLAY\n");
478 case DATA_BMP_LOAD:
479 dprintk(4, "debi DATA_BMP_LOAD\n");
480 xfer = TX_BUFF;
481 break;
482 default:
483 break;
484 }
485debi_done:
486 spin_lock(&av7110->debilock);
487 if (xfer)
488 iwdebi(av7110, DEBINOSWAP, xfer, 0, 2);
489 ARM_ClearMailBox(av7110);
490 spin_unlock(&av7110->debilock);
491}
492
493/* irq from av7110 firmware writing the mailbox register in the DPRAM */
Hans Verkuild45b9b82008-09-04 03:33:43 -0300494static void gpioirq(unsigned long cookie)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495{
Hans Verkuild45b9b82008-09-04 03:33:43 -0300496 struct av7110 *av7110 = (struct av7110 *)cookie;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497 u32 rxbuf, txbuf;
498 int len;
499
500 if (av7110->debitype != -1)
501 /* we shouldn't get any irq while a debi xfer is running */
502 printk("dvb-ttpci: GPIO0 irq oops @ %ld, psr:0x%08x, ssr:0x%08x\n",
503 jiffies, saa7146_read(av7110->dev, PSR),
504 saa7146_read(av7110->dev, SSR));
505
506 if (saa7146_wait_for_debi_done(av7110->dev, 0)) {
Harvey Harrison3ca7fc82008-04-08 23:20:00 -0300507 printk(KERN_ERR "%s: saa7146_wait_for_debi_done timed out\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700508 BUG(); /* maybe we should try resetting the debi? */
509 }
510
511 spin_lock(&av7110->debilock);
512 ARM_ClearIrq(av7110);
513
514 /* see what the av7110 wants */
515 av7110->debitype = irdebi(av7110, DEBINOSWAP, IRQ_STATE, 0, 2);
516 av7110->debilen = irdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
517 rxbuf = irdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
518 txbuf = irdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
519 len = (av7110->debilen + 3) & ~3;
520
521 print_time("gpio");
522 dprintk(8, "GPIO0 irq 0x%04x %d\n", av7110->debitype, av7110->debilen);
523
524 switch (av7110->debitype & 0xff) {
525
526 case DATA_TS_PLAY:
527 case DATA_PES_PLAY:
528 break;
529
530 case DATA_MPEG_VIDEO_EVENT:
531 {
532 u32 h_ar;
533 struct video_event event;
534
535 av7110->video_size.w = irdebi(av7110, DEBINOSWAP, STATUS_MPEG_WIDTH, 0, 2);
536 h_ar = irdebi(av7110, DEBINOSWAP, STATUS_MPEG_HEIGHT_AR, 0, 2);
537
538 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
539 iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
540
541 av7110->video_size.h = h_ar & 0xfff;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700542
543 event.type = VIDEO_EVENT_SIZE_CHANGED;
544 event.u.size.w = av7110->video_size.w;
545 event.u.size.h = av7110->video_size.h;
546 switch ((h_ar >> 12) & 0xf)
547 {
548 case 3:
549 av7110->video_size.aspect_ratio = VIDEO_FORMAT_16_9;
550 event.u.size.aspect_ratio = VIDEO_FORMAT_16_9;
551 av7110->videostate.video_format = VIDEO_FORMAT_16_9;
552 break;
553 case 4:
554 av7110->video_size.aspect_ratio = VIDEO_FORMAT_221_1;
555 event.u.size.aspect_ratio = VIDEO_FORMAT_221_1;
556 av7110->videostate.video_format = VIDEO_FORMAT_221_1;
557 break;
558 default:
559 av7110->video_size.aspect_ratio = VIDEO_FORMAT_4_3;
560 event.u.size.aspect_ratio = VIDEO_FORMAT_4_3;
561 av7110->videostate.video_format = VIDEO_FORMAT_4_3;
562 }
Oliver Endriss66190a22006-01-09 15:32:42 -0200563
564 dprintk(8, "GPIO0 irq: DATA_MPEG_VIDEO_EVENT: w/h/ar = %u/%u/%u\n",
565 av7110->video_size.w, av7110->video_size.h,
566 av7110->video_size.aspect_ratio);
567
Linus Torvalds1da177e2005-04-16 15:20:36 -0700568 dvb_video_add_event(av7110, &event);
569 break;
570 }
571
572 case DATA_CI_PUT:
573 {
574 int avail;
575 struct dvb_ringbuffer *cibuf = &av7110->ci_wbuffer;
576
577 avail = dvb_ringbuffer_avail(cibuf);
578 if (avail <= 2) {
579 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
580 iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
581 iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
582 break;
583 }
584 len = DVB_RINGBUFFER_PEEK(cibuf, 0) << 8;
585 len |= DVB_RINGBUFFER_PEEK(cibuf, 1);
586 if (avail < len + 2) {
587 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
588 iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
589 iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
590 break;
591 }
592 DVB_RINGBUFFER_SKIP(cibuf, 2);
593
Al Virob0ba0e32008-06-22 14:20:29 -0300594 dvb_ringbuffer_read(cibuf, av7110->debi_virt, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595
596 iwdebi(av7110, DEBINOSWAP, TX_LEN, len, 2);
597 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, len, 2);
598 dprintk(8, "DMA: CI\n");
599 start_debi_dma(av7110, DEBI_WRITE, DPRAM_BASE + txbuf, len);
600 spin_unlock(&av7110->debilock);
601 wake_up(&cibuf->queue);
602 return;
603 }
604
605 case DATA_MPEG_PLAY:
606 if (!av7110->playing) {
607 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
608 iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
609 iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
610 break;
611 }
612 len = 0;
613 if (av7110->debitype & 0x100) {
614 spin_lock(&av7110->aout.lock);
615 len = av7110_pes_play(av7110->debi_virt, &av7110->aout, 2048);
616 spin_unlock(&av7110->aout.lock);
617 }
618 if (len <= 0 && (av7110->debitype & 0x200)
619 &&av7110->videostate.play_state != VIDEO_FREEZED) {
620 spin_lock(&av7110->avout.lock);
621 len = av7110_pes_play(av7110->debi_virt, &av7110->avout, 2048);
622 spin_unlock(&av7110->avout.lock);
623 }
624 if (len <= 0) {
625 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
626 iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
627 iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
628 break;
629 }
630 dprintk(8, "GPIO0 PES_PLAY len=%04x\n", len);
631 iwdebi(av7110, DEBINOSWAP, TX_LEN, len, 2);
632 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, len, 2);
633 dprintk(8, "DMA: MPEG_PLAY\n");
634 start_debi_dma(av7110, DEBI_WRITE, DPRAM_BASE + txbuf, len);
635 spin_unlock(&av7110->debilock);
636 return;
637
638 case DATA_BMP_LOAD:
639 len = av7110->debilen;
640 dprintk(8, "gpio DATA_BMP_LOAD len %d\n", len);
641 if (!len) {
642 av7110->bmp_state = BMP_LOADED;
643 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
644 iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
645 iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
646 wake_up(&av7110->bmpq);
647 dprintk(8, "gpio DATA_BMP_LOAD done\n");
648 break;
649 }
650 if (len > av7110->bmplen)
651 len = av7110->bmplen;
652 if (len > 2 * 1024)
653 len = 2 * 1024;
654 iwdebi(av7110, DEBINOSWAP, TX_LEN, len, 2);
655 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, len, 2);
656 memcpy(av7110->debi_virt, av7110->bmpbuf+av7110->bmpp, len);
657 av7110->bmpp += len;
658 av7110->bmplen -= len;
659 dprintk(8, "gpio DATA_BMP_LOAD DMA len %d\n", len);
660 start_debi_dma(av7110, DEBI_WRITE, DPRAM_BASE+txbuf, len);
661 spin_unlock(&av7110->debilock);
662 return;
663
664 case DATA_CI_GET:
665 case DATA_COMMON_INTERFACE:
666 case DATA_FSECTION:
667 case DATA_IPMPE:
668 case DATA_PIPING:
669 if (!len || len > 4 * 1024) {
670 iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
671 break;
672 }
673 /* fall through */
674
675 case DATA_TS_RECORD:
676 case DATA_PES_RECORD:
677 dprintk(8, "DMA: TS_REC etc.\n");
678 start_debi_dma(av7110, DEBI_READ, DPRAM_BASE+rxbuf, len);
679 spin_unlock(&av7110->debilock);
680 return;
681
682 case DATA_DEBUG_MESSAGE:
683 if (!len || len > 0xff) {
684 iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
685 break;
686 }
687 start_debi_dma(av7110, DEBI_READ, Reserved, len);
688 spin_unlock(&av7110->debilock);
689 return;
690
691 case DATA_IRCOMMAND:
Oliver Endrissee820a62007-04-27 12:31:21 -0300692 if (av7110->ir.ir_handler)
693 av7110->ir.ir_handler(av7110,
Oliver Endriss03388ae2005-09-09 13:03:12 -0700694 swahw32(irdebi(av7110, DEBINOSWAP, Reserved, 0, 4)));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700695 iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
696 break;
697
698 default:
699 printk("dvb-ttpci: gpioirq unknown type=%d len=%d\n",
700 av7110->debitype, av7110->debilen);
701 break;
702 }
703 av7110->debitype = -1;
704 ARM_ClearMailBox(av7110);
705 spin_unlock(&av7110->debilock);
706}
707
708
709#ifdef CONFIG_DVB_AV7110_OSD
Arnd Bergmann16ef8de2010-04-27 00:24:00 +0200710static int dvb_osd_ioctl(struct file *file,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711 unsigned int cmd, void *parg)
712{
Tobias Klauserd9bdf772006-12-26 07:33:48 -0300713 struct dvb_device *dvbdev = file->private_data;
714 struct av7110 *av7110 = dvbdev->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700715
716 dprintk(4, "%p\n", av7110);
717
718 if (cmd == OSD_SEND_CMD)
719 return av7110_osd_cmd(av7110, (osd_cmd_t *) parg);
720 if (cmd == OSD_GET_CAPABILITY)
721 return av7110_osd_capability(av7110, (osd_cap_t *) parg);
722
723 return -EINVAL;
724}
725
726
Jan Engelhardt784e29d2009-01-11 06:12:43 -0300727static const struct file_operations dvb_osd_fops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700728 .owner = THIS_MODULE,
Arnd Bergmann16ef8de2010-04-27 00:24:00 +0200729 .unlocked_ioctl = dvb_generic_ioctl,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700730 .open = dvb_generic_open,
731 .release = dvb_generic_release,
Arnd Bergmann6038f372010-08-15 18:52:59 +0200732 .llseek = noop_llseek,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700733};
734
735static struct dvb_device dvbdev_osd = {
736 .priv = NULL,
737 .users = 1,
738 .writers = 1,
739 .fops = &dvb_osd_fops,
740 .kernel_ioctl = dvb_osd_ioctl,
741};
742#endif /* CONFIG_DVB_AV7110_OSD */
743
744
745static inline int SetPIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid,
746 u16 subpid, u16 pcrpid)
747{
Dr. Werner Fink47f36922006-01-09 15:25:07 -0200748 u16 aflags = 0;
749
Linus Torvalds1da177e2005-04-16 15:20:36 -0700750 dprintk(4, "%p\n", av7110);
751
752 if (vpid == 0x1fff || apid == 0x1fff ||
753 ttpid == 0x1fff || subpid == 0x1fff || pcrpid == 0x1fff) {
754 vpid = apid = ttpid = subpid = pcrpid = 0;
755 av7110->pids[DMX_PES_VIDEO] = 0;
756 av7110->pids[DMX_PES_AUDIO] = 0;
757 av7110->pids[DMX_PES_TELETEXT] = 0;
758 av7110->pids[DMX_PES_PCR] = 0;
759 }
760
Dr. Werner Fink47f36922006-01-09 15:25:07 -0200761 if (av7110->audiostate.bypass_mode)
762 aflags |= 0x8000;
763
764 return av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, MultiPID, 6,
765 pcrpid, vpid, apid, ttpid, subpid, aflags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700766}
767
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700768int ChangePIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700769 u16 subpid, u16 pcrpid)
770{
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700771 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772 dprintk(4, "%p\n", av7110);
773
Ingo Molnar3593cab2006-02-07 06:49:14 -0200774 if (mutex_lock_interruptible(&av7110->pid_mutex))
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700775 return -ERESTARTSYS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700776
777 if (!(vpid & 0x8000))
778 av7110->pids[DMX_PES_VIDEO] = vpid;
779 if (!(apid & 0x8000))
780 av7110->pids[DMX_PES_AUDIO] = apid;
781 if (!(ttpid & 0x8000))
782 av7110->pids[DMX_PES_TELETEXT] = ttpid;
783 if (!(pcrpid & 0x8000))
784 av7110->pids[DMX_PES_PCR] = pcrpid;
785
786 av7110->pids[DMX_PES_SUBTITLE] = 0;
787
788 if (av7110->fe_synced) {
789 pcrpid = av7110->pids[DMX_PES_PCR];
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700790 ret = SetPIDs(av7110, vpid, apid, ttpid, subpid, pcrpid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700791 }
792
Ingo Molnar3593cab2006-02-07 06:49:14 -0200793 mutex_unlock(&av7110->pid_mutex);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700794 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700795}
796
797
798/******************************************************************************
799 * hardware filter functions
800 ******************************************************************************/
801
802static int StartHWFilter(struct dvb_demux_filter *dvbdmxfilter)
803{
804 struct dvb_demux_feed *dvbdmxfeed = dvbdmxfilter->feed;
Tobias Klauserd9bdf772006-12-26 07:33:48 -0300805 struct av7110 *av7110 = dvbdmxfeed->demux->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700806 u16 buf[20];
807 int ret, i;
808 u16 handle;
809// u16 mode = 0x0320;
810 u16 mode = 0xb96a;
811
812 dprintk(4, "%p\n", av7110);
813
Oliver Endriss9e615ea2008-09-03 19:15:27 -0300814 if (av7110->full_ts)
815 return 0;
816
Linus Torvalds1da177e2005-04-16 15:20:36 -0700817 if (dvbdmxfilter->type == DMX_TYPE_SEC) {
818 if (hw_sections) {
819 buf[4] = (dvbdmxfilter->filter.filter_value[0] << 8) |
820 dvbdmxfilter->maskandmode[0];
821 for (i = 3; i < 18; i++)
822 buf[i + 4 - 2] =
823 (dvbdmxfilter->filter.filter_value[i] << 8) |
824 dvbdmxfilter->maskandmode[i];
825 mode = 4;
826 }
827 } else if ((dvbdmxfeed->ts_type & TS_PACKET) &&
828 !(dvbdmxfeed->ts_type & TS_PAYLOAD_ONLY)) {
829 av7110_p2t_init(&av7110->p2t_filter[dvbdmxfilter->index], dvbdmxfeed);
830 }
831
832 buf[0] = (COMTYPE_PID_FILTER << 8) + AddPIDFilter;
833 buf[1] = 16;
834 buf[2] = dvbdmxfeed->pid;
835 buf[3] = mode;
836
837 ret = av7110_fw_request(av7110, buf, 20, &handle, 1);
838 if (ret != 0 || handle >= 32) {
839 printk("dvb-ttpci: %s error buf %04x %04x %04x %04x "
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700840 "ret %d handle %04x\n",
Harvey Harrison3ca7fc82008-04-08 23:20:00 -0300841 __func__, buf[0], buf[1], buf[2], buf[3],
Linus Torvalds1da177e2005-04-16 15:20:36 -0700842 ret, handle);
843 dvbdmxfilter->hw_handle = 0xffff;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700844 if (!ret)
845 ret = -1;
846 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700847 }
848
849 av7110->handle2filter[handle] = dvbdmxfilter;
850 dvbdmxfilter->hw_handle = handle;
851
852 return ret;
853}
854
855static int StopHWFilter(struct dvb_demux_filter *dvbdmxfilter)
856{
Tobias Klauserd9bdf772006-12-26 07:33:48 -0300857 struct av7110 *av7110 = dvbdmxfilter->feed->demux->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700858 u16 buf[3];
859 u16 answ[2];
860 int ret;
861 u16 handle;
862
863 dprintk(4, "%p\n", av7110);
864
Oliver Endriss9e615ea2008-09-03 19:15:27 -0300865 if (av7110->full_ts)
866 return 0;
867
Linus Torvalds1da177e2005-04-16 15:20:36 -0700868 handle = dvbdmxfilter->hw_handle;
869 if (handle >= 32) {
870 printk("%s tried to stop invalid filter %04x, filter type = %x\n",
Harvey Harrison3ca7fc82008-04-08 23:20:00 -0300871 __func__, handle, dvbdmxfilter->type);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700872 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700873 }
874
875 av7110->handle2filter[handle] = NULL;
876
877 buf[0] = (COMTYPE_PID_FILTER << 8) + DelPIDFilter;
878 buf[1] = 1;
879 buf[2] = handle;
880 ret = av7110_fw_request(av7110, buf, 3, answ, 2);
881 if (ret != 0 || answ[1] != handle) {
882 printk("dvb-ttpci: %s error cmd %04x %04x %04x ret %x "
883 "resp %04x %04x pid %d\n",
Harvey Harrison3ca7fc82008-04-08 23:20:00 -0300884 __func__, buf[0], buf[1], buf[2], ret,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700885 answ[0], answ[1], dvbdmxfilter->feed->pid);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700886 if (!ret)
887 ret = -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700888 }
889 return ret;
890}
891
892
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700893static int dvb_feed_start_pid(struct dvb_demux_feed *dvbdmxfeed)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700894{
895 struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
Tobias Klauserd9bdf772006-12-26 07:33:48 -0300896 struct av7110 *av7110 = dvbdmx->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700897 u16 *pid = dvbdmx->pids, npids[5];
898 int i;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700899 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700900
901 dprintk(4, "%p\n", av7110);
902
903 npids[0] = npids[1] = npids[2] = npids[3] = npids[4] = 0xffff;
904 i = dvbdmxfeed->pes_type;
905 npids[i] = (pid[i]&0x8000) ? 0 : pid[i];
906 if ((i == 2) && npids[i] && (dvbdmxfeed->ts_type & TS_PACKET)) {
907 npids[i] = 0;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700908 ret = ChangePIDs(av7110, npids[1], npids[0], npids[2], npids[3], npids[4]);
909 if (!ret)
910 ret = StartHWFilter(dvbdmxfeed->filter);
911 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700913 if (dvbdmxfeed->pes_type <= 2 || dvbdmxfeed->pes_type == 4) {
914 ret = ChangePIDs(av7110, npids[1], npids[0], npids[2], npids[3], npids[4]);
915 if (ret)
916 return ret;
917 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918
919 if (dvbdmxfeed->pes_type < 2 && npids[0])
920 if (av7110->fe_synced)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700921 {
922 ret = av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, Scan, 0);
923 if (ret)
924 return ret;
925 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700926
Oliver Endriss9e615ea2008-09-03 19:15:27 -0300927 if ((dvbdmxfeed->ts_type & TS_PACKET) && !av7110->full_ts) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700928 if (dvbdmxfeed->pes_type == 0 && !(dvbdmx->pids[0] & 0x8000))
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700929 ret = av7110_av_start_record(av7110, RP_AUDIO, dvbdmxfeed);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700930 if (dvbdmxfeed->pes_type == 1 && !(dvbdmx->pids[1] & 0x8000))
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700931 ret = av7110_av_start_record(av7110, RP_VIDEO, dvbdmxfeed);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700932 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700933 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700934}
935
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700936static int dvb_feed_stop_pid(struct dvb_demux_feed *dvbdmxfeed)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700937{
938 struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
Tobias Klauserd9bdf772006-12-26 07:33:48 -0300939 struct av7110 *av7110 = dvbdmx->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700940 u16 *pid = dvbdmx->pids, npids[5];
941 int i;
942
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700943 int ret = 0;
944
Linus Torvalds1da177e2005-04-16 15:20:36 -0700945 dprintk(4, "%p\n", av7110);
946
947 if (dvbdmxfeed->pes_type <= 1) {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700948 ret = av7110_av_stop(av7110, dvbdmxfeed->pes_type ? RP_VIDEO : RP_AUDIO);
949 if (ret)
950 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700951 if (!av7110->rec_mode)
952 dvbdmx->recording = 0;
953 if (!av7110->playing)
954 dvbdmx->playing = 0;
955 }
956 npids[0] = npids[1] = npids[2] = npids[3] = npids[4] = 0xffff;
957 i = dvbdmxfeed->pes_type;
958 switch (i) {
959 case 2: //teletext
960 if (dvbdmxfeed->ts_type & TS_PACKET)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700961 ret = StopHWFilter(dvbdmxfeed->filter);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700962 npids[2] = 0;
963 break;
964 case 0:
965 case 1:
966 case 4:
967 if (!pids_off)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700968 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700969 npids[i] = (pid[i]&0x8000) ? 0 : pid[i];
970 break;
971 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700972 if (!ret)
973 ret = ChangePIDs(av7110, npids[1], npids[0], npids[2], npids[3], npids[4]);
974 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975}
976
977static int av7110_start_feed(struct dvb_demux_feed *feed)
978{
979 struct dvb_demux *demux = feed->demux;
980 struct av7110 *av7110 = demux->priv;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700981 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700982
983 dprintk(4, "%p\n", av7110);
984
985 if (!demux->dmx.frontend)
986 return -EINVAL;
987
Oliver Endriss9e615ea2008-09-03 19:15:27 -0300988 if (!av7110->full_ts && feed->pid > 0x1fff)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989 return -EINVAL;
990
991 if (feed->type == DMX_TYPE_TS) {
992 if ((feed->ts_type & TS_DECODER) &&
Mauro Carvalho Chehabfde04ab2013-04-04 13:25:30 -0300993 (feed->pes_type <= DMX_PES_PCR)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700994 switch (demux->dmx.frontend->source) {
995 case DMX_MEMORY_FE:
996 if (feed->ts_type & TS_DECODER)
997 if (feed->pes_type < 2 &&
998 !(demux->pids[0] & 0x8000) &&
999 !(demux->pids[1] & 0x8000)) {
1000 dvb_ringbuffer_flush_spinlock_wakeup(&av7110->avout);
1001 dvb_ringbuffer_flush_spinlock_wakeup(&av7110->aout);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001002 ret = av7110_av_start_play(av7110,RP_AV);
1003 if (!ret)
1004 demux->playing = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001005 }
1006 break;
1007 default:
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001008 ret = dvb_feed_start_pid(feed);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001009 break;
1010 }
1011 } else if ((feed->ts_type & TS_PACKET) &&
1012 (demux->dmx.frontend->source != DMX_MEMORY_FE)) {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001013 ret = StartHWFilter(feed->filter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001014 }
1015 }
1016
Oliver Endriss9e615ea2008-09-03 19:15:27 -03001017 if (av7110->full_ts) {
1018 budget_start_feed(feed);
1019 return ret;
1020 }
1021
1022 if (feed->type == DMX_TYPE_SEC) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001023 int i;
1024
1025 for (i = 0; i < demux->filternum; i++) {
1026 if (demux->filter[i].state != DMX_STATE_READY)
1027 continue;
1028 if (demux->filter[i].type != DMX_TYPE_SEC)
1029 continue;
1030 if (demux->filter[i].filter.parent != &feed->feed.sec)
1031 continue;
1032 demux->filter[i].state = DMX_STATE_GO;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001033 if (demux->dmx.frontend->source != DMX_MEMORY_FE) {
1034 ret = StartHWFilter(&demux->filter[i]);
1035 if (ret)
1036 break;
1037 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001038 }
1039 }
1040
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001041 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001042}
1043
1044
1045static int av7110_stop_feed(struct dvb_demux_feed *feed)
1046{
1047 struct dvb_demux *demux = feed->demux;
1048 struct av7110 *av7110 = demux->priv;
Johannes Stezenbach12ba0502005-07-07 17:58:00 -07001049 int i, rc, ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001050 dprintk(4, "%p\n", av7110);
1051
1052 if (feed->type == DMX_TYPE_TS) {
1053 if (feed->ts_type & TS_DECODER) {
Mauro Carvalho Chehabfde04ab2013-04-04 13:25:30 -03001054 if (feed->pes_type >= DMX_PES_OTHER ||
Linus Torvalds1da177e2005-04-16 15:20:36 -07001055 !demux->pesfilter[feed->pes_type])
1056 return -EINVAL;
1057 demux->pids[feed->pes_type] |= 0x8000;
1058 demux->pesfilter[feed->pes_type] = NULL;
1059 }
1060 if (feed->ts_type & TS_DECODER &&
Mauro Carvalho Chehabfde04ab2013-04-04 13:25:30 -03001061 feed->pes_type < DMX_PES_OTHER) {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001062 ret = dvb_feed_stop_pid(feed);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001063 } else
1064 if ((feed->ts_type & TS_PACKET) &&
1065 (demux->dmx.frontend->source != DMX_MEMORY_FE))
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001066 ret = StopHWFilter(feed->filter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067 }
1068
Oliver Endriss9e615ea2008-09-03 19:15:27 -03001069 if (av7110->full_ts) {
1070 budget_stop_feed(feed);
1071 return ret;
1072 }
1073
1074 if (feed->type == DMX_TYPE_SEC) {
Johannes Stezenbach12ba0502005-07-07 17:58:00 -07001075 for (i = 0; i<demux->filternum; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076 if (demux->filter[i].state == DMX_STATE_GO &&
1077 demux->filter[i].filter.parent == &feed->feed.sec) {
1078 demux->filter[i].state = DMX_STATE_READY;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001079 if (demux->dmx.frontend->source != DMX_MEMORY_FE) {
Johannes Stezenbach12ba0502005-07-07 17:58:00 -07001080 rc = StopHWFilter(&demux->filter[i]);
1081 if (!ret)
1082 ret = rc;
1083 /* keep going, stop as many filters as possible */
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001084 }
Johannes Stezenbach12ba0502005-07-07 17:58:00 -07001085 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001086 }
1087 }
1088
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001089 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001090}
1091
1092
1093static void restart_feeds(struct av7110 *av7110)
1094{
1095 struct dvb_demux *dvbdmx = &av7110->demux;
1096 struct dvb_demux_feed *feed;
1097 int mode;
Oliver Endriss9e615ea2008-09-03 19:15:27 -03001098 int feeding;
Oliver Endriss66190a22006-01-09 15:32:42 -02001099 int i, j;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001100
1101 dprintk(4, "%p\n", av7110);
1102
1103 mode = av7110->playing;
1104 av7110->playing = 0;
1105 av7110->rec_mode = 0;
1106
Oliver Endriss9e615ea2008-09-03 19:15:27 -03001107 feeding = av7110->feeding1; /* full_ts mod */
1108
Oliver Endriss66190a22006-01-09 15:32:42 -02001109 for (i = 0; i < dvbdmx->feednum; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001110 feed = &dvbdmx->feed[i];
Oliver Endriss66190a22006-01-09 15:32:42 -02001111 if (feed->state == DMX_STATE_GO) {
1112 if (feed->type == DMX_TYPE_SEC) {
1113 for (j = 0; j < dvbdmx->filternum; j++) {
1114 if (dvbdmx->filter[j].type != DMX_TYPE_SEC)
1115 continue;
1116 if (dvbdmx->filter[j].filter.parent != &feed->feed.sec)
1117 continue;
1118 if (dvbdmx->filter[j].state == DMX_STATE_GO)
1119 dvbdmx->filter[j].state = DMX_STATE_READY;
1120 }
1121 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001122 av7110_start_feed(feed);
Oliver Endriss66190a22006-01-09 15:32:42 -02001123 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001124 }
1125
Oliver Endriss9e615ea2008-09-03 19:15:27 -03001126 av7110->feeding1 = feeding; /* full_ts mod */
1127
Linus Torvalds1da177e2005-04-16 15:20:36 -07001128 if (mode)
1129 av7110_av_start_play(av7110, mode);
1130}
1131
1132static int dvb_get_stc(struct dmx_demux *demux, unsigned int num,
1133 uint64_t *stc, unsigned int *base)
1134{
1135 int ret;
1136 u16 fwstc[4];
1137 u16 tag = ((COMTYPE_REQUEST << 8) + ReqSTC);
1138 struct dvb_demux *dvbdemux;
1139 struct av7110 *av7110;
1140
1141 /* pointer casting paranoia... */
Eric Sesterhennae246012006-03-13 13:17:11 -03001142 BUG_ON(!demux);
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001143 dvbdemux = demux->priv;
Eric Sesterhennae246012006-03-13 13:17:11 -03001144 BUG_ON(!dvbdemux);
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001145 av7110 = dvbdemux->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001146
1147 dprintk(4, "%p\n", av7110);
1148
1149 if (num != 0)
1150 return -EINVAL;
1151
1152 ret = av7110_fw_request(av7110, &tag, 0, fwstc, 4);
1153 if (ret) {
Harvey Harrison3ca7fc82008-04-08 23:20:00 -03001154 printk(KERN_ERR "%s: av7110_fw_request error\n", __func__);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001155 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001156 }
1157 dprintk(2, "fwstc = %04hx %04hx %04hx %04hx\n",
1158 fwstc[0], fwstc[1], fwstc[2], fwstc[3]);
1159
1160 *stc = (((uint64_t) ((fwstc[3] & 0x8000) >> 15)) << 32) |
1161 (((uint64_t) fwstc[1]) << 16) | ((uint64_t) fwstc[0]);
1162 *base = 1;
1163
1164 dprintk(4, "stc = %lu\n", (unsigned long)*stc);
1165
1166 return 0;
1167}
1168
1169
1170/******************************************************************************
1171 * SEC device file operations
1172 ******************************************************************************/
1173
1174
1175static int av7110_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
1176{
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001177 struct av7110* av7110 = fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001178
1179 switch (tone) {
1180 case SEC_TONE_ON:
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001181 return Set22K(av7110, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001182
1183 case SEC_TONE_OFF:
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001184 return Set22K(av7110, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001185
1186 default:
1187 return -EINVAL;
1188 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001189}
1190
1191static int av7110_diseqc_send_master_cmd(struct dvb_frontend* fe,
1192 struct dvb_diseqc_master_cmd* cmd)
1193{
1194 struct av7110* av7110 = fe->dvb->priv;
1195
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001196 return av7110_diseqc_send(av7110, cmd->msg_len, cmd->msg, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001197}
1198
1199static int av7110_diseqc_send_burst(struct dvb_frontend* fe,
1200 fe_sec_mini_cmd_t minicmd)
1201{
1202 struct av7110* av7110 = fe->dvb->priv;
1203
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001204 return av7110_diseqc_send(av7110, 0, NULL, minicmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001205}
1206
1207/* simplified code from budget-core.c */
1208static int stop_ts_capture(struct av7110 *budget)
1209{
1210 dprintk(2, "budget: %p\n", budget);
1211
1212 if (--budget->feeding1)
1213 return budget->feeding1;
1214 saa7146_write(budget->dev, MC1, MASK_20); /* DMA3 off */
1215 SAA7146_IER_DISABLE(budget->dev, MASK_10);
1216 SAA7146_ISR_CLEAR(budget->dev, MASK_10);
1217 return 0;
1218}
1219
1220static int start_ts_capture(struct av7110 *budget)
1221{
1222 dprintk(2, "budget: %p\n", budget);
1223
1224 if (budget->feeding1)
1225 return ++budget->feeding1;
Oliver Endriss9e615ea2008-09-03 19:15:27 -03001226 memset(budget->grabbing, 0x00, TS_BUFLEN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001227 budget->ttbp = 0;
Oliver Endriss9e615ea2008-09-03 19:15:27 -03001228 SAA7146_ISR_CLEAR(budget->dev, MASK_10); /* VPE */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001229 SAA7146_IER_ENABLE(budget->dev, MASK_10); /* VPE */
1230 saa7146_write(budget->dev, MC1, (MASK_04 | MASK_20)); /* DMA3 on */
1231 return ++budget->feeding1;
1232}
1233
1234static int budget_start_feed(struct dvb_demux_feed *feed)
1235{
1236 struct dvb_demux *demux = feed->demux;
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001237 struct av7110 *budget = demux->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001238 int status;
1239
1240 dprintk(2, "av7110: %p\n", budget);
1241
1242 spin_lock(&budget->feedlock1);
1243 feed->pusi_seen = 0; /* have a clean section start */
1244 status = start_ts_capture(budget);
1245 spin_unlock(&budget->feedlock1);
1246 return status;
1247}
1248
1249static int budget_stop_feed(struct dvb_demux_feed *feed)
1250{
1251 struct dvb_demux *demux = feed->demux;
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001252 struct av7110 *budget = demux->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001253 int status;
1254
1255 dprintk(2, "budget: %p\n", budget);
1256
1257 spin_lock(&budget->feedlock1);
1258 status = stop_ts_capture(budget);
1259 spin_unlock(&budget->feedlock1);
1260 return status;
1261}
1262
Hans Verkuild45b9b82008-09-04 03:33:43 -03001263static void vpeirq(unsigned long cookie)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001264{
Hans Verkuild45b9b82008-09-04 03:33:43 -03001265 struct av7110 *budget = (struct av7110 *)cookie;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001266 u8 *mem = (u8 *) (budget->grabbing);
1267 u32 olddma = budget->ttbp;
1268 u32 newdma = saa7146_read(budget->dev, PCI_VDP3);
Oliver Endriss9e615ea2008-09-03 19:15:27 -03001269 struct dvb_demux *demux = budget->full_ts ? &budget->demux : &budget->demux1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001270
Linus Torvalds1da177e2005-04-16 15:20:36 -07001271 /* nearest lower position divisible by 188 */
1272 newdma -= newdma % 188;
1273
1274 if (newdma >= TS_BUFLEN)
1275 return;
1276
1277 budget->ttbp = newdma;
1278
1279 if (!budget->feeding1 || (newdma == olddma))
1280 return;
1281
Jon Burgess87c30192007-05-03 12:23:44 -03001282 /* Ensure streamed PCI data is synced to CPU */
1283 pci_dma_sync_sg_for_cpu(budget->dev->pci, budget->pt.slist, budget->pt.nents, PCI_DMA_FROMDEVICE);
1284
Linus Torvalds1da177e2005-04-16 15:20:36 -07001285#if 0
1286 /* track rps1 activity */
1287 printk("vpeirq: %02x Event Counter 1 0x%04x\n",
1288 mem[olddma],
1289 saa7146_read(budget->dev, EC1R) & 0x3fff);
1290#endif
1291
1292 if (newdma > olddma)
1293 /* no wraparound, dump olddma..newdma */
Oliver Endriss9e615ea2008-09-03 19:15:27 -03001294 dvb_dmx_swfilter_packets(demux, mem + olddma, (newdma - olddma) / 188);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001295 else {
1296 /* wraparound, dump olddma..buflen and 0..newdma */
Oliver Endriss9e615ea2008-09-03 19:15:27 -03001297 dvb_dmx_swfilter_packets(demux, mem + olddma, (TS_BUFLEN - olddma) / 188);
1298 dvb_dmx_swfilter_packets(demux, mem, newdma / 188);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001299 }
1300}
1301
1302static int av7110_register(struct av7110 *av7110)
1303{
1304 int ret, i;
1305 struct dvb_demux *dvbdemux = &av7110->demux;
1306 struct dvb_demux *dvbdemux1 = &av7110->demux1;
1307
1308 dprintk(4, "%p\n", av7110);
1309
1310 if (av7110->registered)
1311 return -1;
1312
1313 av7110->registered = 1;
1314
1315 dvbdemux->priv = (void *) av7110;
1316
1317 for (i = 0; i < 32; i++)
1318 av7110->handle2filter[i] = NULL;
1319
Oliver Endriss9e615ea2008-09-03 19:15:27 -03001320 dvbdemux->filternum = (av7110->full_ts) ? 256 : 32;
1321 dvbdemux->feednum = (av7110->full_ts) ? 256 : 32;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001322 dvbdemux->start_feed = av7110_start_feed;
1323 dvbdemux->stop_feed = av7110_stop_feed;
1324 dvbdemux->write_to_decoder = av7110_write_to_decoder;
1325 dvbdemux->dmx.capabilities = (DMX_TS_FILTERING | DMX_SECTION_FILTERING |
1326 DMX_MEMORY_BASED_FILTERING);
1327
1328 dvb_dmx_init(&av7110->demux);
1329 av7110->demux.dmx.get_stc = dvb_get_stc;
1330
Oliver Endriss9e615ea2008-09-03 19:15:27 -03001331 av7110->dmxdev.filternum = (av7110->full_ts) ? 256 : 32;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001332 av7110->dmxdev.demux = &dvbdemux->dmx;
1333 av7110->dmxdev.capabilities = 0;
1334
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001335 dvb_dmxdev_init(&av7110->dmxdev, &av7110->dvb_adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001336
1337 av7110->hw_frontend.source = DMX_FRONTEND_0;
1338
1339 ret = dvbdemux->dmx.add_frontend(&dvbdemux->dmx, &av7110->hw_frontend);
1340
1341 if (ret < 0)
1342 return ret;
1343
1344 av7110->mem_frontend.source = DMX_MEMORY_FE;
1345
1346 ret = dvbdemux->dmx.add_frontend(&dvbdemux->dmx, &av7110->mem_frontend);
1347
1348 if (ret < 0)
1349 return ret;
1350
1351 ret = dvbdemux->dmx.connect_frontend(&dvbdemux->dmx,
1352 &av7110->hw_frontend);
1353 if (ret < 0)
1354 return ret;
1355
1356 av7110_av_register(av7110);
1357 av7110_ca_register(av7110);
1358
1359#ifdef CONFIG_DVB_AV7110_OSD
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001360 dvb_register_device(&av7110->dvb_adapter, &av7110->osd_dev,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001361 &dvbdev_osd, av7110, DVB_DEVICE_OSD);
1362#endif
1363
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001364 dvb_net_init(&av7110->dvb_adapter, &av7110->dvb_net, &dvbdemux->dmx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001365
1366 if (budgetpatch) {
1367 /* initialize software demux1 without its own frontend
1368 * demux1 hardware is connected to frontend0 of demux0
1369 */
1370 dvbdemux1->priv = (void *) av7110;
1371
1372 dvbdemux1->filternum = 256;
1373 dvbdemux1->feednum = 256;
1374 dvbdemux1->start_feed = budget_start_feed;
1375 dvbdemux1->stop_feed = budget_stop_feed;
1376 dvbdemux1->write_to_decoder = NULL;
1377
1378 dvbdemux1->dmx.capabilities = (DMX_TS_FILTERING | DMX_SECTION_FILTERING |
1379 DMX_MEMORY_BASED_FILTERING);
1380
1381 dvb_dmx_init(&av7110->demux1);
1382
1383 av7110->dmxdev1.filternum = 256;
1384 av7110->dmxdev1.demux = &dvbdemux1->dmx;
1385 av7110->dmxdev1.capabilities = 0;
1386
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001387 dvb_dmxdev_init(&av7110->dmxdev1, &av7110->dvb_adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001388
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001389 dvb_net_init(&av7110->dvb_adapter, &av7110->dvb_net1, &dvbdemux1->dmx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001390 printk("dvb-ttpci: additional demux1 for budget-patch registered\n");
1391 }
1392 return 0;
1393}
1394
1395
1396static void dvb_unregister(struct av7110 *av7110)
1397{
1398 struct dvb_demux *dvbdemux = &av7110->demux;
1399 struct dvb_demux *dvbdemux1 = &av7110->demux1;
1400
1401 dprintk(4, "%p\n", av7110);
1402
1403 if (!av7110->registered)
1404 return;
1405
1406 if (budgetpatch) {
1407 dvb_net_release(&av7110->dvb_net1);
1408 dvbdemux->dmx.close(&dvbdemux1->dmx);
1409 dvb_dmxdev_release(&av7110->dmxdev1);
1410 dvb_dmx_release(&av7110->demux1);
1411 }
1412
1413 dvb_net_release(&av7110->dvb_net);
1414
1415 dvbdemux->dmx.close(&dvbdemux->dmx);
1416 dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &av7110->hw_frontend);
1417 dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &av7110->mem_frontend);
1418
1419 dvb_dmxdev_release(&av7110->dmxdev);
1420 dvb_dmx_release(&av7110->demux);
1421
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001422 if (av7110->fe != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001423 dvb_unregister_frontend(av7110->fe);
Andrew de Quinceyf52a8382006-08-08 09:10:09 -03001424 dvb_frontend_detach(av7110->fe);
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001425 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001426 dvb_unregister_device(av7110->osd_dev);
1427 av7110_av_unregister(av7110);
1428 av7110_ca_unregister(av7110);
1429}
1430
1431
1432/****************************************************************************
1433 * I2C client commands
1434 ****************************************************************************/
1435
1436int i2c_writereg(struct av7110 *av7110, u8 id, u8 reg, u8 val)
1437{
1438 u8 msg[2] = { reg, val };
1439 struct i2c_msg msgs;
1440
1441 msgs.flags = 0;
1442 msgs.addr = id / 2;
1443 msgs.len = 2;
1444 msgs.buf = msg;
1445 return i2c_transfer(&av7110->i2c_adap, &msgs, 1);
1446}
1447
Linus Torvalds1da177e2005-04-16 15:20:36 -07001448u8 i2c_readreg(struct av7110 *av7110, u8 id, u8 reg)
1449{
1450 u8 mm1[] = {0x00};
1451 u8 mm2[] = {0x00};
1452 struct i2c_msg msgs[2];
1453
1454 msgs[0].flags = 0;
1455 msgs[1].flags = I2C_M_RD;
1456 msgs[0].addr = msgs[1].addr = id / 2;
1457 mm1[0] = reg;
1458 msgs[0].len = 1; msgs[1].len = 1;
1459 msgs[0].buf = mm1; msgs[1].buf = mm2;
1460 i2c_transfer(&av7110->i2c_adap, msgs, 2);
1461
1462 return mm2[0];
1463}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001464
1465/****************************************************************************
1466 * INITIALIZATION
1467 ****************************************************************************/
1468
1469
1470static int check_firmware(struct av7110* av7110)
1471{
1472 u32 crc = 0, len = 0;
1473 unsigned char *ptr;
1474
1475 /* check for firmware magic */
1476 ptr = av7110->bin_fw;
1477 if (ptr[0] != 'A' || ptr[1] != 'V' ||
1478 ptr[2] != 'F' || ptr[3] != 'W') {
1479 printk("dvb-ttpci: this is not an av7110 firmware\n");
1480 return -EINVAL;
1481 }
1482 ptr += 4;
1483
1484 /* check dpram file */
Al Viro3e085622008-05-21 00:30:51 -03001485 crc = get_unaligned_be32(ptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001486 ptr += 4;
Al Viro3e085622008-05-21 00:30:51 -03001487 len = get_unaligned_be32(ptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001488 ptr += 4;
1489 if (len >= 512) {
Alexey Dobriyanbe787ac2006-03-07 22:20:23 -03001490 printk("dvb-ttpci: dpram file is way too big.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001491 return -EINVAL;
1492 }
1493 if (crc != crc32_le(0, ptr, len)) {
1494 printk("dvb-ttpci: crc32 of dpram file does not match.\n");
1495 return -EINVAL;
1496 }
1497 av7110->bin_dpram = ptr;
1498 av7110->size_dpram = len;
1499 ptr += len;
1500
1501 /* check root file */
Al Viro3e085622008-05-21 00:30:51 -03001502 crc = get_unaligned_be32(ptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001503 ptr += 4;
Al Viro3e085622008-05-21 00:30:51 -03001504 len = get_unaligned_be32(ptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001505 ptr += 4;
1506
1507 if (len <= 200000 || len >= 300000 ||
1508 len > ((av7110->bin_fw + av7110->size_fw) - ptr)) {
1509 printk("dvb-ttpci: root file has strange size (%d). aborting.\n", len);
1510 return -EINVAL;
1511 }
1512 if( crc != crc32_le(0, ptr, len)) {
1513 printk("dvb-ttpci: crc32 of root file does not match.\n");
1514 return -EINVAL;
1515 }
1516 av7110->bin_root = ptr;
1517 av7110->size_root = len;
1518 return 0;
1519}
1520
Linus Torvalds1da177e2005-04-16 15:20:36 -07001521static void put_firmware(struct av7110* av7110)
1522{
1523 vfree(av7110->bin_fw);
1524}
1525
1526static int get_firmware(struct av7110* av7110)
1527{
1528 int ret;
1529 const struct firmware *fw;
1530
1531 /* request the av7110 firmware, this will block until someone uploads it */
1532 ret = request_firmware(&fw, "dvb-ttpci-01.fw", &av7110->dev->pci->dev);
1533 if (ret) {
1534 if (ret == -ENOENT) {
1535 printk(KERN_ERR "dvb-ttpci: could not load firmware,"
1536 " file not found: dvb-ttpci-01.fw\n");
Ville Skytt\ä12e66f62006-01-09 15:25:38 -02001537 printk(KERN_ERR "dvb-ttpci: usually this should be in "
1538 "/usr/lib/hotplug/firmware or /lib/firmware\n");
1539 printk(KERN_ERR "dvb-ttpci: and can be downloaded from"
Linus Torvalds1da177e2005-04-16 15:20:36 -07001540 " http://www.linuxtv.org/download/dvb/firmware/\n");
1541 } else
1542 printk(KERN_ERR "dvb-ttpci: cannot request firmware"
1543 " (error %i)\n", ret);
1544 return -EINVAL;
1545 }
1546
1547 if (fw->size <= 200000) {
1548 printk("dvb-ttpci: this firmware is way too small.\n");
1549 release_firmware(fw);
1550 return -EINVAL;
1551 }
1552
1553 /* check if the firmware is available */
Jesper Juhld9bf2c02007-08-25 11:23:54 -03001554 av7110->bin_fw = vmalloc(fw->size);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001555 if (NULL == av7110->bin_fw) {
1556 dprintk(1, "out of memory\n");
1557 release_firmware(fw);
1558 return -ENOMEM;
1559 }
1560
1561 memcpy(av7110->bin_fw, fw->data, fw->size);
1562 av7110->size_fw = fw->size;
1563 if ((ret = check_firmware(av7110)))
1564 vfree(av7110->bin_fw);
1565
1566 release_firmware(fw);
1567 return ret;
1568}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001569
Mauro Carvalho Chehab14d24d12011-12-24 12:24:33 -03001570static int alps_bsrv2_tuner_set_params(struct dvb_frontend *fe)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001571{
Mauro Carvalho Chehabe439aed2011-12-23 08:01:05 -03001572 struct dtv_frontend_properties *p = &fe->dtv_property_cache;
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001573 struct av7110* av7110 = fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001574 u8 pwr = 0;
1575 u8 buf[4];
1576 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
Mauro Carvalho Chehabe439aed2011-12-23 08:01:05 -03001577 u32 div = (p->frequency + 479500) / 125;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001578
Mauro Carvalho Chehabe439aed2011-12-23 08:01:05 -03001579 if (p->frequency > 2000000)
1580 pwr = 3;
1581 else if (p->frequency > 1800000)
1582 pwr = 2;
1583 else if (p->frequency > 1600000)
1584 pwr = 1;
1585 else if (p->frequency > 1200000)
1586 pwr = 0;
1587 else if (p->frequency >= 1100000)
1588 pwr = 1;
1589 else
1590 pwr = 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001591
1592 buf[0] = (div >> 8) & 0x7f;
1593 buf[1] = div & 0xff;
1594 buf[2] = ((div & 0x18000) >> 10) | 0x95;
1595 buf[3] = (pwr << 6) | 0x30;
1596
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -08001597 // NOTE: since we're using a prescaler of 2, we set the
Linus Torvalds1da177e2005-04-16 15:20:36 -07001598 // divisor frequency to 62.5kHz and divide by 125 above
1599
Patrick Boettcherdea74862006-05-14 05:01:31 -03001600 if (fe->ops.i2c_gate_ctrl)
1601 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001602 if (i2c_transfer (&av7110->i2c_adap, &msg, 1) != 1)
1603 return -EIO;
1604 return 0;
1605}
1606
1607static struct ves1x93_config alps_bsrv2_config = {
1608 .demod_address = 0x08,
1609 .xin = 90100000UL,
1610 .invert_pwm = 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001611};
1612
Mauro Carvalho Chehab14d24d12011-12-24 12:24:33 -03001613static int alps_tdbe2_tuner_set_params(struct dvb_frontend *fe)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001614{
Mauro Carvalho Chehabe439aed2011-12-23 08:01:05 -03001615 struct dtv_frontend_properties *p = &fe->dtv_property_cache;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001616 struct av7110* av7110 = fe->dvb->priv;
1617 u32 div;
1618 u8 data[4];
1619 struct i2c_msg msg = { .addr = 0x62, .flags = 0, .buf = data, .len = sizeof(data) };
1620
Mauro Carvalho Chehabe439aed2011-12-23 08:01:05 -03001621 div = (p->frequency + 35937500 + 31250) / 62500;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001622
1623 data[0] = (div >> 8) & 0x7f;
1624 data[1] = div & 0xff;
1625 data[2] = 0x85 | ((div >> 10) & 0x60);
Mauro Carvalho Chehabe439aed2011-12-23 08:01:05 -03001626 data[3] = (p->frequency < 174000000 ? 0x88 : p->frequency < 470000000 ? 0x84 : 0x81);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001627
Patrick Boettcherdea74862006-05-14 05:01:31 -03001628 if (fe->ops.i2c_gate_ctrl)
1629 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001630 if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
1631 return -EIO;
1632 return 0;
1633}
1634
1635static struct ves1820_config alps_tdbe2_config = {
1636 .demod_address = 0x09,
1637 .xin = 57840000UL,
1638 .invert = 1,
1639 .selagc = VES1820_SELAGC_SIGNAMPERR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001640};
1641
1642
1643
1644
Mauro Carvalho Chehab14d24d12011-12-24 12:24:33 -03001645static int grundig_29504_451_tuner_set_params(struct dvb_frontend *fe)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001646{
Mauro Carvalho Chehabe439aed2011-12-23 08:01:05 -03001647 struct dtv_frontend_properties *p = &fe->dtv_property_cache;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001648 struct av7110* av7110 = fe->dvb->priv;
1649 u32 div;
1650 u8 data[4];
1651 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
1652
Mauro Carvalho Chehabe439aed2011-12-23 08:01:05 -03001653 div = p->frequency / 125;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001654 data[0] = (div >> 8) & 0x7f;
1655 data[1] = div & 0xff;
1656 data[2] = 0x8e;
1657 data[3] = 0x00;
1658
Patrick Boettcherdea74862006-05-14 05:01:31 -03001659 if (fe->ops.i2c_gate_ctrl)
1660 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001661 if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
1662 return -EIO;
1663 return 0;
1664}
1665
1666static struct tda8083_config grundig_29504_451_config = {
1667 .demod_address = 0x68,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001668};
1669
1670
1671
Mauro Carvalho Chehab14d24d12011-12-24 12:24:33 -03001672static int philips_cd1516_tuner_set_params(struct dvb_frontend *fe)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001673{
Mauro Carvalho Chehabe439aed2011-12-23 08:01:05 -03001674 struct dtv_frontend_properties *p = &fe->dtv_property_cache;
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -08001675 struct av7110* av7110 = fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001676 u32 div;
Mauro Carvalho Chehabe439aed2011-12-23 08:01:05 -03001677 u32 f = p->frequency;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001678 u8 data[4];
1679 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
1680
1681 div = (f + 36125000 + 31250) / 62500;
1682
1683 data[0] = (div >> 8) & 0x7f;
1684 data[1] = div & 0xff;
1685 data[2] = 0x8e;
1686 data[3] = (f < 174000000 ? 0xa1 : f < 470000000 ? 0x92 : 0x34);
1687
Patrick Boettcherdea74862006-05-14 05:01:31 -03001688 if (fe->ops.i2c_gate_ctrl)
1689 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001690 if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
1691 return -EIO;
1692 return 0;
1693}
1694
1695static struct ves1820_config philips_cd1516_config = {
1696 .demod_address = 0x09,
1697 .xin = 57840000UL,
1698 .invert = 1,
1699 .selagc = VES1820_SELAGC_SIGNAMPERR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001700};
1701
1702
1703
Mauro Carvalho Chehab14d24d12011-12-24 12:24:33 -03001704static int alps_tdlb7_tuner_set_params(struct dvb_frontend *fe)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001705{
Mauro Carvalho Chehabe439aed2011-12-23 08:01:05 -03001706 struct dtv_frontend_properties *p = &fe->dtv_property_cache;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001707 struct av7110* av7110 = fe->dvb->priv;
1708 u32 div, pwr;
1709 u8 data[4];
1710 struct i2c_msg msg = { .addr = 0x60, .flags = 0, .buf = data, .len = sizeof(data) };
1711
Mauro Carvalho Chehabe439aed2011-12-23 08:01:05 -03001712 div = (p->frequency + 36200000) / 166666;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001713
Mauro Carvalho Chehabe439aed2011-12-23 08:01:05 -03001714 if (p->frequency <= 782000000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001715 pwr = 1;
1716 else
1717 pwr = 2;
1718
1719 data[0] = (div >> 8) & 0x7f;
1720 data[1] = div & 0xff;
1721 data[2] = 0x85;
1722 data[3] = pwr << 6;
1723
Patrick Boettcherdea74862006-05-14 05:01:31 -03001724 if (fe->ops.i2c_gate_ctrl)
1725 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001726 if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
1727 return -EIO;
1728 return 0;
1729}
1730
1731static int alps_tdlb7_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name)
1732{
Peter Senna Tschudinb168e812013-01-19 19:41:10 -03001733#if IS_ENABLED(CONFIG_DVB_SP8870)
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001734 struct av7110* av7110 = fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001735
1736 return request_firmware(fw, name, &av7110->dev->pci->dev);
Oliver Endrissd98821e2006-09-14 00:15:13 -03001737#else
1738 return -EINVAL;
1739#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001740}
1741
1742static struct sp8870_config alps_tdlb7_config = {
1743
1744 .demod_address = 0x71,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001745 .request_firmware = alps_tdlb7_request_firmware,
1746};
1747
1748
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001749static u8 nexusca_stv0297_inittab[] = {
1750 0x80, 0x01,
1751 0x80, 0x00,
1752 0x81, 0x01,
1753 0x81, 0x00,
1754 0x00, 0x09,
1755 0x01, 0x69,
1756 0x03, 0x00,
1757 0x04, 0x00,
1758 0x07, 0x00,
1759 0x08, 0x00,
1760 0x20, 0x00,
1761 0x21, 0x40,
1762 0x22, 0x00,
1763 0x23, 0x00,
1764 0x24, 0x40,
1765 0x25, 0x88,
1766 0x30, 0xff,
1767 0x31, 0x00,
1768 0x32, 0xff,
1769 0x33, 0x00,
1770 0x34, 0x50,
1771 0x35, 0x7f,
1772 0x36, 0x00,
1773 0x37, 0x20,
1774 0x38, 0x00,
1775 0x40, 0x1c,
1776 0x41, 0xff,
1777 0x42, 0x29,
1778 0x43, 0x00,
1779 0x44, 0xff,
1780 0x45, 0x00,
1781 0x46, 0x00,
1782 0x49, 0x04,
1783 0x4a, 0x00,
1784 0x4b, 0x7b,
1785 0x52, 0x30,
1786 0x55, 0xae,
1787 0x56, 0x47,
1788 0x57, 0xe1,
1789 0x58, 0x3a,
1790 0x5a, 0x1e,
1791 0x5b, 0x34,
1792 0x60, 0x00,
1793 0x63, 0x00,
1794 0x64, 0x00,
1795 0x65, 0x00,
1796 0x66, 0x00,
1797 0x67, 0x00,
1798 0x68, 0x00,
1799 0x69, 0x00,
1800 0x6a, 0x02,
1801 0x6b, 0x00,
1802 0x70, 0xff,
1803 0x71, 0x00,
1804 0x72, 0x00,
1805 0x73, 0x00,
1806 0x74, 0x0c,
1807 0x80, 0x00,
1808 0x81, 0x00,
1809 0x82, 0x00,
1810 0x83, 0x00,
1811 0x84, 0x04,
1812 0x85, 0x80,
1813 0x86, 0x24,
1814 0x87, 0x78,
1815 0x88, 0x10,
1816 0x89, 0x00,
1817 0x90, 0x01,
1818 0x91, 0x01,
1819 0xa0, 0x04,
1820 0xa1, 0x00,
1821 0xa2, 0x00,
1822 0xb0, 0x91,
1823 0xb1, 0x0b,
1824 0xc0, 0x53,
1825 0xc1, 0x70,
1826 0xc2, 0x12,
1827 0xd0, 0x00,
1828 0xd1, 0x00,
1829 0xd2, 0x00,
1830 0xd3, 0x00,
1831 0xd4, 0x00,
1832 0xd5, 0x00,
1833 0xde, 0x00,
1834 0xdf, 0x00,
1835 0x61, 0x49,
1836 0x62, 0x0b,
1837 0x53, 0x08,
1838 0x59, 0x08,
1839 0xff, 0xff,
1840};
Linus Torvalds1da177e2005-04-16 15:20:36 -07001841
Mauro Carvalho Chehab14d24d12011-12-24 12:24:33 -03001842static int nexusca_stv0297_tuner_set_params(struct dvb_frontend *fe)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001843{
Mauro Carvalho Chehabe439aed2011-12-23 08:01:05 -03001844 struct dtv_frontend_properties *p = &fe->dtv_property_cache;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001845 struct av7110* av7110 = fe->dvb->priv;
1846 u32 div;
1847 u8 data[4];
1848 struct i2c_msg msg = { .addr = 0x63, .flags = 0, .buf = data, .len = sizeof(data) };
1849 struct i2c_msg readmsg = { .addr = 0x63, .flags = I2C_M_RD, .buf = data, .len = 1 };
1850 int i;
1851
Mauro Carvalho Chehabe439aed2011-12-23 08:01:05 -03001852 div = (p->frequency + 36150000 + 31250) / 62500;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001853
1854 data[0] = (div >> 8) & 0x7f;
1855 data[1] = div & 0xff;
1856 data[2] = 0xce;
1857
Mauro Carvalho Chehabe439aed2011-12-23 08:01:05 -03001858 if (p->frequency < 45000000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001859 return -EINVAL;
Mauro Carvalho Chehabe439aed2011-12-23 08:01:05 -03001860 else if (p->frequency < 137000000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001861 data[3] = 0x01;
Mauro Carvalho Chehabe439aed2011-12-23 08:01:05 -03001862 else if (p->frequency < 403000000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001863 data[3] = 0x02;
Mauro Carvalho Chehabe439aed2011-12-23 08:01:05 -03001864 else if (p->frequency < 860000000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001865 data[3] = 0x04;
1866 else
1867 return -EINVAL;
1868
Patrick Boettcherdea74862006-05-14 05:01:31 -03001869 if (fe->ops.i2c_gate_ctrl)
1870 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001871 if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1) {
1872 printk("nexusca: pll transfer failed!\n");
1873 return -EIO;
1874 }
1875
1876 // wait for PLL lock
1877 for(i = 0; i < 20; i++) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001878 if (fe->ops.i2c_gate_ctrl)
1879 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001880 if (i2c_transfer(&av7110->i2c_adap, &readmsg, 1) == 1)
1881 if (data[0] & 0x40) break;
1882 msleep(10);
1883 }
1884
1885 return 0;
1886}
1887
1888static struct stv0297_config nexusca_stv0297_config = {
1889
1890 .demod_address = 0x1C,
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001891 .inittab = nexusca_stv0297_inittab,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001892 .invert = 1,
Thomas Kaiserb8d4c232006-04-27 21:45:20 -03001893 .stop_during_read = 1,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001894};
1895
1896
1897
Mauro Carvalho Chehab14d24d12011-12-24 12:24:33 -03001898static int grundig_29504_401_tuner_set_params(struct dvb_frontend *fe)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001899{
Mauro Carvalho Chehabe439aed2011-12-23 08:01:05 -03001900 struct dtv_frontend_properties *p = &fe->dtv_property_cache;
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001901 struct av7110* av7110 = fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001902 u32 div;
1903 u8 cfg, cpump, band_select;
1904 u8 data[4];
1905 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
1906
Mauro Carvalho Chehabe439aed2011-12-23 08:01:05 -03001907 div = (36125000 + p->frequency) / 166666;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001908
1909 cfg = 0x88;
1910
Mauro Carvalho Chehabe439aed2011-12-23 08:01:05 -03001911 if (p->frequency < 175000000)
1912 cpump = 2;
1913 else if (p->frequency < 390000000)
1914 cpump = 1;
1915 else if (p->frequency < 470000000)
1916 cpump = 2;
1917 else if (p->frequency < 750000000)
1918 cpump = 1;
1919 else
1920 cpump = 3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001921
Mauro Carvalho Chehabe439aed2011-12-23 08:01:05 -03001922 if (p->frequency < 175000000)
1923 band_select = 0x0e;
1924 else if (p->frequency < 470000000)
1925 band_select = 0x05;
1926 else
1927 band_select = 0x03;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001928
1929 data[0] = (div >> 8) & 0x7f;
1930 data[1] = div & 0xff;
1931 data[2] = ((div >> 10) & 0x60) | cfg;
1932 data[3] = (cpump << 6) | band_select;
1933
Patrick Boettcherdea74862006-05-14 05:01:31 -03001934 if (fe->ops.i2c_gate_ctrl)
1935 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001936 if (i2c_transfer (&av7110->i2c_adap, &msg, 1) != 1) return -EIO;
1937 return 0;
1938}
1939
1940static struct l64781_config grundig_29504_401_config = {
1941 .demod_address = 0x55,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001942};
1943
1944
1945
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001946static int av7110_fe_lock_fix(struct av7110* av7110, fe_status_t status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001947{
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001948 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001949 int synced = (status & FE_HAS_LOCK) ? 1 : 0;
1950
1951 av7110->fe_status = status;
1952
1953 if (av7110->fe_synced == synced)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001954 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001955
Oliver Endriss14500d42007-03-03 14:45:48 -03001956 if (av7110->playing) {
1957 av7110->fe_synced = synced;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001958 return 0;
Oliver Endriss14500d42007-03-03 14:45:48 -03001959 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001960
Ingo Molnar3593cab2006-02-07 06:49:14 -02001961 if (mutex_lock_interruptible(&av7110->pid_mutex))
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001962 return -ERESTARTSYS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001963
Oliver Endriss34612152005-07-07 17:58:02 -07001964 if (synced) {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001965 ret = SetPIDs(av7110, av7110->pids[DMX_PES_VIDEO],
Linus Torvalds1da177e2005-04-16 15:20:36 -07001966 av7110->pids[DMX_PES_AUDIO],
1967 av7110->pids[DMX_PES_TELETEXT], 0,
1968 av7110->pids[DMX_PES_PCR]);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001969 if (!ret)
1970 ret = av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, Scan, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001971 } else {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001972 ret = SetPIDs(av7110, 0, 0, 0, 0, 0);
1973 if (!ret) {
1974 ret = av7110_fw_cmd(av7110, COMTYPE_PID_FILTER, FlushTSQueue, 0);
1975 if (!ret)
1976 ret = av7110_wait_msgstate(av7110, GPMQBusy);
1977 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001978 }
1979
Oliver Endriss34612152005-07-07 17:58:02 -07001980 if (!ret)
1981 av7110->fe_synced = synced;
1982
Ingo Molnar3593cab2006-02-07 06:49:14 -02001983 mutex_unlock(&av7110->pid_mutex);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001984 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001985}
1986
Mauro Carvalho Chehabb5c7cfd2011-12-23 18:19:24 -03001987static int av7110_fe_set_frontend(struct dvb_frontend *fe)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001988{
1989 struct av7110* av7110 = fe->dvb->priv;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001990
1991 int ret = av7110_fe_lock_fix(av7110, 0);
Mauro Carvalho Chehabb5c7cfd2011-12-23 18:19:24 -03001992 if (!ret)
1993 ret = av7110->fe_set_frontend(fe);
1994
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001995 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001996}
1997
1998static int av7110_fe_init(struct dvb_frontend* fe)
1999{
2000 struct av7110* av7110 = fe->dvb->priv;
2001
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002002 int ret = av7110_fe_lock_fix(av7110, 0);
2003 if (!ret)
2004 ret = av7110->fe_init(fe);
2005 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002006}
2007
2008static int av7110_fe_read_status(struct dvb_frontend* fe, fe_status_t* status)
2009{
2010 struct av7110* av7110 = fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002011
2012 /* call the real implementation */
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002013 int ret = av7110->fe_read_status(fe, status);
2014 if (!ret)
2015 if (((*status ^ av7110->fe_status) & FE_HAS_LOCK) && (*status & FE_HAS_LOCK))
2016 ret = av7110_fe_lock_fix(av7110, *status);
2017 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002018}
2019
2020static int av7110_fe_diseqc_reset_overload(struct dvb_frontend* fe)
2021{
2022 struct av7110* av7110 = fe->dvb->priv;
2023
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002024 int ret = av7110_fe_lock_fix(av7110, 0);
2025 if (!ret)
2026 ret = av7110->fe_diseqc_reset_overload(fe);
2027 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002028}
2029
2030static int av7110_fe_diseqc_send_master_cmd(struct dvb_frontend* fe,
2031 struct dvb_diseqc_master_cmd* cmd)
2032{
2033 struct av7110* av7110 = fe->dvb->priv;
2034
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002035 int ret = av7110_fe_lock_fix(av7110, 0);
Oliver Endriss66190a22006-01-09 15:32:42 -02002036 if (!ret) {
2037 av7110->saved_master_cmd = *cmd;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002038 ret = av7110->fe_diseqc_send_master_cmd(fe, cmd);
Oliver Endriss66190a22006-01-09 15:32:42 -02002039 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002040 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002041}
2042
2043static int av7110_fe_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd)
2044{
2045 struct av7110* av7110 = fe->dvb->priv;
2046
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002047 int ret = av7110_fe_lock_fix(av7110, 0);
Oliver Endriss66190a22006-01-09 15:32:42 -02002048 if (!ret) {
2049 av7110->saved_minicmd = minicmd;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002050 ret = av7110->fe_diseqc_send_burst(fe, minicmd);
Oliver Endriss66190a22006-01-09 15:32:42 -02002051 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002052 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002053}
2054
2055static int av7110_fe_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
2056{
2057 struct av7110* av7110 = fe->dvb->priv;
2058
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002059 int ret = av7110_fe_lock_fix(av7110, 0);
Oliver Endriss66190a22006-01-09 15:32:42 -02002060 if (!ret) {
2061 av7110->saved_tone = tone;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002062 ret = av7110->fe_set_tone(fe, tone);
Oliver Endriss66190a22006-01-09 15:32:42 -02002063 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002064 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002065}
2066
2067static int av7110_fe_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
2068{
2069 struct av7110* av7110 = fe->dvb->priv;
2070
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002071 int ret = av7110_fe_lock_fix(av7110, 0);
Oliver Endriss66190a22006-01-09 15:32:42 -02002072 if (!ret) {
2073 av7110->saved_voltage = voltage;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002074 ret = av7110->fe_set_voltage(fe, voltage);
Oliver Endriss66190a22006-01-09 15:32:42 -02002075 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002076 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002077}
2078
Peter Beutner400b7082006-01-09 15:32:43 -02002079static int av7110_fe_dishnetwork_send_legacy_command(struct dvb_frontend* fe, unsigned long cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002080{
2081 struct av7110* av7110 = fe->dvb->priv;
2082
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07002083 int ret = av7110_fe_lock_fix(av7110, 0);
2084 if (!ret)
2085 ret = av7110->fe_dishnetwork_send_legacy_command(fe, cmd);
2086 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002087}
2088
Oliver Endriss66190a22006-01-09 15:32:42 -02002089static void dvb_s_recover(struct av7110* av7110)
2090{
2091 av7110_fe_init(av7110->fe);
2092
2093 av7110_fe_set_voltage(av7110->fe, av7110->saved_voltage);
2094 if (av7110->saved_master_cmd.msg_len) {
2095 msleep(20);
2096 av7110_fe_diseqc_send_master_cmd(av7110->fe, &av7110->saved_master_cmd);
2097 }
2098 msleep(20);
2099 av7110_fe_diseqc_send_burst(av7110->fe, av7110->saved_minicmd);
2100 msleep(20);
2101 av7110_fe_set_tone(av7110->fe, av7110->saved_tone);
2102
Mauro Carvalho Chehabb5c7cfd2011-12-23 18:19:24 -03002103 av7110_fe_set_frontend(av7110->fe);
Oliver Endriss66190a22006-01-09 15:32:42 -02002104}
2105
Linus Torvalds1da177e2005-04-16 15:20:36 -07002106static u8 read_pwm(struct av7110* av7110)
2107{
2108 u8 b = 0xff;
2109 u8 pwm;
2110 struct i2c_msg msg[] = { { .addr = 0x50,.flags = 0,.buf = &b,.len = 1 },
2111 { .addr = 0x50,.flags = I2C_M_RD,.buf = &pwm,.len = 1} };
2112
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -08002113 if ((i2c_transfer(&av7110->i2c_adap, msg, 2) != 2) || (pwm == 0xff))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002114 pwm = 0x48;
2115
2116 return pwm;
2117}
2118
2119static int frontend_init(struct av7110 *av7110)
2120{
2121 int ret;
2122
2123 if (av7110->dev->pci->subsystem_vendor == 0x110a) {
2124 switch(av7110->dev->pci->subsystem_device) {
2125 case 0x0000: // Fujitsu/Siemens DVB-Cable (ves1820/Philips CD1516(??))
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002126 av7110->fe = dvb_attach(ves1820_attach, &philips_cd1516_config,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002127 &av7110->i2c_adap, read_pwm(av7110));
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002128 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002129 av7110->fe->ops.tuner_ops.set_params = philips_cd1516_tuner_set_params;
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002130 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002131 break;
2132 }
2133
2134 } else if (av7110->dev->pci->subsystem_vendor == 0x13c2) {
2135 switch(av7110->dev->pci->subsystem_device) {
2136 case 0x0000: // Hauppauge/TT WinTV DVB-S rev1.X
2137 case 0x0003: // Hauppauge/TT WinTV Nexus-S Rev 2.X
2138 case 0x1002: // Hauppauge/TT WinTV DVB-S rev1.3SE
2139
2140 // try the ALPS BSRV2 first of all
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002141 av7110->fe = dvb_attach(ves1x93_attach, &alps_bsrv2_config, &av7110->i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002142 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002143 av7110->fe->ops.tuner_ops.set_params = alps_bsrv2_tuner_set_params;
2144 av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
2145 av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
2146 av7110->fe->ops.set_tone = av7110_set_tone;
Oliver Endriss66190a22006-01-09 15:32:42 -02002147 av7110->recover = dvb_s_recover;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002148 break;
2149 }
2150
2151 // try the ALPS BSRU6 now
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002152 av7110->fe = dvb_attach(stv0299_attach, &alps_bsru6_config, &av7110->i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002153 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002154 av7110->fe->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03002155 av7110->fe->tuner_priv = &av7110->i2c_adap;
2156
Patrick Boettcherdea74862006-05-14 05:01:31 -03002157 av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
2158 av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
2159 av7110->fe->ops.set_tone = av7110_set_tone;
Oliver Endriss66190a22006-01-09 15:32:42 -02002160 av7110->recover = dvb_s_recover;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002161 break;
2162 }
2163
2164 // Try the grundig 29504-451
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002165 av7110->fe = dvb_attach(tda8083_attach, &grundig_29504_451_config, &av7110->i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002166 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002167 av7110->fe->ops.tuner_ops.set_params = grundig_29504_451_tuner_set_params;
2168 av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
2169 av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
2170 av7110->fe->ops.set_tone = av7110_set_tone;
Oliver Endriss66190a22006-01-09 15:32:42 -02002171 av7110->recover = dvb_s_recover;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002172 break;
2173 }
2174
2175 /* Try DVB-C cards */
2176 switch(av7110->dev->pci->subsystem_device) {
2177 case 0x0000:
2178 /* Siemens DVB-C (full-length card) VES1820/Philips CD1516 */
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002179 av7110->fe = dvb_attach(ves1820_attach, &philips_cd1516_config, &av7110->i2c_adap,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002180 read_pwm(av7110));
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002181 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002182 av7110->fe->ops.tuner_ops.set_params = philips_cd1516_tuner_set_params;
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002183 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002184 break;
2185 case 0x0003:
Adrian Bunkf3688fc2006-03-29 22:46:12 -03002186 /* Hauppauge DVB-C 2.1 VES1820/ALPS TDBE2 */
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002187 av7110->fe = dvb_attach(ves1820_attach, &alps_tdbe2_config, &av7110->i2c_adap,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002188 read_pwm(av7110));
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002189 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002190 av7110->fe->ops.tuner_ops.set_params = alps_tdbe2_tuner_set_params;
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002191 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002192 break;
2193 }
2194 break;
2195
2196 case 0x0001: // Hauppauge/TT Nexus-T premium rev1.X
Oliver Endriss8d90ee52006-08-07 02:04:26 -03002197 // try ALPS TDLB7 first, then Grundig 29504-401
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002198 av7110->fe = dvb_attach(sp8870_attach, &alps_tdlb7_config, &av7110->i2c_adap);
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002199 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002200 av7110->fe->ops.tuner_ops.set_params = alps_tdlb7_tuner_set_params;
Oliver Endriss8d90ee52006-08-07 02:04:26 -03002201 break;
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002202 }
Oliver Endriss8d90ee52006-08-07 02:04:26 -03002203 /* fall-thru */
2204
2205 case 0x0008: // Hauppauge/TT DVB-T
2206 // Grundig 29504-401
2207 av7110->fe = dvb_attach(l64781_attach, &grundig_29504_401_config, &av7110->i2c_adap);
2208 if (av7110->fe)
2209 av7110->fe->ops.tuner_ops.set_params = grundig_29504_401_tuner_set_params;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002210 break;
2211
2212 case 0x0002: // Hauppauge/TT DVB-C premium rev2.X
2213
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002214 av7110->fe = dvb_attach(ves1820_attach, &alps_tdbe2_config, &av7110->i2c_adap, read_pwm(av7110));
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002215 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002216 av7110->fe->ops.tuner_ops.set_params = alps_tdbe2_tuner_set_params;
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03002217 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002218 break;
2219
Oliver Endriss8bd63012006-02-07 06:49:11 -02002220 case 0x0004: // Galaxis DVB-S rev1.3
2221 /* ALPS BSRV2 */
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002222 av7110->fe = dvb_attach(ves1x93_attach, &alps_bsrv2_config, &av7110->i2c_adap);
Oliver Endriss8bd63012006-02-07 06:49:11 -02002223 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002224 av7110->fe->ops.tuner_ops.set_params = alps_bsrv2_tuner_set_params;
2225 av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
2226 av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
2227 av7110->fe->ops.set_tone = av7110_set_tone;
Oliver Endriss8bd63012006-02-07 06:49:11 -02002228 av7110->recover = dvb_s_recover;
2229 }
2230 break;
2231
Linus Torvalds1da177e2005-04-16 15:20:36 -07002232 case 0x0006: /* Fujitsu-Siemens DVB-S rev 1.6 */
2233 /* Grundig 29504-451 */
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002234 av7110->fe = dvb_attach(tda8083_attach, &grundig_29504_451_config, &av7110->i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002235 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002236 av7110->fe->ops.tuner_ops.set_params = grundig_29504_451_tuner_set_params;
2237 av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
2238 av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
2239 av7110->fe->ops.set_tone = av7110_set_tone;
Oliver Endriss66190a22006-01-09 15:32:42 -02002240 av7110->recover = dvb_s_recover;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002241 }
2242 break;
2243
Linus Torvalds1da177e2005-04-16 15:20:36 -07002244 case 0x000A: // Hauppauge/TT Nexus-CA rev1.X
2245
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002246 av7110->fe = dvb_attach(stv0297_attach, &nexusca_stv0297_config, &av7110->i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002247 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002248 av7110->fe->ops.tuner_ops.set_params = nexusca_stv0297_tuner_set_params;
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03002249
Linus Torvalds1da177e2005-04-16 15:20:36 -07002250 /* set TDA9819 into DVB mode */
Marco Schluessler6a857742006-07-10 03:34:16 -03002251 saa7146_setgpio(av7110->dev, 1, SAA7146_GPIO_OUTLO); // TDA9819 pin9(STD)
2252 saa7146_setgpio(av7110->dev, 3, SAA7146_GPIO_OUTLO); // TDA9819 pin30(VIF)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002253
2254 /* tuner on this needs a slower i2c bus speed */
2255 av7110->dev->i2c_bitrate = SAA7146_I2C_BUS_BIT_RATE_240;
2256 break;
2257 }
Johannes Stezenbach3dfaebd2005-05-16 21:54:19 -07002258 break;
2259
2260 case 0x000E: /* Hauppauge/TT Nexus-S rev 2.3 */
2261 /* ALPS BSBE1 */
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002262 av7110->fe = dvb_attach(stv0299_attach, &alps_bsbe1_config, &av7110->i2c_adap);
Oliver Endrisseb3daf32006-01-09 15:25:05 -02002263 if (av7110->fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002264 av7110->fe->ops.tuner_ops.set_params = alps_bsbe1_tuner_set_params;
Andrew de Quinceyfa006d82006-04-18 17:47:11 -03002265 av7110->fe->tuner_priv = &av7110->i2c_adap;
2266
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03002267 if (dvb_attach(lnbp21_attach, av7110->fe, &av7110->i2c_adap, 0, 0) == NULL) {
Oliver Endrissdb5d91e2006-02-28 10:32:25 -03002268 printk("dvb-ttpci: LNBP21 not found!\n");
Patrick Boettcherdea74862006-05-14 05:01:31 -03002269 if (av7110->fe->ops.release)
2270 av7110->fe->ops.release(av7110->fe);
Oliver Endrissdb5d91e2006-02-28 10:32:25 -03002271 av7110->fe = NULL;
2272 } else {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002273 av7110->fe->ops.dishnetwork_send_legacy_command = NULL;
Oliver Endrissdb5d91e2006-02-28 10:32:25 -03002274 av7110->recover = dvb_s_recover;
2275 }
Oliver Endrisseb3daf32006-01-09 15:25:05 -02002276 }
Johannes Stezenbach3dfaebd2005-05-16 21:54:19 -07002277 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002278 }
2279 }
2280
2281 if (!av7110->fe) {
2282 /* FIXME: propagate the failure code from the lower layers */
2283 ret = -ENOMEM;
Bjorn Helgaas29e66a62008-09-04 17:24:51 -03002284 printk("dvb-ttpci: A frontend driver was not found for device [%04x:%04x] subsystem [%04x:%04x]\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002285 av7110->dev->pci->vendor,
2286 av7110->dev->pci->device,
2287 av7110->dev->pci->subsystem_vendor,
2288 av7110->dev->pci->subsystem_device);
2289 } else {
Patrick Boettcherdea74862006-05-14 05:01:31 -03002290 FE_FUNC_OVERRIDE(av7110->fe->ops.init, av7110->fe_init, av7110_fe_init);
2291 FE_FUNC_OVERRIDE(av7110->fe->ops.read_status, av7110->fe_read_status, av7110_fe_read_status);
2292 FE_FUNC_OVERRIDE(av7110->fe->ops.diseqc_reset_overload, av7110->fe_diseqc_reset_overload, av7110_fe_diseqc_reset_overload);
2293 FE_FUNC_OVERRIDE(av7110->fe->ops.diseqc_send_master_cmd, av7110->fe_diseqc_send_master_cmd, av7110_fe_diseqc_send_master_cmd);
2294 FE_FUNC_OVERRIDE(av7110->fe->ops.diseqc_send_burst, av7110->fe_diseqc_send_burst, av7110_fe_diseqc_send_burst);
2295 FE_FUNC_OVERRIDE(av7110->fe->ops.set_tone, av7110->fe_set_tone, av7110_fe_set_tone);
Yoann Padioleau8f40a9f2007-07-16 16:54:49 -03002296 FE_FUNC_OVERRIDE(av7110->fe->ops.set_voltage, av7110->fe_set_voltage, av7110_fe_set_voltage);
Patrick Boettcherdea74862006-05-14 05:01:31 -03002297 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 -03002298 FE_FUNC_OVERRIDE(av7110->fe->ops.set_frontend, av7110->fe_set_frontend, av7110_fe_set_frontend);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002299
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07002300 ret = dvb_register_frontend(&av7110->dvb_adapter, av7110->fe);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002301 if (ret < 0) {
2302 printk("av7110: Frontend registration failed!\n");
Andrew de Quinceyf52a8382006-08-08 09:10:09 -03002303 dvb_frontend_detach(av7110->fe);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002304 av7110->fe = NULL;
2305 }
2306 }
2307 return ret;
2308}
2309
2310/* Budgetpatch note:
2311 * Original hardware design by Roberto Deza:
2312 * There is a DVB_Wiki at
Justin P. Mattock631dd1a2010-10-18 11:03:14 +02002313 * http://www.linuxtv.org/
Linus Torvalds1da177e2005-04-16 15:20:36 -07002314 *
2315 * New software triggering design by Emard that works on
2316 * original Roberto Deza's hardware:
2317 *
2318 * rps1 code for budgetpatch will copy internal HS event to GPIO3 pin.
2319 * GPIO3 is in budget-patch hardware connectd to port B VSYNC
2320 * HS is an internal event of 7146, accessible with RPS
2321 * and temporarily raised high every n lines
2322 * (n in defined in the RPS_THRESH1 counter threshold)
2323 * I think HS is raised high on the beginning of the n-th line
2324 * and remains high until this n-th line that triggered
2325 * it is completely received. When the receiption of n-th line
2326 * ends, HS is lowered.
2327 *
2328 * To transmit data over DMA, 7146 needs changing state at
2329 * port B VSYNC pin. Any changing of port B VSYNC will
2330 * cause some DMA data transfer, with more or less packets loss.
2331 * It depends on the phase and frequency of VSYNC and
2332 * the way of 7146 is instructed to trigger on port B (defined
2333 * in DD1_INIT register, 3rd nibble from the right valid
2334 * numbers are 0-7, see datasheet)
2335 *
2336 * The correct triggering can minimize packet loss,
2337 * dvbtraffic should give this stable bandwidths:
2338 * 22k transponder = 33814 kbit/s
2339 * 27.5k transponder = 38045 kbit/s
2340 * by experiment it is found that the best results
2341 * (stable bandwidths and almost no packet loss)
2342 * are obtained using DD1_INIT triggering number 2
2343 * (Va at rising edge of VS Fa = HS x VS-failing forced toggle)
2344 * and a VSYNC phase that occurs in the middle of DMA transfer
2345 * (about byte 188*512=96256 in the DMA window).
2346 *
2347 * Phase of HS is still not clear to me how to control,
2348 * It just happens to be so. It can be seen if one enables
2349 * RPS_IRQ and print Event Counter 1 in vpeirq(). Every
2350 * time RPS_INTERRUPT is called, the Event Counter 1 will
2351 * increment. That's how the 7146 is programmed to do event
2352 * counting in this budget-patch.c
2353 * I *think* HPS setting has something to do with the phase
Lucas De Marchi25985ed2011-03-30 22:57:33 -03002354 * of HS but I can't be 100% sure in that.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002355 *
2356 * hardware debug note: a working budget card (including budget patch)
2357 * with vpeirq() interrupt setup in mode "0x90" (every 64K) will
2358 * generate 3 interrupts per 25-Hz DMA frame of 2*188*512 bytes
2359 * and that means 3*25=75 Hz of interrupt freqency, as seen by
2360 * watch cat /proc/interrupts
2361 *
2362 * If this frequency is 3x lower (and data received in the DMA
2363 * buffer don't start with 0x47, but in the middle of packets,
2364 * whose lengths appear to be like 188 292 188 104 etc.
2365 * this means VSYNC line is not connected in the hardware.
2366 * (check soldering pcb and pins)
2367 * The same behaviour of missing VSYNC can be duplicated on budget
2368 * cards, by seting DD1_INIT trigger mode 7 in 3rd nibble.
2369 */
Greg Kroah-Hartman4c62e972012-12-21 13:17:53 -08002370static int av7110_attach(struct saa7146_dev* dev,
2371 struct saa7146_pci_extension_data *pci_ext)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002372{
2373 const int length = TS_WIDTH * TS_HEIGHT;
2374 struct pci_dev *pdev = dev->pci;
2375 struct av7110 *av7110;
Herbert Poetzl8eec1422007-02-08 14:32:43 -03002376 struct task_struct *thread;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002377 int ret, count = 0;
2378
2379 dprintk(4, "dev: %p\n", dev);
2380
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -08002381 /* Set RPS_IRQ to 1 to track rps1 activity.
2382 * Enabling this won't send any interrupt to PC CPU.
2383 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002384#define RPS_IRQ 0
2385
2386 if (budgetpatch == 1) {
2387 budgetpatch = 0;
2388 /* autodetect the presence of budget patch
2389 * this only works if saa7146 has been recently
2390 * reset with with MASK_31 to MC1
2391 *
2392 * will wait for VBI_B event (vertical blank at port B)
2393 * and will reset GPIO3 after VBI_B is detected.
2394 * (GPIO3 should be raised high by CPU to
2395 * test if GPIO3 will generate vertical blank signal
2396 * in budget patch GPIO3 is connected to VSYNC_B
2397 */
2398
2399 /* RESET SAA7146 */
2400 saa7146_write(dev, MC1, MASK_31);
2401 /* autodetection success seems to be time-dependend after reset */
2402
2403 /* Fix VSYNC level */
2404 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
2405 /* set vsync_b triggering */
2406 saa7146_write(dev, DD1_STREAM_B, 0);
2407 /* port B VSYNC at rising edge */
2408 saa7146_write(dev, DD1_INIT, 0x00000200);
2409 saa7146_write(dev, BRS_CTRL, 0x00000000); // VBI
2410 saa7146_write(dev, MC2,
2411 1 * (MASK_08 | MASK_24) | // BRS control
2412 0 * (MASK_09 | MASK_25) | // a
2413 1 * (MASK_10 | MASK_26) | // b
2414 0 * (MASK_06 | MASK_22) | // HPS_CTRL1
2415 0 * (MASK_05 | MASK_21) | // HPS_CTRL2
2416 0 * (MASK_01 | MASK_15) // DEBI
2417 );
2418
2419 /* start writing RPS1 code from beginning */
2420 count = 0;
2421 /* Disable RPS1 */
2422 saa7146_write(dev, MC1, MASK_29);
2423 /* RPS1 timeout disable */
2424 saa7146_write(dev, RPS_TOV1, 0);
Al Viro153755a2008-06-22 14:19:39 -03002425 WRITE_RPS1(CMD_PAUSE | EVT_VBI_B);
2426 WRITE_RPS1(CMD_WR_REG_MASK | (GPIO_CTRL>>2));
2427 WRITE_RPS1(GPIO3_MSK);
2428 WRITE_RPS1(SAA7146_GPIO_OUTLO<<24);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002429#if RPS_IRQ
2430 /* issue RPS1 interrupt to increment counter */
Al Viro153755a2008-06-22 14:19:39 -03002431 WRITE_RPS1(CMD_INTERRUPT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002432#endif
Al Viro153755a2008-06-22 14:19:39 -03002433 WRITE_RPS1(CMD_STOP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002434 /* Jump to begin of RPS program as safety measure (p37) */
Al Viro153755a2008-06-22 14:19:39 -03002435 WRITE_RPS1(CMD_JUMP);
2436 WRITE_RPS1(dev->d_rps1.dma_handle);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002437
2438#if RPS_IRQ
2439 /* set event counter 1 source as RPS1 interrupt (0x03) (rE4 p53)
2440 * use 0x03 to track RPS1 interrupts - increase by 1 every gpio3 is toggled
2441 * use 0x15 to track VPE interrupts - increase by 1 every vpeirq() is called
2442 */
2443 saa7146_write(dev, EC1SSR, (0x03<<2) | 3 );
André Goddard Rosaaf901ca2009-11-14 13:09:05 -02002444 /* set event counter 1 threshold to maximum allowed value (rEC p55) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002445 saa7146_write(dev, ECT1R, 0x3fff );
2446#endif
2447 /* Set RPS1 Address register to point to RPS code (r108 p42) */
2448 saa7146_write(dev, RPS_ADDR1, dev->d_rps1.dma_handle);
2449 /* Enable RPS1, (rFC p33) */
2450 saa7146_write(dev, MC1, (MASK_13 | MASK_29 ));
2451
2452 mdelay(10);
2453 /* now send VSYNC_B to rps1 by rising GPIO3 */
2454 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI);
2455 mdelay(10);
2456 /* if rps1 responded by lowering the GPIO3,
2457 * then we have budgetpatch hardware
2458 */
2459 if ((saa7146_read(dev, GPIO_CTRL) & 0x10000000) == 0) {
2460 budgetpatch = 1;
2461 printk("dvb-ttpci: BUDGET-PATCH DETECTED.\n");
2462 }
2463 /* Disable RPS1 */
2464 saa7146_write(dev, MC1, ( MASK_29 ));
2465#if RPS_IRQ
2466 printk("dvb-ttpci: Event Counter 1 0x%04x\n", saa7146_read(dev, EC1R) & 0x3fff );
2467#endif
2468 }
2469
2470 /* prepare the av7110 device struct */
Panagiotis Issaris74081872006-01-11 19:40:56 -02002471 av7110 = kzalloc(sizeof(struct av7110), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002472 if (!av7110) {
2473 dprintk(1, "out of memory\n");
2474 return -ENOMEM;
2475 }
2476
Linus Torvalds1da177e2005-04-16 15:20:36 -07002477 av7110->card_name = (char*) pci_ext->ext_priv;
2478 av7110->dev = dev;
2479 dev->ext_priv = av7110;
2480
2481 ret = get_firmware(av7110);
2482 if (ret < 0)
2483 goto err_kfree_0;
2484
2485 ret = dvb_register_adapter(&av7110->dvb_adapter, av7110->card_name,
Janne Grunau78e92002008-04-09 19:13:13 -03002486 THIS_MODULE, &dev->pci->dev, adapter_nr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002487 if (ret < 0)
2488 goto err_put_firmware_1;
2489
2490 /* the Siemens DVB needs this if you want to have the i2c chips
2491 get recognized before the main driver is fully loaded */
2492 saa7146_write(dev, GPIO_CTRL, 0x500000);
2493
Linus Torvalds1da177e2005-04-16 15:20:36 -07002494 strlcpy(av7110->i2c_adap.name, pci_ext->ext_priv, sizeof(av7110->i2c_adap.name));
2495
2496 saa7146_i2c_adapter_prepare(dev, &av7110->i2c_adap, SAA7146_I2C_BUS_BIT_RATE_120); /* 275 kHz */
2497
2498 ret = i2c_add_adapter(&av7110->i2c_adap);
2499 if (ret < 0)
2500 goto err_dvb_unregister_adapter_2;
2501
2502 ttpci_eeprom_parse_mac(&av7110->i2c_adap,
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07002503 av7110->dvb_adapter.proposed_mac);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002504 ret = -ENOMEM;
2505
Oliver Endriss9e615ea2008-09-03 19:15:27 -03002506 /* full-ts mod? */
2507 if (full_ts)
2508 av7110->full_ts = true;
2509
2510 /* check for full-ts flag in eeprom */
2511 if (i2c_readreg(av7110, 0xaa, 0) == 0x4f && i2c_readreg(av7110, 0xaa, 1) == 0x45) {
2512 u8 flags = i2c_readreg(av7110, 0xaa, 2);
2513 if (flags != 0xff && (flags & 0x01))
2514 av7110->full_ts = true;
2515 }
2516
2517 if (av7110->full_ts) {
2518 printk(KERN_INFO "dvb-ttpci: full-ts mode enabled for saa7146 port B\n");
2519 spin_lock_init(&av7110->feedlock1);
2520 av7110->grabbing = saa7146_vmalloc_build_pgtable(pdev, length,
2521 &av7110->pt);
2522 if (!av7110->grabbing)
2523 goto err_i2c_del_3;
2524
2525 saa7146_write(dev, DD1_STREAM_B, 0x00000000);
2526 saa7146_write(dev, MC2, (MASK_10 | MASK_26));
2527
2528 saa7146_write(dev, DD1_INIT, 0x00000600);
2529 saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
2530
2531 saa7146_write(dev, BRS_CTRL, 0x60000000);
2532 saa7146_write(dev, MC2, MASK_08 | MASK_24);
2533
2534 /* dma3 */
2535 saa7146_write(dev, PCI_BT_V1, 0x001c0000 | (saa7146_read(dev, PCI_BT_V1) & ~0x001f0000));
2536 saa7146_write(dev, BASE_ODD3, 0);
2537 saa7146_write(dev, BASE_EVEN3, 0);
2538 saa7146_write(dev, PROT_ADDR3, TS_WIDTH * TS_HEIGHT);
2539 saa7146_write(dev, PITCH3, TS_WIDTH);
2540 saa7146_write(dev, BASE_PAGE3, av7110->pt.dma | ME1 | 0x90);
2541 saa7146_write(dev, NUM_LINE_BYTE3, (TS_HEIGHT << 16) | TS_WIDTH);
2542 saa7146_write(dev, MC2, MASK_04 | MASK_20);
2543
2544 tasklet_init(&av7110->vpe_tasklet, vpeirq, (unsigned long) av7110);
2545
2546 } else if (budgetpatch) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002547 spin_lock_init(&av7110->feedlock1);
2548 av7110->grabbing = saa7146_vmalloc_build_pgtable(pdev, length,
2549 &av7110->pt);
2550 if (!av7110->grabbing)
2551 goto err_i2c_del_3;
2552
2553 saa7146_write(dev, PCI_BT_V1, 0x1c1f101f);
2554 saa7146_write(dev, BCS_CTRL, 0x80400040);
2555 /* set dd1 stream a & b */
2556 saa7146_write(dev, DD1_STREAM_B, 0x00000000);
2557 saa7146_write(dev, DD1_INIT, 0x03000200);
2558 saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
2559 saa7146_write(dev, BRS_CTRL, 0x60000000);
2560 saa7146_write(dev, BASE_ODD3, 0);
2561 saa7146_write(dev, BASE_EVEN3, 0);
2562 saa7146_write(dev, PROT_ADDR3, TS_WIDTH * TS_HEIGHT);
2563 saa7146_write(dev, BASE_PAGE3, av7110->pt.dma | ME1 | 0x90);
2564
2565 saa7146_write(dev, PITCH3, TS_WIDTH);
2566 saa7146_write(dev, NUM_LINE_BYTE3, (TS_HEIGHT << 16) | TS_WIDTH);
2567
2568 /* upload all */
2569 saa7146_write(dev, MC2, 0x077c077c);
2570 saa7146_write(dev, GPIO_CTRL, 0x000000);
2571#if RPS_IRQ
2572 /* set event counter 1 source as RPS1 interrupt (0x03) (rE4 p53)
2573 * use 0x03 to track RPS1 interrupts - increase by 1 every gpio3 is toggled
2574 * use 0x15 to track VPE interrupts - increase by 1 every vpeirq() is called
2575 */
2576 saa7146_write(dev, EC1SSR, (0x03<<2) | 3 );
André Goddard Rosaaf901ca2009-11-14 13:09:05 -02002577 /* set event counter 1 threshold to maximum allowed value (rEC p55) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002578 saa7146_write(dev, ECT1R, 0x3fff );
2579#endif
2580 /* Setup BUDGETPATCH MAIN RPS1 "program" (p35) */
2581 count = 0;
2582
2583 /* Wait Source Line Counter Threshold (p36) */
Al Viro153755a2008-06-22 14:19:39 -03002584 WRITE_RPS1(CMD_PAUSE | EVT_HS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002585 /* Set GPIO3=1 (p42) */
Al Viro153755a2008-06-22 14:19:39 -03002586 WRITE_RPS1(CMD_WR_REG_MASK | (GPIO_CTRL>>2));
2587 WRITE_RPS1(GPIO3_MSK);
2588 WRITE_RPS1(SAA7146_GPIO_OUTHI<<24);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002589#if RPS_IRQ
2590 /* issue RPS1 interrupt */
Al Viro153755a2008-06-22 14:19:39 -03002591 WRITE_RPS1(CMD_INTERRUPT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002592#endif
2593 /* Wait reset Source Line Counter Threshold (p36) */
Al Viro153755a2008-06-22 14:19:39 -03002594 WRITE_RPS1(CMD_PAUSE | RPS_INV | EVT_HS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002595 /* Set GPIO3=0 (p42) */
Al Viro153755a2008-06-22 14:19:39 -03002596 WRITE_RPS1(CMD_WR_REG_MASK | (GPIO_CTRL>>2));
2597 WRITE_RPS1(GPIO3_MSK);
2598 WRITE_RPS1(SAA7146_GPIO_OUTLO<<24);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002599#if RPS_IRQ
2600 /* issue RPS1 interrupt */
Al Viro153755a2008-06-22 14:19:39 -03002601 WRITE_RPS1(CMD_INTERRUPT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002602#endif
2603 /* Jump to begin of RPS program (p37) */
Al Viro153755a2008-06-22 14:19:39 -03002604 WRITE_RPS1(CMD_JUMP);
2605 WRITE_RPS1(dev->d_rps1.dma_handle);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002606
2607 /* Fix VSYNC level */
2608 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
2609 /* Set RPS1 Address register to point to RPS code (r108 p42) */
2610 saa7146_write(dev, RPS_ADDR1, dev->d_rps1.dma_handle);
2611 /* Set Source Line Counter Threshold, using BRS (rCC p43)
2612 * It generates HS event every TS_HEIGHT lines
2613 * this is related to TS_WIDTH set in register
2614 * NUM_LINE_BYTE3. If NUM_LINE_BYTE low 16 bits
2615 * are set to TS_WIDTH bytes (TS_WIDTH=2*188),
2616 * then RPS_THRESH1 should be set to trigger
2617 * every TS_HEIGHT (512) lines.
2618 */
2619 saa7146_write(dev, RPS_THRESH1, (TS_HEIGHT*1) | MASK_12 );
2620
2621 /* Enable RPS1 (rFC p33) */
2622 saa7146_write(dev, MC1, (MASK_13 | MASK_29));
2623
2624 /* end of budgetpatch register initialization */
2625 tasklet_init (&av7110->vpe_tasklet, vpeirq, (unsigned long) av7110);
2626 } else {
2627 saa7146_write(dev, PCI_BT_V1, 0x1c00101f);
2628 saa7146_write(dev, BCS_CTRL, 0x80400040);
2629
2630 /* set dd1 stream a & b */
2631 saa7146_write(dev, DD1_STREAM_B, 0x00000000);
2632 saa7146_write(dev, DD1_INIT, 0x03000000);
2633 saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
2634
2635 /* upload all */
2636 saa7146_write(dev, MC2, 0x077c077c);
2637 saa7146_write(dev, GPIO_CTRL, 0x000000);
2638 }
2639
2640 tasklet_init (&av7110->debi_tasklet, debiirq, (unsigned long) av7110);
2641 tasklet_init (&av7110->gpio_tasklet, gpioirq, (unsigned long) av7110);
2642
Ingo Molnar3593cab2006-02-07 06:49:14 -02002643 mutex_init(&av7110->pid_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002644
2645 /* locks for data transfers from/to AV7110 */
2646 spin_lock_init(&av7110->debilock);
Ingo Molnar3593cab2006-02-07 06:49:14 -02002647 mutex_init(&av7110->dcomlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002648 av7110->debitype = -1;
2649
2650 /* default OSD window */
2651 av7110->osdwin = 1;
Ingo Molnar3593cab2006-02-07 06:49:14 -02002652 mutex_init(&av7110->osd_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002653
C.Y.M2f03ee82006-03-30 04:31:48 -03002654 /* TV standard */
Marco Schluessler58a44042007-10-31 01:20:42 -03002655 av7110->vidmode = tv_standard == 1 ? AV7110_VIDEO_MODE_NTSC
2656 : AV7110_VIDEO_MODE_PAL;
C.Y.M2f03ee82006-03-30 04:31:48 -03002657
Linus Torvalds1da177e2005-04-16 15:20:36 -07002658 /* ARM "watchdog" */
2659 init_waitqueue_head(&av7110->arm_wait);
2660 av7110->arm_thread = NULL;
2661
2662 /* allocate and init buffers */
2663 av7110->debi_virt = pci_alloc_consistent(pdev, 8192, &av7110->debi_bus);
2664 if (!av7110->debi_virt)
2665 goto err_saa71466_vfree_4;
2666
2667
2668 av7110->iobuf = vmalloc(AVOUTLEN+AOUTLEN+BMPLEN+4*IPACKS);
2669 if (!av7110->iobuf)
2670 goto err_pci_free_5;
2671
2672 ret = av7110_av_init(av7110);
2673 if (ret < 0)
2674 goto err_iobuf_vfree_6;
2675
2676 /* init BMP buffer */
2677 av7110->bmpbuf = av7110->iobuf+AVOUTLEN+AOUTLEN;
2678 init_waitqueue_head(&av7110->bmpq);
2679
2680 ret = av7110_ca_init(av7110);
2681 if (ret < 0)
2682 goto err_av7110_av_exit_7;
2683
2684 /* load firmware into AV7110 cards */
2685 ret = av7110_bootarm(av7110);
2686 if (ret < 0)
2687 goto err_av7110_ca_exit_8;
2688
2689 ret = av7110_firmversion(av7110);
2690 if (ret < 0)
2691 goto err_stop_arm_9;
2692
2693 if (FW_VERSION(av7110->arm_app)<0x2501)
2694 printk ("dvb-ttpci: Warning, firmware version 0x%04x is too old. "
2695 "System might be unstable!\n", FW_VERSION(av7110->arm_app));
2696
Herbert Poetzl8eec1422007-02-08 14:32:43 -03002697 thread = kthread_run(arm_thread, (void *) av7110, "arm_mon");
2698 if (IS_ERR(thread)) {
2699 ret = PTR_ERR(thread);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002700 goto err_stop_arm_9;
Herbert Poetzl8eec1422007-02-08 14:32:43 -03002701 }
2702 av7110->arm_thread = thread;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002703
2704 /* set initial volume in mixer struct */
2705 av7110->mixer.volume_left = volume;
2706 av7110->mixer.volume_right = volume;
2707
Linus Torvalds1da177e2005-04-16 15:20:36 -07002708 ret = av7110_register(av7110);
2709 if (ret < 0)
2710 goto err_arm_thread_stop_10;
2711
Oliver Endrissdefd574e2007-07-12 23:08:07 -03002712 init_av7110_av(av7110);
2713
Linus Torvalds1da177e2005-04-16 15:20:36 -07002714 /* special case DVB-C: these cards have an analog tuner
2715 plus need some special handling, so we have separate
2716 saa7146_ext_vv data for these... */
2717 ret = av7110_init_v4l(av7110);
2718 if (ret < 0)
2719 goto err_av7110_unregister_11;
2720
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07002721 av7110->dvb_adapter.priv = av7110;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002722 ret = frontend_init(av7110);
2723 if (ret < 0)
2724 goto err_av7110_exit_v4l_12;
2725
Nikolaus Schulz30ad64b2012-12-23 18:49:07 -03002726 mutex_init(&av7110->ioctl_mutex);
2727
Peter Senna Tschudinb168e812013-01-19 19:41:10 -03002728#if IS_ENABLED(CONFIG_INPUT_EVDEV)
Oliver Endriss03388ae2005-09-09 13:03:12 -07002729 av7110_ir_init(av7110);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002730#endif
2731 printk(KERN_INFO "dvb-ttpci: found av7110-%d.\n", av7110_num);
2732 av7110_num++;
2733out:
2734 return ret;
2735
2736err_av7110_exit_v4l_12:
2737 av7110_exit_v4l(av7110);
2738err_av7110_unregister_11:
2739 dvb_unregister(av7110);
2740err_arm_thread_stop_10:
2741 av7110_arm_sync(av7110);
2742err_stop_arm_9:
2743 /* Nothing to do. Rejoice. */
2744err_av7110_ca_exit_8:
2745 av7110_ca_exit(av7110);
2746err_av7110_av_exit_7:
2747 av7110_av_exit(av7110);
2748err_iobuf_vfree_6:
2749 vfree(av7110->iobuf);
2750err_pci_free_5:
2751 pci_free_consistent(pdev, 8192, av7110->debi_virt, av7110->debi_bus);
2752err_saa71466_vfree_4:
Jon Burgess87c30192007-05-03 12:23:44 -03002753 if (av7110->grabbing)
2754 saa7146_vfree_destroy_pgtable(pdev, av7110->grabbing, &av7110->pt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002755err_i2c_del_3:
2756 i2c_del_adapter(&av7110->i2c_adap);
2757err_dvb_unregister_adapter_2:
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07002758 dvb_unregister_adapter(&av7110->dvb_adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002759err_put_firmware_1:
2760 put_firmware(av7110);
2761err_kfree_0:
2762 kfree(av7110);
2763 goto out;
2764}
2765
Greg Kroah-Hartman4c62e972012-12-21 13:17:53 -08002766static int av7110_detach(struct saa7146_dev* saa)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002767{
2768 struct av7110 *av7110 = saa->ext_priv;
2769 dprintk(4, "%p\n", av7110);
2770
Peter Senna Tschudinb168e812013-01-19 19:41:10 -03002771#if IS_ENABLED(CONFIG_INPUT_EVDEV)
Oliver Endriss03388ae2005-09-09 13:03:12 -07002772 av7110_ir_exit(av7110);
2773#endif
Oliver Endriss9e615ea2008-09-03 19:15:27 -03002774 if (budgetpatch || av7110->full_ts) {
2775 if (budgetpatch) {
2776 /* Disable RPS1 */
2777 saa7146_write(saa, MC1, MASK_29);
2778 /* VSYNC LOW (inactive) */
2779 saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);
2780 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002781 saa7146_write(saa, MC1, MASK_20); /* DMA3 off */
2782 SAA7146_IER_DISABLE(saa, MASK_10);
2783 SAA7146_ISR_CLEAR(saa, MASK_10);
2784 msleep(50);
2785 tasklet_kill(&av7110->vpe_tasklet);
Jon Burgess87c30192007-05-03 12:23:44 -03002786 saa7146_vfree_destroy_pgtable(saa->pci, av7110->grabbing, &av7110->pt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002787 }
2788 av7110_exit_v4l(av7110);
2789
2790 av7110_arm_sync(av7110);
2791
2792 tasklet_kill(&av7110->debi_tasklet);
2793 tasklet_kill(&av7110->gpio_tasklet);
2794
2795 dvb_unregister(av7110);
2796
2797 SAA7146_IER_DISABLE(saa, MASK_19 | MASK_03);
2798 SAA7146_ISR_CLEAR(saa, MASK_19 | MASK_03);
2799
2800 av7110_ca_exit(av7110);
2801 av7110_av_exit(av7110);
2802
2803 vfree(av7110->iobuf);
2804 pci_free_consistent(saa->pci, 8192, av7110->debi_virt,
2805 av7110->debi_bus);
2806
2807 i2c_del_adapter(&av7110->i2c_adap);
2808
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07002809 dvb_unregister_adapter (&av7110->dvb_adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002810
2811 av7110_num--;
2812
2813 put_firmware(av7110);
2814
2815 kfree(av7110);
2816
2817 saa->ext_priv = NULL;
2818
2819 return 0;
2820}
2821
2822
2823static void av7110_irq(struct saa7146_dev* dev, u32 *isr)
2824{
2825 struct av7110 *av7110 = dev->ext_priv;
2826
2827 //print_time("av7110_irq");
2828
2829 /* Note: Don't try to handle the DEBI error irq (MASK_18), in
2830 * intel mode the timeout is asserted all the time...
2831 */
2832
2833 if (*isr & MASK_19) {
2834 //printk("av7110_irq: DEBI\n");
2835 /* Note 1: The DEBI irq is level triggered: We must enable it
2836 * only after we started a DMA xfer, and disable it here
2837 * immediately, or it will be signalled all the time while
2838 * DEBI is idle.
2839 * Note 2: You would think that an irq which is masked is
2840 * not signalled by the hardware. Not so for the SAA7146:
2841 * An irq is signalled as long as the corresponding bit
2842 * in the ISR is set, and disabling irqs just prevents the
2843 * hardware from setting the ISR bit. This means a) that we
2844 * must clear the ISR *after* disabling the irq (which is why
2845 * we must do it here even though saa7146_core did it already),
2846 * and b) that if we were to disable an edge triggered irq
2847 * (like the gpio irqs sadly are) temporarily we would likely
2848 * loose some. This sucks :-(
2849 */
2850 SAA7146_IER_DISABLE(av7110->dev, MASK_19);
2851 SAA7146_ISR_CLEAR(av7110->dev, MASK_19);
2852 tasklet_schedule(&av7110->debi_tasklet);
2853 }
2854
2855 if (*isr & MASK_03) {
2856 //printk("av7110_irq: GPIO\n");
2857 tasklet_schedule(&av7110->gpio_tasklet);
2858 }
2859
Oliver Endriss9e615ea2008-09-03 19:15:27 -03002860 if (*isr & MASK_10)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002861 tasklet_schedule(&av7110->vpe_tasklet);
2862}
2863
2864
Randy Dunlapda517162008-01-10 19:31:47 -03002865static struct saa7146_extension av7110_extension_driver;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002866
2867#define MAKE_AV7110_INFO(x_var,x_name) \
2868static struct saa7146_pci_extension_data x_var = { \
2869 .ext_priv = x_name, \
Randy Dunlapda517162008-01-10 19:31:47 -03002870 .ext = &av7110_extension_driver }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002871
Karl Herz6af4ee12005-09-09 13:03:13 -07002872MAKE_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 -07002873MAKE_AV7110_INFO(ttt_1_X, "Technotrend/Hauppauge WinTV DVB-T rev1.X");
2874MAKE_AV7110_INFO(ttc_1_X, "Technotrend/Hauppauge WinTV Nexus-CA rev1.X");
2875MAKE_AV7110_INFO(ttc_2_X, "Technotrend/Hauppauge WinTV DVB-C rev2.X");
2876MAKE_AV7110_INFO(tts_2_X, "Technotrend/Hauppauge WinTV Nexus-S rev2.X");
Johannes Stezenbach3dfaebd2005-05-16 21:54:19 -07002877MAKE_AV7110_INFO(tts_2_3, "Technotrend/Hauppauge WinTV Nexus-S rev2.3");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002878MAKE_AV7110_INFO(tts_1_3se, "Technotrend/Hauppauge WinTV DVB-S rev1.3 SE");
2879MAKE_AV7110_INFO(ttt, "Technotrend/Hauppauge DVB-T");
2880MAKE_AV7110_INFO(fsc, "Fujitsu Siemens DVB-C");
2881MAKE_AV7110_INFO(fss, "Fujitsu Siemens DVB-S rev1.6");
Oliver Endriss8bd63012006-02-07 06:49:11 -02002882MAKE_AV7110_INFO(gxs_1_3, "Galaxis DVB-S rev1.3");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002883
2884static struct pci_device_id pci_tbl[] = {
Karl Herz6af4ee12005-09-09 13:03:13 -07002885 MAKE_EXTENSION_PCI(fsc, 0x110a, 0x0000),
2886 MAKE_EXTENSION_PCI(tts_1_X_fsc, 0x13c2, 0x0000),
2887 MAKE_EXTENSION_PCI(ttt_1_X, 0x13c2, 0x0001),
2888 MAKE_EXTENSION_PCI(ttc_2_X, 0x13c2, 0x0002),
2889 MAKE_EXTENSION_PCI(tts_2_X, 0x13c2, 0x0003),
Oliver Endriss8bd63012006-02-07 06:49:11 -02002890 MAKE_EXTENSION_PCI(gxs_1_3, 0x13c2, 0x0004),
Karl Herz6af4ee12005-09-09 13:03:13 -07002891 MAKE_EXTENSION_PCI(fss, 0x13c2, 0x0006),
2892 MAKE_EXTENSION_PCI(ttt, 0x13c2, 0x0008),
2893 MAKE_EXTENSION_PCI(ttc_1_X, 0x13c2, 0x000a),
2894 MAKE_EXTENSION_PCI(tts_2_3, 0x13c2, 0x000e),
2895 MAKE_EXTENSION_PCI(tts_1_3se, 0x13c2, 0x1002),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002896
Linus Torvalds1da177e2005-04-16 15:20:36 -07002897/* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0005), UNDEFINED CARD */ // Technisat SkyStar1
2898/* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0009), UNDEFINED CARD */ // TT/Hauppauge WinTV Nexus-CA v????
2899
2900 {
2901 .vendor = 0,
2902 }
2903};
2904
2905MODULE_DEVICE_TABLE(pci, pci_tbl);
2906
2907
Randy Dunlapda517162008-01-10 19:31:47 -03002908static struct saa7146_extension av7110_extension_driver = {
Derek Kelly62929252010-10-16 16:33:53 -03002909 .name = "av7110",
Oliver Endriss00c4cc62006-11-01 13:09:51 -03002910 .flags = SAA7146_USE_I2C_IRQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002911
2912 .module = THIS_MODULE,
2913 .pci_tbl = &pci_tbl[0],
2914 .attach = av7110_attach,
Greg Kroah-Hartman4c62e972012-12-21 13:17:53 -08002915 .detach = av7110_detach,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002916
2917 .irq_mask = MASK_19 | MASK_03 | MASK_10,
2918 .irq_func = av7110_irq,
2919};
2920
2921
2922static int __init av7110_init(void)
2923{
2924 int retval;
Randy Dunlapda517162008-01-10 19:31:47 -03002925 retval = saa7146_register_extension(&av7110_extension_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002926 return retval;
2927}
2928
2929
2930static void __exit av7110_exit(void)
2931{
Randy Dunlapda517162008-01-10 19:31:47 -03002932 saa7146_unregister_extension(&av7110_extension_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002933}
2934
2935module_init(av7110_init);
2936module_exit(av7110_exit);
2937
2938MODULE_DESCRIPTION("driver for the SAA7146 based AV110 PCI DVB cards by "
2939 "Siemens, Technotrend, Hauppauge");
2940MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, others");
2941MODULE_LICENSE("GPL");