Linux-2.6.12-rc2
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / media / dvb / ttpci / budget.c
blob5e6a10f4ad95bb84f9181722622dc2da5be13bc2
1 /*
2 * budget.c: driver for the SAA7146 based Budget DVB cards
4 * Compiled from various sources by Michael Hunold <michael@mihu.de>
6 * Copyright (C) 2002 Ralph Metzler <rjkm@metzlerbros.de>
8 * Copyright (C) 1999-2002 Ralph Metzler
9 * & Marcus Metzler for convergence integrated media GmbH
11 * 26feb2004 Support for FS Activy Card (Grundig tuner) by
12 * Michael Dreher <michael@5dot1.de>,
13 * Oliver Endriss <o.endriss@gmx.de> and
14 * Andreas 'randy' Weinberger
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version 2
19 * of the License, or (at your option) any later version.
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
28 * You should have received a copy of the GNU General Public License
29 * along with this program; if not, write to the Free Software
30 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
31 * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
34 * the project's page is at http://www.linuxtv.org/dvb/
37 #include "budget.h"
38 #include "stv0299.h"
39 #include "ves1x93.h"
40 #include "ves1820.h"
41 #include "l64781.h"
42 #include "tda8083.h"
44 static void Set22K (struct budget *budget, int state)
46 struct saa7146_dev *dev=budget->dev;
47 dprintk(2, "budget: %p\n", budget);
48 saa7146_setgpio(dev, 3, (state ? SAA7146_GPIO_OUTHI : SAA7146_GPIO_OUTLO));
51 /* Diseqc functions only for TT Budget card */
52 /* taken from the Skyvision DVB driver by
53 Ralph Metzler <rjkm@metzlerbros.de> */
55 static void DiseqcSendBit (struct budget *budget, int data)
57 struct saa7146_dev *dev=budget->dev;
58 dprintk(2, "budget: %p\n", budget);
60 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI);
61 udelay(data ? 500 : 1000);
62 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
63 udelay(data ? 1000 : 500);
66 static void DiseqcSendByte (struct budget *budget, int data)
68 int i, par=1, d;
70 dprintk(2, "budget: %p\n", budget);
72 for (i=7; i>=0; i--) {
73 d = (data>>i)&1;
74 par ^= d;
75 DiseqcSendBit(budget, d);
78 DiseqcSendBit(budget, par);
81 static int SendDiSEqCMsg (struct budget *budget, int len, u8 *msg, unsigned long burst)
83 struct saa7146_dev *dev=budget->dev;
84 int i;
86 dprintk(2, "budget: %p\n", budget);
88 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
89 mdelay(16);
91 for (i=0; i<len; i++)
92 DiseqcSendByte(budget, msg[i]);
94 mdelay(16);
96 if (burst!=-1) {
97 if (burst)
98 DiseqcSendByte(budget, 0xff);
99 else {
100 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI);
101 udelay(12500);
102 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
104 msleep(20);
107 return 0;
111 * Routines for the Fujitsu Siemens Activy budget card
112 * 22 kHz tone and DiSEqC are handled by the frontend.
113 * Voltage must be set here.
115 static int SetVoltage_Activy (struct budget *budget, fe_sec_voltage_t voltage)
117 struct saa7146_dev *dev=budget->dev;
119 dprintk(2, "budget: %p\n", budget);
121 switch (voltage) {
122 case SEC_VOLTAGE_13:
123 saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTLO);
124 break;
125 case SEC_VOLTAGE_18:
126 saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTHI);
127 break;
128 default:
129 return -EINVAL;
132 return 0;
135 static int siemens_budget_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
137 struct budget* budget = (struct budget*) fe->dvb->priv;
139 return SetVoltage_Activy (budget, voltage);
142 static int budget_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
144 struct budget* budget = (struct budget*) fe->dvb->priv;
146 switch (tone) {
147 case SEC_TONE_ON:
148 Set22K (budget, 1);
149 break;
151 case SEC_TONE_OFF:
152 Set22K (budget, 0);
153 break;
155 default:
156 return -EINVAL;
159 return 0;
162 static int budget_diseqc_send_master_cmd(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd)
164 struct budget* budget = (struct budget*) fe->dvb->priv;
166 SendDiSEqCMsg (budget, cmd->msg_len, cmd->msg, 0);
168 return 0;
171 static int budget_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd)
173 struct budget* budget = (struct budget*) fe->dvb->priv;
175 SendDiSEqCMsg (budget, 0, NULL, minicmd);
177 return 0;
180 static int alps_bsrv2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
182 struct budget* budget = (struct budget*) fe->dvb->priv;
183 u8 pwr = 0;
184 u8 buf[4];
185 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
186 u32 div = (params->frequency + 479500) / 125;
188 if (params->frequency > 2000000) pwr = 3;
189 else if (params->frequency > 1800000) pwr = 2;
190 else if (params->frequency > 1600000) pwr = 1;
191 else if (params->frequency > 1200000) pwr = 0;
192 else if (params->frequency >= 1100000) pwr = 1;
193 else pwr = 2;
195 buf[0] = (div >> 8) & 0x7f;
196 buf[1] = div & 0xff;
197 buf[2] = ((div & 0x18000) >> 10) | 0x95;
198 buf[3] = (pwr << 6) | 0x30;
200 // NOTE: since we're using a prescaler of 2, we set the
201 // divisor frequency to 62.5kHz and divide by 125 above
203 if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
204 return 0;
207 static struct ves1x93_config alps_bsrv2_config =
209 .demod_address = 0x08,
210 .xin = 90100000UL,
211 .invert_pwm = 0,
212 .pll_set = alps_bsrv2_pll_set,
215 static u8 alps_bsru6_inittab[] = {
216 0x01, 0x15,
217 0x02, 0x00,
218 0x03, 0x00,
219 0x04, 0x7d, /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */
220 0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */
221 0x06, 0x40, /* DAC not used, set to high impendance mode */
222 0x07, 0x00, /* DAC LSB */
223 0x08, 0x40, /* DiSEqC off, LNB power on OP2/LOCK pin on */
224 0x09, 0x00, /* FIFO */
225 0x0c, 0x51, /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */
226 0x0d, 0x82, /* DC offset compensation = ON, beta_agc1 = 2 */
227 0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */
228 0x10, 0x3f, // AGC2 0x3d
229 0x11, 0x84,
230 0x12, 0xb5, // Lock detect: -64 Carrier freq detect:on
231 0x15, 0xc9, // lock detector threshold
232 0x16, 0x00,
233 0x17, 0x00,
234 0x18, 0x00,
235 0x19, 0x00,
236 0x1a, 0x00,
237 0x1f, 0x50,
238 0x20, 0x00,
239 0x21, 0x00,
240 0x22, 0x00,
241 0x23, 0x00,
242 0x28, 0x00, // out imp: normal out type: parallel FEC mode:0
243 0x29, 0x1e, // 1/2 threshold
244 0x2a, 0x14, // 2/3 threshold
245 0x2b, 0x0f, // 3/4 threshold
246 0x2c, 0x09, // 5/6 threshold
247 0x2d, 0x05, // 7/8 threshold
248 0x2e, 0x01,
249 0x31, 0x1f, // test all FECs
250 0x32, 0x19, // viterbi and synchro search
251 0x33, 0xfc, // rs control
252 0x34, 0x93, // error control
253 0x0f, 0x52,
254 0xff, 0xff
257 static int alps_bsru6_set_symbol_rate(struct dvb_frontend* fe, u32 srate, u32 ratio)
259 u8 aclk = 0;
260 u8 bclk = 0;
262 if (srate < 1500000) { aclk = 0xb7; bclk = 0x47; }
263 else if (srate < 3000000) { aclk = 0xb7; bclk = 0x4b; }
264 else if (srate < 7000000) { aclk = 0xb7; bclk = 0x4f; }
265 else if (srate < 14000000) { aclk = 0xb7; bclk = 0x53; }
266 else if (srate < 30000000) { aclk = 0xb6; bclk = 0x53; }
267 else if (srate < 45000000) { aclk = 0xb4; bclk = 0x51; }
269 stv0299_writereg (fe, 0x13, aclk);
270 stv0299_writereg (fe, 0x14, bclk);
271 stv0299_writereg (fe, 0x1f, (ratio >> 16) & 0xff);
272 stv0299_writereg (fe, 0x20, (ratio >> 8) & 0xff);
273 stv0299_writereg (fe, 0x21, (ratio ) & 0xf0);
275 return 0;
278 static int alps_bsru6_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
280 struct budget* budget = (struct budget*) fe->dvb->priv;
281 u8 data[4];
282 u32 div;
283 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
285 if ((params->frequency < 950000) || (params->frequency > 2150000)) return -EINVAL;
287 div = (params->frequency + (125 - 1)) / 125; // round correctly
288 data[0] = (div >> 8) & 0x7f;
289 data[1] = div & 0xff;
290 data[2] = 0x80 | ((div & 0x18000) >> 10) | 4;
291 data[3] = 0xC4;
293 if (params->frequency > 1530000) data[3] = 0xc0;
295 if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
296 return 0;
299 static struct stv0299_config alps_bsru6_config = {
301 .demod_address = 0x68,
302 .inittab = alps_bsru6_inittab,
303 .mclk = 88000000UL,
304 .invert = 1,
305 .enhanced_tuning = 0,
306 .skip_reinit = 0,
307 .lock_output = STV0229_LOCKOUTPUT_1,
308 .volt13_op0_op1 = STV0299_VOLT13_OP1,
309 .min_delay_ms = 100,
310 .set_symbol_rate = alps_bsru6_set_symbol_rate,
311 .pll_set = alps_bsru6_pll_set,
314 static int alps_tdbe2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
316 struct budget* budget = (struct budget*) fe->dvb->priv;
317 u32 div;
318 u8 data[4];
319 struct i2c_msg msg = { .addr = 0x62, .flags = 0, .buf = data, .len = sizeof(data) };
321 div = (params->frequency + 35937500 + 31250) / 62500;
323 data[0] = (div >> 8) & 0x7f;
324 data[1] = div & 0xff;
325 data[2] = 0x85 | ((div >> 10) & 0x60);
326 data[3] = (params->frequency < 174000000 ? 0x88 : params->frequency < 470000000 ? 0x84 : 0x81);
328 if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
329 return 0;
332 static struct ves1820_config alps_tdbe2_config = {
333 .demod_address = 0x09,
334 .xin = 57840000UL,
335 .invert = 1,
336 .selagc = VES1820_SELAGC_SIGNAMPERR,
337 .pll_set = alps_tdbe2_pll_set,
340 static int grundig_29504_401_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
342 struct budget* budget = (struct budget*) fe->dvb->priv;
343 u32 div;
344 u8 cfg, cpump, band_select;
345 u8 data[4];
346 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
348 div = (36125000 + params->frequency) / 166666;
350 cfg = 0x88;
352 if (params->frequency < 175000000) cpump = 2;
353 else if (params->frequency < 390000000) cpump = 1;
354 else if (params->frequency < 470000000) cpump = 2;
355 else if (params->frequency < 750000000) cpump = 1;
356 else cpump = 3;
358 if (params->frequency < 175000000) band_select = 0x0e;
359 else if (params->frequency < 470000000) band_select = 0x05;
360 else band_select = 0x03;
362 data[0] = (div >> 8) & 0x7f;
363 data[1] = div & 0xff;
364 data[2] = ((div >> 10) & 0x60) | cfg;
365 data[3] = (cpump << 6) | band_select;
367 if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
368 return 0;
371 static struct l64781_config grundig_29504_401_config = {
372 .demod_address = 0x55,
373 .pll_set = grundig_29504_401_pll_set,
376 static int grundig_29504_451_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
378 struct budget* budget = (struct budget*) fe->dvb->priv;
379 u32 div;
380 u8 data[4];
381 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
383 div = params->frequency / 125;
384 data[0] = (div >> 8) & 0x7f;
385 data[1] = div & 0xff;
386 data[2] = 0x8e;
387 data[3] = 0x00;
389 if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
390 return 0;
393 static struct tda8083_config grundig_29504_451_config = {
394 .demod_address = 0x68,
395 .pll_set = grundig_29504_451_pll_set,
398 static u8 read_pwm(struct budget* budget)
400 u8 b = 0xff;
401 u8 pwm;
402 struct i2c_msg msg[] = { { .addr = 0x50,.flags = 0,.buf = &b,.len = 1 },
403 { .addr = 0x50,.flags = I2C_M_RD,.buf = &pwm,.len = 1} };
405 if ((i2c_transfer(&budget->i2c_adap, msg, 2) != 2) || (pwm == 0xff))
406 pwm = 0x48;
408 return pwm;
411 static void frontend_init(struct budget *budget)
413 switch(budget->dev->pci->subsystem_device) {
414 case 0x1003: // Hauppauge/TT Nova budget (stv0299/ALPS BSRU6(tsa5059) OR ves1893/ALPS BSRV2(sp5659))
415 case 0x1013:
416 // try the ALPS BSRV2 first of all
417 budget->dvb_frontend = ves1x93_attach(&alps_bsrv2_config, &budget->i2c_adap);
418 if (budget->dvb_frontend) {
419 budget->dvb_frontend->ops->diseqc_send_master_cmd = budget_diseqc_send_master_cmd;
420 budget->dvb_frontend->ops->diseqc_send_burst = budget_diseqc_send_burst;
421 budget->dvb_frontend->ops->set_tone = budget_set_tone;
422 break;
425 // try the ALPS BSRU6 now
426 budget->dvb_frontend = stv0299_attach(&alps_bsru6_config, &budget->i2c_adap);
427 if (budget->dvb_frontend) {
428 budget->dvb_frontend->ops->diseqc_send_master_cmd = budget_diseqc_send_master_cmd;
429 budget->dvb_frontend->ops->diseqc_send_burst = budget_diseqc_send_burst;
430 budget->dvb_frontend->ops->set_tone = budget_set_tone;
431 break;
433 break;
435 case 0x1004: // Hauppauge/TT DVB-C budget (ves1820/ALPS TDBE2(sp5659))
437 budget->dvb_frontend = ves1820_attach(&alps_tdbe2_config, &budget->i2c_adap, read_pwm(budget));
438 if (budget->dvb_frontend) break;
439 break;
441 case 0x1005: // Hauppauge/TT Nova-T budget (L64781/Grundig 29504-401(tsa5060))
443 budget->dvb_frontend = l64781_attach(&grundig_29504_401_config, &budget->i2c_adap);
444 if (budget->dvb_frontend) break;
445 break;
447 case 0x4f60: // Fujitsu Siemens Activy Budget-S PCI rev AL (stv0299/ALPS BSRU6(tsa5059))
448 budget->dvb_frontend = stv0299_attach(&alps_bsru6_config, &budget->i2c_adap);
449 if (budget->dvb_frontend) {
450 budget->dvb_frontend->ops->set_voltage = siemens_budget_set_voltage;
451 break;
453 break;
455 case 0x4f61: // Fujitsu Siemens Activy Budget-S PCI rev GR (tda8083/Grundig 29504-451(tsa5522))
456 budget->dvb_frontend = tda8083_attach(&grundig_29504_451_config, &budget->i2c_adap);
457 if (budget->dvb_frontend) {
458 budget->dvb_frontend->ops->set_voltage = siemens_budget_set_voltage;
459 break;
461 break;
464 if (budget->dvb_frontend == NULL) {
465 printk("budget: A frontend driver was not found for device %04x/%04x subsystem %04x/%04x\n",
466 budget->dev->pci->vendor,
467 budget->dev->pci->device,
468 budget->dev->pci->subsystem_vendor,
469 budget->dev->pci->subsystem_device);
470 } else {
471 if (dvb_register_frontend(budget->dvb_adapter, budget->dvb_frontend)) {
472 printk("budget: Frontend registration failed!\n");
473 if (budget->dvb_frontend->ops->release)
474 budget->dvb_frontend->ops->release(budget->dvb_frontend);
475 budget->dvb_frontend = NULL;
480 static int budget_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_data *info)
482 struct budget *budget = NULL;
483 int err;
485 budget = kmalloc(sizeof(struct budget), GFP_KERNEL);
486 if( NULL == budget ) {
487 return -ENOMEM;
490 dprintk(2, "dev:%p, info:%p, budget:%p\n", dev, info, budget);
492 dev->ext_priv = budget;
494 if ((err = ttpci_budget_init (budget, dev, info, THIS_MODULE))) {
495 printk("==> failed\n");
496 kfree (budget);
497 return err;
500 budget->dvb_adapter->priv = budget;
501 frontend_init(budget);
503 return 0;
506 static int budget_detach (struct saa7146_dev* dev)
508 struct budget *budget = (struct budget*) dev->ext_priv;
509 int err;
511 if (budget->dvb_frontend) dvb_unregister_frontend(budget->dvb_frontend);
513 err = ttpci_budget_deinit (budget);
515 kfree (budget);
516 dev->ext_priv = NULL;
518 return err;
521 static struct saa7146_extension budget_extension;
523 MAKE_BUDGET_INFO(ttbs, "TT-Budget/WinTV-NOVA-S PCI", BUDGET_TT);
524 MAKE_BUDGET_INFO(ttbc, "TT-Budget/WinTV-NOVA-C PCI", BUDGET_TT);
525 MAKE_BUDGET_INFO(ttbt, "TT-Budget/WinTV-NOVA-T PCI", BUDGET_TT);
526 MAKE_BUDGET_INFO(satel, "SATELCO Multimedia PCI", BUDGET_TT_HW_DISEQC);
527 MAKE_BUDGET_INFO(fsacs0, "Fujitsu Siemens Activy Budget-S PCI (rev GR/grundig frontend)", BUDGET_FS_ACTIVY);
528 MAKE_BUDGET_INFO(fsacs1, "Fujitsu Siemens Activy Budget-S PCI (rev AL/alps frontend)", BUDGET_FS_ACTIVY);
530 static struct pci_device_id pci_tbl[] = {
531 MAKE_EXTENSION_PCI(ttbs, 0x13c2, 0x1003),
532 MAKE_EXTENSION_PCI(ttbc, 0x13c2, 0x1004),
533 MAKE_EXTENSION_PCI(ttbt, 0x13c2, 0x1005),
534 MAKE_EXTENSION_PCI(satel, 0x13c2, 0x1013),
535 MAKE_EXTENSION_PCI(fsacs1,0x1131, 0x4f60),
536 MAKE_EXTENSION_PCI(fsacs0,0x1131, 0x4f61),
538 .vendor = 0,
542 MODULE_DEVICE_TABLE(pci, pci_tbl);
544 static struct saa7146_extension budget_extension = {
545 .name = "budget dvb\0",
546 .flags = 0,
548 .module = THIS_MODULE,
549 .pci_tbl = pci_tbl,
550 .attach = budget_attach,
551 .detach = budget_detach,
553 .irq_mask = MASK_10,
554 .irq_func = ttpci_budget_irq10_handler,
557 static int __init budget_init(void)
559 return saa7146_register_extension(&budget_extension);
562 static void __exit budget_exit(void)
564 saa7146_unregister_extension(&budget_extension);
567 module_init(budget_init);
568 module_exit(budget_exit);
570 MODULE_LICENSE("GPL");
571 MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, Michael Hunold, others");
572 MODULE_DESCRIPTION("driver for the SAA7146 based so-called "
573 "budget PCI DVB cards by Siemens, Technotrend, Hauppauge");