[PATCH] dvb: frontend: s5h1420: fixes
[linux-2.6/verdex.git] / drivers / media / dvb / ttpci / budget.c
blob43d6c8268642b5670a5fe40bb4c828b5e1c8ff96
1 /*
2 * budget.c: driver for the SAA7146 based Budget DVB cards
4 * Compiled from various sources by Michael Hunold <michael@mihu.de>
6 * Copyright (C) 2002 Ralph Metzler <rjkm@metzlerbros.de>
8 * Copyright (C) 1999-2002 Ralph Metzler
9 * & Marcus Metzler for convergence integrated media GmbH
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
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.
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.
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
34 * the project's page is at http://www.linuxtv.org/dvb/
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"
45 static void Set22K (struct budget *budget, int state)
47 struct saa7146_dev *dev=budget->dev;
48 dprintk(2, "budget: %p\n", budget);
49 saa7146_setgpio(dev, 3, (state ? SAA7146_GPIO_OUTHI : SAA7146_GPIO_OUTLO));
52 /* Diseqc functions only for TT Budget card */
53 /* taken from the Skyvision DVB driver by
54 Ralph Metzler <rjkm@metzlerbros.de> */
56 static void DiseqcSendBit (struct budget *budget, int data)
58 struct saa7146_dev *dev=budget->dev;
59 dprintk(2, "budget: %p\n", budget);
61 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI);
62 udelay(data ? 500 : 1000);
63 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
64 udelay(data ? 1000 : 500);
67 static void DiseqcSendByte (struct budget *budget, int data)
69 int i, par=1, d;
71 dprintk(2, "budget: %p\n", budget);
73 for (i=7; i>=0; i--) {
74 d = (data>>i)&1;
75 par ^= d;
76 DiseqcSendBit(budget, d);
79 DiseqcSendBit(budget, par);
82 static int SendDiSEqCMsg (struct budget *budget, int len, u8 *msg, unsigned long burst)
84 struct saa7146_dev *dev=budget->dev;
85 int i;
87 dprintk(2, "budget: %p\n", budget);
89 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
90 mdelay(16);
92 for (i=0; i<len; i++)
93 DiseqcSendByte(budget, msg[i]);
95 mdelay(16);
97 if (burst!=-1) {
98 if (burst)
99 DiseqcSendByte(budget, 0xff);
100 else {
101 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI);
102 udelay(12500);
103 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
105 msleep(20);
108 return 0;
112 * Routines for the Fujitsu Siemens Activy budget card
113 * 22 kHz tone and DiSEqC are handled by the frontend.
114 * Voltage must be set here.
116 static int SetVoltage_Activy (struct budget *budget, fe_sec_voltage_t voltage)
118 struct saa7146_dev *dev=budget->dev;
120 dprintk(2, "budget: %p\n", budget);
122 switch (voltage) {
123 case SEC_VOLTAGE_13:
124 saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTLO);
125 break;
126 case SEC_VOLTAGE_18:
127 saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTHI);
128 break;
129 default:
130 return -EINVAL;
133 return 0;
136 static int siemens_budget_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
138 struct budget* budget = (struct budget*) fe->dvb->priv;
140 return SetVoltage_Activy (budget, voltage);
143 static int budget_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
145 struct budget* budget = (struct budget*) fe->dvb->priv;
147 switch (tone) {
148 case SEC_TONE_ON:
149 Set22K (budget, 1);
150 break;
152 case SEC_TONE_OFF:
153 Set22K (budget, 0);
154 break;
156 default:
157 return -EINVAL;
160 return 0;
163 static int budget_diseqc_send_master_cmd(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd)
165 struct budget* budget = (struct budget*) fe->dvb->priv;
167 SendDiSEqCMsg (budget, cmd->msg_len, cmd->msg, 0);
169 return 0;
172 static int budget_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd)
174 struct budget* budget = (struct budget*) fe->dvb->priv;
176 SendDiSEqCMsg (budget, 0, NULL, minicmd);
178 return 0;
181 static int lnbp21_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
183 struct budget* budget = (struct budget*) fe->dvb->priv;
184 u8 buf;
185 struct i2c_msg msg = { .addr = 0x08, .flags = I2C_M_RD, .buf = &buf, .len = sizeof(buf) };
187 if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
189 switch(voltage) {
190 case SEC_VOLTAGE_13:
191 buf = (buf & 0xf7) | 0x04;
192 break;
194 case SEC_VOLTAGE_18:
195 buf = (buf & 0xf7) | 0x0c;
196 break;
198 case SEC_VOLTAGE_OFF:
199 buf = buf & 0xf0;
200 break;
203 msg.flags = 0;
204 if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
206 return 0;
209 static int lnbp21_enable_high_lnb_voltage(struct dvb_frontend* fe, int arg)
211 struct budget* budget = (struct budget*) fe->dvb->priv;
212 u8 buf;
213 struct i2c_msg msg = { .addr = 0x08, .flags = I2C_M_RD, .buf = &buf, .len = sizeof(buf) };
215 if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
217 if (arg) {
218 buf = buf | 0x10;
219 } else {
220 buf = buf & 0xef;
223 msg.flags = 0;
224 if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
226 return 0;
229 static void lnbp21_init(struct budget* budget)
231 u8 buf = 0x00;
232 struct i2c_msg msg = { .addr = 0x08, .flags = 0, .buf = &buf, .len = sizeof(buf) };
234 i2c_transfer (&budget->i2c_adap, &msg, 1);
237 static int alps_bsrv2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
239 struct budget* budget = (struct budget*) fe->dvb->priv;
240 u8 pwr = 0;
241 u8 buf[4];
242 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
243 u32 div = (params->frequency + 479500) / 125;
245 if (params->frequency > 2000000) pwr = 3;
246 else if (params->frequency > 1800000) pwr = 2;
247 else if (params->frequency > 1600000) pwr = 1;
248 else if (params->frequency > 1200000) pwr = 0;
249 else if (params->frequency >= 1100000) pwr = 1;
250 else pwr = 2;
252 buf[0] = (div >> 8) & 0x7f;
253 buf[1] = div & 0xff;
254 buf[2] = ((div & 0x18000) >> 10) | 0x95;
255 buf[3] = (pwr << 6) | 0x30;
257 // NOTE: since we're using a prescaler of 2, we set the
258 // divisor frequency to 62.5kHz and divide by 125 above
260 if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
261 return 0;
264 static struct ves1x93_config alps_bsrv2_config =
266 .demod_address = 0x08,
267 .xin = 90100000UL,
268 .invert_pwm = 0,
269 .pll_set = alps_bsrv2_pll_set,
272 static u8 alps_bsru6_inittab[] = {
273 0x01, 0x15,
274 0x02, 0x00,
275 0x03, 0x00,
276 0x04, 0x7d, /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */
277 0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */
278 0x06, 0x40, /* DAC not used, set to high impendance mode */
279 0x07, 0x00, /* DAC LSB */
280 0x08, 0x40, /* DiSEqC off, LNB power on OP2/LOCK pin on */
281 0x09, 0x00, /* FIFO */
282 0x0c, 0x51, /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */
283 0x0d, 0x82, /* DC offset compensation = ON, beta_agc1 = 2 */
284 0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */
285 0x10, 0x3f, // AGC2 0x3d
286 0x11, 0x84,
287 0x12, 0xb5, // Lock detect: -64 Carrier freq detect:on
288 0x15, 0xc9, // lock detector threshold
289 0x16, 0x00,
290 0x17, 0x00,
291 0x18, 0x00,
292 0x19, 0x00,
293 0x1a, 0x00,
294 0x1f, 0x50,
295 0x20, 0x00,
296 0x21, 0x00,
297 0x22, 0x00,
298 0x23, 0x00,
299 0x28, 0x00, // out imp: normal out type: parallel FEC mode:0
300 0x29, 0x1e, // 1/2 threshold
301 0x2a, 0x14, // 2/3 threshold
302 0x2b, 0x0f, // 3/4 threshold
303 0x2c, 0x09, // 5/6 threshold
304 0x2d, 0x05, // 7/8 threshold
305 0x2e, 0x01,
306 0x31, 0x1f, // test all FECs
307 0x32, 0x19, // viterbi and synchro search
308 0x33, 0xfc, // rs control
309 0x34, 0x93, // error control
310 0x0f, 0x52,
311 0xff, 0xff
314 static int alps_bsru6_set_symbol_rate(struct dvb_frontend* fe, u32 srate, u32 ratio)
316 u8 aclk = 0;
317 u8 bclk = 0;
319 if (srate < 1500000) { aclk = 0xb7; bclk = 0x47; }
320 else if (srate < 3000000) { aclk = 0xb7; bclk = 0x4b; }
321 else if (srate < 7000000) { aclk = 0xb7; bclk = 0x4f; }
322 else if (srate < 14000000) { aclk = 0xb7; bclk = 0x53; }
323 else if (srate < 30000000) { aclk = 0xb6; bclk = 0x53; }
324 else if (srate < 45000000) { aclk = 0xb4; bclk = 0x51; }
326 stv0299_writereg (fe, 0x13, aclk);
327 stv0299_writereg (fe, 0x14, bclk);
328 stv0299_writereg (fe, 0x1f, (ratio >> 16) & 0xff);
329 stv0299_writereg (fe, 0x20, (ratio >> 8) & 0xff);
330 stv0299_writereg (fe, 0x21, (ratio ) & 0xf0);
332 return 0;
335 static int alps_bsru6_pll_set(struct dvb_frontend* fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters* params)
337 u8 data[4];
338 u32 div;
339 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
341 if ((params->frequency < 950000) || (params->frequency > 2150000)) return -EINVAL;
343 div = (params->frequency + (125 - 1)) / 125; // round correctly
344 data[0] = (div >> 8) & 0x7f;
345 data[1] = div & 0xff;
346 data[2] = 0x80 | ((div & 0x18000) >> 10) | 4;
347 data[3] = 0xC4;
349 if (params->frequency > 1530000) data[3] = 0xc0;
351 if (i2c_transfer(i2c, &msg, 1) != 1) return -EIO;
352 return 0;
355 static struct stv0299_config alps_bsru6_config = {
357 .demod_address = 0x68,
358 .inittab = alps_bsru6_inittab,
359 .mclk = 88000000UL,
360 .invert = 1,
361 .enhanced_tuning = 0,
362 .skip_reinit = 0,
363 .lock_output = STV0229_LOCKOUTPUT_1,
364 .volt13_op0_op1 = STV0299_VOLT13_OP1,
365 .min_delay_ms = 100,
366 .set_symbol_rate = alps_bsru6_set_symbol_rate,
367 .pll_set = alps_bsru6_pll_set,
370 static int alps_tdbe2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
372 struct budget* budget = (struct budget*) fe->dvb->priv;
373 u32 div;
374 u8 data[4];
375 struct i2c_msg msg = { .addr = 0x62, .flags = 0, .buf = data, .len = sizeof(data) };
377 div = (params->frequency + 35937500 + 31250) / 62500;
379 data[0] = (div >> 8) & 0x7f;
380 data[1] = div & 0xff;
381 data[2] = 0x85 | ((div >> 10) & 0x60);
382 data[3] = (params->frequency < 174000000 ? 0x88 : params->frequency < 470000000 ? 0x84 : 0x81);
384 if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
385 return 0;
388 static struct ves1820_config alps_tdbe2_config = {
389 .demod_address = 0x09,
390 .xin = 57840000UL,
391 .invert = 1,
392 .selagc = VES1820_SELAGC_SIGNAMPERR,
393 .pll_set = alps_tdbe2_pll_set,
396 static int grundig_29504_401_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
398 struct budget* budget = (struct budget*) fe->dvb->priv;
399 u32 div;
400 u8 cfg, cpump, band_select;
401 u8 data[4];
402 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
404 div = (36125000 + params->frequency) / 166666;
406 cfg = 0x88;
408 if (params->frequency < 175000000) cpump = 2;
409 else if (params->frequency < 390000000) cpump = 1;
410 else if (params->frequency < 470000000) cpump = 2;
411 else if (params->frequency < 750000000) cpump = 1;
412 else cpump = 3;
414 if (params->frequency < 175000000) band_select = 0x0e;
415 else if (params->frequency < 470000000) band_select = 0x05;
416 else band_select = 0x03;
418 data[0] = (div >> 8) & 0x7f;
419 data[1] = div & 0xff;
420 data[2] = ((div >> 10) & 0x60) | cfg;
421 data[3] = (cpump << 6) | band_select;
423 if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
424 return 0;
427 static struct l64781_config grundig_29504_401_config = {
428 .demod_address = 0x55,
429 .pll_set = grundig_29504_401_pll_set,
432 static int grundig_29504_451_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
434 struct budget* budget = (struct budget*) fe->dvb->priv;
435 u32 div;
436 u8 data[4];
437 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
439 div = params->frequency / 125;
440 data[0] = (div >> 8) & 0x7f;
441 data[1] = div & 0xff;
442 data[2] = 0x8e;
443 data[3] = 0x00;
445 if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
446 return 0;
449 static struct tda8083_config grundig_29504_451_config = {
450 .demod_address = 0x68,
451 .pll_set = grundig_29504_451_pll_set,
454 static int s5h1420_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u32* freqout)
456 struct budget* budget = (struct budget*) fe->dvb->priv;
457 u32 div;
458 u8 data[4];
459 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
461 div = params->frequency / 1000;
462 data[0] = (div >> 8) & 0x7f;
463 data[1] = div & 0xff;
464 data[2] = 0xc2;
466 if (div < 1450)
467 data[3] = 0x00;
468 else if (div < 1850)
469 data[3] = 0x40;
470 else if (div < 2000)
471 data[3] = 0x80;
472 else
473 data[3] = 0xc0;
475 if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
477 *freqout = div * 1000;
478 return 0;
481 static struct s5h1420_config s5h1420_config = {
482 .demod_address = 0x53,
483 .invert = 1,
484 .pll_set = s5h1420_pll_set,
487 static u8 read_pwm(struct budget* budget)
489 u8 b = 0xff;
490 u8 pwm;
491 struct i2c_msg msg[] = { { .addr = 0x50,.flags = 0,.buf = &b,.len = 1 },
492 { .addr = 0x50,.flags = I2C_M_RD,.buf = &pwm,.len = 1} };
494 if ((i2c_transfer(&budget->i2c_adap, msg, 2) != 2) || (pwm == 0xff))
495 pwm = 0x48;
497 return pwm;
500 static void frontend_init(struct budget *budget)
502 switch(budget->dev->pci->subsystem_device) {
503 case 0x1003: // Hauppauge/TT Nova budget (stv0299/ALPS BSRU6(tsa5059) OR ves1893/ALPS BSRV2(sp5659))
504 case 0x1013:
505 // try the ALPS BSRV2 first of all
506 budget->dvb_frontend = ves1x93_attach(&alps_bsrv2_config, &budget->i2c_adap);
507 if (budget->dvb_frontend) {
508 budget->dvb_frontend->ops->diseqc_send_master_cmd = budget_diseqc_send_master_cmd;
509 budget->dvb_frontend->ops->diseqc_send_burst = budget_diseqc_send_burst;
510 budget->dvb_frontend->ops->set_tone = budget_set_tone;
511 break;
514 // try the ALPS BSRU6 now
515 budget->dvb_frontend = stv0299_attach(&alps_bsru6_config, &budget->i2c_adap);
516 if (budget->dvb_frontend) {
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 break;
522 break;
524 case 0x1004: // Hauppauge/TT DVB-C budget (ves1820/ALPS TDBE2(sp5659))
526 budget->dvb_frontend = ves1820_attach(&alps_tdbe2_config, &budget->i2c_adap, read_pwm(budget));
527 if (budget->dvb_frontend) break;
528 break;
530 case 0x1005: // Hauppauge/TT Nova-T budget (L64781/Grundig 29504-401(tsa5060))
532 budget->dvb_frontend = l64781_attach(&grundig_29504_401_config, &budget->i2c_adap);
533 if (budget->dvb_frontend) break;
534 break;
536 case 0x4f60: // Fujitsu Siemens Activy Budget-S PCI rev AL (stv0299/ALPS BSRU6(tsa5059))
537 budget->dvb_frontend = stv0299_attach(&alps_bsru6_config, &budget->i2c_adap);
538 if (budget->dvb_frontend) {
539 budget->dvb_frontend->ops->set_voltage = siemens_budget_set_voltage;
540 break;
542 break;
544 case 0x4f61: // Fujitsu Siemens Activy Budget-S PCI rev GR (tda8083/Grundig 29504-451(tsa5522))
545 budget->dvb_frontend = tda8083_attach(&grundig_29504_451_config, &budget->i2c_adap);
546 if (budget->dvb_frontend) {
547 budget->dvb_frontend->ops->set_voltage = siemens_budget_set_voltage;
548 break;
550 break;
552 case 0x1016: // Hauppauge/TT Nova-S SE (samsung s5h1420/????(tda8260))
553 budget->dvb_frontend = s5h1420_attach(&s5h1420_config, &budget->i2c_adap);
554 if (budget->dvb_frontend) {
555 budget->dvb_frontend->ops->set_voltage = lnbp21_set_voltage;
556 budget->dvb_frontend->ops->enable_high_lnb_voltage = lnbp21_enable_high_lnb_voltage;
557 lnbp21_init(budget);
558 break;
562 if (budget->dvb_frontend == NULL) {
563 printk("budget: A frontend driver was not found for device %04x/%04x subsystem %04x/%04x\n",
564 budget->dev->pci->vendor,
565 budget->dev->pci->device,
566 budget->dev->pci->subsystem_vendor,
567 budget->dev->pci->subsystem_device);
568 } else {
569 if (dvb_register_frontend(&budget->dvb_adapter, budget->dvb_frontend)) {
570 printk("budget: Frontend registration failed!\n");
571 if (budget->dvb_frontend->ops->release)
572 budget->dvb_frontend->ops->release(budget->dvb_frontend);
573 budget->dvb_frontend = NULL;
578 static int budget_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_data *info)
580 struct budget *budget = NULL;
581 int err;
583 budget = kmalloc(sizeof(struct budget), GFP_KERNEL);
584 if( NULL == budget ) {
585 return -ENOMEM;
588 dprintk(2, "dev:%p, info:%p, budget:%p\n", dev, info, budget);
590 dev->ext_priv = budget;
592 if ((err = ttpci_budget_init (budget, dev, info, THIS_MODULE))) {
593 printk("==> failed\n");
594 kfree (budget);
595 return err;
598 budget->dvb_adapter.priv = budget;
599 frontend_init(budget);
601 return 0;
604 static int budget_detach (struct saa7146_dev* dev)
606 struct budget *budget = (struct budget*) dev->ext_priv;
607 int err;
609 if (budget->dvb_frontend) dvb_unregister_frontend(budget->dvb_frontend);
611 err = ttpci_budget_deinit (budget);
613 kfree (budget);
614 dev->ext_priv = NULL;
616 return err;
619 static struct saa7146_extension budget_extension;
621 MAKE_BUDGET_INFO(ttbs, "TT-Budget/WinTV-NOVA-S PCI", BUDGET_TT);
622 MAKE_BUDGET_INFO(ttbc, "TT-Budget/WinTV-NOVA-C PCI", BUDGET_TT);
623 MAKE_BUDGET_INFO(ttbt, "TT-Budget/WinTV-NOVA-T PCI", BUDGET_TT);
624 MAKE_BUDGET_INFO(satel, "SATELCO Multimedia PCI", BUDGET_TT_HW_DISEQC);
625 MAKE_BUDGET_INFO(fsacs0, "Fujitsu Siemens Activy Budget-S PCI (rev GR/grundig frontend)", BUDGET_FS_ACTIVY);
626 MAKE_BUDGET_INFO(fsacs1, "Fujitsu Siemens Activy Budget-S PCI (rev AL/alps frontend)", BUDGET_FS_ACTIVY);
628 static struct pci_device_id pci_tbl[] = {
629 MAKE_EXTENSION_PCI(ttbs, 0x13c2, 0x1003),
630 MAKE_EXTENSION_PCI(ttbc, 0x13c2, 0x1004),
631 MAKE_EXTENSION_PCI(ttbt, 0x13c2, 0x1005),
632 MAKE_EXTENSION_PCI(satel, 0x13c2, 0x1013),
633 MAKE_EXTENSION_PCI(ttbs, 0x13c2, 0x1016),
634 MAKE_EXTENSION_PCI(fsacs1,0x1131, 0x4f60),
635 MAKE_EXTENSION_PCI(fsacs0,0x1131, 0x4f61),
637 .vendor = 0,
641 MODULE_DEVICE_TABLE(pci, pci_tbl);
643 static struct saa7146_extension budget_extension = {
644 .name = "budget dvb\0",
645 .flags = 0,
647 .module = THIS_MODULE,
648 .pci_tbl = pci_tbl,
649 .attach = budget_attach,
650 .detach = budget_detach,
652 .irq_mask = MASK_10,
653 .irq_func = ttpci_budget_irq10_handler,
656 static int __init budget_init(void)
658 return saa7146_register_extension(&budget_extension);
661 static void __exit budget_exit(void)
663 saa7146_unregister_extension(&budget_extension);
666 module_init(budget_init);
667 module_exit(budget_exit);
669 MODULE_LICENSE("GPL");
670 MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, Michael Hunold, others");
671 MODULE_DESCRIPTION("driver for the SAA7146 based so-called "
672 "budget PCI DVB cards by Siemens, Technotrend, Hauppauge");