1 /* 2 * ngene-cards.c: nGene PCIe bridge driver - card specific info 3 * 4 * Copyright (C) 2005-2007 Micronas 5 * 6 * Copyright (C) 2008-2009 Ralph Metzler <rjkm@metzlerbros.de> 7 * Modifications for new nGene firmware, 8 * support for EEPROM-copying, 9 * support for new dual DVB-S2 card prototype 10 * 11 * 12 * This program is free software; you can redistribute it and/or 13 * modify it under the terms of the GNU General Public License 14 * version 2 only, as published by the Free Software Foundation. 15 * 16 * 17 * This program is distributed in the hope that it will be useful, 18 * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 * GNU General Public License for more details. 21 * 22 * To obtain the license, point your browser to 23 * http://www.gnu.org/copyleft/gpl.html 24 */ 25 26 #include <linux/module.h> 27 #include <linux/init.h> 28 #include <linux/pci.h> 29 #include <linux/pci_ids.h> 30 31 #include "ngene.h" 32 33 /* demods/tuners */ 34 #include "stv6110x.h" 35 #include "stv090x.h" 36 #include "lnbh24.h" 37 #include "lgdt330x.h" 38 #include "mt2131.h" 39 #include "tda18271c2dd.h" 40 #include "drxk.h" 41 #include "drxd.h" 42 #include "dvb-pll.h" 43 44 45 /****************************************************************************/ 46 /* Demod/tuner attachment ***************************************************/ 47 /****************************************************************************/ 48 49 static int tuner_attach_stv6110(struct ngene_channel *chan) 50 { 51 struct i2c_adapter *i2c; 52 struct stv090x_config *feconf = (struct stv090x_config *) 53 chan->dev->card_info->fe_config[chan->number]; 54 struct stv6110x_config *tunerconf = (struct stv6110x_config *) 55 chan->dev->card_info->tuner_config[chan->number]; 56 const struct stv6110x_devctl *ctl; 57 58 /* tuner 1+2: i2c adapter #0, tuner 3+4: i2c adapter #1 */ 59 if (chan->number < 2) 60 i2c = &chan->dev->channel[0].i2c_adapter; 61 else 62 i2c = &chan->dev->channel[1].i2c_adapter; 63 64 ctl = dvb_attach(stv6110x_attach, chan->fe, tunerconf, i2c); 65 if (ctl == NULL) { 66 printk(KERN_ERR DEVICE_NAME ": No STV6110X found!\n"); 67 return -ENODEV; 68 } 69 70 feconf->tuner_init = ctl->tuner_init; 71 feconf->tuner_sleep = ctl->tuner_sleep; 72 feconf->tuner_set_mode = ctl->tuner_set_mode; 73 feconf->tuner_set_frequency = ctl->tuner_set_frequency; 74 feconf->tuner_get_frequency = ctl->tuner_get_frequency; 75 feconf->tuner_set_bandwidth = ctl->tuner_set_bandwidth; 76 feconf->tuner_get_bandwidth = ctl->tuner_get_bandwidth; 77 feconf->tuner_set_bbgain = ctl->tuner_set_bbgain; 78 feconf->tuner_get_bbgain = ctl->tuner_get_bbgain; 79 feconf->tuner_set_refclk = ctl->tuner_set_refclk; 80 feconf->tuner_get_status = ctl->tuner_get_status; 81 82 return 0; 83 } 84 85 86 static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable) 87 { 88 struct ngene_channel *chan = fe->sec_priv; 89 int status; 90 91 if (enable) { 92 down(&chan->dev->pll_mutex); 93 status = chan->gate_ctrl(fe, 1); 94 } else { 95 status = chan->gate_ctrl(fe, 0); 96 up(&chan->dev->pll_mutex); 97 } 98 return status; 99 } 100 101 static int tuner_attach_tda18271(struct ngene_channel *chan) 102 { 103 struct i2c_adapter *i2c; 104 struct dvb_frontend *fe; 105 106 i2c = &chan->dev->channel[0].i2c_adapter; 107 if (chan->fe->ops.i2c_gate_ctrl) 108 chan->fe->ops.i2c_gate_ctrl(chan->fe, 1); 109 fe = dvb_attach(tda18271c2dd_attach, chan->fe, i2c, 0x60); 110 if (chan->fe->ops.i2c_gate_ctrl) 111 chan->fe->ops.i2c_gate_ctrl(chan->fe, 0); 112 if (!fe) { 113 printk(KERN_ERR "No TDA18271 found!\n"); 114 return -ENODEV; 115 } 116 117 return 0; 118 } 119 120 static int tuner_attach_probe(struct ngene_channel *chan) 121 { 122 if (chan->demod_type == 0) 123 return tuner_attach_stv6110(chan); 124 if (chan->demod_type == 1) 125 return tuner_attach_tda18271(chan); 126 return -EINVAL; 127 } 128 129 static int demod_attach_stv0900(struct ngene_channel *chan) 130 { 131 struct i2c_adapter *i2c; 132 struct stv090x_config *feconf = (struct stv090x_config *) 133 chan->dev->card_info->fe_config[chan->number]; 134 135 /* tuner 1+2: i2c adapter #0, tuner 3+4: i2c adapter #1 */ 136 /* Note: Both adapters share the same i2c bus, but the demod */ 137 /* driver requires that each demod has its own i2c adapter */ 138 if (chan->number < 2) 139 i2c = &chan->dev->channel[0].i2c_adapter; 140 else 141 i2c = &chan->dev->channel[1].i2c_adapter; 142 143 chan->fe = dvb_attach(stv090x_attach, feconf, i2c, 144 (chan->number & 1) == 0 ? STV090x_DEMODULATOR_0 145 : STV090x_DEMODULATOR_1); 146 if (chan->fe == NULL) { 147 printk(KERN_ERR DEVICE_NAME ": No STV0900 found!\n"); 148 return -ENODEV; 149 } 150 151 /* store channel info */ 152 if (feconf->tuner_i2c_lock) 153 chan->fe->analog_demod_priv = chan; 154 155 if (!dvb_attach(lnbh24_attach, chan->fe, i2c, 0, 156 0, chan->dev->card_info->lnb[chan->number])) { 157 printk(KERN_ERR DEVICE_NAME ": No LNBH24 found!\n"); 158 dvb_frontend_detach(chan->fe); 159 chan->fe = NULL; 160 return -ENODEV; 161 } 162 163 return 0; 164 } 165 166 static void cineS2_tuner_i2c_lock(struct dvb_frontend *fe, int lock) 167 { 168 struct ngene_channel *chan = fe->analog_demod_priv; 169 170 if (lock) 171 down(&chan->dev->pll_mutex); 172 else 173 up(&chan->dev->pll_mutex); 174 } 175 176 static int i2c_read(struct i2c_adapter *adapter, u8 adr, u8 *val) 177 { 178 struct i2c_msg msgs[1] = {{.addr = adr, .flags = I2C_M_RD, 179 .buf = val, .len = 1 } }; 180 return (i2c_transfer(adapter, msgs, 1) == 1) ? 0 : -1; 181 } 182 183 static int i2c_read_reg16(struct i2c_adapter *adapter, u8 adr, 184 u16 reg, u8 *val) 185 { 186 u8 msg[2] = {reg>>8, reg&0xff}; 187 struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, 188 .buf = msg, .len = 2}, 189 {.addr = adr, .flags = I2C_M_RD, 190 .buf = val, .len = 1} }; 191 return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1; 192 } 193 194 static int port_has_stv0900(struct i2c_adapter *i2c, int port) 195 { 196 u8 val; 197 if (i2c_read_reg16(i2c, 0x68+port/2, 0xf100, &val) < 0) 198 return 0; 199 return 1; 200 } 201 202 static int port_has_drxk(struct i2c_adapter *i2c, int port) 203 { 204 u8 val; 205 206 if (i2c_read(i2c, 0x29+port, &val) < 0) 207 return 0; 208 return 1; 209 } 210 211 static int demod_attach_drxk(struct ngene_channel *chan, 212 struct i2c_adapter *i2c) 213 { 214 struct drxk_config config; 215 216 memset(&config, 0, sizeof(config)); 217 config.microcode_name = "drxk_a3.mc"; 218 config.qam_demod_parameter_count = 4; 219 config.adr = 0x29 + (chan->number ^ 2); 220 221 chan->fe = dvb_attach(drxk_attach, &config, i2c); 222 if (!chan->fe) { 223 printk(KERN_ERR "No DRXK found!\n"); 224 return -ENODEV; 225 } 226 chan->fe->sec_priv = chan; 227 chan->gate_ctrl = chan->fe->ops.i2c_gate_ctrl; 228 chan->fe->ops.i2c_gate_ctrl = drxk_gate_ctrl; 229 return 0; 230 } 231 232 static int cineS2_probe(struct ngene_channel *chan) 233 { 234 struct i2c_adapter *i2c; 235 struct stv090x_config *fe_conf; 236 u8 buf[3]; 237 struct i2c_msg i2c_msg = { .flags = 0, .buf = buf }; 238 int rc; 239 240 /* tuner 1+2: i2c adapter #0, tuner 3+4: i2c adapter #1 */ 241 if (chan->number < 2) 242 i2c = &chan->dev->channel[0].i2c_adapter; 243 else 244 i2c = &chan->dev->channel[1].i2c_adapter; 245 246 if (port_has_stv0900(i2c, chan->number)) { 247 chan->demod_type = 0; 248 fe_conf = chan->dev->card_info->fe_config[chan->number]; 249 /* demod found, attach it */ 250 rc = demod_attach_stv0900(chan); 251 if (rc < 0 || chan->number < 2) 252 return rc; 253 254 /* demod #2: reprogram outputs DPN1 & DPN2 */ 255 i2c_msg.addr = fe_conf->address; 256 i2c_msg.len = 3; 257 buf[0] = 0xf1; 258 switch (chan->number) { 259 case 2: 260 buf[1] = 0x5c; 261 buf[2] = 0xc2; 262 break; 263 case 3: 264 buf[1] = 0x61; 265 buf[2] = 0xcc; 266 break; 267 default: 268 return -ENODEV; 269 } 270 rc = i2c_transfer(i2c, &i2c_msg, 1); 271 if (rc != 1) { 272 printk(KERN_ERR DEVICE_NAME ": could not setup DPNx\n"); 273 return -EIO; 274 } 275 } else if (port_has_drxk(i2c, chan->number^2)) { 276 chan->demod_type = 1; 277 demod_attach_drxk(chan, i2c); 278 } else { 279 printk(KERN_ERR "No demod found on chan %d\n", chan->number); 280 return -ENODEV; 281 } 282 return 0; 283 } 284 285 286 static struct lgdt330x_config aver_m780 = { 287 .demod_address = 0xb2 >> 1, 288 .demod_chip = LGDT3303, 289 .serial_mpeg = 0x00, /* PARALLEL */ 290 .clock_polarity_flip = 1, 291 }; 292 293 static struct mt2131_config m780_tunerconfig = { 294 0xc0 >> 1 295 }; 296 297 /* A single func to attach the demo and tuner, rather than 298 * use two sep funcs like the current design mandates. 299 */ 300 static int demod_attach_lg330x(struct ngene_channel *chan) 301 { 302 chan->fe = dvb_attach(lgdt330x_attach, &aver_m780, &chan->i2c_adapter); 303 if (chan->fe == NULL) { 304 printk(KERN_ERR DEVICE_NAME ": No LGDT330x found!\n"); 305 return -ENODEV; 306 } 307 308 dvb_attach(mt2131_attach, chan->fe, &chan->i2c_adapter, 309 &m780_tunerconfig, 0); 310 311 return (chan->fe) ? 0 : -ENODEV; 312 } 313 314 static int demod_attach_drxd(struct ngene_channel *chan) 315 { 316 struct drxd_config *feconf; 317 318 feconf = chan->dev->card_info->fe_config[chan->number]; 319 320 chan->fe = dvb_attach(drxd_attach, feconf, chan, 321 &chan->i2c_adapter, &chan->dev->pci_dev->dev); 322 if (!chan->fe) { 323 pr_err("No DRXD found!\n"); 324 return -ENODEV; 325 } 326 return 0; 327 } 328 329 static int tuner_attach_dtt7520x(struct ngene_channel *chan) 330 { 331 struct drxd_config *feconf; 332 333 feconf = chan->dev->card_info->fe_config[chan->number]; 334 335 if (!dvb_attach(dvb_pll_attach, chan->fe, feconf->pll_address, 336 &chan->i2c_adapter, 337 feconf->pll_type)) { 338 pr_err("No pll(%d) found!\n", feconf->pll_type); 339 return -ENODEV; 340 } 341 return 0; 342 } 343 344 /****************************************************************************/ 345 /* EEPROM TAGS **************************************************************/ 346 /****************************************************************************/ 347 348 #define MICNG_EE_START 0x0100 349 #define MICNG_EE_END 0x0FF0 350 351 #define MICNG_EETAG_END0 0x0000 352 #define MICNG_EETAG_END1 0xFFFF 353 354 /* 0x0001 - 0x000F reserved for housekeeping */ 355 /* 0xFFFF - 0xFFFE reserved for housekeeping */ 356 357 /* Micronas assigned tags 358 EEProm tags for hardware support */ 359 360 #define MICNG_EETAG_DRXD1_OSCDEVIATION 0x1000 /* 2 Bytes data */ 361 #define MICNG_EETAG_DRXD2_OSCDEVIATION 0x1001 /* 2 Bytes data */ 362 363 #define MICNG_EETAG_MT2060_1_1STIF 0x1100 /* 2 Bytes data */ 364 #define MICNG_EETAG_MT2060_2_1STIF 0x1101 /* 2 Bytes data */ 365 366 /* Tag range for OEMs */ 367 368 #define MICNG_EETAG_OEM_FIRST 0xC000 369 #define MICNG_EETAG_OEM_LAST 0xFFEF 370 371 static int i2c_write_eeprom(struct i2c_adapter *adapter, 372 u8 adr, u16 reg, u8 data) 373 { 374 u8 m[3] = {(reg >> 8), (reg & 0xff), data}; 375 struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = m, 376 .len = sizeof(m)}; 377 378 if (i2c_transfer(adapter, &msg, 1) != 1) { 379 pr_err(DEVICE_NAME ": Error writing EEPROM!\n"); 380 return -EIO; 381 } 382 return 0; 383 } 384 385 static int i2c_read_eeprom(struct i2c_adapter *adapter, 386 u8 adr, u16 reg, u8 *data, int len) 387 { 388 u8 msg[2] = {(reg >> 8), (reg & 0xff)}; 389 struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, 390 .buf = msg, .len = 2 }, 391 {.addr = adr, .flags = I2C_M_RD, 392 .buf = data, .len = len} }; 393 394 if (i2c_transfer(adapter, msgs, 2) != 2) { 395 pr_err(DEVICE_NAME ": Error reading EEPROM\n"); 396 return -EIO; 397 } 398 return 0; 399 } 400 401 static int ReadEEProm(struct i2c_adapter *adapter, 402 u16 Tag, u32 MaxLen, u8 *data, u32 *pLength) 403 { 404 int status = 0; 405 u16 Addr = MICNG_EE_START, Length, tag = 0; 406 u8 EETag[3]; 407 408 while (Addr + sizeof(u16) + 1 < MICNG_EE_END) { 409 if (i2c_read_eeprom(adapter, 0x50, Addr, EETag, sizeof(EETag))) 410 return -1; 411 tag = (EETag[0] << 8) | EETag[1]; 412 if (tag == MICNG_EETAG_END0 || tag == MICNG_EETAG_END1) 413 return -1; 414 if (tag == Tag) 415 break; 416 Addr += sizeof(u16) + 1 + EETag[2]; 417 } 418 if (Addr + sizeof(u16) + 1 + EETag[2] > MICNG_EE_END) { 419 pr_err(DEVICE_NAME 420 ": Reached EOEE @ Tag = %04x Length = %3d\n", 421 tag, EETag[2]); 422 return -1; 423 } 424 Length = EETag[2]; 425 if (Length > MaxLen) 426 Length = (u16) MaxLen; 427 if (Length > 0) { 428 Addr += sizeof(u16) + 1; 429 status = i2c_read_eeprom(adapter, 0x50, Addr, data, Length); 430 if (!status) { 431 *pLength = EETag[2]; 432 #if 0 433 if (Length < EETag[2]) 434 status = STATUS_BUFFER_OVERFLOW; 435 #endif 436 } 437 } 438 return status; 439 } 440 441 static int WriteEEProm(struct i2c_adapter *adapter, 442 u16 Tag, u32 Length, u8 *data) 443 { 444 int status = 0; 445 u16 Addr = MICNG_EE_START; 446 u8 EETag[3]; 447 u16 tag = 0; 448 int retry, i; 449 450 while (Addr + sizeof(u16) + 1 < MICNG_EE_END) { 451 if (i2c_read_eeprom(adapter, 0x50, Addr, EETag, sizeof(EETag))) 452 return -1; 453 tag = (EETag[0] << 8) | EETag[1]; 454 if (tag == MICNG_EETAG_END0 || tag == MICNG_EETAG_END1) 455 return -1; 456 if (tag == Tag) 457 break; 458 Addr += sizeof(u16) + 1 + EETag[2]; 459 } 460 if (Addr + sizeof(u16) + 1 + EETag[2] > MICNG_EE_END) { 461 pr_err(DEVICE_NAME 462 ": Reached EOEE @ Tag = %04x Length = %3d\n", 463 tag, EETag[2]); 464 return -1; 465 } 466 467 if (Length > EETag[2]) 468 return -EINVAL; 469 /* Note: We write the data one byte at a time to avoid 470 issues with page sizes. (which are different for 471 each manufacture and eeprom size) 472 */ 473 Addr += sizeof(u16) + 1; 474 for (i = 0; i < Length; i++, Addr++) { 475 status = i2c_write_eeprom(adapter, 0x50, Addr, data[i]); 476 477 if (status) 478 break; 479 480 /* Poll for finishing write cycle */ 481 retry = 10; 482 while (retry) { 483 u8 Tmp; 484 485 msleep(50); 486 status = i2c_read_eeprom(adapter, 0x50, Addr, &Tmp, 1); 487 if (status) 488 break; 489 if (Tmp != data[i]) 490 pr_err(DEVICE_NAME 491 "eeprom write error\n"); 492 retry -= 1; 493 } 494 if (status) { 495 pr_err(DEVICE_NAME 496 ": Timeout polling eeprom\n"); 497 break; 498 } 499 } 500 return status; 501 } 502 503 static int eeprom_read_ushort(struct i2c_adapter *adapter, u16 tag, u16 *data) 504 { 505 int stat; 506 u8 buf[2]; 507 u32 len = 0; 508 509 stat = ReadEEProm(adapter, tag, 2, buf, &len); 510 if (stat) 511 return stat; 512 if (len != 2) 513 return -EINVAL; 514 515 *data = (buf[0] << 8) | buf[1]; 516 return 0; 517 } 518 519 static int eeprom_write_ushort(struct i2c_adapter *adapter, u16 tag, u16 data) 520 { 521 int stat; 522 u8 buf[2]; 523 524 buf[0] = data >> 8; 525 buf[1] = data & 0xff; 526 stat = WriteEEProm(adapter, tag, 2, buf); 527 if (stat) 528 return stat; 529 return 0; 530 } 531 532 static s16 osc_deviation(void *priv, s16 deviation, int flag) 533 { 534 struct ngene_channel *chan = priv; 535 struct i2c_adapter *adap = &chan->i2c_adapter; 536 u16 data = 0; 537 538 if (flag) { 539 data = (u16) deviation; 540 pr_info(DEVICE_NAME ": write deviation %d\n", 541 deviation); 542 eeprom_write_ushort(adap, 0x1000 + chan->number, data); 543 } else { 544 if (eeprom_read_ushort(adap, 0x1000 + chan->number, &data)) 545 data = 0; 546 pr_info(DEVICE_NAME ": read deviation %d\n", 547 (s16) data); 548 } 549 550 return (s16) data; 551 } 552 553 /****************************************************************************/ 554 /* Switch control (I2C gates, etc.) *****************************************/ 555 /****************************************************************************/ 556 557 558 static struct stv090x_config fe_cineS2 = { 559 .device = STV0900, 560 .demod_mode = STV090x_DUAL, 561 .clk_mode = STV090x_CLK_EXT, 562 563 .xtal = 27000000, 564 .address = 0x68, 565 566 .ts1_mode = STV090x_TSMODE_SERIAL_PUNCTURED, 567 .ts2_mode = STV090x_TSMODE_SERIAL_PUNCTURED, 568 569 .repeater_level = STV090x_RPTLEVEL_16, 570 571 .adc1_range = STV090x_ADC_1Vpp, 572 .adc2_range = STV090x_ADC_1Vpp, 573 574 .diseqc_envelope_mode = true, 575 576 .tuner_i2c_lock = cineS2_tuner_i2c_lock, 577 }; 578 579 static struct stv090x_config fe_cineS2_2 = { 580 .device = STV0900, 581 .demod_mode = STV090x_DUAL, 582 .clk_mode = STV090x_CLK_EXT, 583 584 .xtal = 27000000, 585 .address = 0x69, 586 587 .ts1_mode = STV090x_TSMODE_SERIAL_PUNCTURED, 588 .ts2_mode = STV090x_TSMODE_SERIAL_PUNCTURED, 589 590 .repeater_level = STV090x_RPTLEVEL_16, 591 592 .adc1_range = STV090x_ADC_1Vpp, 593 .adc2_range = STV090x_ADC_1Vpp, 594 595 .diseqc_envelope_mode = true, 596 597 .tuner_i2c_lock = cineS2_tuner_i2c_lock, 598 }; 599 600 static struct stv6110x_config tuner_cineS2_0 = { 601 .addr = 0x60, 602 .refclk = 27000000, 603 .clk_div = 1, 604 }; 605 606 static struct stv6110x_config tuner_cineS2_1 = { 607 .addr = 0x63, 608 .refclk = 27000000, 609 .clk_div = 1, 610 }; 611 612 static const struct ngene_info ngene_info_cineS2 = { 613 .type = NGENE_SIDEWINDER, 614 .name = "Linux4Media cineS2 DVB-S2 Twin Tuner", 615 .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN}, 616 .demod_attach = {demod_attach_stv0900, demod_attach_stv0900}, 617 .tuner_attach = {tuner_attach_stv6110, tuner_attach_stv6110}, 618 .fe_config = {&fe_cineS2, &fe_cineS2}, 619 .tuner_config = {&tuner_cineS2_0, &tuner_cineS2_1}, 620 .lnb = {0x0b, 0x08}, 621 .tsf = {3, 3}, 622 .fw_version = 18, 623 .msi_supported = true, 624 }; 625 626 static const struct ngene_info ngene_info_satixS2 = { 627 .type = NGENE_SIDEWINDER, 628 .name = "Mystique SaTiX-S2 Dual", 629 .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN}, 630 .demod_attach = {demod_attach_stv0900, demod_attach_stv0900}, 631 .tuner_attach = {tuner_attach_stv6110, tuner_attach_stv6110}, 632 .fe_config = {&fe_cineS2, &fe_cineS2}, 633 .tuner_config = {&tuner_cineS2_0, &tuner_cineS2_1}, 634 .lnb = {0x0b, 0x08}, 635 .tsf = {3, 3}, 636 .fw_version = 18, 637 .msi_supported = true, 638 }; 639 640 static const struct ngene_info ngene_info_satixS2v2 = { 641 .type = NGENE_SIDEWINDER, 642 .name = "Mystique SaTiX-S2 Dual (v2)", 643 .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN, 644 NGENE_IO_TSOUT}, 645 .demod_attach = {demod_attach_stv0900, demod_attach_stv0900, cineS2_probe, cineS2_probe}, 646 .tuner_attach = {tuner_attach_stv6110, tuner_attach_stv6110, tuner_attach_probe, tuner_attach_probe}, 647 .fe_config = {&fe_cineS2, &fe_cineS2, &fe_cineS2_2, &fe_cineS2_2}, 648 .tuner_config = {&tuner_cineS2_0, &tuner_cineS2_1, &tuner_cineS2_0, &tuner_cineS2_1}, 649 .lnb = {0x0a, 0x08, 0x0b, 0x09}, 650 .tsf = {3, 3}, 651 .fw_version = 18, 652 .msi_supported = true, 653 }; 654 655 static const struct ngene_info ngene_info_cineS2v5 = { 656 .type = NGENE_SIDEWINDER, 657 .name = "Linux4Media cineS2 DVB-S2 Twin Tuner (v5)", 658 .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN, 659 NGENE_IO_TSOUT}, 660 .demod_attach = {demod_attach_stv0900, demod_attach_stv0900, cineS2_probe, cineS2_probe}, 661 .tuner_attach = {tuner_attach_stv6110, tuner_attach_stv6110, tuner_attach_probe, tuner_attach_probe}, 662 .fe_config = {&fe_cineS2, &fe_cineS2, &fe_cineS2_2, &fe_cineS2_2}, 663 .tuner_config = {&tuner_cineS2_0, &tuner_cineS2_1, &tuner_cineS2_0, &tuner_cineS2_1}, 664 .lnb = {0x0a, 0x08, 0x0b, 0x09}, 665 .tsf = {3, 3}, 666 .fw_version = 18, 667 .msi_supported = true, 668 }; 669 670 671 static const struct ngene_info ngene_info_duoFlex = { 672 .type = NGENE_SIDEWINDER, 673 .name = "Digital Devices DuoFlex PCIe or miniPCIe", 674 .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN, 675 NGENE_IO_TSOUT}, 676 .demod_attach = {cineS2_probe, cineS2_probe, cineS2_probe, cineS2_probe}, 677 .tuner_attach = {tuner_attach_probe, tuner_attach_probe, tuner_attach_probe, tuner_attach_probe}, 678 .fe_config = {&fe_cineS2, &fe_cineS2, &fe_cineS2_2, &fe_cineS2_2}, 679 .tuner_config = {&tuner_cineS2_0, &tuner_cineS2_1, &tuner_cineS2_0, &tuner_cineS2_1}, 680 .lnb = {0x0a, 0x08, 0x0b, 0x09}, 681 .tsf = {3, 3}, 682 .fw_version = 18, 683 .msi_supported = true, 684 }; 685 686 static const struct ngene_info ngene_info_m780 = { 687 .type = NGENE_APP, 688 .name = "Aver M780 ATSC/QAM-B", 689 690 /* Channel 0 is analog, which is currently unsupported */ 691 .io_type = { NGENE_IO_NONE, NGENE_IO_TSIN }, 692 .demod_attach = { NULL, demod_attach_lg330x }, 693 694 /* Ensure these are NULL else the frame will call them (as funcs) */ 695 .tuner_attach = { NULL, NULL, NULL, NULL }, 696 .fe_config = { NULL, &aver_m780 }, 697 .avf = { 0 }, 698 699 /* A custom electrical interface config for the demod to bridge */ 700 .tsf = { 4, 4 }, 701 .fw_version = 15, 702 }; 703 704 static struct drxd_config fe_terratec_dvbt_0 = { 705 .index = 0, 706 .demod_address = 0x70, 707 .demod_revision = 0xa2, 708 .demoda_address = 0x00, 709 .pll_address = 0x60, 710 .pll_type = DVB_PLL_THOMSON_DTT7520X, 711 .clock = 20000, 712 .osc_deviation = osc_deviation, 713 }; 714 715 static struct drxd_config fe_terratec_dvbt_1 = { 716 .index = 1, 717 .demod_address = 0x71, 718 .demod_revision = 0xa2, 719 .demoda_address = 0x00, 720 .pll_address = 0x60, 721 .pll_type = DVB_PLL_THOMSON_DTT7520X, 722 .clock = 20000, 723 .osc_deviation = osc_deviation, 724 }; 725 726 static const struct ngene_info ngene_info_terratec = { 727 .type = NGENE_TERRATEC, 728 .name = "Terratec Integra/Cinergy2400i Dual DVB-T", 729 .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN}, 730 .demod_attach = {demod_attach_drxd, demod_attach_drxd}, 731 .tuner_attach = {tuner_attach_dtt7520x, tuner_attach_dtt7520x}, 732 .fe_config = {&fe_terratec_dvbt_0, &fe_terratec_dvbt_1}, 733 .i2c_access = 1, 734 }; 735 736 /****************************************************************************/ 737 738 739 740 /****************************************************************************/ 741 /* PCI Subsystem ID *********************************************************/ 742 /****************************************************************************/ 743 744 #define NGENE_ID(_subvend, _subdev, _driverdata) { \ 745 .vendor = NGENE_VID, .device = NGENE_PID, \ 746 .subvendor = _subvend, .subdevice = _subdev, \ 747 .driver_data = (unsigned long) &_driverdata } 748 749 /****************************************************************************/ 750 751 static const struct pci_device_id ngene_id_tbl[] = { 752 NGENE_ID(0x18c3, 0xabc3, ngene_info_cineS2), 753 NGENE_ID(0x18c3, 0xabc4, ngene_info_cineS2), 754 NGENE_ID(0x18c3, 0xdb01, ngene_info_satixS2), 755 NGENE_ID(0x18c3, 0xdb02, ngene_info_satixS2v2), 756 NGENE_ID(0x18c3, 0xdd00, ngene_info_cineS2v5), 757 NGENE_ID(0x18c3, 0xdd10, ngene_info_duoFlex), 758 NGENE_ID(0x18c3, 0xdd20, ngene_info_duoFlex), 759 NGENE_ID(0x1461, 0x062e, ngene_info_m780), 760 NGENE_ID(0x153b, 0x1167, ngene_info_terratec), 761 {0} 762 }; 763 MODULE_DEVICE_TABLE(pci, ngene_id_tbl); 764 765 /****************************************************************************/ 766 /* Init/Exit ****************************************************************/ 767 /****************************************************************************/ 768 769 static pci_ers_result_t ngene_error_detected(struct pci_dev *dev, 770 enum pci_channel_state state) 771 { 772 printk(KERN_ERR DEVICE_NAME ": PCI error\n"); 773 if (state == pci_channel_io_perm_failure) 774 return PCI_ERS_RESULT_DISCONNECT; 775 if (state == pci_channel_io_frozen) 776 return PCI_ERS_RESULT_NEED_RESET; 777 return PCI_ERS_RESULT_CAN_RECOVER; 778 } 779 780 static pci_ers_result_t ngene_slot_reset(struct pci_dev *dev) 781 { 782 printk(KERN_INFO DEVICE_NAME ": slot reset\n"); 783 return 0; 784 } 785 786 static void ngene_resume(struct pci_dev *dev) 787 { 788 printk(KERN_INFO DEVICE_NAME ": resume\n"); 789 } 790 791 static const struct pci_error_handlers ngene_errors = { 792 .error_detected = ngene_error_detected, 793 .slot_reset = ngene_slot_reset, 794 .resume = ngene_resume, 795 }; 796 797 static struct pci_driver ngene_pci_driver = { 798 .name = "ngene", 799 .id_table = ngene_id_tbl, 800 .probe = ngene_probe, 801 .remove = ngene_remove, 802 .err_handler = &ngene_errors, 803 .shutdown = ngene_shutdown, 804 }; 805 806 static __init int module_init_ngene(void) 807 { 808 printk(KERN_INFO 809 "nGene PCIE bridge driver, Copyright (C) 2005-2007 Micronas\n"); 810 return pci_register_driver(&ngene_pci_driver); 811 } 812 813 static __exit void module_exit_ngene(void) 814 { 815 pci_unregister_driver(&ngene_pci_driver); 816 } 817 818 module_init(module_init_ngene); 819 module_exit(module_exit_ngene); 820 821 MODULE_DESCRIPTION("nGene"); 822 MODULE_AUTHOR("Micronas, Ralph Metzler, Manfred Voelkel"); 823 MODULE_LICENSE("GPL"); 824