blob: 0f6ead848e4d153b0ee10df81492faed40e07144 [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"
Linus Torvalds1da177e2005-04-16 15:20:36 -070044
45static 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
56static 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
67static 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
82static 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 */
116static 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
136static 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
143static 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
163static 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
172static 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
Andrew de Quincey96bf2f22005-07-07 17:57:53 -0700181static 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
209static 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
Martin Zwickel9691bb12005-11-08 21:35:10 -0800229static int lnbp21_init(struct budget* budget)
Andrew de Quincey96bf2f22005-07-07 17:57:53 -0700230{
231 u8 buf = 0x00;
232 struct i2c_msg msg = { .addr = 0x08, .flags = 0, .buf = &buf, .len = sizeof(buf) };
233
Martin Zwickel9691bb12005-11-08 21:35:10 -0800234 if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1)
235 return -EIO;
236 return 0;
Andrew de Quincey96bf2f22005-07-07 17:57:53 -0700237}
238
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239static int alps_bsrv2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
240{
241 struct budget* budget = (struct budget*) fe->dvb->priv;
242 u8 pwr = 0;
243 u8 buf[4];
244 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
245 u32 div = (params->frequency + 479500) / 125;
246
247 if (params->frequency > 2000000) pwr = 3;
248 else if (params->frequency > 1800000) pwr = 2;
249 else if (params->frequency > 1600000) pwr = 1;
250 else if (params->frequency > 1200000) pwr = 0;
251 else if (params->frequency >= 1100000) pwr = 1;
252 else pwr = 2;
253
254 buf[0] = (div >> 8) & 0x7f;
255 buf[1] = div & 0xff;
256 buf[2] = ((div & 0x18000) >> 10) | 0x95;
257 buf[3] = (pwr << 6) | 0x30;
258
259 // NOTE: since we're using a prescaler of 2, we set the
260 // divisor frequency to 62.5kHz and divide by 125 above
261
262 if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
263 return 0;
264}
265
266static struct ves1x93_config alps_bsrv2_config =
267{
268 .demod_address = 0x08,
269 .xin = 90100000UL,
270 .invert_pwm = 0,
271 .pll_set = alps_bsrv2_pll_set,
272};
273
274static u8 alps_bsru6_inittab[] = {
275 0x01, 0x15,
276 0x02, 0x00,
277 0x03, 0x00,
Martin Zwickel9691bb12005-11-08 21:35:10 -0800278 0x04, 0x7d, /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279 0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */
280 0x06, 0x40, /* DAC not used, set to high impendance mode */
281 0x07, 0x00, /* DAC LSB */
282 0x08, 0x40, /* DiSEqC off, LNB power on OP2/LOCK pin on */
283 0x09, 0x00, /* FIFO */
284 0x0c, 0x51, /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */
285 0x0d, 0x82, /* DC offset compensation = ON, beta_agc1 = 2 */
286 0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */
287 0x10, 0x3f, // AGC2 0x3d
288 0x11, 0x84,
289 0x12, 0xb5, // Lock detect: -64 Carrier freq detect:on
290 0x15, 0xc9, // lock detector threshold
291 0x16, 0x00,
292 0x17, 0x00,
293 0x18, 0x00,
294 0x19, 0x00,
295 0x1a, 0x00,
296 0x1f, 0x50,
297 0x20, 0x00,
298 0x21, 0x00,
299 0x22, 0x00,
300 0x23, 0x00,
301 0x28, 0x00, // out imp: normal out type: parallel FEC mode:0
302 0x29, 0x1e, // 1/2 threshold
303 0x2a, 0x14, // 2/3 threshold
304 0x2b, 0x0f, // 3/4 threshold
305 0x2c, 0x09, // 5/6 threshold
306 0x2d, 0x05, // 7/8 threshold
307 0x2e, 0x01,
308 0x31, 0x1f, // test all FECs
309 0x32, 0x19, // viterbi and synchro search
310 0x33, 0xfc, // rs control
311 0x34, 0x93, // error control
312 0x0f, 0x52,
313 0xff, 0xff
314};
315
316static int alps_bsru6_set_symbol_rate(struct dvb_frontend* fe, u32 srate, u32 ratio)
317{
318 u8 aclk = 0;
319 u8 bclk = 0;
320
321 if (srate < 1500000) { aclk = 0xb7; bclk = 0x47; }
322 else if (srate < 3000000) { aclk = 0xb7; bclk = 0x4b; }
323 else if (srate < 7000000) { aclk = 0xb7; bclk = 0x4f; }
324 else if (srate < 14000000) { aclk = 0xb7; bclk = 0x53; }
325 else if (srate < 30000000) { aclk = 0xb6; bclk = 0x53; }
326 else if (srate < 45000000) { aclk = 0xb4; bclk = 0x51; }
327
328 stv0299_writereg (fe, 0x13, aclk);
329 stv0299_writereg (fe, 0x14, bclk);
330 stv0299_writereg (fe, 0x1f, (ratio >> 16) & 0xff);
331 stv0299_writereg (fe, 0x20, (ratio >> 8) & 0xff);
332 stv0299_writereg (fe, 0x21, (ratio ) & 0xf0);
333
334 return 0;
335}
336
Andreas Oberrittercfbfce12005-09-09 13:02:30 -0700337static 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 -0700338{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700339 u8 data[4];
340 u32 div;
341 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
342
343 if ((params->frequency < 950000) || (params->frequency > 2150000)) return -EINVAL;
344
345 div = (params->frequency + (125 - 1)) / 125; // round correctly
346 data[0] = (div >> 8) & 0x7f;
347 data[1] = div & 0xff;
348 data[2] = 0x80 | ((div & 0x18000) >> 10) | 4;
349 data[3] = 0xC4;
350
351 if (params->frequency > 1530000) data[3] = 0xc0;
352
Andreas Oberrittercfbfce12005-09-09 13:02:30 -0700353 if (i2c_transfer(i2c, &msg, 1) != 1) return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700354 return 0;
355}
356
357static struct stv0299_config alps_bsru6_config = {
358
359 .demod_address = 0x68,
360 .inittab = alps_bsru6_inittab,
361 .mclk = 88000000UL,
362 .invert = 1,
363 .enhanced_tuning = 0,
364 .skip_reinit = 0,
365 .lock_output = STV0229_LOCKOUTPUT_1,
366 .volt13_op0_op1 = STV0299_VOLT13_OP1,
367 .min_delay_ms = 100,
368 .set_symbol_rate = alps_bsru6_set_symbol_rate,
369 .pll_set = alps_bsru6_pll_set,
370};
371
Martin Zwickel9691bb12005-11-08 21:35:10 -0800372static u8 alps_bsbe1_inittab[] = {
373 0x01, 0x15,
374 0x02, 0x30,
375 0x03, 0x00,
376 0x04, 0x7d, /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */
377 0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */
378 0x06, 0x40, /* DAC not used, set to high impendance mode */
379 0x07, 0x00, /* DAC LSB */
380 0x08, 0x40, /* DiSEqC off, LNB power on OP2/LOCK pin on */
381 0x09, 0x00, /* FIFO */
382 0x0c, 0x51, /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */
383 0x0d, 0x82, /* DC offset compensation = ON, beta_agc1 = 2 */
384 0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */
385 0x10, 0x3f, // AGC2 0x3d
386 0x11, 0x84,
387 0x12, 0xb5, // Lock detect: -64 Carrier freq detect:on
388 0x15, 0xc9, // lock detector threshold
389 0x16, 0x00,
390 0x17, 0x00,
391 0x18, 0x00,
392 0x19, 0x00,
393 0x1a, 0x00,
394 0x1f, 0x50,
395 0x20, 0x00,
396 0x21, 0x00,
397 0x22, 0x00,
398 0x23, 0x00,
399 0x28, 0x00, // out imp: normal out type: parallel FEC mode:0
400 0x29, 0x1e, // 1/2 threshold
401 0x2a, 0x14, // 2/3 threshold
402 0x2b, 0x0f, // 3/4 threshold
403 0x2c, 0x09, // 5/6 threshold
404 0x2d, 0x05, // 7/8 threshold
405 0x2e, 0x01,
406 0x31, 0x1f, // test all FECs
407 0x32, 0x19, // viterbi and synchro search
408 0x33, 0xfc, // rs control
409 0x34, 0x93, // error control
410 0x0f, 0x92, // 0x80 = inverse AGC
411 0xff, 0xff
412};
413
414static int alps_bsbe1_pll_set(struct dvb_frontend* fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters* params)
415{
416 int ret;
417 u8 data[4];
418 u32 div;
419 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
420
421 if ((params->frequency < 950000) || (params->frequency > 2150000))
422 return -EINVAL;
423
424 div = (params->frequency + (125 - 1)) / 125; // round correctly
425 data[0] = (div >> 8) & 0x7f;
426 data[1] = div & 0xff;
427 data[2] = 0x80 | ((div & 0x18000) >> 10) | 4;
428 data[3] = (params->frequency > 1530000) ? 0xE0 : 0xE4;
429
430 ret = i2c_transfer(i2c, &msg, 1);
431 return (ret != 1) ? -EIO : 0;
432}
433
434static struct stv0299_config alps_bsbe1_config = {
435 .demod_address = 0x68,
436 .inittab = alps_bsbe1_inittab,
437 .mclk = 88000000UL,
438 .invert = 1,
439 .enhanced_tuning = 0,
440 .skip_reinit = 0,
441 .min_delay_ms = 100,
442 .set_symbol_rate = alps_bsru6_set_symbol_rate,
443 .pll_set = alps_bsbe1_pll_set,
444};
445
Linus Torvalds1da177e2005-04-16 15:20:36 -0700446static int alps_tdbe2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
447{
448 struct budget* budget = (struct budget*) fe->dvb->priv;
449 u32 div;
450 u8 data[4];
451 struct i2c_msg msg = { .addr = 0x62, .flags = 0, .buf = data, .len = sizeof(data) };
452
453 div = (params->frequency + 35937500 + 31250) / 62500;
454
455 data[0] = (div >> 8) & 0x7f;
456 data[1] = div & 0xff;
457 data[2] = 0x85 | ((div >> 10) & 0x60);
458 data[3] = (params->frequency < 174000000 ? 0x88 : params->frequency < 470000000 ? 0x84 : 0x81);
459
460 if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
461 return 0;
462}
463
464static struct ves1820_config alps_tdbe2_config = {
465 .demod_address = 0x09,
466 .xin = 57840000UL,
467 .invert = 1,
468 .selagc = VES1820_SELAGC_SIGNAMPERR,
469 .pll_set = alps_tdbe2_pll_set,
470};
471
472static int grundig_29504_401_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
473{
474 struct budget* budget = (struct budget*) fe->dvb->priv;
475 u32 div;
476 u8 cfg, cpump, band_select;
477 u8 data[4];
478 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
479
480 div = (36125000 + params->frequency) / 166666;
481
482 cfg = 0x88;
483
484 if (params->frequency < 175000000) cpump = 2;
485 else if (params->frequency < 390000000) cpump = 1;
486 else if (params->frequency < 470000000) cpump = 2;
487 else if (params->frequency < 750000000) cpump = 1;
488 else cpump = 3;
489
490 if (params->frequency < 175000000) band_select = 0x0e;
491 else if (params->frequency < 470000000) band_select = 0x05;
492 else band_select = 0x03;
493
494 data[0] = (div >> 8) & 0x7f;
495 data[1] = div & 0xff;
496 data[2] = ((div >> 10) & 0x60) | cfg;
497 data[3] = (cpump << 6) | band_select;
498
499 if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
500 return 0;
501}
502
503static struct l64781_config grundig_29504_401_config = {
504 .demod_address = 0x55,
505 .pll_set = grundig_29504_401_pll_set,
506};
507
508static int grundig_29504_451_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
509{
510 struct budget* budget = (struct budget*) fe->dvb->priv;
511 u32 div;
512 u8 data[4];
513 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
514
515 div = params->frequency / 125;
516 data[0] = (div >> 8) & 0x7f;
517 data[1] = div & 0xff;
518 data[2] = 0x8e;
519 data[3] = 0x00;
520
521 if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
522 return 0;
523}
524
525static struct tda8083_config grundig_29504_451_config = {
526 .demod_address = 0x68,
527 .pll_set = grundig_29504_451_pll_set,
528};
529
Andrew de Quincey96bf2f22005-07-07 17:57:53 -0700530static int s5h1420_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u32* freqout)
531{
532 struct budget* budget = (struct budget*) fe->dvb->priv;
533 u32 div;
534 u8 data[4];
535 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
536
537 div = params->frequency / 1000;
538 data[0] = (div >> 8) & 0x7f;
539 data[1] = div & 0xff;
540 data[2] = 0xc2;
541
542 if (div < 1450)
543 data[3] = 0x00;
544 else if (div < 1850)
545 data[3] = 0x40;
546 else if (div < 2000)
547 data[3] = 0x80;
548 else
549 data[3] = 0xc0;
550
551 if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
552
553 *freqout = div * 1000;
554 return 0;
555}
556
557static struct s5h1420_config s5h1420_config = {
558 .demod_address = 0x53,
Andrew de Quinceya9d6a802005-09-09 13:02:31 -0700559 .invert = 1,
Andrew de Quincey96bf2f22005-07-07 17:57:53 -0700560 .pll_set = s5h1420_pll_set,
561};
562
Linus Torvalds1da177e2005-04-16 15:20:36 -0700563static u8 read_pwm(struct budget* budget)
564{
565 u8 b = 0xff;
566 u8 pwm;
567 struct i2c_msg msg[] = { { .addr = 0x50,.flags = 0,.buf = &b,.len = 1 },
568 { .addr = 0x50,.flags = I2C_M_RD,.buf = &pwm,.len = 1} };
569
570 if ((i2c_transfer(&budget->i2c_adap, msg, 2) != 2) || (pwm == 0xff))
571 pwm = 0x48;
572
573 return pwm;
574}
575
576static void frontend_init(struct budget *budget)
577{
578 switch(budget->dev->pci->subsystem_device) {
Martin Zwickel9691bb12005-11-08 21:35:10 -0800579 case 0x1017:
580 // try the ALPS BSBE1 now
581 budget->dvb_frontend = stv0299_attach(&alps_bsbe1_config, &budget->i2c_adap);
582 if (budget->dvb_frontend) {
583 budget->dvb_frontend->ops->set_voltage = lnbp21_set_voltage;
584 budget->dvb_frontend->ops->enable_high_lnb_voltage = lnbp21_enable_high_lnb_voltage;
585 if (lnbp21_init(budget)) {
586 printk("%s: No LNBP21 found!\n", __FUNCTION__);
587 goto error_out;
588 }
589 }
590
591 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700592 case 0x1003: // Hauppauge/TT Nova budget (stv0299/ALPS BSRU6(tsa5059) OR ves1893/ALPS BSRV2(sp5659))
593 case 0x1013:
594 // try the ALPS BSRV2 first of all
595 budget->dvb_frontend = ves1x93_attach(&alps_bsrv2_config, &budget->i2c_adap);
596 if (budget->dvb_frontend) {
597 budget->dvb_frontend->ops->diseqc_send_master_cmd = budget_diseqc_send_master_cmd;
598 budget->dvb_frontend->ops->diseqc_send_burst = budget_diseqc_send_burst;
599 budget->dvb_frontend->ops->set_tone = budget_set_tone;
600 break;
601 }
602
603 // try the ALPS BSRU6 now
604 budget->dvb_frontend = stv0299_attach(&alps_bsru6_config, &budget->i2c_adap);
605 if (budget->dvb_frontend) {
606 budget->dvb_frontend->ops->diseqc_send_master_cmd = budget_diseqc_send_master_cmd;
607 budget->dvb_frontend->ops->diseqc_send_burst = budget_diseqc_send_burst;
608 budget->dvb_frontend->ops->set_tone = budget_set_tone;
609 break;
610 }
611 break;
612
613 case 0x1004: // Hauppauge/TT DVB-C budget (ves1820/ALPS TDBE2(sp5659))
614
615 budget->dvb_frontend = ves1820_attach(&alps_tdbe2_config, &budget->i2c_adap, read_pwm(budget));
616 if (budget->dvb_frontend) break;
617 break;
618
619 case 0x1005: // Hauppauge/TT Nova-T budget (L64781/Grundig 29504-401(tsa5060))
620
621 budget->dvb_frontend = l64781_attach(&grundig_29504_401_config, &budget->i2c_adap);
622 if (budget->dvb_frontend) break;
623 break;
624
625 case 0x4f60: // Fujitsu Siemens Activy Budget-S PCI rev AL (stv0299/ALPS BSRU6(tsa5059))
626 budget->dvb_frontend = stv0299_attach(&alps_bsru6_config, &budget->i2c_adap);
627 if (budget->dvb_frontend) {
628 budget->dvb_frontend->ops->set_voltage = siemens_budget_set_voltage;
629 break;
630 }
631 break;
632
633 case 0x4f61: // Fujitsu Siemens Activy Budget-S PCI rev GR (tda8083/Grundig 29504-451(tsa5522))
634 budget->dvb_frontend = tda8083_attach(&grundig_29504_451_config, &budget->i2c_adap);
635 if (budget->dvb_frontend) {
636 budget->dvb_frontend->ops->set_voltage = siemens_budget_set_voltage;
637 break;
638 }
639 break;
Andrew de Quincey96bf2f22005-07-07 17:57:53 -0700640
641 case 0x1016: // Hauppauge/TT Nova-S SE (samsung s5h1420/????(tda8260))
642 budget->dvb_frontend = s5h1420_attach(&s5h1420_config, &budget->i2c_adap);
643 if (budget->dvb_frontend) {
644 budget->dvb_frontend->ops->set_voltage = lnbp21_set_voltage;
645 budget->dvb_frontend->ops->enable_high_lnb_voltage = lnbp21_enable_high_lnb_voltage;
Martin Zwickel9691bb12005-11-08 21:35:10 -0800646 if (lnbp21_init(budget)) {
647 printk("%s: No LNBP21 found!\n", __FUNCTION__);
648 goto error_out;
649 }
Andrew de Quincey96bf2f22005-07-07 17:57:53 -0700650 break;
651 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700652 }
653
654 if (budget->dvb_frontend == NULL) {
655 printk("budget: A frontend driver was not found for device %04x/%04x subsystem %04x/%04x\n",
656 budget->dev->pci->vendor,
657 budget->dev->pci->device,
658 budget->dev->pci->subsystem_vendor,
659 budget->dev->pci->subsystem_device);
660 } else {
Martin Zwickel9691bb12005-11-08 21:35:10 -0800661 if (dvb_register_frontend(&budget->dvb_adapter, budget->dvb_frontend))
662 goto error_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663 }
Martin Zwickel9691bb12005-11-08 21:35:10 -0800664 return;
665
666error_out:
667 printk("budget: Frontend registration failed!\n");
668 if (budget->dvb_frontend->ops->release)
669 budget->dvb_frontend->ops->release(budget->dvb_frontend);
670 budget->dvb_frontend = NULL;
671 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700672}
673
674static int budget_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_data *info)
675{
676 struct budget *budget = NULL;
677 int err;
678
679 budget = kmalloc(sizeof(struct budget), GFP_KERNEL);
680 if( NULL == budget ) {
681 return -ENOMEM;
682 }
683
684 dprintk(2, "dev:%p, info:%p, budget:%p\n", dev, info, budget);
685
686 dev->ext_priv = budget;
687
688 if ((err = ttpci_budget_init (budget, dev, info, THIS_MODULE))) {
689 printk("==> failed\n");
690 kfree (budget);
691 return err;
692 }
693
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -0700694 budget->dvb_adapter.priv = budget;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700695 frontend_init(budget);
696
697 return 0;
698}
699
700static int budget_detach (struct saa7146_dev* dev)
701{
702 struct budget *budget = (struct budget*) dev->ext_priv;
703 int err;
704
705 if (budget->dvb_frontend) dvb_unregister_frontend(budget->dvb_frontend);
706
707 err = ttpci_budget_deinit (budget);
708
709 kfree (budget);
710 dev->ext_priv = NULL;
711
712 return err;
713}
714
715static struct saa7146_extension budget_extension;
716
Martin Zwickel9691bb12005-11-08 21:35:10 -0800717MAKE_BUDGET_INFO(ttbs2, "TT-Budget/WinTV-NOVA-S PCI (rev AL/alps bsbe1 lnbp21 frontend)", BUDGET_TT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700718MAKE_BUDGET_INFO(ttbs, "TT-Budget/WinTV-NOVA-S PCI", BUDGET_TT);
719MAKE_BUDGET_INFO(ttbc, "TT-Budget/WinTV-NOVA-C PCI", BUDGET_TT);
720MAKE_BUDGET_INFO(ttbt, "TT-Budget/WinTV-NOVA-T PCI", BUDGET_TT);
721MAKE_BUDGET_INFO(satel, "SATELCO Multimedia PCI", BUDGET_TT_HW_DISEQC);
722MAKE_BUDGET_INFO(fsacs0, "Fujitsu Siemens Activy Budget-S PCI (rev GR/grundig frontend)", BUDGET_FS_ACTIVY);
723MAKE_BUDGET_INFO(fsacs1, "Fujitsu Siemens Activy Budget-S PCI (rev AL/alps frontend)", BUDGET_FS_ACTIVY);
724
725static struct pci_device_id pci_tbl[] = {
726 MAKE_EXTENSION_PCI(ttbs, 0x13c2, 0x1003),
727 MAKE_EXTENSION_PCI(ttbc, 0x13c2, 0x1004),
728 MAKE_EXTENSION_PCI(ttbt, 0x13c2, 0x1005),
729 MAKE_EXTENSION_PCI(satel, 0x13c2, 0x1013),
Martin Zwickel9691bb12005-11-08 21:35:10 -0800730 MAKE_EXTENSION_PCI(ttbs2, 0x13c2, 0x1017),
Andrew de Quincey96bf2f22005-07-07 17:57:53 -0700731 MAKE_EXTENSION_PCI(ttbs, 0x13c2, 0x1016),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700732 MAKE_EXTENSION_PCI(fsacs1,0x1131, 0x4f60),
733 MAKE_EXTENSION_PCI(fsacs0,0x1131, 0x4f61),
734 {
735 .vendor = 0,
736 }
737};
738
739MODULE_DEVICE_TABLE(pci, pci_tbl);
740
741static struct saa7146_extension budget_extension = {
742 .name = "budget dvb\0",
743 .flags = 0,
744
745 .module = THIS_MODULE,
746 .pci_tbl = pci_tbl,
747 .attach = budget_attach,
748 .detach = budget_detach,
749
750 .irq_mask = MASK_10,
751 .irq_func = ttpci_budget_irq10_handler,
752};
753
754static int __init budget_init(void)
755{
756 return saa7146_register_extension(&budget_extension);
757}
758
759static void __exit budget_exit(void)
760{
761 saa7146_unregister_extension(&budget_extension);
762}
763
764module_init(budget_init);
765module_exit(budget_exit);
766
767MODULE_LICENSE("GPL");
768MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, Michael Hunold, others");
769MODULE_DESCRIPTION("driver for the SAA7146 based so-called "
770 "budget PCI DVB cards by Siemens, Technotrend, Hauppauge");