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#include "tda10086.h" 45#include "tda826x.h" 46#include "lnbp21.h" 47#include "bsru6.h" 48 49static int diseqc_method; 50module_param(diseqc_method, int, 0444); 51MODULE_PARM_DESC(diseqc_method, "Select DiSEqC method for subsystem id 13c2:1003, 0: default, 1: more reliable (for newer revisions only)"); 52 53static void Set22K (struct budget *budget, int state) 54{ 55 struct saa7146_dev *dev=budget->dev; 56 dprintk(2, "budget: %p\n", budget); 57 saa7146_setgpio(dev, 3, (state ? SAA7146_GPIO_OUTHI : SAA7146_GPIO_OUTLO)); 58} 59 60/* Diseqc functions only for TT Budget card */ 61/* taken from the Skyvision DVB driver by 62 Ralph Metzler <rjkm@metzlerbros.de> */ 63 64static void DiseqcSendBit (struct budget *budget, int data) 65{ 66 struct saa7146_dev *dev=budget->dev; 67 dprintk(2, "budget: %p\n", budget); 68 69 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI); 70 udelay(data ? 500 : 1000); 71 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); 72 udelay(data ? 1000 : 500); 73} 74 75static void DiseqcSendByte (struct budget *budget, int data) 76{ 77 int i, par=1, d; 78 79 dprintk(2, "budget: %p\n", budget); 80 81 for (i=7; i>=0; i--) { 82 d = (data>>i)&1; 83 par ^= d; 84 DiseqcSendBit(budget, d); 85 } 86 87 DiseqcSendBit(budget, par); 88} 89 90static int SendDiSEqCMsg (struct budget *budget, int len, u8 *msg, unsigned long burst) 91{ 92 struct saa7146_dev *dev=budget->dev; 93 int i; 94 95 dprintk(2, "budget: %p\n", budget); 96 97 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); 98 mdelay(16); 99 100 for (i=0; i<len; i++) 101 DiseqcSendByte(budget, msg[i]); 102 103 mdelay(16); 104 105 if (burst!=-1) { 106 if (burst) 107 DiseqcSendByte(budget, 0xff); 108 else { 109 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI); 110 udelay(12500); 111 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); 112 } 113 msleep(20); 114 } 115 116 return 0; 117} 118 119/* 120 * Routines for the Fujitsu Siemens Activy budget card 121 * 22 kHz tone and DiSEqC are handled by the frontend. 122 * Voltage must be set here. 123 * GPIO 1: LNBP EN, GPIO 2: LNBP VSEL 124 */ 125static int SetVoltage_Activy (struct budget *budget, fe_sec_voltage_t voltage) 126{ 127 struct saa7146_dev *dev=budget->dev; 128 129 dprintk(2, "budget: %p\n", budget); 130 131 switch (voltage) { 132 case SEC_VOLTAGE_13: 133 saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); 134 saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTLO); 135 break; 136 case SEC_VOLTAGE_18: 137 saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); 138 saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTHI); 139 break; 140 case SEC_VOLTAGE_OFF: 141 saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTLO); 142 break; 143 default: 144 return -EINVAL; 145 } 146 147 return 0; 148} 149 150static int siemens_budget_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage) 151{ 152 struct budget* budget = (struct budget*) fe->dvb->priv; 153 154 return SetVoltage_Activy (budget, voltage); 155} 156 157static int budget_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone) 158{ 159 struct budget* budget = (struct budget*) fe->dvb->priv; 160 161 switch (tone) { 162 case SEC_TONE_ON: 163 Set22K (budget, 1); 164 break; 165 166 case SEC_TONE_OFF: 167 Set22K (budget, 0); 168 break; 169 170 default: 171 return -EINVAL; 172 } 173 174 return 0; 175} 176 177static int budget_diseqc_send_master_cmd(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd) 178{ 179 struct budget* budget = (struct budget*) fe->dvb->priv; 180 181 SendDiSEqCMsg (budget, cmd->msg_len, cmd->msg, 0); 182 183 return 0; 184} 185 186static int budget_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd) 187{ 188 struct budget* budget = (struct budget*) fe->dvb->priv; 189 190 SendDiSEqCMsg (budget, 0, NULL, minicmd); 191 192 return 0; 193} 194 195static int alps_bsrv2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) 196{ 197 struct budget* budget = (struct budget*) fe->dvb->priv; 198 u8 pwr = 0; 199 u8 buf[4]; 200 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) }; 201 u32 div = (params->frequency + 479500) / 125; 202 203 if (params->frequency > 2000000) pwr = 3; 204 else if (params->frequency > 1800000) pwr = 2; 205 else if (params->frequency > 1600000) pwr = 1; 206 else if (params->frequency > 1200000) pwr = 0; 207 else if (params->frequency >= 1100000) pwr = 1; 208 else pwr = 2; 209 210 buf[0] = (div >> 8) & 0x7f; 211 buf[1] = div & 0xff; 212 buf[2] = ((div & 0x18000) >> 10) | 0x95; 213 buf[3] = (pwr << 6) | 0x30; 214 215 // NOTE: since we're using a prescaler of 2, we set the 216 // divisor frequency to 62.5kHz and divide by 125 above 217 218 if (fe->ops.i2c_gate_ctrl) 219 fe->ops.i2c_gate_ctrl(fe, 1); 220 if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO; 221 return 0; 222} 223 224static struct ves1x93_config alps_bsrv2_config = 225{ 226 .demod_address = 0x08, 227 .xin = 90100000UL, 228 .invert_pwm = 0, 229}; 230 231static int alps_tdbe2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) 232{ 233 struct budget* budget = (struct budget*) fe->dvb->priv; 234 u32 div; 235 u8 data[4]; 236 struct i2c_msg msg = { .addr = 0x62, .flags = 0, .buf = data, .len = sizeof(data) }; 237 238 div = (params->frequency + 35937500 + 31250) / 62500; 239 240 data[0] = (div >> 8) & 0x7f; 241 data[1] = div & 0xff; 242 data[2] = 0x85 | ((div >> 10) & 0x60); 243 data[3] = (params->frequency < 174000000 ? 0x88 : params->frequency < 470000000 ? 0x84 : 0x81); 244 245 if (fe->ops.i2c_gate_ctrl) 246 fe->ops.i2c_gate_ctrl(fe, 1); 247 if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO; 248 return 0; 249} 250 251static struct ves1820_config alps_tdbe2_config = { 252 .demod_address = 0x09, 253 .xin = 57840000UL, 254 .invert = 1, 255 .selagc = VES1820_SELAGC_SIGNAMPERR, 256}; 257 258static int grundig_29504_401_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) 259{ 260 struct budget* budget = (struct budget*) fe->dvb->priv; 261 u32 div; 262 u8 cfg, cpump, band_select; 263 u8 data[4]; 264 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) }; 265 266 div = (36125000 + params->frequency) / 166666; 267 268 cfg = 0x88; 269 270 if (params->frequency < 175000000) cpump = 2; 271 else if (params->frequency < 390000000) cpump = 1; 272 else if (params->frequency < 470000000) cpump = 2; 273 else if (params->frequency < 750000000) cpump = 1; 274 else cpump = 3; 275 276 if (params->frequency < 175000000) band_select = 0x0e; 277 else if (params->frequency < 470000000) band_select = 0x05; 278 else band_select = 0x03; 279 280 data[0] = (div >> 8) & 0x7f; 281 data[1] = div & 0xff; 282 data[2] = ((div >> 10) & 0x60) | cfg; 283 data[3] = (cpump << 6) | band_select; 284 285 if (fe->ops.i2c_gate_ctrl) 286 fe->ops.i2c_gate_ctrl(fe, 1); 287 if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO; 288 return 0; 289} 290 291static struct l64781_config grundig_29504_401_config = { 292 .demod_address = 0x55, 293}; 294 295static int grundig_29504_451_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) 296{ 297 struct budget* budget = (struct budget*) fe->dvb->priv; 298 u32 div; 299 u8 data[4]; 300 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) }; 301 302 div = params->frequency / 125; 303 data[0] = (div >> 8) & 0x7f; 304 data[1] = div & 0xff; 305 data[2] = 0x8e; 306 data[3] = 0x00; 307 308 if (fe->ops.i2c_gate_ctrl) 309 fe->ops.i2c_gate_ctrl(fe, 1); 310 if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO; 311 return 0; 312} 313 314static struct tda8083_config grundig_29504_451_config = { 315 .demod_address = 0x68, 316}; 317 318static int s5h1420_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) 319{ 320 struct budget* budget = (struct budget*) fe->dvb->priv; 321 u32 div; 322 u8 data[4]; 323 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) }; 324 325 div = params->frequency / 1000; 326 data[0] = (div >> 8) & 0x7f; 327 data[1] = div & 0xff; 328 data[2] = 0xc2; 329 330 if (div < 1450) 331 data[3] = 0x00; 332 else if (div < 1850) 333 data[3] = 0x40; 334 else if (div < 2000) 335 data[3] = 0x80; 336 else 337 data[3] = 0xc0; 338 339 if (fe->ops.i2c_gate_ctrl) 340 fe->ops.i2c_gate_ctrl(fe, 1); 341 if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO; 342 343 return 0; 344} 345 346static struct s5h1420_config s5h1420_config = { 347 .demod_address = 0x53, 348 .invert = 1, 349}; 350 351static struct tda10086_config tda10086_config = { 352 .demod_address = 0x0e, 353 .invert = 0, 354}; 355 356static u8 read_pwm(struct budget* budget) 357{ 358 u8 b = 0xff; 359 u8 pwm; 360 struct i2c_msg msg[] = { { .addr = 0x50,.flags = 0,.buf = &b,.len = 1 }, 361 { .addr = 0x50,.flags = I2C_M_RD,.buf = &pwm,.len = 1} }; 362 363 if ((i2c_transfer(&budget->i2c_adap, msg, 2) != 2) || (pwm == 0xff)) 364 pwm = 0x48; 365 366 return pwm; 367} 368 369static void frontend_init(struct budget *budget) 370{ 371 switch(budget->dev->pci->subsystem_device) { 372 case 0x1003: // Hauppauge/TT Nova budget (stv0299/ALPS BSRU6(tsa5059) OR ves1893/ALPS BSRV2(sp5659)) 373 case 0x1013: 374 // try the ALPS BSRV2 first of all 375 budget->dvb_frontend = dvb_attach(ves1x93_attach, &alps_bsrv2_config, &budget->i2c_adap); 376 if (budget->dvb_frontend) { 377 budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsrv2_tuner_set_params; 378 budget->dvb_frontend->ops.diseqc_send_master_cmd = budget_diseqc_send_master_cmd; 379 budget->dvb_frontend->ops.diseqc_send_burst = budget_diseqc_send_burst; 380 budget->dvb_frontend->ops.set_tone = budget_set_tone; 381 break; 382 } 383 384 // try the ALPS BSRU6 now 385 budget->dvb_frontend = dvb_attach(stv0299_attach, &alps_bsru6_config, &budget->i2c_adap); 386 if (budget->dvb_frontend) { 387 budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params; 388 budget->dvb_frontend->tuner_priv = &budget->i2c_adap; 389 if (budget->dev->pci->subsystem_device == 0x1003 && diseqc_method == 0) { 390 budget->dvb_frontend->ops.diseqc_send_master_cmd = budget_diseqc_send_master_cmd; 391 budget->dvb_frontend->ops.diseqc_send_burst = budget_diseqc_send_burst; 392 budget->dvb_frontend->ops.set_tone = budget_set_tone; 393 } 394 break; 395 } 396 break; 397 398 case 0x1004: // Hauppauge/TT DVB-C budget (ves1820/ALPS TDBE2(sp5659)) 399 400 budget->dvb_frontend = dvb_attach(ves1820_attach, &alps_tdbe2_config, &budget->i2c_adap, read_pwm(budget)); 401 if (budget->dvb_frontend) { 402 budget->dvb_frontend->ops.tuner_ops.set_params = alps_tdbe2_tuner_set_params; 403 break; 404 } 405 break; 406 407 case 0x1005: // Hauppauge/TT Nova-T budget (L64781/Grundig 29504-401(tsa5060)) 408 409 budget->dvb_frontend = dvb_attach(l64781_attach, &grundig_29504_401_config, &budget->i2c_adap); 410 if (budget->dvb_frontend) { 411 budget->dvb_frontend->ops.tuner_ops.set_params = grundig_29504_401_tuner_set_params; 412 break; 413 } 414 break; 415 416 case 0x4f60: // Fujitsu Siemens Activy Budget-S PCI rev AL (stv0299/ALPS BSRU6(tsa5059)) 417 budget->dvb_frontend = dvb_attach(stv0299_attach, &alps_bsru6_config, &budget->i2c_adap); 418 if (budget->dvb_frontend) { 419 budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params; 420 budget->dvb_frontend->tuner_priv = &budget->i2c_adap; 421 budget->dvb_frontend->ops.set_voltage = siemens_budget_set_voltage; 422 budget->dvb_frontend->ops.dishnetwork_send_legacy_command = NULL; 423 } 424 break; 425 426 case 0x4f61: // Fujitsu Siemens Activy Budget-S PCI rev GR (tda8083/Grundig 29504-451(tsa5522)) 427 budget->dvb_frontend = dvb_attach(tda8083_attach, &grundig_29504_451_config, &budget->i2c_adap); 428 if (budget->dvb_frontend) { 429 budget->dvb_frontend->ops.tuner_ops.set_params = grundig_29504_451_tuner_set_params; 430 budget->dvb_frontend->ops.set_voltage = siemens_budget_set_voltage; 431 budget->dvb_frontend->ops.dishnetwork_send_legacy_command = NULL; 432 } 433 break; 434 435 case 0x1016: // Hauppauge/TT Nova-S SE (samsung s5h1420/????(tda8260)) 436 budget->dvb_frontend = dvb_attach(s5h1420_attach, &s5h1420_config, &budget->i2c_adap); 437 if (budget->dvb_frontend) { 438 budget->dvb_frontend->ops.tuner_ops.set_params = s5h1420_tuner_set_params; 439 if (dvb_attach(lnbp21_attach, budget->dvb_frontend, &budget->i2c_adap, 0, 0) == NULL) { 440 printk("%s: No LNBP21 found!\n", __FUNCTION__); 441 goto error_out; 442 } 443 break; 444 } 445 446 case 0x1018: // TT Budget-S-1401 (philips tda10086/philips tda8262) 447 // gpio2 is connected to CLB - reset it + leave it high 448 saa7146_setgpio(budget->dev, 2, SAA7146_GPIO_OUTLO); 449 msleep(1); 450 saa7146_setgpio(budget->dev, 2, SAA7146_GPIO_OUTHI); 451 msleep(1); 452 453 budget->dvb_frontend = dvb_attach(tda10086_attach, &tda10086_config, &budget->i2c_adap); 454 if (budget->dvb_frontend) { 455 if (dvb_attach(tda826x_attach, budget->dvb_frontend, 0x60, &budget->i2c_adap, 0) == NULL) 456 printk("%s: No tda826x found!\n", __FUNCTION__); 457 if (dvb_attach(lnbp21_attach, budget->dvb_frontend, &budget->i2c_adap, 0, 0) == NULL) { 458 printk("%s: No LNBP21 found!\n", __FUNCTION__); 459 goto error_out; 460 } 461 break; 462 } 463 } 464 465 if (budget->dvb_frontend == NULL) { 466 printk("budget: A frontend driver was not found for device %04x/%04x subsystem %04x/%04x\n", 467 budget->dev->pci->vendor, 468 budget->dev->pci->device, 469 budget->dev->pci->subsystem_vendor, 470 budget->dev->pci->subsystem_device); 471 } else { 472 if (dvb_register_frontend(&budget->dvb_adapter, budget->dvb_frontend)) 473 goto error_out; 474 } 475 return; 476 477error_out: 478 printk("budget: Frontend registration failed!\n"); 479 dvb_frontend_detach(budget->dvb_frontend); 480 budget->dvb_frontend = NULL; 481 return; 482} 483 484static int budget_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_data *info) 485{ 486 struct budget *budget = NULL; 487 int err; 488 489 budget = kmalloc(sizeof(struct budget), GFP_KERNEL); 490 if( NULL == budget ) { 491 return -ENOMEM; 492 } 493 494 dprintk(2, "dev:%p, info:%p, budget:%p\n", dev, info, budget); 495 496 dev->ext_priv = budget; 497 498 if ((err = ttpci_budget_init (budget, dev, info, THIS_MODULE))) { 499 printk("==> failed\n"); 500 kfree (budget); 501 return err; 502 } 503 504 budget->dvb_adapter.priv = budget; 505 frontend_init(budget); 506 507 ttpci_budget_init_hooks(budget); 508 509 return 0; 510} 511 512static int budget_detach (struct saa7146_dev* dev) 513{ 514 struct budget *budget = (struct budget*) dev->ext_priv; 515 int err; 516 517 if (budget->dvb_frontend) { 518 dvb_unregister_frontend(budget->dvb_frontend); 519 dvb_frontend_detach(budget->dvb_frontend); 520 } 521 522 err = ttpci_budget_deinit (budget); 523 524 kfree (budget); 525 dev->ext_priv = NULL; 526 527 return err; 528} 529 530static struct saa7146_extension budget_extension; 531 532MAKE_BUDGET_INFO(ttbs, "TT-Budget/WinTV-NOVA-S PCI", BUDGET_TT); 533MAKE_BUDGET_INFO(ttbc, "TT-Budget/WinTV-NOVA-C PCI", BUDGET_TT); 534MAKE_BUDGET_INFO(ttbt, "TT-Budget/WinTV-NOVA-T PCI", BUDGET_TT); 535MAKE_BUDGET_INFO(satel, "SATELCO Multimedia PCI", BUDGET_TT_HW_DISEQC); 536MAKE_BUDGET_INFO(ttbs1401, "TT-Budget-S-1401 PCI", BUDGET_TT); 537MAKE_BUDGET_INFO(fsacs0, "Fujitsu Siemens Activy Budget-S PCI (rev GR/grundig frontend)", BUDGET_FS_ACTIVY); 538MAKE_BUDGET_INFO(fsacs1, "Fujitsu Siemens Activy Budget-S PCI (rev AL/alps frontend)", BUDGET_FS_ACTIVY); 539 540static struct pci_device_id pci_tbl[] = { 541 MAKE_EXTENSION_PCI(ttbs, 0x13c2, 0x1003), 542 MAKE_EXTENSION_PCI(ttbc, 0x13c2, 0x1004), 543 MAKE_EXTENSION_PCI(ttbt, 0x13c2, 0x1005), 544 MAKE_EXTENSION_PCI(satel, 0x13c2, 0x1013), 545 MAKE_EXTENSION_PCI(ttbs, 0x13c2, 0x1016), 546 MAKE_EXTENSION_PCI(ttbs1401, 0x13c2, 0x1018), 547 MAKE_EXTENSION_PCI(fsacs1,0x1131, 0x4f60), 548 MAKE_EXTENSION_PCI(fsacs0,0x1131, 0x4f61), 549 { 550 .vendor = 0, 551 } 552}; 553 554MODULE_DEVICE_TABLE(pci, pci_tbl); 555 556static struct saa7146_extension budget_extension = { 557 .name = "budget dvb", 558 .flags = SAA7146_USE_I2C_IRQ, 559 560 .module = THIS_MODULE, 561 .pci_tbl = pci_tbl, 562 .attach = budget_attach, 563 .detach = budget_detach, 564 565 .irq_mask = MASK_10, 566 .irq_func = ttpci_budget_irq10_handler, 567}; 568 569static int __init budget_init(void) 570{ 571 return saa7146_register_extension(&budget_extension); 572} 573 574static void __exit budget_exit(void) 575{ 576 saa7146_unregister_extension(&budget_extension); 577} 578 579module_init(budget_init); 580module_exit(budget_exit); 581 582MODULE_LICENSE("GPL"); 583MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, Michael Hunold, others"); 584MODULE_DESCRIPTION("driver for the SAA7146 based so-called " 585 "budget PCI DVB cards by Siemens, Technotrend, Hauppauge"); 586