Merge master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-for-linus-2.6
[sfrench/cifs-2.6.git] / drivers / media / dvb / ttpci / budget.c
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/dvb/
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
45 static void Set22K (struct budget *budget, int state)
46 {
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));
50 }
51
52 /* Diseqc functions only for TT Budget card */
53 /* taken from the Skyvision DVB driver by
54    Ralph Metzler <rjkm@metzlerbros.de> */
55
56 static void DiseqcSendBit (struct budget *budget, int data)
57 {
58         struct saa7146_dev *dev=budget->dev;
59         dprintk(2, "budget: %p\n", budget);
60
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);
65 }
66
67 static void DiseqcSendByte (struct budget *budget, int data)
68 {
69         int i, par=1, d;
70
71         dprintk(2, "budget: %p\n", budget);
72
73         for (i=7; i>=0; i--) {
74                 d = (data>>i)&1;
75                 par ^= d;
76                 DiseqcSendBit(budget, d);
77         }
78
79         DiseqcSendBit(budget, par);
80 }
81
82 static int SendDiSEqCMsg (struct budget *budget, int len, u8 *msg, unsigned long burst)
83 {
84         struct saa7146_dev *dev=budget->dev;
85         int i;
86
87         dprintk(2, "budget: %p\n", budget);
88
89         saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
90         mdelay(16);
91
92         for (i=0; i<len; i++)
93                 DiseqcSendByte(budget, msg[i]);
94
95         mdelay(16);
96
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);
104                 }
105                 msleep(20);
106         }
107
108         return 0;
109 }
110
111 /*
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.
115  */
116 static int SetVoltage_Activy (struct budget *budget, fe_sec_voltage_t voltage)
117 {
118         struct saa7146_dev *dev=budget->dev;
119
120         dprintk(2, "budget: %p\n", budget);
121
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;
131         }
132
133         return 0;
134 }
135
136 static int siemens_budget_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
137 {
138         struct budget* budget = (struct budget*) fe->dvb->priv;
139
140         return SetVoltage_Activy (budget, voltage);
141 }
142
143 static int budget_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
144 {
145         struct budget* budget = (struct budget*) fe->dvb->priv;
146
147         switch (tone) {
148         case SEC_TONE_ON:
149                 Set22K (budget, 1);
150                 break;
151
152         case SEC_TONE_OFF:
153                 Set22K (budget, 0);
154                 break;
155
156         default:
157                 return -EINVAL;
158         }
159
160         return 0;
161 }
162
163 static int budget_diseqc_send_master_cmd(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd)
164 {
165         struct budget* budget = (struct budget*) fe->dvb->priv;
166
167         SendDiSEqCMsg (budget, cmd->msg_len, cmd->msg, 0);
168
169         return 0;
170 }
171
172 static int budget_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd)
173 {
174         struct budget* budget = (struct budget*) fe->dvb->priv;
175
176         SendDiSEqCMsg (budget, 0, NULL, minicmd);
177
178         return 0;
179 }
180
181 static int lnbp21_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
182 {
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) };
186
187         if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
188
189         switch(voltage) {
190         case SEC_VOLTAGE_13:
191                 buf = (buf & 0xf7) | 0x04;
192                 break;
193
194         case SEC_VOLTAGE_18:
195                 buf = (buf & 0xf7) | 0x0c;
196                 break;
197
198         case SEC_VOLTAGE_OFF:
199                 buf = buf & 0xf0;
200                 break;
201         }
202
203         msg.flags = 0;
204         if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
205
206         return 0;
207 }
208
209 static int lnbp21_enable_high_lnb_voltage(struct dvb_frontend* fe, int arg)
210 {
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) };
214
215         if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
216
217         if (arg) {
218                 buf = buf | 0x10;
219         } else {
220                 buf = buf & 0xef;
221         }
222
223         msg.flags = 0;
224         if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
225
226         return 0;
227 }
228
229 static void lnbp21_init(struct budget* budget)
230 {
231         u8 buf = 0x00;
232         struct i2c_msg msg = { .addr = 0x08, .flags = 0, .buf = &buf, .len = sizeof(buf) };
233
234         i2c_transfer (&budget->i2c_adap, &msg, 1);
235 }
236
237 static int alps_bsrv2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
238 {
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;
244
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;
251
252         buf[0] = (div >> 8) & 0x7f;
253         buf[1] = div & 0xff;
254         buf[2] = ((div & 0x18000) >> 10) | 0x95;
255         buf[3] = (pwr << 6) | 0x30;
256
257         // NOTE: since we're using a prescaler of 2, we set the
258         // divisor frequency to 62.5kHz and divide by 125 above
259
260         if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
261         return 0;
262 }
263
264 static struct ves1x93_config alps_bsrv2_config =
265 {
266         .demod_address = 0x08,
267         .xin = 90100000UL,
268         .invert_pwm = 0,
269         .pll_set = alps_bsrv2_pll_set,
270 };
271
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
312 };
313
314 static int alps_bsru6_set_symbol_rate(struct dvb_frontend* fe, u32 srate, u32 ratio)
315 {
316         u8 aclk = 0;
317         u8 bclk = 0;
318
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; }
325
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);
331
332         return 0;
333 }
334
335 static int alps_bsru6_pll_set(struct dvb_frontend* fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters* params)
336 {
337         u8 data[4];
338         u32 div;
339         struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
340
341         if ((params->frequency < 950000) || (params->frequency > 2150000)) return -EINVAL;
342
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;
348
349         if (params->frequency > 1530000) data[3] = 0xc0;
350
351         if (i2c_transfer(i2c, &msg, 1) != 1) return -EIO;
352         return 0;
353 }
354
355 static struct stv0299_config alps_bsru6_config = {
356
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,
368 };
369
370 static int alps_tdbe2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
371 {
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) };
376
377         div = (params->frequency + 35937500 + 31250) / 62500;
378
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);
383
384         if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
385         return 0;
386 }
387
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,
394 };
395
396 static int grundig_29504_401_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
397 {
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) };
403
404         div = (36125000 + params->frequency) / 166666;
405
406         cfg = 0x88;
407
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;
413
414         if (params->frequency < 175000000) band_select = 0x0e;
415         else if (params->frequency < 470000000) band_select = 0x05;
416         else band_select = 0x03;
417
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;
422
423         if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
424         return 0;
425 }
426
427 static struct l64781_config grundig_29504_401_config = {
428         .demod_address = 0x55,
429         .pll_set = grundig_29504_401_pll_set,
430 };
431
432 static int grundig_29504_451_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
433 {
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) };
438
439         div = params->frequency / 125;
440         data[0] = (div >> 8) & 0x7f;
441         data[1] = div & 0xff;
442         data[2] = 0x8e;
443         data[3] = 0x00;
444
445         if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
446         return 0;
447 }
448
449 static struct tda8083_config grundig_29504_451_config = {
450         .demod_address = 0x68,
451         .pll_set = grundig_29504_451_pll_set,
452 };
453
454 static int s5h1420_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u32* freqout)
455 {
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) };
460
461         div = params->frequency / 1000;
462         data[0] = (div >> 8) & 0x7f;
463         data[1] = div & 0xff;
464         data[2] = 0xc2;
465
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;
474
475         if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
476
477         *freqout = div * 1000;
478         return 0;
479 }
480
481 static struct s5h1420_config s5h1420_config = {
482         .demod_address = 0x53,
483         .invert = 1,
484         .pll_set = s5h1420_pll_set,
485 };
486
487 static u8 read_pwm(struct budget* budget)
488 {
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} };
493
494         if ((i2c_transfer(&budget->i2c_adap, msg, 2) != 2) || (pwm == 0xff))
495                 pwm = 0x48;
496
497         return pwm;
498 }
499
500 static void frontend_init(struct budget *budget)
501 {
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;
512                 }
513
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;
521                 }
522                 break;
523
524         case 0x1004: // Hauppauge/TT DVB-C budget (ves1820/ALPS TDBE2(sp5659))
525
526                 budget->dvb_frontend = ves1820_attach(&alps_tdbe2_config, &budget->i2c_adap, read_pwm(budget));
527                 if (budget->dvb_frontend) break;
528                 break;
529
530         case 0x1005: // Hauppauge/TT Nova-T budget (L64781/Grundig 29504-401(tsa5060))
531
532                 budget->dvb_frontend = l64781_attach(&grundig_29504_401_config, &budget->i2c_adap);
533                 if (budget->dvb_frontend) break;
534                 break;
535
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;
541                 }
542                 break;
543
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;
549                 }
550                 break;
551
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;
559                 }
560         }
561
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;
574                 }
575         }
576 }
577
578 static int budget_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_data *info)
579 {
580         struct budget *budget = NULL;
581         int err;
582
583         budget = kmalloc(sizeof(struct budget), GFP_KERNEL);
584         if( NULL == budget ) {
585                 return -ENOMEM;
586         }
587
588         dprintk(2, "dev:%p, info:%p, budget:%p\n", dev, info, budget);
589
590         dev->ext_priv = budget;
591
592         if ((err = ttpci_budget_init (budget, dev, info, THIS_MODULE))) {
593                 printk("==> failed\n");
594                 kfree (budget);
595                 return err;
596         }
597
598         budget->dvb_adapter.priv = budget;
599         frontend_init(budget);
600
601         return 0;
602 }
603
604 static int budget_detach (struct saa7146_dev* dev)
605 {
606         struct budget *budget = (struct budget*) dev->ext_priv;
607         int err;
608
609         if (budget->dvb_frontend) dvb_unregister_frontend(budget->dvb_frontend);
610
611         err = ttpci_budget_deinit (budget);
612
613         kfree (budget);
614         dev->ext_priv = NULL;
615
616         return err;
617 }
618
619 static struct saa7146_extension budget_extension;
620
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);
627
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),
636         {
637                 .vendor    = 0,
638         }
639 };
640
641 MODULE_DEVICE_TABLE(pci, pci_tbl);
642
643 static struct saa7146_extension budget_extension = {
644         .name           = "budget dvb\0",
645         .flags          = 0,
646
647         .module         = THIS_MODULE,
648         .pci_tbl        = pci_tbl,
649         .attach         = budget_attach,
650         .detach         = budget_detach,
651
652         .irq_mask       = MASK_10,
653         .irq_func       = ttpci_budget_irq10_handler,
654 };
655
656 static int __init budget_init(void)
657 {
658         return saa7146_register_extension(&budget_extension);
659 }
660
661 static void __exit budget_exit(void)
662 {
663         saa7146_unregister_extension(&budget_extension);
664 }
665
666 module_init(budget_init);
667 module_exit(budget_exit);
668
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");