[go: nahoru, domu]

1/*
2 * budget-av.c: driver for the SAA7146 based Budget DVB cards
3 *              with analog video in
4 *
5 * Compiled from various sources by Michael Hunold <michael@mihu.de>
6 *
7 * CI interface support (c) 2004 Olivier Gournet <ogournet@anevia.com> &
8 *                               Andrew de Quincey <adq_dvb@lidskialf.net>
9 *
10 * Copyright (C) 2002 Ralph Metzler <rjkm@metzlerbros.de>
11 *
12 * Copyright (C) 1999-2002 Ralph  Metzler
13 *                       & Marcus Metzler for convergence integrated media GmbH
14 *
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
19 *
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24 * GNU General Public License for more details.
25 *
26 *
27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to the Free Software
29 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
30 * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
31 *
32 *
33 * the project's page is at http://www.linuxtv.org/
34 */
35
36#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
37
38#include "budget.h"
39#include "stv0299.h"
40#include "stb0899_drv.h"
41#include "stb0899_reg.h"
42#include "stb0899_cfg.h"
43#include "tda8261.h"
44#include "tda8261_cfg.h"
45#include "tda1002x.h"
46#include "tda1004x.h"
47#include "tua6100.h"
48#include "dvb-pll.h"
49#include <media/saa7146_vv.h>
50#include <linux/module.h>
51#include <linux/errno.h>
52#include <linux/slab.h>
53#include <linux/interrupt.h>
54#include <linux/input.h>
55#include <linux/spinlock.h>
56
57#include "dvb_ca_en50221.h"
58
59#define DEBICICAM		0x02420000
60
61#define SLOTSTATUS_NONE         1
62#define SLOTSTATUS_PRESENT      2
63#define SLOTSTATUS_RESET        4
64#define SLOTSTATUS_READY        8
65#define SLOTSTATUS_OCCUPIED     (SLOTSTATUS_PRESENT|SLOTSTATUS_RESET|SLOTSTATUS_READY)
66
67DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
68
69struct budget_av {
70	struct budget budget;
71	struct video_device *vd;
72	int cur_input;
73	int has_saa7113;
74	struct tasklet_struct ciintf_irq_tasklet;
75	int slot_status;
76	struct dvb_ca_en50221 ca;
77	u8 reinitialise_demod:1;
78};
79
80static int ciintf_slot_shutdown(struct dvb_ca_en50221 *ca, int slot);
81
82
83/* GPIO Connections:
84 * 0 - Vcc/Reset (Reset is controlled by capacitor). Resets the frontend *AS WELL*!
85 * 1 - CI memory select 0=>IO memory, 1=>Attribute Memory
86 * 2 - CI Card Enable (Active Low)
87 * 3 - CI Card Detect
88 */
89
90/****************************************************************************
91 * INITIALIZATION
92 ****************************************************************************/
93
94static u8 i2c_readreg(struct i2c_adapter *i2c, u8 id, u8 reg)
95{
96	u8 mm1[] = { 0x00 };
97	u8 mm2[] = { 0x00 };
98	struct i2c_msg msgs[2];
99
100	msgs[0].flags = 0;
101	msgs[1].flags = I2C_M_RD;
102	msgs[0].addr = msgs[1].addr = id / 2;
103	mm1[0] = reg;
104	msgs[0].len = 1;
105	msgs[1].len = 1;
106	msgs[0].buf = mm1;
107	msgs[1].buf = mm2;
108
109	i2c_transfer(i2c, msgs, 2);
110
111	return mm2[0];
112}
113
114static int i2c_readregs(struct i2c_adapter *i2c, u8 id, u8 reg, u8 * buf, u8 len)
115{
116	u8 mm1[] = { reg };
117	struct i2c_msg msgs[2] = {
118		{.addr = id / 2,.flags = 0,.buf = mm1,.len = 1},
119		{.addr = id / 2,.flags = I2C_M_RD,.buf = buf,.len = len}
120	};
121
122	if (i2c_transfer(i2c, msgs, 2) != 2)
123		return -EIO;
124
125	return 0;
126}
127
128static int i2c_writereg(struct i2c_adapter *i2c, u8 id, u8 reg, u8 val)
129{
130	u8 msg[2] = { reg, val };
131	struct i2c_msg msgs;
132
133	msgs.flags = 0;
134	msgs.addr = id / 2;
135	msgs.len = 2;
136	msgs.buf = msg;
137	return i2c_transfer(i2c, &msgs, 1);
138}
139
140static int ciintf_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address)
141{
142	struct budget_av *budget_av = (struct budget_av *) ca->data;
143	int result;
144
145	if (slot != 0)
146		return -EINVAL;
147
148	saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTHI);
149	udelay(1);
150
151	result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 0xfff, 1, 0, 1);
152	if (result == -ETIMEDOUT) {
153		ciintf_slot_shutdown(ca, slot);
154		pr_info("cam ejected 1\n");
155	}
156	return result;
157}
158
159static int ciintf_write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address, u8 value)
160{
161	struct budget_av *budget_av = (struct budget_av *) ca->data;
162	int result;
163
164	if (slot != 0)
165		return -EINVAL;
166
167	saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTHI);
168	udelay(1);
169
170	result = ttpci_budget_debiwrite(&budget_av->budget, DEBICICAM, address & 0xfff, 1, value, 0, 1);
171	if (result == -ETIMEDOUT) {
172		ciintf_slot_shutdown(ca, slot);
173		pr_info("cam ejected 2\n");
174	}
175	return result;
176}
177
178static int ciintf_read_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address)
179{
180	struct budget_av *budget_av = (struct budget_av *) ca->data;
181	int result;
182
183	if (slot != 0)
184		return -EINVAL;
185
186	saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO);
187	udelay(1);
188
189	result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 3, 1, 0, 0);
190	if (result == -ETIMEDOUT) {
191		ciintf_slot_shutdown(ca, slot);
192		pr_info("cam ejected 3\n");
193		return -ETIMEDOUT;
194	}
195	return result;
196}
197
198static int ciintf_write_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address, u8 value)
199{
200	struct budget_av *budget_av = (struct budget_av *) ca->data;
201	int result;
202
203	if (slot != 0)
204		return -EINVAL;
205
206	saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO);
207	udelay(1);
208
209	result = ttpci_budget_debiwrite(&budget_av->budget, DEBICICAM, address & 3, 1, value, 0, 0);
210	if (result == -ETIMEDOUT) {
211		ciintf_slot_shutdown(ca, slot);
212		pr_info("cam ejected 5\n");
213	}
214	return result;
215}
216
217static int ciintf_slot_reset(struct dvb_ca_en50221 *ca, int slot)
218{
219	struct budget_av *budget_av = (struct budget_av *) ca->data;
220	struct saa7146_dev *saa = budget_av->budget.dev;
221
222	if (slot != 0)
223		return -EINVAL;
224
225	dprintk(1, "ciintf_slot_reset\n");
226	budget_av->slot_status = SLOTSTATUS_RESET;
227
228	saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTHI); /* disable card */
229
230	saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTHI); /* Vcc off */
231	msleep(2);
232	saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO); /* Vcc on */
233	msleep(20); /* 20 ms Vcc settling time */
234
235	saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTLO); /* enable card */
236	ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);
237	msleep(20);
238
239	/* reinitialise the frontend if necessary */
240	if (budget_av->reinitialise_demod)
241		dvb_frontend_reinitialise(budget_av->budget.dvb_frontend);
242
243	return 0;
244}
245
246static int ciintf_slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
247{
248	struct budget_av *budget_av = (struct budget_av *) ca->data;
249	struct saa7146_dev *saa = budget_av->budget.dev;
250
251	if (slot != 0)
252		return -EINVAL;
253
254	dprintk(1, "ciintf_slot_shutdown\n");
255
256	ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);
257	budget_av->slot_status = SLOTSTATUS_NONE;
258
259	return 0;
260}
261
262static int ciintf_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
263{
264	struct budget_av *budget_av = (struct budget_av *) ca->data;
265	struct saa7146_dev *saa = budget_av->budget.dev;
266
267	if (slot != 0)
268		return -EINVAL;
269
270	dprintk(1, "ciintf_slot_ts_enable: %d\n", budget_av->slot_status);
271
272	ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTA);
273
274	return 0;
275}
276
277static int ciintf_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open)
278{
279	struct budget_av *budget_av = (struct budget_av *) ca->data;
280	struct saa7146_dev *saa = budget_av->budget.dev;
281	int result;
282
283	if (slot != 0)
284		return -EINVAL;
285
286	/* test the card detect line - needs to be done carefully
287	 * since it never goes high for some CAMs on this interface (e.g. topuptv) */
288	if (budget_av->slot_status == SLOTSTATUS_NONE) {
289		saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);
290		udelay(1);
291		if (saa7146_read(saa, PSR) & MASK_06) {
292			if (budget_av->slot_status == SLOTSTATUS_NONE) {
293				budget_av->slot_status = SLOTSTATUS_PRESENT;
294				pr_info("cam inserted A\n");
295			}
296		}
297		saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);
298	}
299
300	/* We also try and read from IO memory to work round the above detection bug. If
301	 * there is no CAM, we will get a timeout. Only done if there is no cam
302	 * present, since this test actually breaks some cams :(
303	 *
304	 * if the CI interface is not open, we also do the above test since we
305	 * don't care if the cam has problems - we'll be resetting it on open() anyway */
306	if ((budget_av->slot_status == SLOTSTATUS_NONE) || (!open)) {
307		saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO);
308		result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, 0, 1, 0, 1);
309		if ((result >= 0) && (budget_av->slot_status == SLOTSTATUS_NONE)) {
310			budget_av->slot_status = SLOTSTATUS_PRESENT;
311			pr_info("cam inserted B\n");
312		} else if (result < 0) {
313			if (budget_av->slot_status != SLOTSTATUS_NONE) {
314				ciintf_slot_shutdown(ca, slot);
315				pr_info("cam ejected 5\n");
316				return 0;
317			}
318		}
319	}
320
321	/* read from attribute memory in reset/ready state to know when the CAM is ready */
322	if (budget_av->slot_status == SLOTSTATUS_RESET) {
323		result = ciintf_read_attribute_mem(ca, slot, 0);
324		if (result == 0x1d) {
325			budget_av->slot_status = SLOTSTATUS_READY;
326		}
327	}
328
329	/* work out correct return code */
330	if (budget_av->slot_status != SLOTSTATUS_NONE) {
331		if (budget_av->slot_status & SLOTSTATUS_READY) {
332			return DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY;
333		}
334		return DVB_CA_EN50221_POLL_CAM_PRESENT;
335	}
336	return 0;
337}
338
339static int ciintf_init(struct budget_av *budget_av)
340{
341	struct saa7146_dev *saa = budget_av->budget.dev;
342	int result;
343
344	memset(&budget_av->ca, 0, sizeof(struct dvb_ca_en50221));
345
346	saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO);
347	saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTLO);
348	saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTLO);
349	saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);
350
351	/* Enable DEBI pins */
352	saa7146_write(saa, MC1, MASK_27 | MASK_11);
353
354	/* register CI interface */
355	budget_av->ca.owner = THIS_MODULE;
356	budget_av->ca.read_attribute_mem = ciintf_read_attribute_mem;
357	budget_av->ca.write_attribute_mem = ciintf_write_attribute_mem;
358	budget_av->ca.read_cam_control = ciintf_read_cam_control;
359	budget_av->ca.write_cam_control = ciintf_write_cam_control;
360	budget_av->ca.slot_reset = ciintf_slot_reset;
361	budget_av->ca.slot_shutdown = ciintf_slot_shutdown;
362	budget_av->ca.slot_ts_enable = ciintf_slot_ts_enable;
363	budget_av->ca.poll_slot_status = ciintf_poll_slot_status;
364	budget_av->ca.data = budget_av;
365	budget_av->budget.ci_present = 1;
366	budget_av->slot_status = SLOTSTATUS_NONE;
367
368	if ((result = dvb_ca_en50221_init(&budget_av->budget.dvb_adapter,
369					  &budget_av->ca, 0, 1)) != 0) {
370		pr_err("ci initialisation failed\n");
371		goto error;
372	}
373
374	pr_info("ci interface initialised\n");
375	return 0;
376
377error:
378	saa7146_write(saa, MC1, MASK_27);
379	return result;
380}
381
382static void ciintf_deinit(struct budget_av *budget_av)
383{
384	struct saa7146_dev *saa = budget_av->budget.dev;
385
386	saa7146_setgpio(saa, 0, SAA7146_GPIO_INPUT);
387	saa7146_setgpio(saa, 1, SAA7146_GPIO_INPUT);
388	saa7146_setgpio(saa, 2, SAA7146_GPIO_INPUT);
389	saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);
390
391	/* release the CA device */
392	dvb_ca_en50221_release(&budget_av->ca);
393
394	/* disable DEBI pins */
395	saa7146_write(saa, MC1, MASK_27);
396}
397
398
399static const u8 saa7113_tab[] = {
400	0x01, 0x08,
401	0x02, 0xc0,
402	0x03, 0x33,
403	0x04, 0x00,
404	0x05, 0x00,
405	0x06, 0xeb,
406	0x07, 0xe0,
407	0x08, 0x28,
408	0x09, 0x00,
409	0x0a, 0x80,
410	0x0b, 0x47,
411	0x0c, 0x40,
412	0x0d, 0x00,
413	0x0e, 0x01,
414	0x0f, 0x44,
415
416	0x10, 0x08,
417	0x11, 0x0c,
418	0x12, 0x7b,
419	0x13, 0x00,
420	0x15, 0x00, 0x16, 0x00, 0x17, 0x00,
421
422	0x57, 0xff,
423	0x40, 0x82, 0x58, 0x00, 0x59, 0x54, 0x5a, 0x07,
424	0x5b, 0x83, 0x5e, 0x00,
425	0xff
426};
427
428static int saa7113_init(struct budget_av *budget_av)
429{
430	struct budget *budget = &budget_av->budget;
431	struct saa7146_dev *saa = budget->dev;
432	const u8 *data = saa7113_tab;
433
434	saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTHI);
435	msleep(200);
436
437	if (i2c_writereg(&budget->i2c_adap, 0x4a, 0x01, 0x08) != 1) {
438		dprintk(1, "saa7113 not found on KNC card\n");
439		return -ENODEV;
440	}
441
442	dprintk(1, "saa7113 detected and initializing\n");
443
444	while (*data != 0xff) {
445		i2c_writereg(&budget->i2c_adap, 0x4a, *data, *(data + 1));
446		data += 2;
447	}
448
449	dprintk(1, "saa7113  status=%02x\n", i2c_readreg(&budget->i2c_adap, 0x4a, 0x1f));
450
451	return 0;
452}
453
454static int saa7113_setinput(struct budget_av *budget_av, int input)
455{
456	struct budget *budget = &budget_av->budget;
457
458	if (1 != budget_av->has_saa7113)
459		return -ENODEV;
460
461	if (input == 1) {
462		i2c_writereg(&budget->i2c_adap, 0x4a, 0x02, 0xc7);
463		i2c_writereg(&budget->i2c_adap, 0x4a, 0x09, 0x80);
464	} else if (input == 0) {
465		i2c_writereg(&budget->i2c_adap, 0x4a, 0x02, 0xc0);
466		i2c_writereg(&budget->i2c_adap, 0x4a, 0x09, 0x00);
467	} else
468		return -EINVAL;
469
470	budget_av->cur_input = input;
471	return 0;
472}
473
474
475static int philips_su1278_ty_ci_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ratio)
476{
477	u8 aclk = 0;
478	u8 bclk = 0;
479	u8 m1;
480
481	aclk = 0xb5;
482	if (srate < 2000000)
483		bclk = 0x86;
484	else if (srate < 5000000)
485		bclk = 0x89;
486	else if (srate < 15000000)
487		bclk = 0x8f;
488	else if (srate < 45000000)
489		bclk = 0x95;
490
491	m1 = 0x14;
492	if (srate < 4000000)
493		m1 = 0x10;
494
495	stv0299_writereg(fe, 0x13, aclk);
496	stv0299_writereg(fe, 0x14, bclk);
497	stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);
498	stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff);
499	stv0299_writereg(fe, 0x21, (ratio) & 0xf0);
500	stv0299_writereg(fe, 0x0f, 0x80 | m1);
501
502	return 0;
503}
504
505static int philips_su1278_ty_ci_tuner_set_params(struct dvb_frontend *fe)
506{
507	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
508	u32 div;
509	u8 buf[4];
510	struct budget *budget = (struct budget *) fe->dvb->priv;
511	struct i2c_msg msg = {.addr = 0x61,.flags = 0,.buf = buf,.len = sizeof(buf) };
512
513	if ((c->frequency < 950000) || (c->frequency > 2150000))
514		return -EINVAL;
515
516	div = (c->frequency + (125 - 1)) / 125;	/* round correctly */
517	buf[0] = (div >> 8) & 0x7f;
518	buf[1] = div & 0xff;
519	buf[2] = 0x80 | ((div & 0x18000) >> 10) | 4;
520	buf[3] = 0x20;
521
522	if (c->symbol_rate < 4000000)
523		buf[3] |= 1;
524
525	if (c->frequency < 1250000)
526		buf[3] |= 0;
527	else if (c->frequency < 1550000)
528		buf[3] |= 0x40;
529	else if (c->frequency < 2050000)
530		buf[3] |= 0x80;
531	else if (c->frequency < 2150000)
532		buf[3] |= 0xC0;
533
534	if (fe->ops.i2c_gate_ctrl)
535		fe->ops.i2c_gate_ctrl(fe, 1);
536	if (i2c_transfer(&budget->i2c_adap, &msg, 1) != 1)
537		return -EIO;
538	return 0;
539}
540
541static u8 typhoon_cinergy1200s_inittab[] = {
542	0x01, 0x15,
543	0x02, 0x30,
544	0x03, 0x00,
545	0x04, 0x7d,		/* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */
546	0x05, 0x35,		/* I2CT = 0, SCLT = 1, SDAT = 1 */
547	0x06, 0x40,		/* DAC not used, set to high impendance mode */
548	0x07, 0x00,		/* DAC LSB */
549	0x08, 0x40,		/* DiSEqC off */
550	0x09, 0x00,		/* FIFO */
551	0x0c, 0x51,		/* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */
552	0x0d, 0x82,		/* DC offset compensation = ON, beta_agc1 = 2 */
553	0x0e, 0x23,		/* alpha_tmg = 2, beta_tmg = 3 */
554	0x10, 0x3f,		// AGC2  0x3d
555	0x11, 0x84,
556	0x12, 0xb9,
557	0x15, 0xc9,		// lock detector threshold
558	0x16, 0x00,
559	0x17, 0x00,
560	0x18, 0x00,
561	0x19, 0x00,
562	0x1a, 0x00,
563	0x1f, 0x50,
564	0x20, 0x00,
565	0x21, 0x00,
566	0x22, 0x00,
567	0x23, 0x00,
568	0x28, 0x00,		// out imp: normal  out type: parallel FEC mode:0
569	0x29, 0x1e,		// 1/2 threshold
570	0x2a, 0x14,		// 2/3 threshold
571	0x2b, 0x0f,		// 3/4 threshold
572	0x2c, 0x09,		// 5/6 threshold
573	0x2d, 0x05,		// 7/8 threshold
574	0x2e, 0x01,
575	0x31, 0x1f,		// test all FECs
576	0x32, 0x19,		// viterbi and synchro search
577	0x33, 0xfc,		// rs control
578	0x34, 0x93,		// error control
579	0x0f, 0x92,
580	0xff, 0xff
581};
582
583static struct stv0299_config typhoon_config = {
584	.demod_address = 0x68,
585	.inittab = typhoon_cinergy1200s_inittab,
586	.mclk = 88000000UL,
587	.invert = 0,
588	.skip_reinit = 0,
589	.lock_output = STV0299_LOCKOUTPUT_1,
590	.volt13_op0_op1 = STV0299_VOLT13_OP0,
591	.min_delay_ms = 100,
592	.set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate,
593};
594
595
596static struct stv0299_config cinergy_1200s_config = {
597	.demod_address = 0x68,
598	.inittab = typhoon_cinergy1200s_inittab,
599	.mclk = 88000000UL,
600	.invert = 0,
601	.skip_reinit = 0,
602	.lock_output = STV0299_LOCKOUTPUT_0,
603	.volt13_op0_op1 = STV0299_VOLT13_OP0,
604	.min_delay_ms = 100,
605	.set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate,
606};
607
608static struct stv0299_config cinergy_1200s_1894_0010_config = {
609	.demod_address = 0x68,
610	.inittab = typhoon_cinergy1200s_inittab,
611	.mclk = 88000000UL,
612	.invert = 1,
613	.skip_reinit = 0,
614	.lock_output = STV0299_LOCKOUTPUT_1,
615	.volt13_op0_op1 = STV0299_VOLT13_OP0,
616	.min_delay_ms = 100,
617	.set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate,
618};
619
620static int philips_cu1216_tuner_set_params(struct dvb_frontend *fe)
621{
622	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
623	struct budget *budget = (struct budget *) fe->dvb->priv;
624	u8 buf[6];
625	struct i2c_msg msg = {.addr = 0x60,.flags = 0,.buf = buf,.len = sizeof(buf) };
626	int i;
627
628#define CU1216_IF 36125000
629#define TUNER_MUL 62500
630
631	u32 div = (c->frequency + CU1216_IF + TUNER_MUL / 2) / TUNER_MUL;
632
633	buf[0] = (div >> 8) & 0x7f;
634	buf[1] = div & 0xff;
635	buf[2] = 0xce;
636	buf[3] = (c->frequency < 150000000 ? 0x01 :
637		  c->frequency < 445000000 ? 0x02 : 0x04);
638	buf[4] = 0xde;
639	buf[5] = 0x20;
640
641	if (fe->ops.i2c_gate_ctrl)
642		fe->ops.i2c_gate_ctrl(fe, 1);
643	if (i2c_transfer(&budget->i2c_adap, &msg, 1) != 1)
644		return -EIO;
645
646	/* wait for the pll lock */
647	msg.flags = I2C_M_RD;
648	msg.len = 1;
649	for (i = 0; i < 20; i++) {
650		if (fe->ops.i2c_gate_ctrl)
651			fe->ops.i2c_gate_ctrl(fe, 1);
652		if (i2c_transfer(&budget->i2c_adap, &msg, 1) == 1 && (buf[0] & 0x40))
653			break;
654		msleep(10);
655	}
656
657	/* switch the charge pump to the lower current */
658	msg.flags = 0;
659	msg.len = 2;
660	msg.buf = &buf[2];
661	buf[2] &= ~0x40;
662	if (fe->ops.i2c_gate_ctrl)
663		fe->ops.i2c_gate_ctrl(fe, 1);
664	if (i2c_transfer(&budget->i2c_adap, &msg, 1) != 1)
665		return -EIO;
666
667	return 0;
668}
669
670static struct tda1002x_config philips_cu1216_config = {
671	.demod_address = 0x0c,
672	.invert = 1,
673};
674
675static struct tda1002x_config philips_cu1216_config_altaddress = {
676	.demod_address = 0x0d,
677	.invert = 0,
678};
679
680static struct tda10023_config philips_cu1216_tda10023_config = {
681	.demod_address = 0x0c,
682	.invert = 1,
683};
684
685static int philips_tu1216_tuner_init(struct dvb_frontend *fe)
686{
687	struct budget *budget = (struct budget *) fe->dvb->priv;
688	static u8 tu1216_init[] = { 0x0b, 0xf5, 0x85, 0xab };
689	struct i2c_msg tuner_msg = {.addr = 0x60,.flags = 0,.buf = tu1216_init,.len = sizeof(tu1216_init) };
690
691	// setup PLL configuration
692	if (fe->ops.i2c_gate_ctrl)
693		fe->ops.i2c_gate_ctrl(fe, 1);
694	if (i2c_transfer(&budget->i2c_adap, &tuner_msg, 1) != 1)
695		return -EIO;
696	msleep(1);
697
698	return 0;
699}
700
701static int philips_tu1216_tuner_set_params(struct dvb_frontend *fe)
702{
703	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
704	struct budget *budget = (struct budget *) fe->dvb->priv;
705	u8 tuner_buf[4];
706	struct i2c_msg tuner_msg = {.addr = 0x60,.flags = 0,.buf = tuner_buf,.len =
707			sizeof(tuner_buf) };
708	int tuner_frequency = 0;
709	u8 band, cp, filter;
710
711	// determine charge pump
712	tuner_frequency = c->frequency + 36166000;
713	if (tuner_frequency < 87000000)
714		return -EINVAL;
715	else if (tuner_frequency < 130000000)
716		cp = 3;
717	else if (tuner_frequency < 160000000)
718		cp = 5;
719	else if (tuner_frequency < 200000000)
720		cp = 6;
721	else if (tuner_frequency < 290000000)
722		cp = 3;
723	else if (tuner_frequency < 420000000)
724		cp = 5;
725	else if (tuner_frequency < 480000000)
726		cp = 6;
727	else if (tuner_frequency < 620000000)
728		cp = 3;
729	else if (tuner_frequency < 830000000)
730		cp = 5;
731	else if (tuner_frequency < 895000000)
732		cp = 7;
733	else
734		return -EINVAL;
735
736	// determine band
737	if (c->frequency < 49000000)
738		return -EINVAL;
739	else if (c->frequency < 161000000)
740		band = 1;
741	else if (c->frequency < 444000000)
742		band = 2;
743	else if (c->frequency < 861000000)
744		band = 4;
745	else
746		return -EINVAL;
747
748	// setup PLL filter
749	switch (c->bandwidth_hz) {
750	case 6000000:
751		filter = 0;
752		break;
753
754	case 7000000:
755		filter = 0;
756		break;
757
758	case 8000000:
759		filter = 1;
760		break;
761
762	default:
763		return -EINVAL;
764	}
765
766	// calculate divisor
767	// ((36166000+((1000000/6)/2)) + Finput)/(1000000/6)
768	tuner_frequency = (((c->frequency / 1000) * 6) + 217496) / 1000;
769
770	// setup tuner buffer
771	tuner_buf[0] = (tuner_frequency >> 8) & 0x7f;
772	tuner_buf[1] = tuner_frequency & 0xff;
773	tuner_buf[2] = 0xca;
774	tuner_buf[3] = (cp << 5) | (filter << 3) | band;
775
776	if (fe->ops.i2c_gate_ctrl)
777		fe->ops.i2c_gate_ctrl(fe, 1);
778	if (i2c_transfer(&budget->i2c_adap, &tuner_msg, 1) != 1)
779		return -EIO;
780
781	msleep(1);
782	return 0;
783}
784
785static int philips_tu1216_request_firmware(struct dvb_frontend *fe,
786					   const struct firmware **fw, char *name)
787{
788	struct budget *budget = (struct budget *) fe->dvb->priv;
789
790	return request_firmware(fw, name, &budget->dev->pci->dev);
791}
792
793static struct tda1004x_config philips_tu1216_config = {
794
795	.demod_address = 0x8,
796	.invert = 1,
797	.invert_oclk = 1,
798	.xtal_freq = TDA10046_XTAL_4M,
799	.agc_config = TDA10046_AGC_DEFAULT,
800	.if_freq = TDA10046_FREQ_3617,
801	.request_firmware = philips_tu1216_request_firmware,
802};
803
804static u8 philips_sd1878_inittab[] = {
805	0x01, 0x15,
806	0x02, 0x30,
807	0x03, 0x00,
808	0x04, 0x7d,
809	0x05, 0x35,
810	0x06, 0x40,
811	0x07, 0x00,
812	0x08, 0x43,
813	0x09, 0x02,
814	0x0C, 0x51,
815	0x0D, 0x82,
816	0x0E, 0x23,
817	0x10, 0x3f,
818	0x11, 0x84,
819	0x12, 0xb9,
820	0x15, 0xc9,
821	0x16, 0x19,
822	0x17, 0x8c,
823	0x18, 0x59,
824	0x19, 0xf8,
825	0x1a, 0xfe,
826	0x1c, 0x7f,
827	0x1d, 0x00,
828	0x1e, 0x00,
829	0x1f, 0x50,
830	0x20, 0x00,
831	0x21, 0x00,
832	0x22, 0x00,
833	0x23, 0x00,
834	0x28, 0x00,
835	0x29, 0x28,
836	0x2a, 0x14,
837	0x2b, 0x0f,
838	0x2c, 0x09,
839	0x2d, 0x09,
840	0x31, 0x1f,
841	0x32, 0x19,
842	0x33, 0xfc,
843	0x34, 0x93,
844	0xff, 0xff
845};
846
847static int philips_sd1878_ci_set_symbol_rate(struct dvb_frontend *fe,
848		u32 srate, u32 ratio)
849{
850	u8 aclk = 0;
851	u8 bclk = 0;
852	u8 m1;
853
854	aclk = 0xb5;
855	if (srate < 2000000)
856		bclk = 0x86;
857	else if (srate < 5000000)
858		bclk = 0x89;
859	else if (srate < 15000000)
860		bclk = 0x8f;
861	else if (srate < 45000000)
862		bclk = 0x95;
863
864	m1 = 0x14;
865	if (srate < 4000000)
866		m1 = 0x10;
867
868	stv0299_writereg(fe, 0x0e, 0x23);
869	stv0299_writereg(fe, 0x0f, 0x94);
870	stv0299_writereg(fe, 0x10, 0x39);
871	stv0299_writereg(fe, 0x13, aclk);
872	stv0299_writereg(fe, 0x14, bclk);
873	stv0299_writereg(fe, 0x15, 0xc9);
874	stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);
875	stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff);
876	stv0299_writereg(fe, 0x21, (ratio) & 0xf0);
877	stv0299_writereg(fe, 0x0f, 0x80 | m1);
878
879	return 0;
880}
881
882static struct stv0299_config philips_sd1878_config = {
883	.demod_address = 0x68,
884     .inittab = philips_sd1878_inittab,
885	.mclk = 88000000UL,
886	.invert = 0,
887	.skip_reinit = 0,
888	.lock_output = STV0299_LOCKOUTPUT_1,
889	.volt13_op0_op1 = STV0299_VOLT13_OP0,
890	.min_delay_ms = 100,
891	.set_symbol_rate = philips_sd1878_ci_set_symbol_rate,
892};
893
894/* KNC1 DVB-S (STB0899) Inittab	*/
895static const struct stb0899_s1_reg knc1_stb0899_s1_init_1[] = {
896
897	{ STB0899_DEV_ID		, 0x81 },
898	{ STB0899_DISCNTRL1		, 0x32 },
899	{ STB0899_DISCNTRL2		, 0x80 },
900	{ STB0899_DISRX_ST0		, 0x04 },
901	{ STB0899_DISRX_ST1		, 0x00 },
902	{ STB0899_DISPARITY		, 0x00 },
903	{ STB0899_DISSTATUS		, 0x20 },
904	{ STB0899_DISF22		, 0x8c },
905	{ STB0899_DISF22RX		, 0x9a },
906	{ STB0899_SYSREG		, 0x0b },
907	{ STB0899_ACRPRESC		, 0x11 },
908	{ STB0899_ACRDIV1		, 0x0a },
909	{ STB0899_ACRDIV2		, 0x05 },
910	{ STB0899_DACR1			, 0x00 },
911	{ STB0899_DACR2			, 0x00 },
912	{ STB0899_OUTCFG		, 0x00 },
913	{ STB0899_MODECFG		, 0x00 },
914	{ STB0899_IRQSTATUS_3		, 0x30 },
915	{ STB0899_IRQSTATUS_2		, 0x00 },
916	{ STB0899_IRQSTATUS_1		, 0x00 },
917	{ STB0899_IRQSTATUS_0		, 0x00 },
918	{ STB0899_IRQMSK_3		, 0xf3 },
919	{ STB0899_IRQMSK_2		, 0xfc },
920	{ STB0899_IRQMSK_1		, 0xff },
921	{ STB0899_IRQMSK_0		, 0xff },
922	{ STB0899_IRQCFG		, 0x00 },
923	{ STB0899_I2CCFG		, 0x88 },
924	{ STB0899_I2CRPT		, 0x58 }, /* Repeater=8, Stop=disabled */
925	{ STB0899_IOPVALUE5		, 0x00 },
926	{ STB0899_IOPVALUE4		, 0x20 },
927	{ STB0899_IOPVALUE3		, 0xc9 },
928	{ STB0899_IOPVALUE2		, 0x90 },
929	{ STB0899_IOPVALUE1		, 0x40 },
930	{ STB0899_IOPVALUE0		, 0x00 },
931	{ STB0899_GPIO00CFG		, 0x82 },
932	{ STB0899_GPIO01CFG		, 0x82 },
933	{ STB0899_GPIO02CFG		, 0x82 },
934	{ STB0899_GPIO03CFG		, 0x82 },
935	{ STB0899_GPIO04CFG		, 0x82 },
936	{ STB0899_GPIO05CFG		, 0x82 },
937	{ STB0899_GPIO06CFG		, 0x82 },
938	{ STB0899_GPIO07CFG		, 0x82 },
939	{ STB0899_GPIO08CFG		, 0x82 },
940	{ STB0899_GPIO09CFG		, 0x82 },
941	{ STB0899_GPIO10CFG		, 0x82 },
942	{ STB0899_GPIO11CFG		, 0x82 },
943	{ STB0899_GPIO12CFG		, 0x82 },
944	{ STB0899_GPIO13CFG		, 0x82 },
945	{ STB0899_GPIO14CFG		, 0x82 },
946	{ STB0899_GPIO15CFG		, 0x82 },
947	{ STB0899_GPIO16CFG		, 0x82 },
948	{ STB0899_GPIO17CFG		, 0x82 },
949	{ STB0899_GPIO18CFG		, 0x82 },
950	{ STB0899_GPIO19CFG		, 0x82 },
951	{ STB0899_GPIO20CFG		, 0x82 },
952	{ STB0899_SDATCFG		, 0xb8 },
953	{ STB0899_SCLTCFG		, 0xba },
954	{ STB0899_AGCRFCFG		, 0x08 }, /* 0x1c */
955	{ STB0899_GPIO22		, 0x82 }, /* AGCBB2CFG */
956	{ STB0899_GPIO21		, 0x91 }, /* AGCBB1CFG */
957	{ STB0899_DIRCLKCFG		, 0x82 },
958	{ STB0899_CLKOUT27CFG		, 0x7e },
959	{ STB0899_STDBYCFG		, 0x82 },
960	{ STB0899_CS0CFG		, 0x82 },
961	{ STB0899_CS1CFG		, 0x82 },
962	{ STB0899_DISEQCOCFG		, 0x20 },
963	{ STB0899_GPIO32CFG		, 0x82 },
964	{ STB0899_GPIO33CFG		, 0x82 },
965	{ STB0899_GPIO34CFG		, 0x82 },
966	{ STB0899_GPIO35CFG		, 0x82 },
967	{ STB0899_GPIO36CFG		, 0x82 },
968	{ STB0899_GPIO37CFG		, 0x82 },
969	{ STB0899_GPIO38CFG		, 0x82 },
970	{ STB0899_GPIO39CFG		, 0x82 },
971	{ STB0899_NCOARSE		, 0x15 }, /* 0x15 = 27 Mhz Clock, F/3 = 198MHz, F/6 = 99MHz */
972	{ STB0899_SYNTCTRL		, 0x02 }, /* 0x00 = CLK from CLKI, 0x02 = CLK from XTALI */
973	{ STB0899_FILTCTRL		, 0x00 },
974	{ STB0899_SYSCTRL		, 0x00 },
975	{ STB0899_STOPCLK1		, 0x20 },
976	{ STB0899_STOPCLK2		, 0x00 },
977	{ STB0899_INTBUFSTATUS		, 0x00 },
978	{ STB0899_INTBUFCTRL		, 0x0a },
979	{ 0xffff			, 0xff },
980};
981
982static const struct stb0899_s1_reg knc1_stb0899_s1_init_3[] = {
983	{ STB0899_DEMOD			, 0x00 },
984	{ STB0899_RCOMPC		, 0xc9 },
985	{ STB0899_AGC1CN		, 0x41 },
986	{ STB0899_AGC1REF		, 0x08 },
987	{ STB0899_RTC			, 0x7a },
988	{ STB0899_TMGCFG		, 0x4e },
989	{ STB0899_AGC2REF		, 0x33 },
990	{ STB0899_TLSR			, 0x84 },
991	{ STB0899_CFD			, 0xee },
992	{ STB0899_ACLC			, 0x87 },
993	{ STB0899_BCLC			, 0x94 },
994	{ STB0899_EQON			, 0x41 },
995	{ STB0899_LDT			, 0xdd },
996	{ STB0899_LDT2			, 0xc9 },
997	{ STB0899_EQUALREF		, 0xb4 },
998	{ STB0899_TMGRAMP		, 0x10 },
999	{ STB0899_TMGTHD		, 0x30 },
1000	{ STB0899_IDCCOMP		, 0xfb },
1001	{ STB0899_QDCCOMP		, 0x03 },
1002	{ STB0899_POWERI		, 0x3b },
1003	{ STB0899_POWERQ		, 0x3d },
1004	{ STB0899_RCOMP			, 0x81 },
1005	{ STB0899_AGCIQIN		, 0x80 },
1006	{ STB0899_AGC2I1		, 0x04 },
1007	{ STB0899_AGC2I2		, 0xf5 },
1008	{ STB0899_TLIR			, 0x25 },
1009	{ STB0899_RTF			, 0x80 },
1010	{ STB0899_DSTATUS		, 0x00 },
1011	{ STB0899_LDI			, 0xca },
1012	{ STB0899_CFRM			, 0xf1 },
1013	{ STB0899_CFRL			, 0xf3 },
1014	{ STB0899_NIRM			, 0x2a },
1015	{ STB0899_NIRL			, 0x05 },
1016	{ STB0899_ISYMB			, 0x17 },
1017	{ STB0899_QSYMB			, 0xfa },
1018	{ STB0899_SFRH			, 0x2f },
1019	{ STB0899_SFRM			, 0x68 },
1020	{ STB0899_SFRL			, 0x40 },
1021	{ STB0899_SFRUPH		, 0x2f },
1022	{ STB0899_SFRUPM		, 0x68 },
1023	{ STB0899_SFRUPL		, 0x40 },
1024	{ STB0899_EQUAI1		, 0xfd },
1025	{ STB0899_EQUAQ1		, 0x04 },
1026	{ STB0899_EQUAI2		, 0x0f },
1027	{ STB0899_EQUAQ2		, 0xff },
1028	{ STB0899_EQUAI3		, 0xdf },
1029	{ STB0899_EQUAQ3		, 0xfa },
1030	{ STB0899_EQUAI4		, 0x37 },
1031	{ STB0899_EQUAQ4		, 0x0d },
1032	{ STB0899_EQUAI5		, 0xbd },
1033	{ STB0899_EQUAQ5		, 0xf7 },
1034	{ STB0899_DSTATUS2		, 0x00 },
1035	{ STB0899_VSTATUS		, 0x00 },
1036	{ STB0899_VERROR		, 0xff },
1037	{ STB0899_IQSWAP		, 0x2a },
1038	{ STB0899_ECNT1M		, 0x00 },
1039	{ STB0899_ECNT1L		, 0x00 },
1040	{ STB0899_ECNT2M		, 0x00 },
1041	{ STB0899_ECNT2L		, 0x00 },
1042	{ STB0899_ECNT3M		, 0x00 },
1043	{ STB0899_ECNT3L		, 0x00 },
1044	{ STB0899_FECAUTO1		, 0x06 },
1045	{ STB0899_FECM			, 0x01 },
1046	{ STB0899_VTH12			, 0xf0 },
1047	{ STB0899_VTH23			, 0xa0 },
1048	{ STB0899_VTH34			, 0x78 },
1049	{ STB0899_VTH56			, 0x4e },
1050	{ STB0899_VTH67			, 0x48 },
1051	{ STB0899_VTH78			, 0x38 },
1052	{ STB0899_PRVIT			, 0xff },
1053	{ STB0899_VITSYNC		, 0x19 },
1054	{ STB0899_RSULC			, 0xb1 }, /* DVB = 0xb1, DSS = 0xa1 */
1055	{ STB0899_TSULC			, 0x42 },
1056	{ STB0899_RSLLC			, 0x40 },
1057	{ STB0899_TSLPL			, 0x12 },
1058	{ STB0899_TSCFGH		, 0x0c },
1059	{ STB0899_TSCFGM		, 0x00 },
1060	{ STB0899_TSCFGL		, 0x0c },
1061	{ STB0899_TSOUT			, 0x4d }, /* 0x0d for CAM */
1062	{ STB0899_RSSYNCDEL		, 0x00 },
1063	{ STB0899_TSINHDELH		, 0x02 },
1064	{ STB0899_TSINHDELM		, 0x00 },
1065	{ STB0899_TSINHDELL		, 0x00 },
1066	{ STB0899_TSLLSTKM		, 0x00 },
1067	{ STB0899_TSLLSTKL		, 0x00 },
1068	{ STB0899_TSULSTKM		, 0x00 },
1069	{ STB0899_TSULSTKL		, 0xab },
1070	{ STB0899_PCKLENUL		, 0x00 },
1071	{ STB0899_PCKLENLL		, 0xcc },
1072	{ STB0899_RSPCKLEN		, 0xcc },
1073	{ STB0899_TSSTATUS		, 0x80 },
1074	{ STB0899_ERRCTRL1		, 0xb6 },
1075	{ STB0899_ERRCTRL2		, 0x96 },
1076	{ STB0899_ERRCTRL3		, 0x89 },
1077	{ STB0899_DMONMSK1		, 0x27 },
1078	{ STB0899_DMONMSK0		, 0x03 },
1079	{ STB0899_DEMAPVIT		, 0x5c },
1080	{ STB0899_PLPARM		, 0x1f },
1081	{ STB0899_PDELCTRL		, 0x48 },
1082	{ STB0899_PDELCTRL2		, 0x00 },
1083	{ STB0899_BBHCTRL1		, 0x00 },
1084	{ STB0899_BBHCTRL2		, 0x00 },
1085	{ STB0899_HYSTTHRESH		, 0x77 },
1086	{ STB0899_MATCSTM		, 0x00 },
1087	{ STB0899_MATCSTL		, 0x00 },
1088	{ STB0899_UPLCSTM		, 0x00 },
1089	{ STB0899_UPLCSTL		, 0x00 },
1090	{ STB0899_DFLCSTM		, 0x00 },
1091	{ STB0899_DFLCSTL		, 0x00 },
1092	{ STB0899_SYNCCST		, 0x00 },
1093	{ STB0899_SYNCDCSTM		, 0x00 },
1094	{ STB0899_SYNCDCSTL		, 0x00 },
1095	{ STB0899_ISI_ENTRY		, 0x00 },
1096	{ STB0899_ISI_BIT_EN		, 0x00 },
1097	{ STB0899_MATSTRM		, 0x00 },
1098	{ STB0899_MATSTRL		, 0x00 },
1099	{ STB0899_UPLSTRM		, 0x00 },
1100	{ STB0899_UPLSTRL		, 0x00 },
1101	{ STB0899_DFLSTRM		, 0x00 },
1102	{ STB0899_DFLSTRL		, 0x00 },
1103	{ STB0899_SYNCSTR		, 0x00 },
1104	{ STB0899_SYNCDSTRM		, 0x00 },
1105	{ STB0899_SYNCDSTRL		, 0x00 },
1106	{ STB0899_CFGPDELSTATUS1	, 0x10 },
1107	{ STB0899_CFGPDELSTATUS2	, 0x00 },
1108	{ STB0899_BBFERRORM		, 0x00 },
1109	{ STB0899_BBFERRORL		, 0x00 },
1110	{ STB0899_UPKTERRORM		, 0x00 },
1111	{ STB0899_UPKTERRORL		, 0x00 },
1112	{ 0xffff			, 0xff },
1113};
1114
1115/* STB0899 demodulator config for the KNC1 and clones */
1116static struct stb0899_config knc1_dvbs2_config = {
1117	.init_dev		= knc1_stb0899_s1_init_1,
1118	.init_s2_demod		= stb0899_s2_init_2,
1119	.init_s1_demod		= knc1_stb0899_s1_init_3,
1120	.init_s2_fec		= stb0899_s2_init_4,
1121	.init_tst		= stb0899_s1_init_5,
1122
1123	.postproc		= NULL,
1124
1125	.demod_address		= 0x68,
1126//	.ts_output_mode		= STB0899_OUT_PARALLEL,	/* types = SERIAL/PARALLEL	*/
1127	.block_sync_mode	= STB0899_SYNC_FORCED,	/* DSS, SYNC_FORCED/UNSYNCED	*/
1128//	.ts_pfbit_toggle	= STB0899_MPEG_NORMAL,	/* DirecTV, MPEG toggling seq	*/
1129
1130	.xtal_freq		= 27000000,
1131	.inversion		= IQ_SWAP_OFF,
1132
1133	.lo_clk			= 76500000,
1134	.hi_clk			= 90000000,
1135
1136	.esno_ave		= STB0899_DVBS2_ESNO_AVE,
1137	.esno_quant		= STB0899_DVBS2_ESNO_QUANT,
1138	.avframes_coarse	= STB0899_DVBS2_AVFRAMES_COARSE,
1139	.avframes_fine		= STB0899_DVBS2_AVFRAMES_FINE,
1140	.miss_threshold		= STB0899_DVBS2_MISS_THRESHOLD,
1141	.uwp_threshold_acq	= STB0899_DVBS2_UWP_THRESHOLD_ACQ,
1142	.uwp_threshold_track	= STB0899_DVBS2_UWP_THRESHOLD_TRACK,
1143	.uwp_threshold_sof	= STB0899_DVBS2_UWP_THRESHOLD_SOF,
1144	.sof_search_timeout	= STB0899_DVBS2_SOF_SEARCH_TIMEOUT,
1145
1146	.btr_nco_bits		= STB0899_DVBS2_BTR_NCO_BITS,
1147	.btr_gain_shift_offset	= STB0899_DVBS2_BTR_GAIN_SHIFT_OFFSET,
1148	.crl_nco_bits		= STB0899_DVBS2_CRL_NCO_BITS,
1149	.ldpc_max_iter		= STB0899_DVBS2_LDPC_MAX_ITER,
1150
1151	.tuner_get_frequency	= tda8261_get_frequency,
1152	.tuner_set_frequency	= tda8261_set_frequency,
1153	.tuner_set_bandwidth	= NULL,
1154	.tuner_get_bandwidth	= tda8261_get_bandwidth,
1155	.tuner_set_rfsiggain	= NULL
1156};
1157
1158/*
1159 * SD1878/SHA tuner config
1160 * 1F, Single I/P, Horizontal mount, High Sensitivity
1161 */
1162static const struct tda8261_config sd1878c_config = {
1163//	.name		= "SD1878/SHA",
1164	.addr		= 0x60,
1165	.step_size	= TDA8261_STEP_1000 /* kHz */
1166};
1167
1168static u8 read_pwm(struct budget_av *budget_av)
1169{
1170	u8 b = 0xff;
1171	u8 pwm;
1172	struct i2c_msg msg[] = { {.addr = 0x50,.flags = 0,.buf = &b,.len = 1},
1173	{.addr = 0x50,.flags = I2C_M_RD,.buf = &pwm,.len = 1}
1174	};
1175
1176	if ((i2c_transfer(&budget_av->budget.i2c_adap, msg, 2) != 2)
1177	    || (pwm == 0xff))
1178		pwm = 0x48;
1179
1180	return pwm;
1181}
1182
1183#define SUBID_DVBS_KNC1			0x0010
1184#define SUBID_DVBS_KNC1_PLUS		0x0011
1185#define SUBID_DVBS_TYPHOON		0x4f56
1186#define SUBID_DVBS_CINERGY1200		0x1154
1187#define SUBID_DVBS_CYNERGY1200N 	0x1155
1188#define SUBID_DVBS_TV_STAR		0x0014
1189#define SUBID_DVBS_TV_STAR_PLUS_X4	0x0015
1190#define SUBID_DVBS_TV_STAR_CI		0x0016
1191#define SUBID_DVBS2_KNC1		0x0018
1192#define SUBID_DVBS2_KNC1_OEM		0x0019
1193#define SUBID_DVBS_EASYWATCH_1  	0x001a
1194#define SUBID_DVBS_EASYWATCH_2  	0x001b
1195#define SUBID_DVBS2_EASYWATCH		0x001d
1196#define SUBID_DVBS_EASYWATCH		0x001e
1197
1198#define SUBID_DVBC_EASYWATCH		0x002a
1199#define SUBID_DVBC_EASYWATCH_MK3	0x002c
1200#define SUBID_DVBC_KNC1			0x0020
1201#define SUBID_DVBC_KNC1_PLUS		0x0021
1202#define SUBID_DVBC_KNC1_MK3		0x0022
1203#define SUBID_DVBC_KNC1_TDA10024	0x0028
1204#define SUBID_DVBC_KNC1_PLUS_MK3	0x0023
1205#define SUBID_DVBC_CINERGY1200		0x1156
1206#define SUBID_DVBC_CINERGY1200_MK3	0x1176
1207
1208#define SUBID_DVBT_EASYWATCH		0x003a
1209#define SUBID_DVBT_KNC1_PLUS		0x0031
1210#define SUBID_DVBT_KNC1			0x0030
1211#define SUBID_DVBT_CINERGY1200		0x1157
1212
1213static void frontend_init(struct budget_av *budget_av)
1214{
1215	struct saa7146_dev * saa = budget_av->budget.dev;
1216	struct dvb_frontend * fe = NULL;
1217
1218	/* Enable / PowerON Frontend */
1219	saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO);
1220
1221	/* Wait for PowerON */
1222	msleep(100);
1223
1224	/* additional setup necessary for the PLUS cards */
1225	switch (saa->pci->subsystem_device) {
1226		case SUBID_DVBS_KNC1_PLUS:
1227		case SUBID_DVBC_KNC1_PLUS:
1228		case SUBID_DVBT_KNC1_PLUS:
1229		case SUBID_DVBC_EASYWATCH:
1230		case SUBID_DVBC_KNC1_PLUS_MK3:
1231		case SUBID_DVBS2_KNC1:
1232		case SUBID_DVBS2_KNC1_OEM:
1233		case SUBID_DVBS2_EASYWATCH:
1234			saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTHI);
1235			break;
1236	}
1237
1238	switch (saa->pci->subsystem_device) {
1239
1240	case SUBID_DVBS_KNC1:
1241		/*
1242		 * maybe that setting is needed for other dvb-s cards as well,
1243		 * but so far it has been only confirmed for this type
1244		 */
1245		budget_av->reinitialise_demod = 1;
1246		/* fall through */
1247	case SUBID_DVBS_KNC1_PLUS:
1248	case SUBID_DVBS_EASYWATCH_1:
1249		if (saa->pci->subsystem_vendor == 0x1894) {
1250			fe = dvb_attach(stv0299_attach, &cinergy_1200s_1894_0010_config,
1251					     &budget_av->budget.i2c_adap);
1252			if (fe) {
1253				dvb_attach(tua6100_attach, fe, 0x60, &budget_av->budget.i2c_adap);
1254			}
1255		} else {
1256			fe = dvb_attach(stv0299_attach, &typhoon_config,
1257					     &budget_av->budget.i2c_adap);
1258			if (fe) {
1259				fe->ops.tuner_ops.set_params = philips_su1278_ty_ci_tuner_set_params;
1260			}
1261		}
1262		break;
1263
1264	case SUBID_DVBS_TV_STAR:
1265	case SUBID_DVBS_TV_STAR_PLUS_X4:
1266	case SUBID_DVBS_TV_STAR_CI:
1267	case SUBID_DVBS_CYNERGY1200N:
1268	case SUBID_DVBS_EASYWATCH:
1269	case SUBID_DVBS_EASYWATCH_2:
1270		fe = dvb_attach(stv0299_attach, &philips_sd1878_config,
1271				&budget_av->budget.i2c_adap);
1272		if (fe) {
1273			dvb_attach(dvb_pll_attach, fe, 0x60,
1274				   &budget_av->budget.i2c_adap,
1275				   DVB_PLL_PHILIPS_SD1878_TDA8261);
1276		}
1277		break;
1278
1279	case SUBID_DVBS_TYPHOON:
1280		fe = dvb_attach(stv0299_attach, &typhoon_config,
1281				    &budget_av->budget.i2c_adap);
1282		if (fe) {
1283			fe->ops.tuner_ops.set_params = philips_su1278_ty_ci_tuner_set_params;
1284		}
1285		break;
1286	case SUBID_DVBS2_KNC1:
1287	case SUBID_DVBS2_KNC1_OEM:
1288	case SUBID_DVBS2_EASYWATCH:
1289		budget_av->reinitialise_demod = 1;
1290		if ((fe = dvb_attach(stb0899_attach, &knc1_dvbs2_config, &budget_av->budget.i2c_adap)))
1291			dvb_attach(tda8261_attach, fe, &sd1878c_config, &budget_av->budget.i2c_adap);
1292
1293		break;
1294	case SUBID_DVBS_CINERGY1200:
1295		fe = dvb_attach(stv0299_attach, &cinergy_1200s_config,
1296				    &budget_av->budget.i2c_adap);
1297		if (fe) {
1298			fe->ops.tuner_ops.set_params = philips_su1278_ty_ci_tuner_set_params;
1299		}
1300		break;
1301
1302	case SUBID_DVBC_KNC1:
1303	case SUBID_DVBC_KNC1_PLUS:
1304	case SUBID_DVBC_CINERGY1200:
1305	case SUBID_DVBC_EASYWATCH:
1306		budget_av->reinitialise_demod = 1;
1307		budget_av->budget.dev->i2c_bitrate = SAA7146_I2C_BUS_BIT_RATE_240;
1308		fe = dvb_attach(tda10021_attach, &philips_cu1216_config,
1309				     &budget_av->budget.i2c_adap,
1310				     read_pwm(budget_av));
1311		if (fe == NULL)
1312			fe = dvb_attach(tda10021_attach, &philips_cu1216_config_altaddress,
1313					     &budget_av->budget.i2c_adap,
1314					     read_pwm(budget_av));
1315		if (fe) {
1316			fe->ops.tuner_ops.set_params = philips_cu1216_tuner_set_params;
1317		}
1318		break;
1319
1320	case SUBID_DVBC_EASYWATCH_MK3:
1321	case SUBID_DVBC_CINERGY1200_MK3:
1322	case SUBID_DVBC_KNC1_MK3:
1323	case SUBID_DVBC_KNC1_TDA10024:
1324	case SUBID_DVBC_KNC1_PLUS_MK3:
1325		budget_av->reinitialise_demod = 1;
1326		budget_av->budget.dev->i2c_bitrate = SAA7146_I2C_BUS_BIT_RATE_240;
1327		fe = dvb_attach(tda10023_attach,
1328			&philips_cu1216_tda10023_config,
1329			&budget_av->budget.i2c_adap,
1330			read_pwm(budget_av));
1331		if (fe) {
1332			fe->ops.tuner_ops.set_params = philips_cu1216_tuner_set_params;
1333		}
1334		break;
1335
1336	case SUBID_DVBT_EASYWATCH:
1337	case SUBID_DVBT_KNC1:
1338	case SUBID_DVBT_KNC1_PLUS:
1339	case SUBID_DVBT_CINERGY1200:
1340		budget_av->reinitialise_demod = 1;
1341		fe = dvb_attach(tda10046_attach, &philips_tu1216_config,
1342				     &budget_av->budget.i2c_adap);
1343		if (fe) {
1344			fe->ops.tuner_ops.init = philips_tu1216_tuner_init;
1345			fe->ops.tuner_ops.set_params = philips_tu1216_tuner_set_params;
1346		}
1347		break;
1348	}
1349
1350	if (fe == NULL) {
1351		pr_err("A frontend driver was not found for device [%04x:%04x] subsystem [%04x:%04x]\n",
1352		       saa->pci->vendor,
1353		       saa->pci->device,
1354		       saa->pci->subsystem_vendor,
1355		       saa->pci->subsystem_device);
1356		return;
1357	}
1358
1359	budget_av->budget.dvb_frontend = fe;
1360
1361	if (dvb_register_frontend(&budget_av->budget.dvb_adapter,
1362				  budget_av->budget.dvb_frontend)) {
1363		pr_err("Frontend registration failed!\n");
1364		dvb_frontend_detach(budget_av->budget.dvb_frontend);
1365		budget_av->budget.dvb_frontend = NULL;
1366	}
1367}
1368
1369
1370static void budget_av_irq(struct saa7146_dev *dev, u32 * isr)
1371{
1372	struct budget_av *budget_av = (struct budget_av *) dev->ext_priv;
1373
1374	dprintk(8, "dev: %p, budget_av: %p\n", dev, budget_av);
1375
1376	if (*isr & MASK_10)
1377		ttpci_budget_irq10_handler(dev, isr);
1378}
1379
1380static int budget_av_detach(struct saa7146_dev *dev)
1381{
1382	struct budget_av *budget_av = (struct budget_av *) dev->ext_priv;
1383	int err;
1384
1385	dprintk(2, "dev: %p\n", dev);
1386
1387	if (1 == budget_av->has_saa7113) {
1388		saa7146_setgpio(dev, 0, SAA7146_GPIO_OUTLO);
1389
1390		msleep(200);
1391
1392		saa7146_unregister_device(&budget_av->vd, dev);
1393
1394		saa7146_vv_release(dev);
1395	}
1396
1397	if (budget_av->budget.ci_present)
1398		ciintf_deinit(budget_av);
1399
1400	if (budget_av->budget.dvb_frontend != NULL) {
1401		dvb_unregister_frontend(budget_av->budget.dvb_frontend);
1402		dvb_frontend_detach(budget_av->budget.dvb_frontend);
1403	}
1404	err = ttpci_budget_deinit(&budget_av->budget);
1405
1406	kfree(budget_av);
1407
1408	return err;
1409}
1410
1411#define KNC1_INPUTS 2
1412static struct v4l2_input knc1_inputs[KNC1_INPUTS] = {
1413	{ 0, "Composite", V4L2_INPUT_TYPE_TUNER, 1, 0,
1414		V4L2_STD_PAL_BG | V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD },
1415	{ 1, "S-Video", V4L2_INPUT_TYPE_CAMERA, 2, 0,
1416		V4L2_STD_PAL_BG | V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD },
1417};
1418
1419static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
1420{
1421	dprintk(1, "VIDIOC_ENUMINPUT %d\n", i->index);
1422	if (i->index >= KNC1_INPUTS)
1423		return -EINVAL;
1424	memcpy(i, &knc1_inputs[i->index], sizeof(struct v4l2_input));
1425	return 0;
1426}
1427
1428static int vidioc_g_input(struct file *file, void *fh, unsigned int *i)
1429{
1430	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
1431	struct budget_av *budget_av = (struct budget_av *)dev->ext_priv;
1432
1433	*i = budget_av->cur_input;
1434
1435	dprintk(1, "VIDIOC_G_INPUT %d\n", *i);
1436	return 0;
1437}
1438
1439static int vidioc_s_input(struct file *file, void *fh, unsigned int input)
1440{
1441	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
1442	struct budget_av *budget_av = (struct budget_av *)dev->ext_priv;
1443
1444	dprintk(1, "VIDIOC_S_INPUT %d\n", input);
1445	return saa7113_setinput(budget_av, input);
1446}
1447
1448static struct saa7146_ext_vv vv_data;
1449
1450static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)
1451{
1452	struct budget_av *budget_av;
1453	u8 *mac;
1454	int err;
1455
1456	dprintk(2, "dev: %p\n", dev);
1457
1458	if (!(budget_av = kzalloc(sizeof(struct budget_av), GFP_KERNEL)))
1459		return -ENOMEM;
1460
1461	budget_av->has_saa7113 = 0;
1462	budget_av->budget.ci_present = 0;
1463
1464	dev->ext_priv = budget_av;
1465
1466	err = ttpci_budget_init(&budget_av->budget, dev, info, THIS_MODULE,
1467				adapter_nr);
1468	if (err) {
1469		kfree(budget_av);
1470		return err;
1471	}
1472
1473	/* knc1 initialization */
1474	saa7146_write(dev, DD1_STREAM_B, 0x04000000);
1475	saa7146_write(dev, DD1_INIT, 0x07000600);
1476	saa7146_write(dev, MC2, MASK_09 | MASK_25 | MASK_10 | MASK_26);
1477
1478	if (saa7113_init(budget_av) == 0) {
1479		budget_av->has_saa7113 = 1;
1480		err = saa7146_vv_init(dev, &vv_data);
1481		if (err != 0) {
1482			/* fixme: proper cleanup here */
1483			ERR("cannot init vv subsystem\n");
1484			return err;
1485		}
1486		vv_data.vid_ops.vidioc_enum_input = vidioc_enum_input;
1487		vv_data.vid_ops.vidioc_g_input = vidioc_g_input;
1488		vv_data.vid_ops.vidioc_s_input = vidioc_s_input;
1489
1490		if ((err = saa7146_register_device(&budget_av->vd, dev, "knc1", VFL_TYPE_GRABBER))) {
1491			/* fixme: proper cleanup here */
1492			ERR("cannot register capture v4l2 device\n");
1493			saa7146_vv_release(dev);
1494			return err;
1495		}
1496
1497		/* beware: this modifies dev->vv ... */
1498		saa7146_set_hps_source_and_sync(dev, SAA7146_HPS_SOURCE_PORT_A,
1499						SAA7146_HPS_SYNC_PORT_A);
1500
1501		saa7113_setinput(budget_av, 0);
1502	}
1503
1504	/* fixme: find some sane values here... */
1505	saa7146_write(dev, PCI_BT_V1, 0x1c00101f);
1506
1507	mac = budget_av->budget.dvb_adapter.proposed_mac;
1508	if (i2c_readregs(&budget_av->budget.i2c_adap, 0xa0, 0x30, mac, 6)) {
1509		pr_err("KNC1-%d: Could not read MAC from KNC1 card\n",
1510		       budget_av->budget.dvb_adapter.num);
1511		memset(mac, 0, 6);
1512	} else {
1513		pr_info("KNC1-%d: MAC addr = %pM\n",
1514			budget_av->budget.dvb_adapter.num, mac);
1515	}
1516
1517	budget_av->budget.dvb_adapter.priv = budget_av;
1518	frontend_init(budget_av);
1519	ciintf_init(budget_av);
1520
1521	ttpci_budget_init_hooks(&budget_av->budget);
1522
1523	return 0;
1524}
1525
1526static struct saa7146_standard standard[] = {
1527	{.name = "PAL",.id = V4L2_STD_PAL,
1528	 .v_offset = 0x17,.v_field = 288,
1529	 .h_offset = 0x14,.h_pixels = 680,
1530	 .v_max_out = 576,.h_max_out = 768 },
1531
1532	{.name = "NTSC",.id = V4L2_STD_NTSC,
1533	 .v_offset = 0x16,.v_field = 240,
1534	 .h_offset = 0x06,.h_pixels = 708,
1535	 .v_max_out = 480,.h_max_out = 640, },
1536};
1537
1538static struct saa7146_ext_vv vv_data = {
1539	.inputs = 2,
1540	.capabilities = 0,	// perhaps later: V4L2_CAP_VBI_CAPTURE, but that need tweaking with the saa7113
1541	.flags = 0,
1542	.stds = &standard[0],
1543	.num_stds = ARRAY_SIZE(standard),
1544};
1545
1546static struct saa7146_extension budget_extension;
1547
1548MAKE_BUDGET_INFO(knc1s, "KNC1 DVB-S", BUDGET_KNC1S);
1549MAKE_BUDGET_INFO(knc1s2,"KNC1 DVB-S2", BUDGET_KNC1S2);
1550MAKE_BUDGET_INFO(sates2,"Satelco EasyWatch DVB-S2", BUDGET_KNC1S2);
1551MAKE_BUDGET_INFO(knc1c, "KNC1 DVB-C", BUDGET_KNC1C);
1552MAKE_BUDGET_INFO(knc1t, "KNC1 DVB-T", BUDGET_KNC1T);
1553MAKE_BUDGET_INFO(kncxs, "KNC TV STAR DVB-S", BUDGET_TVSTAR);
1554MAKE_BUDGET_INFO(satewpls, "Satelco EasyWatch DVB-S light", BUDGET_TVSTAR);
1555MAKE_BUDGET_INFO(satewpls1, "Satelco EasyWatch DVB-S light", BUDGET_KNC1S);
1556MAKE_BUDGET_INFO(satewps, "Satelco EasyWatch DVB-S", BUDGET_KNC1S);
1557MAKE_BUDGET_INFO(satewplc, "Satelco EasyWatch DVB-C", BUDGET_KNC1CP);
1558MAKE_BUDGET_INFO(satewcmk3, "Satelco EasyWatch DVB-C MK3", BUDGET_KNC1C_MK3);
1559MAKE_BUDGET_INFO(satewt, "Satelco EasyWatch DVB-T", BUDGET_KNC1T);
1560MAKE_BUDGET_INFO(knc1sp, "KNC1 DVB-S Plus", BUDGET_KNC1SP);
1561MAKE_BUDGET_INFO(knc1spx4, "KNC1 DVB-S Plus X4", BUDGET_KNC1SP);
1562MAKE_BUDGET_INFO(knc1cp, "KNC1 DVB-C Plus", BUDGET_KNC1CP);
1563MAKE_BUDGET_INFO(knc1cmk3, "KNC1 DVB-C MK3", BUDGET_KNC1C_MK3);
1564MAKE_BUDGET_INFO(knc1ctda10024, "KNC1 DVB-C TDA10024", BUDGET_KNC1C_TDA10024);
1565MAKE_BUDGET_INFO(knc1cpmk3, "KNC1 DVB-C Plus MK3", BUDGET_KNC1CP_MK3);
1566MAKE_BUDGET_INFO(knc1tp, "KNC1 DVB-T Plus", BUDGET_KNC1TP);
1567MAKE_BUDGET_INFO(cin1200s, "TerraTec Cinergy 1200 DVB-S", BUDGET_CIN1200S);
1568MAKE_BUDGET_INFO(cin1200sn, "TerraTec Cinergy 1200 DVB-S", BUDGET_CIN1200S);
1569MAKE_BUDGET_INFO(cin1200c, "Terratec Cinergy 1200 DVB-C", BUDGET_CIN1200C);
1570MAKE_BUDGET_INFO(cin1200cmk3, "Terratec Cinergy 1200 DVB-C MK3", BUDGET_CIN1200C_MK3);
1571MAKE_BUDGET_INFO(cin1200t, "Terratec Cinergy 1200 DVB-T", BUDGET_CIN1200T);
1572
1573static struct pci_device_id pci_tbl[] = {
1574	MAKE_EXTENSION_PCI(knc1s, 0x1131, 0x4f56),
1575	MAKE_EXTENSION_PCI(knc1s, 0x1131, 0x0010),
1576	MAKE_EXTENSION_PCI(knc1s, 0x1894, 0x0010),
1577	MAKE_EXTENSION_PCI(knc1sp, 0x1131, 0x0011),
1578	MAKE_EXTENSION_PCI(knc1sp, 0x1894, 0x0011),
1579	MAKE_EXTENSION_PCI(kncxs, 0x1894, 0x0014),
1580	MAKE_EXTENSION_PCI(knc1spx4, 0x1894, 0x0015),
1581	MAKE_EXTENSION_PCI(kncxs, 0x1894, 0x0016),
1582	MAKE_EXTENSION_PCI(knc1s2, 0x1894, 0x0018),
1583	MAKE_EXTENSION_PCI(knc1s2, 0x1894, 0x0019),
1584	MAKE_EXTENSION_PCI(sates2, 0x1894, 0x001d),
1585	MAKE_EXTENSION_PCI(satewpls, 0x1894, 0x001e),
1586	MAKE_EXTENSION_PCI(satewpls1, 0x1894, 0x001a),
1587	MAKE_EXTENSION_PCI(satewps, 0x1894, 0x001b),
1588	MAKE_EXTENSION_PCI(satewplc, 0x1894, 0x002a),
1589	MAKE_EXTENSION_PCI(satewcmk3, 0x1894, 0x002c),
1590	MAKE_EXTENSION_PCI(satewt, 0x1894, 0x003a),
1591	MAKE_EXTENSION_PCI(knc1c, 0x1894, 0x0020),
1592	MAKE_EXTENSION_PCI(knc1cp, 0x1894, 0x0021),
1593	MAKE_EXTENSION_PCI(knc1cmk3, 0x1894, 0x0022),
1594	MAKE_EXTENSION_PCI(knc1ctda10024, 0x1894, 0x0028),
1595	MAKE_EXTENSION_PCI(knc1cpmk3, 0x1894, 0x0023),
1596	MAKE_EXTENSION_PCI(knc1t, 0x1894, 0x0030),
1597	MAKE_EXTENSION_PCI(knc1tp, 0x1894, 0x0031),
1598	MAKE_EXTENSION_PCI(cin1200s, 0x153b, 0x1154),
1599	MAKE_EXTENSION_PCI(cin1200sn, 0x153b, 0x1155),
1600	MAKE_EXTENSION_PCI(cin1200c, 0x153b, 0x1156),
1601	MAKE_EXTENSION_PCI(cin1200cmk3, 0x153b, 0x1176),
1602	MAKE_EXTENSION_PCI(cin1200t, 0x153b, 0x1157),
1603	{
1604	 .vendor = 0,
1605	}
1606};
1607
1608MODULE_DEVICE_TABLE(pci, pci_tbl);
1609
1610static struct saa7146_extension budget_extension = {
1611	.name = "budget_av",
1612	.flags = SAA7146_USE_I2C_IRQ,
1613
1614	.pci_tbl = pci_tbl,
1615
1616	.module = THIS_MODULE,
1617	.attach = budget_av_attach,
1618	.detach = budget_av_detach,
1619
1620	.irq_mask = MASK_10,
1621	.irq_func = budget_av_irq,
1622};
1623
1624static int __init budget_av_init(void)
1625{
1626	return saa7146_register_extension(&budget_extension);
1627}
1628
1629static void __exit budget_av_exit(void)
1630{
1631	saa7146_unregister_extension(&budget_extension);
1632}
1633
1634module_init(budget_av_init);
1635module_exit(budget_av_exit);
1636
1637MODULE_LICENSE("GPL");
1638MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, Michael Hunold, others");
1639MODULE_DESCRIPTION("driver for the SAA7146 based so-called "
1640		   "budget PCI DVB w/ analog input and CI-module (e.g. the KNC cards)");
1641