xref: /openbmc/linux/drivers/media/pci/ttpci/budget.c (revision e2f1cf25)
1 /*
2  * budget.c: driver for the SAA7146 based Budget DVB cards
3  *
4  * Compiled from various sources by Michael Hunold <michael@mihu.de>
5  *
6  * Copyright (C) 2002 Ralph Metzler <rjkm@metzlerbros.de>
7  *
8  * Copyright (C) 1999-2002 Ralph  Metzler
9  *                       & Marcus Metzler for convergence integrated media GmbH
10  *
11  * 26feb2004 Support for FS Activy Card (Grundig tuner) by
12  *           Michael Dreher <michael@5dot1.de>,
13  *           Oliver Endriss <o.endriss@gmx.de> and
14  *           Andreas 'randy' Weinberger
15  *
16  * This program is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU General Public License
18  * as published by the Free Software Foundation; either version 2
19  * of the License, or (at your option) any later version.
20  *
21  *
22  * This program is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25  * GNU General Public License for more details.
26  *
27  *
28  * You should have received a copy of the GNU General Public License
29  * along with this program; if not, write to the Free Software
30  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
31  * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
32  *
33  *
34  * the project's page is at http://www.linuxtv.org/
35  */
36 
37 #include "budget.h"
38 #include "stv0299.h"
39 #include "ves1x93.h"
40 #include "ves1820.h"
41 #include "l64781.h"
42 #include "tda8083.h"
43 #include "s5h1420.h"
44 #include "tda10086.h"
45 #include "tda826x.h"
46 #include "lnbp21.h"
47 #include "bsru6.h"
48 #include "bsbe1.h"
49 #include "tdhd1.h"
50 #include "stv6110x.h"
51 #include "stv090x.h"
52 #include "isl6423.h"
53 #include "lnbh24.h"
54 
55 
56 static int diseqc_method;
57 module_param(diseqc_method, int, 0444);
58 MODULE_PARM_DESC(diseqc_method, "Select DiSEqC method for subsystem id 13c2:1003, 0: default, 1: more reliable (for newer revisions only)");
59 
60 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
61 
62 static void Set22K (struct budget *budget, int state)
63 {
64 	struct saa7146_dev *dev=budget->dev;
65 	dprintk(2, "budget: %p\n", budget);
66 	saa7146_setgpio(dev, 3, (state ? SAA7146_GPIO_OUTHI : SAA7146_GPIO_OUTLO));
67 }
68 
69 /* Diseqc functions only for TT Budget card */
70 /* taken from the Skyvision DVB driver by
71    Ralph Metzler <rjkm@metzlerbros.de> */
72 
73 static void DiseqcSendBit (struct budget *budget, int data)
74 {
75 	struct saa7146_dev *dev=budget->dev;
76 	dprintk(2, "budget: %p\n", budget);
77 
78 	saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI);
79 	udelay(data ? 500 : 1000);
80 	saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
81 	udelay(data ? 1000 : 500);
82 }
83 
84 static void DiseqcSendByte (struct budget *budget, int data)
85 {
86 	int i, par=1, d;
87 
88 	dprintk(2, "budget: %p\n", budget);
89 
90 	for (i=7; i>=0; i--) {
91 		d = (data>>i)&1;
92 		par ^= d;
93 		DiseqcSendBit(budget, d);
94 	}
95 
96 	DiseqcSendBit(budget, par);
97 }
98 
99 static int SendDiSEqCMsg (struct budget *budget, int len, u8 *msg, unsigned long burst)
100 {
101 	struct saa7146_dev *dev=budget->dev;
102 	int i;
103 
104 	dprintk(2, "budget: %p\n", budget);
105 
106 	saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
107 	mdelay(16);
108 
109 	for (i=0; i<len; i++)
110 		DiseqcSendByte(budget, msg[i]);
111 
112 	mdelay(16);
113 
114 	if (burst!=-1) {
115 		if (burst)
116 			DiseqcSendByte(budget, 0xff);
117 		else {
118 			saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI);
119 			mdelay(12);
120 			udelay(500);
121 			saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
122 		}
123 		msleep(20);
124 	}
125 
126 	return 0;
127 }
128 
129 /*
130  *   Routines for the Fujitsu Siemens Activy budget card
131  *   22 kHz tone and DiSEqC are handled by the frontend.
132  *   Voltage must be set here.
133  *   GPIO 1: LNBP EN, GPIO 2: LNBP VSEL
134  */
135 static int SetVoltage_Activy(struct budget *budget,
136 			     enum fe_sec_voltage voltage)
137 {
138 	struct saa7146_dev *dev=budget->dev;
139 
140 	dprintk(2, "budget: %p\n", budget);
141 
142 	switch (voltage) {
143 		case SEC_VOLTAGE_13:
144 			saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI);
145 			saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTLO);
146 			break;
147 		case SEC_VOLTAGE_18:
148 			saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI);
149 			saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTHI);
150 			break;
151 		case SEC_VOLTAGE_OFF:
152 			saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTLO);
153 			break;
154 		default:
155 			return -EINVAL;
156 	}
157 
158 	return 0;
159 }
160 
161 static int siemens_budget_set_voltage(struct dvb_frontend *fe,
162 				      enum fe_sec_voltage voltage)
163 {
164 	struct budget* budget = (struct budget*) fe->dvb->priv;
165 
166 	return SetVoltage_Activy (budget, voltage);
167 }
168 
169 static int budget_set_tone(struct dvb_frontend *fe,
170 			   enum fe_sec_tone_mode tone)
171 {
172 	struct budget* budget = (struct budget*) fe->dvb->priv;
173 
174 	switch (tone) {
175 	case SEC_TONE_ON:
176 		Set22K (budget, 1);
177 		break;
178 
179 	case SEC_TONE_OFF:
180 		Set22K (budget, 0);
181 		break;
182 
183 	default:
184 		return -EINVAL;
185 	}
186 
187 	return 0;
188 }
189 
190 static int budget_diseqc_send_master_cmd(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd)
191 {
192 	struct budget* budget = (struct budget*) fe->dvb->priv;
193 
194 	SendDiSEqCMsg (budget, cmd->msg_len, cmd->msg, 0);
195 
196 	return 0;
197 }
198 
199 static int budget_diseqc_send_burst(struct dvb_frontend *fe,
200 				    enum fe_sec_mini_cmd minicmd)
201 {
202 	struct budget* budget = (struct budget*) fe->dvb->priv;
203 
204 	SendDiSEqCMsg (budget, 0, NULL, minicmd);
205 
206 	return 0;
207 }
208 
209 static int alps_bsrv2_tuner_set_params(struct dvb_frontend *fe)
210 {
211 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
212 	struct budget* budget = (struct budget*) fe->dvb->priv;
213 	u8 pwr = 0;
214 	u8 buf[4];
215 	struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
216 	u32 div = (c->frequency + 479500) / 125;
217 
218 	if (c->frequency > 2000000)
219 		pwr = 3;
220 	else if (c->frequency > 1800000)
221 		pwr = 2;
222 	else if (c->frequency > 1600000)
223 		pwr = 1;
224 	else if (c->frequency > 1200000)
225 		pwr = 0;
226 	else if (c->frequency >= 1100000)
227 		pwr = 1;
228 	else pwr = 2;
229 
230 	buf[0] = (div >> 8) & 0x7f;
231 	buf[1] = div & 0xff;
232 	buf[2] = ((div & 0x18000) >> 10) | 0x95;
233 	buf[3] = (pwr << 6) | 0x30;
234 
235 	// NOTE: since we're using a prescaler of 2, we set the
236 	// divisor frequency to 62.5kHz and divide by 125 above
237 
238 	if (fe->ops.i2c_gate_ctrl)
239 		fe->ops.i2c_gate_ctrl(fe, 1);
240 	if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
241 	return 0;
242 }
243 
244 static struct ves1x93_config alps_bsrv2_config =
245 {
246 	.demod_address = 0x08,
247 	.xin = 90100000UL,
248 	.invert_pwm = 0,
249 };
250 
251 static int alps_tdbe2_tuner_set_params(struct dvb_frontend *fe)
252 {
253 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
254 	struct budget* budget = (struct budget*) fe->dvb->priv;
255 	u32 div;
256 	u8 data[4];
257 	struct i2c_msg msg = { .addr = 0x62, .flags = 0, .buf = data, .len = sizeof(data) };
258 
259 	div = (c->frequency + 35937500 + 31250) / 62500;
260 
261 	data[0] = (div >> 8) & 0x7f;
262 	data[1] = div & 0xff;
263 	data[2] = 0x85 | ((div >> 10) & 0x60);
264 	data[3] = (c->frequency < 174000000 ? 0x88 : c->frequency < 470000000 ? 0x84 : 0x81);
265 
266 	if (fe->ops.i2c_gate_ctrl)
267 		fe->ops.i2c_gate_ctrl(fe, 1);
268 	if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
269 	return 0;
270 }
271 
272 static struct ves1820_config alps_tdbe2_config = {
273 	.demod_address = 0x09,
274 	.xin = 57840000UL,
275 	.invert = 1,
276 	.selagc = VES1820_SELAGC_SIGNAMPERR,
277 };
278 
279 static int grundig_29504_401_tuner_set_params(struct dvb_frontend *fe)
280 {
281 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
282 	struct budget *budget = fe->dvb->priv;
283 	u8 *tuner_addr = fe->tuner_priv;
284 	u32 div;
285 	u8 cfg, cpump, band_select;
286 	u8 data[4];
287 	struct i2c_msg msg = { .flags = 0, .buf = data, .len = sizeof(data) };
288 
289 	if (tuner_addr)
290 		msg.addr = *tuner_addr;
291 	else
292 		msg.addr = 0x61;
293 
294 	div = (36125000 + c->frequency) / 166666;
295 
296 	cfg = 0x88;
297 
298 	if (c->frequency < 175000000)
299 		cpump = 2;
300 	else if (c->frequency < 390000000)
301 		cpump = 1;
302 	else if (c->frequency < 470000000)
303 		cpump = 2;
304 	else if (c->frequency < 750000000)
305 		cpump = 1;
306 	else
307 		cpump = 3;
308 
309 	if (c->frequency < 175000000)
310 		band_select = 0x0e;
311 	else if (c->frequency < 470000000)
312 		band_select = 0x05;
313 	else
314 		band_select = 0x03;
315 
316 	data[0] = (div >> 8) & 0x7f;
317 	data[1] = div & 0xff;
318 	data[2] = ((div >> 10) & 0x60) | cfg;
319 	data[3] = (cpump << 6) | band_select;
320 
321 	if (fe->ops.i2c_gate_ctrl)
322 		fe->ops.i2c_gate_ctrl(fe, 1);
323 	if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
324 	return 0;
325 }
326 
327 static struct l64781_config grundig_29504_401_config = {
328 	.demod_address = 0x55,
329 };
330 
331 static struct l64781_config grundig_29504_401_config_activy = {
332 	.demod_address = 0x54,
333 };
334 
335 static u8 tuner_address_grundig_29504_401_activy = 0x60;
336 
337 static int grundig_29504_451_tuner_set_params(struct dvb_frontend *fe)
338 {
339 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
340 	struct budget* budget = (struct budget*) fe->dvb->priv;
341 	u32 div;
342 	u8 data[4];
343 	struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
344 
345 	div = c->frequency / 125;
346 	data[0] = (div >> 8) & 0x7f;
347 	data[1] = div & 0xff;
348 	data[2] = 0x8e;
349 	data[3] = 0x00;
350 
351 	if (fe->ops.i2c_gate_ctrl)
352 		fe->ops.i2c_gate_ctrl(fe, 1);
353 	if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
354 	return 0;
355 }
356 
357 static struct tda8083_config grundig_29504_451_config = {
358 	.demod_address = 0x68,
359 };
360 
361 static int s5h1420_tuner_set_params(struct dvb_frontend *fe)
362 {
363 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
364 	struct budget* budget = (struct budget*) fe->dvb->priv;
365 	u32 div;
366 	u8 data[4];
367 	struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
368 
369 	div = c->frequency / 1000;
370 	data[0] = (div >> 8) & 0x7f;
371 	data[1] = div & 0xff;
372 	data[2] = 0xc2;
373 
374 	if (div < 1450)
375 		data[3] = 0x00;
376 	else if (div < 1850)
377 		data[3] = 0x40;
378 	else if (div < 2000)
379 		data[3] = 0x80;
380 	else
381 		data[3] = 0xc0;
382 
383 	if (fe->ops.i2c_gate_ctrl)
384 		fe->ops.i2c_gate_ctrl(fe, 1);
385 	if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
386 
387 	return 0;
388 }
389 
390 static struct s5h1420_config s5h1420_config = {
391 	.demod_address = 0x53,
392 	.invert = 1,
393 	.cdclk_polarity = 1,
394 };
395 
396 static struct tda10086_config tda10086_config = {
397 	.demod_address = 0x0e,
398 	.invert = 0,
399 	.diseqc_tone = 1,
400 	.xtal_freq = TDA10086_XTAL_16M,
401 };
402 
403 static struct stv0299_config alps_bsru6_config_activy = {
404 	.demod_address = 0x68,
405 	.inittab = alps_bsru6_inittab,
406 	.mclk = 88000000UL,
407 	.invert = 1,
408 	.op0_off = 1,
409 	.min_delay_ms = 100,
410 	.set_symbol_rate = alps_bsru6_set_symbol_rate,
411 };
412 
413 static struct stv0299_config alps_bsbe1_config_activy = {
414 	.demod_address = 0x68,
415 	.inittab = alps_bsbe1_inittab,
416 	.mclk = 88000000UL,
417 	.invert = 1,
418 	.op0_off = 1,
419 	.min_delay_ms = 100,
420 	.set_symbol_rate = alps_bsbe1_set_symbol_rate,
421 };
422 
423 static int alps_tdhd1_204_request_firmware(struct dvb_frontend *fe, const struct firmware **fw, char *name)
424 {
425 	struct budget *budget = (struct budget *)fe->dvb->priv;
426 
427 	return request_firmware(fw, name, &budget->dev->pci->dev);
428 }
429 
430 
431 static int i2c_readreg(struct i2c_adapter *i2c, u8 adr, u8 reg)
432 {
433 	u8 val;
434 	struct i2c_msg msg[] = {
435 		{ .addr = adr, .flags = 0, .buf = &reg, .len = 1 },
436 		{ .addr = adr, .flags = I2C_M_RD, .buf = &val, .len = 1 }
437 	};
438 
439 	return (i2c_transfer(i2c, msg, 2) != 2) ? -EIO : val;
440 }
441 
442 static u8 read_pwm(struct budget* budget)
443 {
444 	u8 b = 0xff;
445 	u8 pwm;
446 	struct i2c_msg msg[] = { { .addr = 0x50,.flags = 0,.buf = &b,.len = 1 },
447 				 { .addr = 0x50,.flags = I2C_M_RD,.buf = &pwm,.len = 1} };
448 
449 	if ((i2c_transfer(&budget->i2c_adap, msg, 2) != 2) || (pwm == 0xff))
450 		pwm = 0x48;
451 
452 	return pwm;
453 }
454 
455 static struct stv090x_config tt1600_stv090x_config = {
456 	.device			= STV0903,
457 	.demod_mode		= STV090x_SINGLE,
458 	.clk_mode		= STV090x_CLK_EXT,
459 
460 	.xtal			= 13500000,
461 	.address		= 0x68,
462 
463 	.ts1_mode		= STV090x_TSMODE_DVBCI,
464 	.ts2_mode		= STV090x_TSMODE_SERIAL_CONTINUOUS,
465 
466 	.repeater_level		= STV090x_RPTLEVEL_16,
467 
468 	.tuner_init		= NULL,
469 	.tuner_sleep		= NULL,
470 	.tuner_set_mode		= NULL,
471 	.tuner_set_frequency	= NULL,
472 	.tuner_get_frequency	= NULL,
473 	.tuner_set_bandwidth	= NULL,
474 	.tuner_get_bandwidth	= NULL,
475 	.tuner_set_bbgain	= NULL,
476 	.tuner_get_bbgain	= NULL,
477 	.tuner_set_refclk	= NULL,
478 	.tuner_get_status	= NULL,
479 };
480 
481 static struct stv6110x_config tt1600_stv6110x_config = {
482 	.addr			= 0x60,
483 	.refclk			= 27000000,
484 	.clk_div		= 2,
485 };
486 
487 static struct isl6423_config tt1600_isl6423_config = {
488 	.current_max		= SEC_CURRENT_515m,
489 	.curlim			= SEC_CURRENT_LIM_ON,
490 	.mod_extern		= 1,
491 	.addr			= 0x08,
492 };
493 
494 static void frontend_init(struct budget *budget)
495 {
496 	(void)alps_bsbe1_config; /* avoid warning */
497 
498 	switch(budget->dev->pci->subsystem_device) {
499 	case 0x1003: // Hauppauge/TT Nova budget (stv0299/ALPS BSRU6(tsa5059) OR ves1893/ALPS BSRV2(sp5659))
500 	case 0x1013:
501 		// try the ALPS BSRV2 first of all
502 		budget->dvb_frontend = dvb_attach(ves1x93_attach, &alps_bsrv2_config, &budget->i2c_adap);
503 		if (budget->dvb_frontend) {
504 			budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsrv2_tuner_set_params;
505 			budget->dvb_frontend->ops.diseqc_send_master_cmd = budget_diseqc_send_master_cmd;
506 			budget->dvb_frontend->ops.diseqc_send_burst = budget_diseqc_send_burst;
507 			budget->dvb_frontend->ops.set_tone = budget_set_tone;
508 			break;
509 		}
510 
511 		// try the ALPS BSRU6 now
512 		budget->dvb_frontend = dvb_attach(stv0299_attach, &alps_bsru6_config, &budget->i2c_adap);
513 		if (budget->dvb_frontend) {
514 			budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
515 			budget->dvb_frontend->tuner_priv = &budget->i2c_adap;
516 			if (budget->dev->pci->subsystem_device == 0x1003 && diseqc_method == 0) {
517 				budget->dvb_frontend->ops.diseqc_send_master_cmd = budget_diseqc_send_master_cmd;
518 				budget->dvb_frontend->ops.diseqc_send_burst = budget_diseqc_send_burst;
519 				budget->dvb_frontend->ops.set_tone = budget_set_tone;
520 			}
521 			break;
522 		}
523 		break;
524 
525 	case 0x1004: // Hauppauge/TT DVB-C budget (ves1820/ALPS TDBE2(sp5659))
526 
527 		budget->dvb_frontend = dvb_attach(ves1820_attach, &alps_tdbe2_config, &budget->i2c_adap, read_pwm(budget));
528 		if (budget->dvb_frontend) {
529 			budget->dvb_frontend->ops.tuner_ops.set_params = alps_tdbe2_tuner_set_params;
530 			break;
531 		}
532 		break;
533 
534 	case 0x1005: // Hauppauge/TT Nova-T budget (L64781/Grundig 29504-401(tsa5060))
535 
536 		budget->dvb_frontend = dvb_attach(l64781_attach, &grundig_29504_401_config, &budget->i2c_adap);
537 		if (budget->dvb_frontend) {
538 			budget->dvb_frontend->ops.tuner_ops.set_params = grundig_29504_401_tuner_set_params;
539 			budget->dvb_frontend->tuner_priv = NULL;
540 			break;
541 		}
542 		break;
543 
544 	case 0x4f52: /* Cards based on Philips Semi Sylt PCI ref. design */
545 		budget->dvb_frontend = dvb_attach(stv0299_attach, &alps_bsru6_config, &budget->i2c_adap);
546 		if (budget->dvb_frontend) {
547 			printk(KERN_INFO "budget: tuner ALPS BSRU6 in Philips Semi. Sylt detected\n");
548 			budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
549 			budget->dvb_frontend->tuner_priv = &budget->i2c_adap;
550 			break;
551 		}
552 		break;
553 
554 	case 0x4f60: /* Fujitsu Siemens Activy Budget-S PCI rev AL (stv0299/tsa5059) */
555 	{
556 		int subtype = i2c_readreg(&budget->i2c_adap, 0x50, 0x67);
557 
558 		if (subtype < 0)
559 			break;
560 		/* fixme: find a better way to identify the card */
561 		if (subtype < 0x36) {
562 			/* assume ALPS BSRU6 */
563 			budget->dvb_frontend = dvb_attach(stv0299_attach, &alps_bsru6_config_activy, &budget->i2c_adap);
564 			if (budget->dvb_frontend) {
565 				printk(KERN_INFO "budget: tuner ALPS BSRU6 detected\n");
566 				budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
567 				budget->dvb_frontend->tuner_priv = &budget->i2c_adap;
568 				budget->dvb_frontend->ops.set_voltage = siemens_budget_set_voltage;
569 				budget->dvb_frontend->ops.dishnetwork_send_legacy_command = NULL;
570 				break;
571 			}
572 		} else {
573 			/* assume ALPS BSBE1 */
574 			/* reset tuner */
575 			saa7146_setgpio(budget->dev, 3, SAA7146_GPIO_OUTLO);
576 			msleep(50);
577 			saa7146_setgpio(budget->dev, 3, SAA7146_GPIO_OUTHI);
578 			msleep(250);
579 			budget->dvb_frontend = dvb_attach(stv0299_attach, &alps_bsbe1_config_activy, &budget->i2c_adap);
580 			if (budget->dvb_frontend) {
581 				printk(KERN_INFO "budget: tuner ALPS BSBE1 detected\n");
582 				budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsbe1_tuner_set_params;
583 				budget->dvb_frontend->tuner_priv = &budget->i2c_adap;
584 				budget->dvb_frontend->ops.set_voltage = siemens_budget_set_voltage;
585 				budget->dvb_frontend->ops.dishnetwork_send_legacy_command = NULL;
586 				break;
587 			}
588 		}
589 		break;
590 	}
591 
592 	case 0x4f61: // Fujitsu Siemens Activy Budget-S PCI rev GR (tda8083/Grundig 29504-451(tsa5522))
593 		budget->dvb_frontend = dvb_attach(tda8083_attach, &grundig_29504_451_config, &budget->i2c_adap);
594 		if (budget->dvb_frontend) {
595 			budget->dvb_frontend->ops.tuner_ops.set_params = grundig_29504_451_tuner_set_params;
596 			budget->dvb_frontend->ops.set_voltage = siemens_budget_set_voltage;
597 			budget->dvb_frontend->ops.dishnetwork_send_legacy_command = NULL;
598 		}
599 		break;
600 
601 	case 0x5f60: /* Fujitsu Siemens Activy Budget-T PCI rev AL (tda10046/ALPS TDHD1-204A) */
602 		budget->dvb_frontend = dvb_attach(tda10046_attach, &alps_tdhd1_204a_config, &budget->i2c_adap);
603 		if (budget->dvb_frontend) {
604 			budget->dvb_frontend->ops.tuner_ops.set_params = alps_tdhd1_204a_tuner_set_params;
605 			budget->dvb_frontend->tuner_priv = &budget->i2c_adap;
606 		}
607 		break;
608 
609 	case 0x5f61: /* Fujitsu Siemens Activy Budget-T PCI rev GR (L64781/Grundig 29504-401(tsa5060)) */
610 		budget->dvb_frontend = dvb_attach(l64781_attach, &grundig_29504_401_config_activy, &budget->i2c_adap);
611 		if (budget->dvb_frontend) {
612 			budget->dvb_frontend->tuner_priv = &tuner_address_grundig_29504_401_activy;
613 			budget->dvb_frontend->ops.tuner_ops.set_params = grundig_29504_401_tuner_set_params;
614 		}
615 		break;
616 
617 	case 0x1016: // Hauppauge/TT Nova-S SE (samsung s5h1420/????(tda8260))
618 		budget->dvb_frontend = dvb_attach(s5h1420_attach, &s5h1420_config, &budget->i2c_adap);
619 		if (budget->dvb_frontend) {
620 			budget->dvb_frontend->ops.tuner_ops.set_params = s5h1420_tuner_set_params;
621 			if (dvb_attach(lnbp21_attach, budget->dvb_frontend, &budget->i2c_adap, 0, 0) == NULL) {
622 				printk("%s: No LNBP21 found!\n", __func__);
623 				goto error_out;
624 			}
625 			break;
626 		}
627 
628 	case 0x1018: // TT Budget-S-1401 (philips tda10086/philips tda8262)
629 		// gpio2 is connected to CLB - reset it + leave it high
630 		saa7146_setgpio(budget->dev, 2, SAA7146_GPIO_OUTLO);
631 		msleep(1);
632 		saa7146_setgpio(budget->dev, 2, SAA7146_GPIO_OUTHI);
633 		msleep(1);
634 
635 		budget->dvb_frontend = dvb_attach(tda10086_attach, &tda10086_config, &budget->i2c_adap);
636 		if (budget->dvb_frontend) {
637 			if (dvb_attach(tda826x_attach, budget->dvb_frontend, 0x60, &budget->i2c_adap, 0) == NULL)
638 				printk("%s: No tda826x found!\n", __func__);
639 			if (dvb_attach(lnbp21_attach, budget->dvb_frontend, &budget->i2c_adap, 0, 0) == NULL) {
640 				printk("%s: No LNBP21 found!\n", __func__);
641 				goto error_out;
642 			}
643 			break;
644 		}
645 
646 	case 0x101c: { /* TT S2-1600 */
647 			struct stv6110x_devctl *ctl;
648 			saa7146_setgpio(budget->dev, 2, SAA7146_GPIO_OUTLO);
649 			msleep(50);
650 			saa7146_setgpio(budget->dev, 2, SAA7146_GPIO_OUTHI);
651 			msleep(250);
652 
653 			budget->dvb_frontend = dvb_attach(stv090x_attach,
654 							  &tt1600_stv090x_config,
655 							  &budget->i2c_adap,
656 							  STV090x_DEMODULATOR_0);
657 
658 			if (budget->dvb_frontend) {
659 
660 				ctl = dvb_attach(stv6110x_attach,
661 						 budget->dvb_frontend,
662 						 &tt1600_stv6110x_config,
663 						 &budget->i2c_adap);
664 
665 				if (ctl) {
666 					tt1600_stv090x_config.tuner_init	  = ctl->tuner_init;
667 					tt1600_stv090x_config.tuner_sleep	  = ctl->tuner_sleep;
668 					tt1600_stv090x_config.tuner_set_mode	  = ctl->tuner_set_mode;
669 					tt1600_stv090x_config.tuner_set_frequency = ctl->tuner_set_frequency;
670 					tt1600_stv090x_config.tuner_get_frequency = ctl->tuner_get_frequency;
671 					tt1600_stv090x_config.tuner_set_bandwidth = ctl->tuner_set_bandwidth;
672 					tt1600_stv090x_config.tuner_get_bandwidth = ctl->tuner_get_bandwidth;
673 					tt1600_stv090x_config.tuner_set_bbgain	  = ctl->tuner_set_bbgain;
674 					tt1600_stv090x_config.tuner_get_bbgain	  = ctl->tuner_get_bbgain;
675 					tt1600_stv090x_config.tuner_set_refclk	  = ctl->tuner_set_refclk;
676 					tt1600_stv090x_config.tuner_get_status	  = ctl->tuner_get_status;
677 
678 					/* call the init function once to initialize
679 					   tuner's clock output divider and demod's
680 					   master clock */
681 					if (budget->dvb_frontend->ops.init)
682 						budget->dvb_frontend->ops.init(budget->dvb_frontend);
683 
684 					if (dvb_attach(isl6423_attach,
685 						       budget->dvb_frontend,
686 						       &budget->i2c_adap,
687 						       &tt1600_isl6423_config) == NULL) {
688 						printk(KERN_ERR "%s: No Intersil ISL6423 found!\n", __func__);
689 						goto error_out;
690 					}
691 				} else {
692 					printk(KERN_ERR "%s: No STV6110(A) Silicon Tuner found!\n", __func__);
693 					goto error_out;
694 				}
695 			}
696 		}
697 		break;
698 
699 	case 0x1020: { /* Omicom S2 */
700 			struct stv6110x_devctl *ctl;
701 			saa7146_setgpio(budget->dev, 2, SAA7146_GPIO_OUTLO);
702 			msleep(50);
703 			saa7146_setgpio(budget->dev, 2, SAA7146_GPIO_OUTHI);
704 			msleep(250);
705 
706 			budget->dvb_frontend = dvb_attach(stv090x_attach,
707 							  &tt1600_stv090x_config,
708 							  &budget->i2c_adap,
709 							  STV090x_DEMODULATOR_0);
710 
711 			if (budget->dvb_frontend) {
712 				printk(KERN_INFO "budget: Omicom S2 detected\n");
713 
714 				ctl = dvb_attach(stv6110x_attach,
715 						 budget->dvb_frontend,
716 						 &tt1600_stv6110x_config,
717 						 &budget->i2c_adap);
718 
719 				if (ctl) {
720 					tt1600_stv090x_config.tuner_init	  = ctl->tuner_init;
721 					tt1600_stv090x_config.tuner_sleep	  = ctl->tuner_sleep;
722 					tt1600_stv090x_config.tuner_set_mode	  = ctl->tuner_set_mode;
723 					tt1600_stv090x_config.tuner_set_frequency = ctl->tuner_set_frequency;
724 					tt1600_stv090x_config.tuner_get_frequency = ctl->tuner_get_frequency;
725 					tt1600_stv090x_config.tuner_set_bandwidth = ctl->tuner_set_bandwidth;
726 					tt1600_stv090x_config.tuner_get_bandwidth = ctl->tuner_get_bandwidth;
727 					tt1600_stv090x_config.tuner_set_bbgain	  = ctl->tuner_set_bbgain;
728 					tt1600_stv090x_config.tuner_get_bbgain	  = ctl->tuner_get_bbgain;
729 					tt1600_stv090x_config.tuner_set_refclk	  = ctl->tuner_set_refclk;
730 					tt1600_stv090x_config.tuner_get_status	  = ctl->tuner_get_status;
731 
732 					/* call the init function once to initialize
733 					   tuner's clock output divider and demod's
734 					   master clock */
735 					if (budget->dvb_frontend->ops.init)
736 						budget->dvb_frontend->ops.init(budget->dvb_frontend);
737 
738 					if (dvb_attach(lnbh24_attach,
739 							budget->dvb_frontend,
740 							&budget->i2c_adap,
741 							LNBH24_PCL | LNBH24_TTX,
742 							LNBH24_TEN, 0x14>>1) == NULL) {
743 						printk(KERN_ERR
744 						"No LNBH24 found!\n");
745 						goto error_out;
746 					}
747 				} else {
748 					printk(KERN_ERR "%s: No STV6110(A) Silicon Tuner found!\n", __func__);
749 					goto error_out;
750 				}
751 			}
752 		}
753 		break;
754 	}
755 
756 	if (budget->dvb_frontend == NULL) {
757 		printk("budget: A frontend driver was not found for device [%04x:%04x] subsystem [%04x:%04x]\n",
758 		       budget->dev->pci->vendor,
759 		       budget->dev->pci->device,
760 		       budget->dev->pci->subsystem_vendor,
761 		       budget->dev->pci->subsystem_device);
762 	} else {
763 		if (dvb_register_frontend(&budget->dvb_adapter, budget->dvb_frontend))
764 			goto error_out;
765 	}
766 	return;
767 
768 error_out:
769 	printk("budget: Frontend registration failed!\n");
770 	dvb_frontend_detach(budget->dvb_frontend);
771 	budget->dvb_frontend = NULL;
772 	return;
773 }
774 
775 static int budget_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_data *info)
776 {
777 	struct budget *budget = NULL;
778 	int err;
779 
780 	budget = kmalloc(sizeof(struct budget), GFP_KERNEL);
781 	if( NULL == budget ) {
782 		return -ENOMEM;
783 	}
784 
785 	dprintk(2, "dev:%p, info:%p, budget:%p\n", dev, info, budget);
786 
787 	dev->ext_priv = budget;
788 
789 	err = ttpci_budget_init(budget, dev, info, THIS_MODULE, adapter_nr);
790 	if (err) {
791 		printk("==> failed\n");
792 		kfree (budget);
793 		return err;
794 	}
795 
796 	budget->dvb_adapter.priv = budget;
797 	frontend_init(budget);
798 
799 	ttpci_budget_init_hooks(budget);
800 
801 	return 0;
802 }
803 
804 static int budget_detach (struct saa7146_dev* dev)
805 {
806 	struct budget *budget = (struct budget*) dev->ext_priv;
807 	int err;
808 
809 	if (budget->dvb_frontend) {
810 		dvb_unregister_frontend(budget->dvb_frontend);
811 		dvb_frontend_detach(budget->dvb_frontend);
812 	}
813 
814 	err = ttpci_budget_deinit (budget);
815 
816 	kfree (budget);
817 	dev->ext_priv = NULL;
818 
819 	return err;
820 }
821 
822 static struct saa7146_extension budget_extension;
823 
824 MAKE_BUDGET_INFO(ttbs,	"TT-Budget/WinTV-NOVA-S  PCI",	BUDGET_TT);
825 MAKE_BUDGET_INFO(ttbc,	"TT-Budget/WinTV-NOVA-C  PCI",	BUDGET_TT);
826 MAKE_BUDGET_INFO(ttbt,	"TT-Budget/WinTV-NOVA-T  PCI",	BUDGET_TT);
827 MAKE_BUDGET_INFO(satel,	"SATELCO Multimedia PCI",	BUDGET_TT_HW_DISEQC);
828 MAKE_BUDGET_INFO(ttbs1401, "TT-Budget-S-1401 PCI", BUDGET_TT);
829 MAKE_BUDGET_INFO(tt1600, "TT-Budget S2-1600 PCI", BUDGET_TT);
830 MAKE_BUDGET_INFO(fsacs0, "Fujitsu Siemens Activy Budget-S PCI (rev GR/grundig frontend)", BUDGET_FS_ACTIVY);
831 MAKE_BUDGET_INFO(fsacs1, "Fujitsu Siemens Activy Budget-S PCI (rev AL/alps frontend)", BUDGET_FS_ACTIVY);
832 MAKE_BUDGET_INFO(fsact,	 "Fujitsu Siemens Activy Budget-T PCI (rev GR/Grundig frontend)", BUDGET_FS_ACTIVY);
833 MAKE_BUDGET_INFO(fsact1, "Fujitsu Siemens Activy Budget-T PCI (rev AL/ALPS TDHD1-204A)", BUDGET_FS_ACTIVY);
834 MAKE_BUDGET_INFO(omicom, "Omicom S2 PCI", BUDGET_TT);
835 MAKE_BUDGET_INFO(sylt,   "Philips Semi Sylt PCI", BUDGET_TT_HW_DISEQC);
836 
837 static struct pci_device_id pci_tbl[] = {
838 	MAKE_EXTENSION_PCI(ttbs,  0x13c2, 0x1003),
839 	MAKE_EXTENSION_PCI(ttbc,  0x13c2, 0x1004),
840 	MAKE_EXTENSION_PCI(ttbt,  0x13c2, 0x1005),
841 	MAKE_EXTENSION_PCI(satel, 0x13c2, 0x1013),
842 	MAKE_EXTENSION_PCI(ttbs,  0x13c2, 0x1016),
843 	MAKE_EXTENSION_PCI(ttbs1401, 0x13c2, 0x1018),
844 	MAKE_EXTENSION_PCI(tt1600, 0x13c2, 0x101c),
845 	MAKE_EXTENSION_PCI(fsacs1,0x1131, 0x4f60),
846 	MAKE_EXTENSION_PCI(fsacs0,0x1131, 0x4f61),
847 	MAKE_EXTENSION_PCI(fsact1, 0x1131, 0x5f60),
848 	MAKE_EXTENSION_PCI(fsact, 0x1131, 0x5f61),
849 	MAKE_EXTENSION_PCI(omicom, 0x14c4, 0x1020),
850 	MAKE_EXTENSION_PCI(sylt, 0x1131, 0x4f52),
851 	{
852 		.vendor    = 0,
853 	}
854 };
855 
856 MODULE_DEVICE_TABLE(pci, pci_tbl);
857 
858 static struct saa7146_extension budget_extension = {
859 	.name		= "budget dvb",
860 	.flags		= SAA7146_USE_I2C_IRQ,
861 
862 	.module		= THIS_MODULE,
863 	.pci_tbl	= pci_tbl,
864 	.attach		= budget_attach,
865 	.detach		= budget_detach,
866 
867 	.irq_mask	= MASK_10,
868 	.irq_func	= ttpci_budget_irq10_handler,
869 };
870 
871 static int __init budget_init(void)
872 {
873 	return saa7146_register_extension(&budget_extension);
874 }
875 
876 static void __exit budget_exit(void)
877 {
878 	saa7146_unregister_extension(&budget_extension);
879 }
880 
881 module_init(budget_init);
882 module_exit(budget_exit);
883 
884 MODULE_LICENSE("GPL");
885 MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, Michael Hunold, others");
886 MODULE_DESCRIPTION("driver for the SAA7146 based so-called "
887 		   "budget PCI DVB cards by Siemens, Technotrend, Hauppauge");
888