blob: fafe6407b3d0d3deb7ba658ea440321de1da44ee [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
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -0800259 // NOTE: since we're using a prescaler of 2, we set the
Linus Torvalds1da177e2005-04-16 15:20:36 -0700260 // 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,
Oliver Endrissff29d062005-11-08 21:35:43 -0800289 0x12, 0xb9,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700290 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,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700363 .skip_reinit = 0,
364 .lock_output = STV0229_LOCKOUTPUT_1,
365 .volt13_op0_op1 = STV0299_VOLT13_OP1,
366 .min_delay_ms = 100,
367 .set_symbol_rate = alps_bsru6_set_symbol_rate,
368 .pll_set = alps_bsru6_pll_set,
369};
370
Martin Zwickel9691bb12005-11-08 21:35:10 -0800371static u8 alps_bsbe1_inittab[] = {
372 0x01, 0x15,
373 0x02, 0x30,
374 0x03, 0x00,
375 0x04, 0x7d, /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */
376 0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */
377 0x06, 0x40, /* DAC not used, set to high impendance mode */
378 0x07, 0x00, /* DAC LSB */
379 0x08, 0x40, /* DiSEqC off, LNB power on OP2/LOCK pin on */
380 0x09, 0x00, /* FIFO */
381 0x0c, 0x51, /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */
382 0x0d, 0x82, /* DC offset compensation = ON, beta_agc1 = 2 */
383 0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */
384 0x10, 0x3f, // AGC2 0x3d
385 0x11, 0x84,
Oliver Endrissff29d062005-11-08 21:35:43 -0800386 0x12, 0xb9,
Martin Zwickel9691bb12005-11-08 21:35:10 -0800387 0x15, 0xc9, // lock detector threshold
388 0x16, 0x00,
389 0x17, 0x00,
390 0x18, 0x00,
391 0x19, 0x00,
392 0x1a, 0x00,
393 0x1f, 0x50,
394 0x20, 0x00,
395 0x21, 0x00,
396 0x22, 0x00,
397 0x23, 0x00,
398 0x28, 0x00, // out imp: normal out type: parallel FEC mode:0
399 0x29, 0x1e, // 1/2 threshold
400 0x2a, 0x14, // 2/3 threshold
401 0x2b, 0x0f, // 3/4 threshold
402 0x2c, 0x09, // 5/6 threshold
403 0x2d, 0x05, // 7/8 threshold
404 0x2e, 0x01,
405 0x31, 0x1f, // test all FECs
406 0x32, 0x19, // viterbi and synchro search
407 0x33, 0xfc, // rs control
408 0x34, 0x93, // error control
409 0x0f, 0x92, // 0x80 = inverse AGC
410 0xff, 0xff
411};
412
413static int alps_bsbe1_pll_set(struct dvb_frontend* fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters* params)
414{
415 int ret;
416 u8 data[4];
417 u32 div;
418 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
419
420 if ((params->frequency < 950000) || (params->frequency > 2150000))
421 return -EINVAL;
422
423 div = (params->frequency + (125 - 1)) / 125; // round correctly
424 data[0] = (div >> 8) & 0x7f;
425 data[1] = div & 0xff;
426 data[2] = 0x80 | ((div & 0x18000) >> 10) | 4;
427 data[3] = (params->frequency > 1530000) ? 0xE0 : 0xE4;
428
429 ret = i2c_transfer(i2c, &msg, 1);
430 return (ret != 1) ? -EIO : 0;
431}
432
433static struct stv0299_config alps_bsbe1_config = {
434 .demod_address = 0x68,
435 .inittab = alps_bsbe1_inittab,
436 .mclk = 88000000UL,
437 .invert = 1,
Martin Zwickel9691bb12005-11-08 21:35:10 -0800438 .skip_reinit = 0,
439 .min_delay_ms = 100,
440 .set_symbol_rate = alps_bsru6_set_symbol_rate,
441 .pll_set = alps_bsbe1_pll_set,
442};
443
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444static int alps_tdbe2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
445{
446 struct budget* budget = (struct budget*) fe->dvb->priv;
447 u32 div;
448 u8 data[4];
449 struct i2c_msg msg = { .addr = 0x62, .flags = 0, .buf = data, .len = sizeof(data) };
450
451 div = (params->frequency + 35937500 + 31250) / 62500;
452
453 data[0] = (div >> 8) & 0x7f;
454 data[1] = div & 0xff;
455 data[2] = 0x85 | ((div >> 10) & 0x60);
456 data[3] = (params->frequency < 174000000 ? 0x88 : params->frequency < 470000000 ? 0x84 : 0x81);
457
458 if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
459 return 0;
460}
461
462static struct ves1820_config alps_tdbe2_config = {
463 .demod_address = 0x09,
464 .xin = 57840000UL,
465 .invert = 1,
466 .selagc = VES1820_SELAGC_SIGNAMPERR,
467 .pll_set = alps_tdbe2_pll_set,
468};
469
470static int grundig_29504_401_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
471{
472 struct budget* budget = (struct budget*) fe->dvb->priv;
473 u32 div;
474 u8 cfg, cpump, band_select;
475 u8 data[4];
476 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
477
478 div = (36125000 + params->frequency) / 166666;
479
480 cfg = 0x88;
481
482 if (params->frequency < 175000000) cpump = 2;
483 else if (params->frequency < 390000000) cpump = 1;
484 else if (params->frequency < 470000000) cpump = 2;
485 else if (params->frequency < 750000000) cpump = 1;
486 else cpump = 3;
487
488 if (params->frequency < 175000000) band_select = 0x0e;
489 else if (params->frequency < 470000000) band_select = 0x05;
490 else band_select = 0x03;
491
492 data[0] = (div >> 8) & 0x7f;
493 data[1] = div & 0xff;
494 data[2] = ((div >> 10) & 0x60) | cfg;
495 data[3] = (cpump << 6) | band_select;
496
497 if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
498 return 0;
499}
500
501static struct l64781_config grundig_29504_401_config = {
502 .demod_address = 0x55,
503 .pll_set = grundig_29504_401_pll_set,
504};
505
506static int grundig_29504_451_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
507{
508 struct budget* budget = (struct budget*) fe->dvb->priv;
509 u32 div;
510 u8 data[4];
511 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
512
513 div = params->frequency / 125;
514 data[0] = (div >> 8) & 0x7f;
515 data[1] = div & 0xff;
516 data[2] = 0x8e;
517 data[3] = 0x00;
518
519 if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
520 return 0;
521}
522
523static struct tda8083_config grundig_29504_451_config = {
524 .demod_address = 0x68,
525 .pll_set = grundig_29504_451_pll_set,
526};
527
Andrew de Quincey96bf2f22005-07-07 17:57:53 -0700528static int s5h1420_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u32* freqout)
529{
530 struct budget* budget = (struct budget*) fe->dvb->priv;
531 u32 div;
532 u8 data[4];
533 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
534
535 div = params->frequency / 1000;
536 data[0] = (div >> 8) & 0x7f;
537 data[1] = div & 0xff;
538 data[2] = 0xc2;
539
540 if (div < 1450)
541 data[3] = 0x00;
542 else if (div < 1850)
543 data[3] = 0x40;
544 else if (div < 2000)
545 data[3] = 0x80;
546 else
547 data[3] = 0xc0;
548
549 if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
550
551 *freqout = div * 1000;
552 return 0;
553}
554
555static struct s5h1420_config s5h1420_config = {
556 .demod_address = 0x53,
Andrew de Quinceya9d6a802005-09-09 13:02:31 -0700557 .invert = 1,
Andrew de Quincey96bf2f22005-07-07 17:57:53 -0700558 .pll_set = s5h1420_pll_set,
559};
560
Linus Torvalds1da177e2005-04-16 15:20:36 -0700561static u8 read_pwm(struct budget* budget)
562{
563 u8 b = 0xff;
564 u8 pwm;
565 struct i2c_msg msg[] = { { .addr = 0x50,.flags = 0,.buf = &b,.len = 1 },
566 { .addr = 0x50,.flags = I2C_M_RD,.buf = &pwm,.len = 1} };
567
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -0800568 if ((i2c_transfer(&budget->i2c_adap, msg, 2) != 2) || (pwm == 0xff))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700569 pwm = 0x48;
570
571 return pwm;
572}
573
574static void frontend_init(struct budget *budget)
575{
576 switch(budget->dev->pci->subsystem_device) {
Martin Zwickel9691bb12005-11-08 21:35:10 -0800577 case 0x1017:
578 // try the ALPS BSBE1 now
579 budget->dvb_frontend = stv0299_attach(&alps_bsbe1_config, &budget->i2c_adap);
580 if (budget->dvb_frontend) {
581 budget->dvb_frontend->ops->set_voltage = lnbp21_set_voltage;
582 budget->dvb_frontend->ops->enable_high_lnb_voltage = lnbp21_enable_high_lnb_voltage;
583 if (lnbp21_init(budget)) {
584 printk("%s: No LNBP21 found!\n", __FUNCTION__);
585 goto error_out;
586 }
587 }
588
589 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590 case 0x1003: // Hauppauge/TT Nova budget (stv0299/ALPS BSRU6(tsa5059) OR ves1893/ALPS BSRV2(sp5659))
591 case 0x1013:
592 // try the ALPS BSRV2 first of all
593 budget->dvb_frontend = ves1x93_attach(&alps_bsrv2_config, &budget->i2c_adap);
594 if (budget->dvb_frontend) {
595 budget->dvb_frontend->ops->diseqc_send_master_cmd = budget_diseqc_send_master_cmd;
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -0800596 budget->dvb_frontend->ops->diseqc_send_burst = budget_diseqc_send_burst;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700597 budget->dvb_frontend->ops->set_tone = budget_set_tone;
598 break;
599 }
600
601 // try the ALPS BSRU6 now
602 budget->dvb_frontend = stv0299_attach(&alps_bsru6_config, &budget->i2c_adap);
603 if (budget->dvb_frontend) {
604 budget->dvb_frontend->ops->diseqc_send_master_cmd = budget_diseqc_send_master_cmd;
605 budget->dvb_frontend->ops->diseqc_send_burst = budget_diseqc_send_burst;
606 budget->dvb_frontend->ops->set_tone = budget_set_tone;
607 break;
608 }
609 break;
610
611 case 0x1004: // Hauppauge/TT DVB-C budget (ves1820/ALPS TDBE2(sp5659))
612
613 budget->dvb_frontend = ves1820_attach(&alps_tdbe2_config, &budget->i2c_adap, read_pwm(budget));
614 if (budget->dvb_frontend) break;
615 break;
616
617 case 0x1005: // Hauppauge/TT Nova-T budget (L64781/Grundig 29504-401(tsa5060))
618
619 budget->dvb_frontend = l64781_attach(&grundig_29504_401_config, &budget->i2c_adap);
620 if (budget->dvb_frontend) break;
621 break;
622
623 case 0x4f60: // Fujitsu Siemens Activy Budget-S PCI rev AL (stv0299/ALPS BSRU6(tsa5059))
624 budget->dvb_frontend = stv0299_attach(&alps_bsru6_config, &budget->i2c_adap);
625 if (budget->dvb_frontend) {
626 budget->dvb_frontend->ops->set_voltage = siemens_budget_set_voltage;
627 break;
628 }
629 break;
630
631 case 0x4f61: // Fujitsu Siemens Activy Budget-S PCI rev GR (tda8083/Grundig 29504-451(tsa5522))
632 budget->dvb_frontend = tda8083_attach(&grundig_29504_451_config, &budget->i2c_adap);
633 if (budget->dvb_frontend) {
634 budget->dvb_frontend->ops->set_voltage = siemens_budget_set_voltage;
635 break;
636 }
637 break;
Andrew de Quincey96bf2f22005-07-07 17:57:53 -0700638
639 case 0x1016: // Hauppauge/TT Nova-S SE (samsung s5h1420/????(tda8260))
640 budget->dvb_frontend = s5h1420_attach(&s5h1420_config, &budget->i2c_adap);
641 if (budget->dvb_frontend) {
642 budget->dvb_frontend->ops->set_voltage = lnbp21_set_voltage;
643 budget->dvb_frontend->ops->enable_high_lnb_voltage = lnbp21_enable_high_lnb_voltage;
Martin Zwickel9691bb12005-11-08 21:35:10 -0800644 if (lnbp21_init(budget)) {
645 printk("%s: No LNBP21 found!\n", __FUNCTION__);
646 goto error_out;
647 }
Andrew de Quincey96bf2f22005-07-07 17:57:53 -0700648 break;
649 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700650 }
651
652 if (budget->dvb_frontend == NULL) {
653 printk("budget: A frontend driver was not found for device %04x/%04x subsystem %04x/%04x\n",
654 budget->dev->pci->vendor,
655 budget->dev->pci->device,
656 budget->dev->pci->subsystem_vendor,
657 budget->dev->pci->subsystem_device);
658 } else {
Martin Zwickel9691bb12005-11-08 21:35:10 -0800659 if (dvb_register_frontend(&budget->dvb_adapter, budget->dvb_frontend))
660 goto error_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700661 }
Martin Zwickel9691bb12005-11-08 21:35:10 -0800662 return;
663
664error_out:
665 printk("budget: Frontend registration failed!\n");
666 if (budget->dvb_frontend->ops->release)
667 budget->dvb_frontend->ops->release(budget->dvb_frontend);
668 budget->dvb_frontend = NULL;
669 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700670}
671
672static int budget_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_data *info)
673{
674 struct budget *budget = NULL;
675 int err;
676
677 budget = kmalloc(sizeof(struct budget), GFP_KERNEL);
678 if( NULL == budget ) {
679 return -ENOMEM;
680 }
681
682 dprintk(2, "dev:%p, info:%p, budget:%p\n", dev, info, budget);
683
684 dev->ext_priv = budget;
685
686 if ((err = ttpci_budget_init (budget, dev, info, THIS_MODULE))) {
687 printk("==> failed\n");
688 kfree (budget);
689 return err;
690 }
691
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -0700692 budget->dvb_adapter.priv = budget;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700693 frontend_init(budget);
694
695 return 0;
696}
697
698static int budget_detach (struct saa7146_dev* dev)
699{
700 struct budget *budget = (struct budget*) dev->ext_priv;
701 int err;
702
703 if (budget->dvb_frontend) dvb_unregister_frontend(budget->dvb_frontend);
704
705 err = ttpci_budget_deinit (budget);
706
707 kfree (budget);
708 dev->ext_priv = NULL;
709
710 return err;
711}
712
713static struct saa7146_extension budget_extension;
714
Martin Zwickel9691bb12005-11-08 21:35:10 -0800715MAKE_BUDGET_INFO(ttbs2, "TT-Budget/WinTV-NOVA-S PCI (rev AL/alps bsbe1 lnbp21 frontend)", BUDGET_TT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700716MAKE_BUDGET_INFO(ttbs, "TT-Budget/WinTV-NOVA-S PCI", BUDGET_TT);
717MAKE_BUDGET_INFO(ttbc, "TT-Budget/WinTV-NOVA-C PCI", BUDGET_TT);
718MAKE_BUDGET_INFO(ttbt, "TT-Budget/WinTV-NOVA-T PCI", BUDGET_TT);
719MAKE_BUDGET_INFO(satel, "SATELCO Multimedia PCI", BUDGET_TT_HW_DISEQC);
720MAKE_BUDGET_INFO(fsacs0, "Fujitsu Siemens Activy Budget-S PCI (rev GR/grundig frontend)", BUDGET_FS_ACTIVY);
721MAKE_BUDGET_INFO(fsacs1, "Fujitsu Siemens Activy Budget-S PCI (rev AL/alps frontend)", BUDGET_FS_ACTIVY);
722
723static struct pci_device_id pci_tbl[] = {
724 MAKE_EXTENSION_PCI(ttbs, 0x13c2, 0x1003),
725 MAKE_EXTENSION_PCI(ttbc, 0x13c2, 0x1004),
726 MAKE_EXTENSION_PCI(ttbt, 0x13c2, 0x1005),
727 MAKE_EXTENSION_PCI(satel, 0x13c2, 0x1013),
Martin Zwickel9691bb12005-11-08 21:35:10 -0800728 MAKE_EXTENSION_PCI(ttbs2, 0x13c2, 0x1017),
Andrew de Quincey96bf2f22005-07-07 17:57:53 -0700729 MAKE_EXTENSION_PCI(ttbs, 0x13c2, 0x1016),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700730 MAKE_EXTENSION_PCI(fsacs1,0x1131, 0x4f60),
731 MAKE_EXTENSION_PCI(fsacs0,0x1131, 0x4f61),
732 {
733 .vendor = 0,
734 }
735};
736
737MODULE_DEVICE_TABLE(pci, pci_tbl);
738
739static struct saa7146_extension budget_extension = {
740 .name = "budget dvb\0",
Oliver Endriss69459f3d2005-12-01 00:51:48 -0800741 .flags = SAA7146_I2C_SHORT_DELAY,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700742
743 .module = THIS_MODULE,
744 .pci_tbl = pci_tbl,
745 .attach = budget_attach,
746 .detach = budget_detach,
747
748 .irq_mask = MASK_10,
749 .irq_func = ttpci_budget_irq10_handler,
750};
751
752static int __init budget_init(void)
753{
754 return saa7146_register_extension(&budget_extension);
755}
756
757static void __exit budget_exit(void)
758{
759 saa7146_unregister_extension(&budget_extension);
760}
761
762module_init(budget_init);
763module_exit(budget_exit);
764
765MODULE_LICENSE("GPL");
766MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, Michael Hunold, others");
767MODULE_DESCRIPTION("driver for the SAA7146 based so-called "
768 "budget PCI DVB cards by Siemens, Technotrend, Hauppauge");