blob: bfb80925019aa228f5ea8f4174b82b1545ab8dcc [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
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"
Andrew de Quincey96bf2f22005-07-07 17:57:53 -070043#include "s5h1420.h"
Oliver Endriss2f27bdc2006-02-28 09:31:16 -030044#include "lnbp21.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070045
46static void Set22K (struct budget *budget, int state)
47{
48 struct saa7146_dev *dev=budget->dev;
49 dprintk(2, "budget: %p\n", budget);
50 saa7146_setgpio(dev, 3, (state ? SAA7146_GPIO_OUTHI : SAA7146_GPIO_OUTLO));
51}
52
53/* Diseqc functions only for TT Budget card */
54/* taken from the Skyvision DVB driver by
55 Ralph Metzler <rjkm@metzlerbros.de> */
56
57static void DiseqcSendBit (struct budget *budget, int data)
58{
59 struct saa7146_dev *dev=budget->dev;
60 dprintk(2, "budget: %p\n", budget);
61
62 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI);
63 udelay(data ? 500 : 1000);
64 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
65 udelay(data ? 1000 : 500);
66}
67
68static void DiseqcSendByte (struct budget *budget, int data)
69{
70 int i, par=1, d;
71
72 dprintk(2, "budget: %p\n", budget);
73
74 for (i=7; i>=0; i--) {
75 d = (data>>i)&1;
76 par ^= d;
77 DiseqcSendBit(budget, d);
78 }
79
80 DiseqcSendBit(budget, par);
81}
82
83static int SendDiSEqCMsg (struct budget *budget, int len, u8 *msg, unsigned long burst)
84{
85 struct saa7146_dev *dev=budget->dev;
86 int i;
87
88 dprintk(2, "budget: %p\n", budget);
89
90 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
91 mdelay(16);
92
93 for (i=0; i<len; i++)
94 DiseqcSendByte(budget, msg[i]);
95
96 mdelay(16);
97
98 if (burst!=-1) {
99 if (burst)
100 DiseqcSendByte(budget, 0xff);
101 else {
102 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI);
103 udelay(12500);
104 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
105 }
106 msleep(20);
107 }
108
109 return 0;
110}
111
112/*
113 * Routines for the Fujitsu Siemens Activy budget card
114 * 22 kHz tone and DiSEqC are handled by the frontend.
115 * Voltage must be set here.
Oliver Endrissf49cc152006-01-09 15:25:06 -0200116 * GPIO 1: LNBP EN, GPIO 2: LNBP VSEL
Linus Torvalds1da177e2005-04-16 15:20:36 -0700117 */
118static int SetVoltage_Activy (struct budget *budget, fe_sec_voltage_t voltage)
119{
120 struct saa7146_dev *dev=budget->dev;
121
122 dprintk(2, "budget: %p\n", budget);
123
124 switch (voltage) {
125 case SEC_VOLTAGE_13:
Oliver Endrissf49cc152006-01-09 15:25:06 -0200126 saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127 saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTLO);
128 break;
129 case SEC_VOLTAGE_18:
Oliver Endrissf49cc152006-01-09 15:25:06 -0200130 saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700131 saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTHI);
132 break;
Oliver Endrissf49cc152006-01-09 15:25:06 -0200133 case SEC_VOLTAGE_OFF:
134 saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTLO);
135 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700136 default:
137 return -EINVAL;
138 }
139
140 return 0;
141}
142
143static int siemens_budget_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
144{
145 struct budget* budget = (struct budget*) fe->dvb->priv;
146
147 return SetVoltage_Activy (budget, voltage);
148}
149
150static int budget_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
151{
152 struct budget* budget = (struct budget*) fe->dvb->priv;
153
154 switch (tone) {
155 case SEC_TONE_ON:
156 Set22K (budget, 1);
157 break;
158
159 case SEC_TONE_OFF:
160 Set22K (budget, 0);
161 break;
162
163 default:
164 return -EINVAL;
165 }
166
167 return 0;
168}
169
170static int budget_diseqc_send_master_cmd(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd)
171{
172 struct budget* budget = (struct budget*) fe->dvb->priv;
173
174 SendDiSEqCMsg (budget, cmd->msg_len, cmd->msg, 0);
175
176 return 0;
177}
178
179static int budget_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd)
180{
181 struct budget* budget = (struct budget*) fe->dvb->priv;
182
183 SendDiSEqCMsg (budget, 0, NULL, minicmd);
184
185 return 0;
186}
187
188static int alps_bsrv2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
189{
190 struct budget* budget = (struct budget*) fe->dvb->priv;
191 u8 pwr = 0;
192 u8 buf[4];
193 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
194 u32 div = (params->frequency + 479500) / 125;
195
196 if (params->frequency > 2000000) pwr = 3;
197 else if (params->frequency > 1800000) pwr = 2;
198 else if (params->frequency > 1600000) pwr = 1;
199 else if (params->frequency > 1200000) pwr = 0;
200 else if (params->frequency >= 1100000) pwr = 1;
201 else pwr = 2;
202
203 buf[0] = (div >> 8) & 0x7f;
204 buf[1] = div & 0xff;
205 buf[2] = ((div & 0x18000) >> 10) | 0x95;
206 buf[3] = (pwr << 6) | 0x30;
207
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -0800208 // NOTE: since we're using a prescaler of 2, we set the
Linus Torvalds1da177e2005-04-16 15:20:36 -0700209 // divisor frequency to 62.5kHz and divide by 125 above
210
211 if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
212 return 0;
213}
214
215static struct ves1x93_config alps_bsrv2_config =
216{
217 .demod_address = 0x08,
218 .xin = 90100000UL,
219 .invert_pwm = 0,
220 .pll_set = alps_bsrv2_pll_set,
221};
222
223static u8 alps_bsru6_inittab[] = {
224 0x01, 0x15,
225 0x02, 0x00,
226 0x03, 0x00,
Martin Zwickel9691bb12005-11-08 21:35:10 -0800227 0x04, 0x7d, /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700228 0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */
229 0x06, 0x40, /* DAC not used, set to high impendance mode */
230 0x07, 0x00, /* DAC LSB */
231 0x08, 0x40, /* DiSEqC off, LNB power on OP2/LOCK pin on */
232 0x09, 0x00, /* FIFO */
233 0x0c, 0x51, /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */
234 0x0d, 0x82, /* DC offset compensation = ON, beta_agc1 = 2 */
235 0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */
236 0x10, 0x3f, // AGC2 0x3d
237 0x11, 0x84,
Oliver Endrissff29d062005-11-08 21:35:43 -0800238 0x12, 0xb9,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239 0x15, 0xc9, // lock detector threshold
240 0x16, 0x00,
241 0x17, 0x00,
242 0x18, 0x00,
243 0x19, 0x00,
244 0x1a, 0x00,
245 0x1f, 0x50,
246 0x20, 0x00,
247 0x21, 0x00,
248 0x22, 0x00,
249 0x23, 0x00,
250 0x28, 0x00, // out imp: normal out type: parallel FEC mode:0
251 0x29, 0x1e, // 1/2 threshold
252 0x2a, 0x14, // 2/3 threshold
253 0x2b, 0x0f, // 3/4 threshold
254 0x2c, 0x09, // 5/6 threshold
255 0x2d, 0x05, // 7/8 threshold
256 0x2e, 0x01,
257 0x31, 0x1f, // test all FECs
258 0x32, 0x19, // viterbi and synchro search
259 0x33, 0xfc, // rs control
260 0x34, 0x93, // error control
261 0x0f, 0x52,
262 0xff, 0xff
263};
264
265static int alps_bsru6_set_symbol_rate(struct dvb_frontend* fe, u32 srate, u32 ratio)
266{
267 u8 aclk = 0;
268 u8 bclk = 0;
269
270 if (srate < 1500000) { aclk = 0xb7; bclk = 0x47; }
271 else if (srate < 3000000) { aclk = 0xb7; bclk = 0x4b; }
272 else if (srate < 7000000) { aclk = 0xb7; bclk = 0x4f; }
273 else if (srate < 14000000) { aclk = 0xb7; bclk = 0x53; }
274 else if (srate < 30000000) { aclk = 0xb6; bclk = 0x53; }
275 else if (srate < 45000000) { aclk = 0xb4; bclk = 0x51; }
276
277 stv0299_writereg (fe, 0x13, aclk);
278 stv0299_writereg (fe, 0x14, bclk);
279 stv0299_writereg (fe, 0x1f, (ratio >> 16) & 0xff);
280 stv0299_writereg (fe, 0x20, (ratio >> 8) & 0xff);
281 stv0299_writereg (fe, 0x21, (ratio ) & 0xf0);
282
283 return 0;
284}
285
Andreas Oberrittercfbfce12005-09-09 13:02:30 -0700286static int alps_bsru6_pll_set(struct dvb_frontend* fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters* params)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288 u8 data[4];
289 u32 div;
290 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
291
292 if ((params->frequency < 950000) || (params->frequency > 2150000)) return -EINVAL;
293
294 div = (params->frequency + (125 - 1)) / 125; // round correctly
295 data[0] = (div >> 8) & 0x7f;
296 data[1] = div & 0xff;
297 data[2] = 0x80 | ((div & 0x18000) >> 10) | 4;
298 data[3] = 0xC4;
299
300 if (params->frequency > 1530000) data[3] = 0xc0;
301
Andreas Oberrittercfbfce12005-09-09 13:02:30 -0700302 if (i2c_transfer(i2c, &msg, 1) != 1) return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700303 return 0;
304}
305
306static struct stv0299_config alps_bsru6_config = {
307
308 .demod_address = 0x68,
309 .inittab = alps_bsru6_inittab,
310 .mclk = 88000000UL,
311 .invert = 1,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700312 .skip_reinit = 0,
313 .lock_output = STV0229_LOCKOUTPUT_1,
314 .volt13_op0_op1 = STV0299_VOLT13_OP1,
315 .min_delay_ms = 100,
316 .set_symbol_rate = alps_bsru6_set_symbol_rate,
317 .pll_set = alps_bsru6_pll_set,
318};
319
320static int alps_tdbe2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
321{
322 struct budget* budget = (struct budget*) fe->dvb->priv;
323 u32 div;
324 u8 data[4];
325 struct i2c_msg msg = { .addr = 0x62, .flags = 0, .buf = data, .len = sizeof(data) };
326
327 div = (params->frequency + 35937500 + 31250) / 62500;
328
329 data[0] = (div >> 8) & 0x7f;
330 data[1] = div & 0xff;
331 data[2] = 0x85 | ((div >> 10) & 0x60);
332 data[3] = (params->frequency < 174000000 ? 0x88 : params->frequency < 470000000 ? 0x84 : 0x81);
333
334 if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
335 return 0;
336}
337
338static struct ves1820_config alps_tdbe2_config = {
339 .demod_address = 0x09,
340 .xin = 57840000UL,
341 .invert = 1,
342 .selagc = VES1820_SELAGC_SIGNAMPERR,
343 .pll_set = alps_tdbe2_pll_set,
344};
345
346static int grundig_29504_401_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
347{
348 struct budget* budget = (struct budget*) fe->dvb->priv;
349 u32 div;
350 u8 cfg, cpump, band_select;
351 u8 data[4];
352 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
353
354 div = (36125000 + params->frequency) / 166666;
355
356 cfg = 0x88;
357
358 if (params->frequency < 175000000) cpump = 2;
359 else if (params->frequency < 390000000) cpump = 1;
360 else if (params->frequency < 470000000) cpump = 2;
361 else if (params->frequency < 750000000) cpump = 1;
362 else cpump = 3;
363
364 if (params->frequency < 175000000) band_select = 0x0e;
365 else if (params->frequency < 470000000) band_select = 0x05;
366 else band_select = 0x03;
367
368 data[0] = (div >> 8) & 0x7f;
369 data[1] = div & 0xff;
370 data[2] = ((div >> 10) & 0x60) | cfg;
371 data[3] = (cpump << 6) | band_select;
372
373 if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
374 return 0;
375}
376
377static struct l64781_config grundig_29504_401_config = {
378 .demod_address = 0x55,
379 .pll_set = grundig_29504_401_pll_set,
380};
381
382static int grundig_29504_451_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
383{
384 struct budget* budget = (struct budget*) fe->dvb->priv;
385 u32 div;
386 u8 data[4];
387 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
388
389 div = params->frequency / 125;
390 data[0] = (div >> 8) & 0x7f;
391 data[1] = div & 0xff;
392 data[2] = 0x8e;
393 data[3] = 0x00;
394
395 if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
396 return 0;
397}
398
399static struct tda8083_config grundig_29504_451_config = {
400 .demod_address = 0x68,
401 .pll_set = grundig_29504_451_pll_set,
402};
403
Andrew de Quincey96bf2f22005-07-07 17:57:53 -0700404static int s5h1420_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u32* freqout)
405{
406 struct budget* budget = (struct budget*) fe->dvb->priv;
407 u32 div;
408 u8 data[4];
409 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
410
411 div = params->frequency / 1000;
412 data[0] = (div >> 8) & 0x7f;
413 data[1] = div & 0xff;
414 data[2] = 0xc2;
415
416 if (div < 1450)
417 data[3] = 0x00;
418 else if (div < 1850)
419 data[3] = 0x40;
420 else if (div < 2000)
421 data[3] = 0x80;
422 else
423 data[3] = 0xc0;
424
425 if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
426
427 *freqout = div * 1000;
428 return 0;
429}
430
431static struct s5h1420_config s5h1420_config = {
432 .demod_address = 0x53,
Andrew de Quinceya9d6a802005-09-09 13:02:31 -0700433 .invert = 1,
Andrew de Quincey96bf2f22005-07-07 17:57:53 -0700434 .pll_set = s5h1420_pll_set,
435};
436
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437static u8 read_pwm(struct budget* budget)
438{
439 u8 b = 0xff;
440 u8 pwm;
441 struct i2c_msg msg[] = { { .addr = 0x50,.flags = 0,.buf = &b,.len = 1 },
442 { .addr = 0x50,.flags = I2C_M_RD,.buf = &pwm,.len = 1} };
443
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -0800444 if ((i2c_transfer(&budget->i2c_adap, msg, 2) != 2) || (pwm == 0xff))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445 pwm = 0x48;
446
447 return pwm;
448}
449
450static void frontend_init(struct budget *budget)
451{
452 switch(budget->dev->pci->subsystem_device) {
453 case 0x1003: // Hauppauge/TT Nova budget (stv0299/ALPS BSRU6(tsa5059) OR ves1893/ALPS BSRV2(sp5659))
454 case 0x1013:
455 // try the ALPS BSRV2 first of all
456 budget->dvb_frontend = ves1x93_attach(&alps_bsrv2_config, &budget->i2c_adap);
457 if (budget->dvb_frontend) {
458 budget->dvb_frontend->ops->diseqc_send_master_cmd = budget_diseqc_send_master_cmd;
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -0800459 budget->dvb_frontend->ops->diseqc_send_burst = budget_diseqc_send_burst;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460 budget->dvb_frontend->ops->set_tone = budget_set_tone;
461 break;
462 }
463
464 // try the ALPS BSRU6 now
465 budget->dvb_frontend = stv0299_attach(&alps_bsru6_config, &budget->i2c_adap);
466 if (budget->dvb_frontend) {
467 budget->dvb_frontend->ops->diseqc_send_master_cmd = budget_diseqc_send_master_cmd;
468 budget->dvb_frontend->ops->diseqc_send_burst = budget_diseqc_send_burst;
469 budget->dvb_frontend->ops->set_tone = budget_set_tone;
470 break;
471 }
472 break;
473
474 case 0x1004: // Hauppauge/TT DVB-C budget (ves1820/ALPS TDBE2(sp5659))
475
476 budget->dvb_frontend = ves1820_attach(&alps_tdbe2_config, &budget->i2c_adap, read_pwm(budget));
477 if (budget->dvb_frontend) break;
478 break;
479
480 case 0x1005: // Hauppauge/TT Nova-T budget (L64781/Grundig 29504-401(tsa5060))
481
482 budget->dvb_frontend = l64781_attach(&grundig_29504_401_config, &budget->i2c_adap);
483 if (budget->dvb_frontend) break;
484 break;
485
486 case 0x4f60: // Fujitsu Siemens Activy Budget-S PCI rev AL (stv0299/ALPS BSRU6(tsa5059))
487 budget->dvb_frontend = stv0299_attach(&alps_bsru6_config, &budget->i2c_adap);
488 if (budget->dvb_frontend) {
489 budget->dvb_frontend->ops->set_voltage = siemens_budget_set_voltage;
Oliver Endrissf49cc152006-01-09 15:25:06 -0200490 budget->dvb_frontend->ops->dishnetwork_send_legacy_command = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700491 }
492 break;
493
494 case 0x4f61: // Fujitsu Siemens Activy Budget-S PCI rev GR (tda8083/Grundig 29504-451(tsa5522))
495 budget->dvb_frontend = tda8083_attach(&grundig_29504_451_config, &budget->i2c_adap);
496 if (budget->dvb_frontend) {
497 budget->dvb_frontend->ops->set_voltage = siemens_budget_set_voltage;
Oliver Endrissf49cc152006-01-09 15:25:06 -0200498 budget->dvb_frontend->ops->dishnetwork_send_legacy_command = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499 }
500 break;
Andrew de Quincey96bf2f22005-07-07 17:57:53 -0700501
502 case 0x1016: // Hauppauge/TT Nova-S SE (samsung s5h1420/????(tda8260))
503 budget->dvb_frontend = s5h1420_attach(&s5h1420_config, &budget->i2c_adap);
504 if (budget->dvb_frontend) {
Oliver Endriss2f27bdc2006-02-28 09:31:16 -0300505 if (lnbp21_init(budget->dvb_frontend, &budget->i2c_adap, 0, 0)) {
Martin Zwickel9691bb12005-11-08 21:35:10 -0800506 printk("%s: No LNBP21 found!\n", __FUNCTION__);
507 goto error_out;
508 }
Andrew de Quincey96bf2f22005-07-07 17:57:53 -0700509 break;
510 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700511 }
512
513 if (budget->dvb_frontend == NULL) {
514 printk("budget: A frontend driver was not found for device %04x/%04x subsystem %04x/%04x\n",
515 budget->dev->pci->vendor,
516 budget->dev->pci->device,
517 budget->dev->pci->subsystem_vendor,
518 budget->dev->pci->subsystem_device);
519 } else {
Martin Zwickel9691bb12005-11-08 21:35:10 -0800520 if (dvb_register_frontend(&budget->dvb_adapter, budget->dvb_frontend))
521 goto error_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522 }
Martin Zwickel9691bb12005-11-08 21:35:10 -0800523 return;
524
525error_out:
526 printk("budget: Frontend registration failed!\n");
527 if (budget->dvb_frontend->ops->release)
528 budget->dvb_frontend->ops->release(budget->dvb_frontend);
529 budget->dvb_frontend = NULL;
530 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700531}
532
533static int budget_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_data *info)
534{
535 struct budget *budget = NULL;
536 int err;
537
538 budget = kmalloc(sizeof(struct budget), GFP_KERNEL);
539 if( NULL == budget ) {
540 return -ENOMEM;
541 }
542
543 dprintk(2, "dev:%p, info:%p, budget:%p\n", dev, info, budget);
544
545 dev->ext_priv = budget;
546
547 if ((err = ttpci_budget_init (budget, dev, info, THIS_MODULE))) {
548 printk("==> failed\n");
549 kfree (budget);
550 return err;
551 }
552
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -0700553 budget->dvb_adapter.priv = budget;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700554 frontend_init(budget);
555
556 return 0;
557}
558
559static int budget_detach (struct saa7146_dev* dev)
560{
561 struct budget *budget = (struct budget*) dev->ext_priv;
562 int err;
563
564 if (budget->dvb_frontend) dvb_unregister_frontend(budget->dvb_frontend);
565
566 err = ttpci_budget_deinit (budget);
567
568 kfree (budget);
569 dev->ext_priv = NULL;
570
571 return err;
572}
573
574static struct saa7146_extension budget_extension;
575
576MAKE_BUDGET_INFO(ttbs, "TT-Budget/WinTV-NOVA-S PCI", BUDGET_TT);
577MAKE_BUDGET_INFO(ttbc, "TT-Budget/WinTV-NOVA-C PCI", BUDGET_TT);
578MAKE_BUDGET_INFO(ttbt, "TT-Budget/WinTV-NOVA-T PCI", BUDGET_TT);
579MAKE_BUDGET_INFO(satel, "SATELCO Multimedia PCI", BUDGET_TT_HW_DISEQC);
580MAKE_BUDGET_INFO(fsacs0, "Fujitsu Siemens Activy Budget-S PCI (rev GR/grundig frontend)", BUDGET_FS_ACTIVY);
581MAKE_BUDGET_INFO(fsacs1, "Fujitsu Siemens Activy Budget-S PCI (rev AL/alps frontend)", BUDGET_FS_ACTIVY);
582
583static struct pci_device_id pci_tbl[] = {
584 MAKE_EXTENSION_PCI(ttbs, 0x13c2, 0x1003),
585 MAKE_EXTENSION_PCI(ttbc, 0x13c2, 0x1004),
586 MAKE_EXTENSION_PCI(ttbt, 0x13c2, 0x1005),
587 MAKE_EXTENSION_PCI(satel, 0x13c2, 0x1013),
Andrew de Quincey96bf2f22005-07-07 17:57:53 -0700588 MAKE_EXTENSION_PCI(ttbs, 0x13c2, 0x1016),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700589 MAKE_EXTENSION_PCI(fsacs1,0x1131, 0x4f60),
590 MAKE_EXTENSION_PCI(fsacs0,0x1131, 0x4f61),
591 {
592 .vendor = 0,
593 }
594};
595
596MODULE_DEVICE_TABLE(pci, pci_tbl);
597
598static struct saa7146_extension budget_extension = {
599 .name = "budget dvb\0",
Oliver Endriss69459f3d2005-12-01 00:51:48 -0800600 .flags = SAA7146_I2C_SHORT_DELAY,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700601
602 .module = THIS_MODULE,
603 .pci_tbl = pci_tbl,
604 .attach = budget_attach,
605 .detach = budget_detach,
606
607 .irq_mask = MASK_10,
608 .irq_func = ttpci_budget_irq10_handler,
609};
610
611static int __init budget_init(void)
612{
613 return saa7146_register_extension(&budget_extension);
614}
615
616static void __exit budget_exit(void)
617{
618 saa7146_unregister_extension(&budget_extension);
619}
620
621module_init(budget_init);
622module_exit(budget_exit);
623
624MODULE_LICENSE("GPL");
625MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, Michael Hunold, others");
626MODULE_DESCRIPTION("driver for the SAA7146 based so-called "
627 "budget PCI DVB cards by Siemens, Technotrend, Hauppauge");