1 /* 2 Frontend/Card driver for TwinHan DST Frontend 3 Copyright (C) 2003 Jamie Honan 4 Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.com) 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 2 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program; if not, write to the Free Software 18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 */ 20 21 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 22 23 #include <linux/kernel.h> 24 #include <linux/module.h> 25 #include <linux/init.h> 26 #include <linux/string.h> 27 #include <linux/slab.h> 28 #include <linux/vmalloc.h> 29 #include <linux/delay.h> 30 #include <asm/div64.h> 31 #include "dvb_frontend.h" 32 #include "dst_priv.h" 33 #include "dst_common.h" 34 35 static unsigned int verbose; 36 module_param(verbose, int, 0644); 37 MODULE_PARM_DESC(verbose, "verbosity level (0 to 3)"); 38 39 static unsigned int dst_addons; 40 module_param(dst_addons, int, 0644); 41 MODULE_PARM_DESC(dst_addons, "CA daughterboard, default is 0 (No addons)"); 42 43 static unsigned int dst_algo; 44 module_param(dst_algo, int, 0644); 45 MODULE_PARM_DESC(dst_algo, "tuning algo: default is 0=(SW), 1=(HW)"); 46 47 #define HAS_LOCK 1 48 #define ATTEMPT_TUNE 2 49 #define HAS_POWER 4 50 51 #define dprintk(level, fmt, arg...) do { \ 52 if (level >= verbose) \ 53 printk(KERN_DEBUG pr_fmt("%s: " fmt), \ 54 __func__, ##arg); \ 55 } while(0) 56 57 static int dst_command(struct dst_state *state, u8 *data, u8 len); 58 59 static void dst_packsize(struct dst_state *state, int psize) 60 { 61 union dst_gpio_packet bits; 62 63 bits.psize = psize; 64 bt878_device_control(state->bt, DST_IG_TS, &bits); 65 } 66 67 static int dst_gpio_outb(struct dst_state *state, u32 mask, u32 enbb, 68 u32 outhigh, int delay) 69 { 70 union dst_gpio_packet enb; 71 union dst_gpio_packet bits; 72 int err; 73 74 enb.enb.mask = mask; 75 enb.enb.enable = enbb; 76 77 dprintk(2, "mask=[%04x], enbb=[%04x], outhigh=[%04x]\n", 78 mask, enbb, outhigh); 79 if ((err = bt878_device_control(state->bt, DST_IG_ENABLE, &enb)) < 0) { 80 dprintk(2, "dst_gpio_enb error (err == %i, mask == %02x, enb == %02x)\n", 81 err, mask, enbb); 82 return -EREMOTEIO; 83 } 84 udelay(1000); 85 /* because complete disabling means no output, no need to do output packet */ 86 if (enbb == 0) 87 return 0; 88 if (delay) 89 msleep(10); 90 bits.outp.mask = enbb; 91 bits.outp.highvals = outhigh; 92 if ((err = bt878_device_control(state->bt, DST_IG_WRITE, &bits)) < 0) { 93 dprintk(2, "dst_gpio_outb error (err == %i, enbb == %02x, outhigh == %02x)\n", 94 err, enbb, outhigh); 95 return -EREMOTEIO; 96 } 97 98 return 0; 99 } 100 101 static int dst_gpio_inb(struct dst_state *state, u8 *result) 102 { 103 union dst_gpio_packet rd_packet; 104 int err; 105 106 *result = 0; 107 if ((err = bt878_device_control(state->bt, DST_IG_READ, &rd_packet)) < 0) { 108 pr_err("dst_gpio_inb error (err == %i)\n", err); 109 return -EREMOTEIO; 110 } 111 *result = (u8) rd_packet.rd.value; 112 113 return 0; 114 } 115 116 int rdc_reset_state(struct dst_state *state) 117 { 118 dprintk(2, "Resetting state machine\n"); 119 if (dst_gpio_outb(state, RDC_8820_INT, RDC_8820_INT, 0, NO_DELAY) < 0) { 120 pr_err("dst_gpio_outb ERROR !\n"); 121 return -1; 122 } 123 msleep(10); 124 if (dst_gpio_outb(state, RDC_8820_INT, RDC_8820_INT, RDC_8820_INT, NO_DELAY) < 0) { 125 pr_err("dst_gpio_outb ERROR !\n"); 126 msleep(10); 127 return -1; 128 } 129 130 return 0; 131 } 132 EXPORT_SYMBOL(rdc_reset_state); 133 134 static int rdc_8820_reset(struct dst_state *state) 135 { 136 dprintk(3, "Resetting DST\n"); 137 if (dst_gpio_outb(state, RDC_8820_RESET, RDC_8820_RESET, 0, NO_DELAY) < 0) { 138 pr_err("dst_gpio_outb ERROR !\n"); 139 return -1; 140 } 141 udelay(1000); 142 if (dst_gpio_outb(state, RDC_8820_RESET, RDC_8820_RESET, RDC_8820_RESET, DELAY) < 0) { 143 pr_err("dst_gpio_outb ERROR !\n"); 144 return -1; 145 } 146 147 return 0; 148 } 149 150 static int dst_pio_enable(struct dst_state *state) 151 { 152 if (dst_gpio_outb(state, ~0, RDC_8820_PIO_0_ENABLE, 0, NO_DELAY) < 0) { 153 pr_err("dst_gpio_outb ERROR !\n"); 154 return -1; 155 } 156 udelay(1000); 157 158 return 0; 159 } 160 161 int dst_pio_disable(struct dst_state *state) 162 { 163 if (dst_gpio_outb(state, ~0, RDC_8820_PIO_0_DISABLE, RDC_8820_PIO_0_DISABLE, NO_DELAY) < 0) { 164 pr_err("dst_gpio_outb ERROR !\n"); 165 return -1; 166 } 167 if (state->type_flags & DST_TYPE_HAS_FW_1) 168 udelay(1000); 169 170 return 0; 171 } 172 EXPORT_SYMBOL(dst_pio_disable); 173 174 int dst_wait_dst_ready(struct dst_state *state, u8 delay_mode) 175 { 176 u8 reply; 177 int i; 178 179 for (i = 0; i < 200; i++) { 180 if (dst_gpio_inb(state, &reply) < 0) { 181 pr_err("dst_gpio_inb ERROR !\n"); 182 return -1; 183 } 184 if ((reply & RDC_8820_PIO_0_ENABLE) == 0) { 185 dprintk(2, "dst wait ready after %d\n", i); 186 return 1; 187 } 188 msleep(10); 189 } 190 dprintk(1, "dst wait NOT ready after %d\n", i); 191 192 return 0; 193 } 194 EXPORT_SYMBOL(dst_wait_dst_ready); 195 196 int dst_error_recovery(struct dst_state *state) 197 { 198 dprintk(1, "Trying to return from previous errors.\n"); 199 dst_pio_disable(state); 200 msleep(10); 201 dst_pio_enable(state); 202 msleep(10); 203 204 return 0; 205 } 206 EXPORT_SYMBOL(dst_error_recovery); 207 208 int dst_error_bailout(struct dst_state *state) 209 { 210 dprintk(2, "Trying to bailout from previous error.\n"); 211 rdc_8820_reset(state); 212 dst_pio_disable(state); 213 msleep(10); 214 215 return 0; 216 } 217 EXPORT_SYMBOL(dst_error_bailout); 218 219 int dst_comm_init(struct dst_state *state) 220 { 221 dprintk(2, "Initializing DST.\n"); 222 if ((dst_pio_enable(state)) < 0) { 223 pr_err("PIO Enable Failed\n"); 224 return -1; 225 } 226 if ((rdc_reset_state(state)) < 0) { 227 pr_err("RDC 8820 State RESET Failed.\n"); 228 return -1; 229 } 230 if (state->type_flags & DST_TYPE_HAS_FW_1) 231 msleep(100); 232 else 233 msleep(5); 234 235 return 0; 236 } 237 EXPORT_SYMBOL(dst_comm_init); 238 239 int write_dst(struct dst_state *state, u8 *data, u8 len) 240 { 241 struct i2c_msg msg = { 242 .addr = state->config->demod_address, 243 .flags = 0, 244 .buf = data, 245 .len = len 246 }; 247 248 int err; 249 u8 cnt; 250 251 dprintk(1, "writing [ %*ph ]\n", len, data); 252 253 for (cnt = 0; cnt < 2; cnt++) { 254 if ((err = i2c_transfer(state->i2c, &msg, 1)) < 0) { 255 dprintk(2, "_write_dst error (err == %i, len == 0x%02x, b0 == 0x%02x)\n", 256 err, len, data[0]); 257 dst_error_recovery(state); 258 continue; 259 } else 260 break; 261 } 262 if (cnt >= 2) { 263 dprintk(2, "RDC 8820 RESET\n"); 264 dst_error_bailout(state); 265 266 return -1; 267 } 268 269 return 0; 270 } 271 EXPORT_SYMBOL(write_dst); 272 273 int read_dst(struct dst_state *state, u8 *ret, u8 len) 274 { 275 struct i2c_msg msg = { 276 .addr = state->config->demod_address, 277 .flags = I2C_M_RD, 278 .buf = ret, 279 .len = len 280 }; 281 282 int err; 283 int cnt; 284 285 for (cnt = 0; cnt < 2; cnt++) { 286 if ((err = i2c_transfer(state->i2c, &msg, 1)) < 0) { 287 dprintk(2, "read_dst error (err == %i, len == 0x%02x, b0 == 0x%02x)\n", 288 err, len, ret[0]); 289 dst_error_recovery(state); 290 continue; 291 } else 292 break; 293 } 294 if (cnt >= 2) { 295 dprintk(2, "RDC 8820 RESET\n"); 296 dst_error_bailout(state); 297 298 return -1; 299 } 300 dprintk(3, "reply is %*ph\n", len, ret); 301 302 return 0; 303 } 304 EXPORT_SYMBOL(read_dst); 305 306 static int dst_set_polarization(struct dst_state *state) 307 { 308 switch (state->voltage) { 309 case SEC_VOLTAGE_13: /* Vertical */ 310 dprintk(2, "Polarization=[Vertical]\n"); 311 state->tx_tuna[8] &= ~0x40; 312 break; 313 case SEC_VOLTAGE_18: /* Horizontal */ 314 dprintk(2, "Polarization=[Horizontal]\n"); 315 state->tx_tuna[8] |= 0x40; 316 break; 317 case SEC_VOLTAGE_OFF: 318 break; 319 } 320 321 return 0; 322 } 323 324 static int dst_set_freq(struct dst_state *state, u32 freq) 325 { 326 state->frequency = freq; 327 dprintk(2, "set Frequency %u\n", freq); 328 329 if (state->dst_type == DST_TYPE_IS_SAT) { 330 freq = freq / 1000; 331 if (freq < 950 || freq > 2150) 332 return -EINVAL; 333 state->tx_tuna[2] = (freq >> 8); 334 state->tx_tuna[3] = (u8) freq; 335 state->tx_tuna[4] = 0x01; 336 state->tx_tuna[8] &= ~0x04; 337 if (state->type_flags & DST_TYPE_HAS_OBS_REGS) { 338 if (freq < 1531) 339 state->tx_tuna[8] |= 0x04; 340 } 341 } else if (state->dst_type == DST_TYPE_IS_TERR) { 342 freq = freq / 1000; 343 if (freq < 137000 || freq > 858000) 344 return -EINVAL; 345 state->tx_tuna[2] = (freq >> 16) & 0xff; 346 state->tx_tuna[3] = (freq >> 8) & 0xff; 347 state->tx_tuna[4] = (u8) freq; 348 } else if (state->dst_type == DST_TYPE_IS_CABLE) { 349 freq = freq / 1000; 350 state->tx_tuna[2] = (freq >> 16) & 0xff; 351 state->tx_tuna[3] = (freq >> 8) & 0xff; 352 state->tx_tuna[4] = (u8) freq; 353 } else if (state->dst_type == DST_TYPE_IS_ATSC) { 354 freq = freq / 1000; 355 if (freq < 51000 || freq > 858000) 356 return -EINVAL; 357 state->tx_tuna[2] = (freq >> 16) & 0xff; 358 state->tx_tuna[3] = (freq >> 8) & 0xff; 359 state->tx_tuna[4] = (u8) freq; 360 state->tx_tuna[5] = 0x00; /* ATSC */ 361 state->tx_tuna[6] = 0x00; 362 if (state->dst_hw_cap & DST_TYPE_HAS_ANALOG) 363 state->tx_tuna[7] = 0x00; /* Digital */ 364 } else 365 return -EINVAL; 366 367 return 0; 368 } 369 370 static int dst_set_bandwidth(struct dst_state *state, u32 bandwidth) 371 { 372 state->bandwidth = bandwidth; 373 374 if (state->dst_type != DST_TYPE_IS_TERR) 375 return -EOPNOTSUPP; 376 377 switch (bandwidth) { 378 case 6000000: 379 if (state->dst_hw_cap & DST_TYPE_HAS_CA) 380 state->tx_tuna[7] = 0x06; 381 else { 382 state->tx_tuna[6] = 0x06; 383 state->tx_tuna[7] = 0x00; 384 } 385 break; 386 case 7000000: 387 if (state->dst_hw_cap & DST_TYPE_HAS_CA) 388 state->tx_tuna[7] = 0x07; 389 else { 390 state->tx_tuna[6] = 0x07; 391 state->tx_tuna[7] = 0x00; 392 } 393 break; 394 case 8000000: 395 if (state->dst_hw_cap & DST_TYPE_HAS_CA) 396 state->tx_tuna[7] = 0x08; 397 else { 398 state->tx_tuna[6] = 0x08; 399 state->tx_tuna[7] = 0x00; 400 } 401 break; 402 default: 403 return -EINVAL; 404 } 405 406 return 0; 407 } 408 409 static int dst_set_inversion(struct dst_state *state, 410 enum fe_spectral_inversion inversion) 411 { 412 state->inversion = inversion; 413 switch (inversion) { 414 case INVERSION_OFF: /* Inversion = Normal */ 415 state->tx_tuna[8] &= ~0x80; 416 break; 417 case INVERSION_ON: 418 state->tx_tuna[8] |= 0x80; 419 break; 420 default: 421 return -EINVAL; 422 } 423 424 return 0; 425 } 426 427 static int dst_set_fec(struct dst_state *state, enum fe_code_rate fec) 428 { 429 state->fec = fec; 430 return 0; 431 } 432 433 static enum fe_code_rate dst_get_fec(struct dst_state *state) 434 { 435 return state->fec; 436 } 437 438 static int dst_set_symbolrate(struct dst_state *state, u32 srate) 439 { 440 u32 symcalc; 441 u64 sval; 442 443 state->symbol_rate = srate; 444 if (state->dst_type == DST_TYPE_IS_TERR) { 445 return -EOPNOTSUPP; 446 } 447 dprintk(2, "set symrate %u\n", srate); 448 srate /= 1000; 449 if (state->dst_type == DST_TYPE_IS_SAT) { 450 if (state->type_flags & DST_TYPE_HAS_SYMDIV) { 451 sval = srate; 452 sval <<= 20; 453 do_div(sval, 88000); 454 symcalc = (u32) sval; 455 dprintk(2, "set symcalc %u\n", symcalc); 456 state->tx_tuna[5] = (u8) (symcalc >> 12); 457 state->tx_tuna[6] = (u8) (symcalc >> 4); 458 state->tx_tuna[7] = (u8) (symcalc << 4); 459 } else { 460 state->tx_tuna[5] = (u8) (srate >> 16) & 0x7f; 461 state->tx_tuna[6] = (u8) (srate >> 8); 462 state->tx_tuna[7] = (u8) srate; 463 } 464 state->tx_tuna[8] &= ~0x20; 465 if (state->type_flags & DST_TYPE_HAS_OBS_REGS) { 466 if (srate > 8000) 467 state->tx_tuna[8] |= 0x20; 468 } 469 } else if (state->dst_type == DST_TYPE_IS_CABLE) { 470 dprintk(3, "%s\n", state->fw_name); 471 if (!strncmp(state->fw_name, "DCTNEW", 6)) { 472 state->tx_tuna[5] = (u8) (srate >> 8); 473 state->tx_tuna[6] = (u8) srate; 474 state->tx_tuna[7] = 0x00; 475 } else if (!strncmp(state->fw_name, "DCT-CI", 6)) { 476 state->tx_tuna[5] = 0x00; 477 state->tx_tuna[6] = (u8) (srate >> 8); 478 state->tx_tuna[7] = (u8) srate; 479 } 480 } 481 return 0; 482 } 483 484 static int dst_set_modulation(struct dst_state *state, 485 enum fe_modulation modulation) 486 { 487 if (state->dst_type != DST_TYPE_IS_CABLE) 488 return -EOPNOTSUPP; 489 490 state->modulation = modulation; 491 switch (modulation) { 492 case QAM_16: 493 state->tx_tuna[8] = 0x10; 494 break; 495 case QAM_32: 496 state->tx_tuna[8] = 0x20; 497 break; 498 case QAM_64: 499 state->tx_tuna[8] = 0x40; 500 break; 501 case QAM_128: 502 state->tx_tuna[8] = 0x80; 503 break; 504 case QAM_256: 505 if (!strncmp(state->fw_name, "DCTNEW", 6)) 506 state->tx_tuna[8] = 0xff; 507 else if (!strncmp(state->fw_name, "DCT-CI", 6)) 508 state->tx_tuna[8] = 0x00; 509 break; 510 case QPSK: 511 case QAM_AUTO: 512 case VSB_8: 513 case VSB_16: 514 default: 515 return -EINVAL; 516 517 } 518 519 return 0; 520 } 521 522 static enum fe_modulation dst_get_modulation(struct dst_state *state) 523 { 524 return state->modulation; 525 } 526 527 528 u8 dst_check_sum(u8 *buf, u32 len) 529 { 530 u32 i; 531 u8 val = 0; 532 if (!len) 533 return 0; 534 for (i = 0; i < len; i++) { 535 val += buf[i]; 536 } 537 return ((~val) + 1); 538 } 539 EXPORT_SYMBOL(dst_check_sum); 540 541 static void dst_type_flags_print(struct dst_state *state) 542 { 543 u32 type_flags = state->type_flags; 544 545 pr_err("DST type flags :\n"); 546 if (type_flags & DST_TYPE_HAS_TS188) 547 pr_err(" 0x%x newtuner\n", DST_TYPE_HAS_TS188); 548 if (type_flags & DST_TYPE_HAS_NEWTUNE_2) 549 pr_err(" 0x%x newtuner 2\n", DST_TYPE_HAS_NEWTUNE_2); 550 if (type_flags & DST_TYPE_HAS_TS204) 551 pr_err(" 0x%x ts204\n", DST_TYPE_HAS_TS204); 552 if (type_flags & DST_TYPE_HAS_VLF) 553 pr_err(" 0x%x VLF\n", DST_TYPE_HAS_VLF); 554 if (type_flags & DST_TYPE_HAS_SYMDIV) 555 pr_err(" 0x%x symdiv\n", DST_TYPE_HAS_SYMDIV); 556 if (type_flags & DST_TYPE_HAS_FW_1) 557 pr_err(" 0x%x firmware version = 1\n", DST_TYPE_HAS_FW_1); 558 if (type_flags & DST_TYPE_HAS_FW_2) 559 pr_err(" 0x%x firmware version = 2\n", DST_TYPE_HAS_FW_2); 560 if (type_flags & DST_TYPE_HAS_FW_3) 561 pr_err(" 0x%x firmware version = 3\n", DST_TYPE_HAS_FW_3); 562 pr_err("\n"); 563 } 564 565 566 static int dst_type_print(struct dst_state *state, u8 type) 567 { 568 char *otype; 569 switch (type) { 570 case DST_TYPE_IS_SAT: 571 otype = "satellite"; 572 break; 573 574 case DST_TYPE_IS_TERR: 575 otype = "terrestrial"; 576 break; 577 578 case DST_TYPE_IS_CABLE: 579 otype = "cable"; 580 break; 581 582 case DST_TYPE_IS_ATSC: 583 otype = "atsc"; 584 break; 585 586 default: 587 dprintk(2, "invalid dst type %d\n", type); 588 return -EINVAL; 589 } 590 dprintk(2, "DST type: %s\n", otype); 591 592 return 0; 593 } 594 595 static struct tuner_types tuner_list[] = { 596 { 597 .tuner_type = TUNER_TYPE_L64724, 598 .tuner_name = "L 64724", 599 .board_name = "UNKNOWN", 600 .fw_name = "UNKNOWN" 601 }, 602 603 { 604 .tuner_type = TUNER_TYPE_STV0299, 605 .tuner_name = "STV 0299", 606 .board_name = "VP1020", 607 .fw_name = "DST-MOT" 608 }, 609 610 { 611 .tuner_type = TUNER_TYPE_STV0299, 612 .tuner_name = "STV 0299", 613 .board_name = "VP1020", 614 .fw_name = "DST-03T" 615 }, 616 617 { 618 .tuner_type = TUNER_TYPE_MB86A15, 619 .tuner_name = "MB 86A15", 620 .board_name = "VP1022", 621 .fw_name = "DST-03T" 622 }, 623 624 { 625 .tuner_type = TUNER_TYPE_MB86A15, 626 .tuner_name = "MB 86A15", 627 .board_name = "VP1025", 628 .fw_name = "DST-03T" 629 }, 630 631 { 632 .tuner_type = TUNER_TYPE_STV0299, 633 .tuner_name = "STV 0299", 634 .board_name = "VP1030", 635 .fw_name = "DST-CI" 636 }, 637 638 { 639 .tuner_type = TUNER_TYPE_STV0299, 640 .tuner_name = "STV 0299", 641 .board_name = "VP1030", 642 .fw_name = "DSTMCI" 643 }, 644 645 { 646 .tuner_type = TUNER_TYPE_UNKNOWN, 647 .tuner_name = "UNKNOWN", 648 .board_name = "VP2021", 649 .fw_name = "DCTNEW" 650 }, 651 652 { 653 .tuner_type = TUNER_TYPE_UNKNOWN, 654 .tuner_name = "UNKNOWN", 655 .board_name = "VP2030", 656 .fw_name = "DCT-CI" 657 }, 658 659 { 660 .tuner_type = TUNER_TYPE_UNKNOWN, 661 .tuner_name = "UNKNOWN", 662 .board_name = "VP2031", 663 .fw_name = "DCT-CI" 664 }, 665 666 { 667 .tuner_type = TUNER_TYPE_UNKNOWN, 668 .tuner_name = "UNKNOWN", 669 .board_name = "VP2040", 670 .fw_name = "DCT-CI" 671 }, 672 673 { 674 .tuner_type = TUNER_TYPE_UNKNOWN, 675 .tuner_name = "UNKNOWN", 676 .board_name = "VP3020", 677 .fw_name = "DTTFTA" 678 }, 679 680 { 681 .tuner_type = TUNER_TYPE_UNKNOWN, 682 .tuner_name = "UNKNOWN", 683 .board_name = "VP3021", 684 .fw_name = "DTTFTA" 685 }, 686 687 { 688 .tuner_type = TUNER_TYPE_TDA10046, 689 .tuner_name = "TDA10046", 690 .board_name = "VP3040", 691 .fw_name = "DTT-CI" 692 }, 693 694 { 695 .tuner_type = TUNER_TYPE_UNKNOWN, 696 .tuner_name = "UNKNOWN", 697 .board_name = "VP3051", 698 .fw_name = "DTTNXT" 699 }, 700 701 { 702 .tuner_type = TUNER_TYPE_NXT200x, 703 .tuner_name = "NXT200x", 704 .board_name = "VP3220", 705 .fw_name = "ATSCDI" 706 }, 707 708 { 709 .tuner_type = TUNER_TYPE_NXT200x, 710 .tuner_name = "NXT200x", 711 .board_name = "VP3250", 712 .fw_name = "ATSCAD" 713 }, 714 }; 715 716 /* 717 Known cards list 718 Satellite 719 ------------------- 720 200103A 721 VP-1020 DST-MOT LG(old), TS=188 722 723 VP-1020 DST-03T LG(new), TS=204 724 VP-1022 DST-03T LG(new), TS=204 725 VP-1025 DST-03T LG(new), TS=204 726 727 VP-1030 DSTMCI, LG(new), TS=188 728 VP-1032 DSTMCI, LG(new), TS=188 729 730 Cable 731 ------------------- 732 VP-2030 DCT-CI, Samsung, TS=204 733 VP-2021 DCT-CI, Unknown, TS=204 734 VP-2031 DCT-CI, Philips, TS=188 735 VP-2040 DCT-CI, Philips, TS=188, with CA daughter board 736 VP-2040 DCT-CI, Philips, TS=204, without CA daughter board 737 738 Terrestrial 739 ------------------- 740 VP-3050 DTTNXT TS=188 741 VP-3040 DTT-CI, Philips, TS=188 742 VP-3040 DTT-CI, Philips, TS=204 743 744 ATSC 745 ------------------- 746 VP-3220 ATSCDI, TS=188 747 VP-3250 ATSCAD, TS=188 748 749 */ 750 751 static struct dst_types dst_tlist[] = { 752 { 753 .device_id = "200103A", 754 .offset = 0, 755 .dst_type = DST_TYPE_IS_SAT, 756 .type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_FW_1 | DST_TYPE_HAS_OBS_REGS, 757 .dst_feature = 0, 758 .tuner_type = 0 759 }, /* obsolete */ 760 761 { 762 .device_id = "DST-020", 763 .offset = 0, 764 .dst_type = DST_TYPE_IS_SAT, 765 .type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_FW_1, 766 .dst_feature = 0, 767 .tuner_type = 0 768 }, /* obsolete */ 769 770 { 771 .device_id = "DST-030", 772 .offset = 0, 773 .dst_type = DST_TYPE_IS_SAT, 774 .type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_TS188 | DST_TYPE_HAS_FW_1, 775 .dst_feature = 0, 776 .tuner_type = 0 777 }, /* obsolete */ 778 779 { 780 .device_id = "DST-03T", 781 .offset = 0, 782 .dst_type = DST_TYPE_IS_SAT, 783 .type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_TS204 | DST_TYPE_HAS_FW_2, 784 .dst_feature = DST_TYPE_HAS_DISEQC3 | DST_TYPE_HAS_DISEQC4 | DST_TYPE_HAS_DISEQC5 785 | DST_TYPE_HAS_MAC | DST_TYPE_HAS_MOTO, 786 .tuner_type = TUNER_TYPE_MULTI 787 }, 788 789 { 790 .device_id = "DST-MOT", 791 .offset = 0, 792 .dst_type = DST_TYPE_IS_SAT, 793 .type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_FW_1, 794 .dst_feature = 0, 795 .tuner_type = 0 796 }, /* obsolete */ 797 798 { 799 .device_id = "DST-CI", 800 .offset = 1, 801 .dst_type = DST_TYPE_IS_SAT, 802 .type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_FW_1, 803 .dst_feature = DST_TYPE_HAS_CA, 804 .tuner_type = 0 805 }, /* An OEM board */ 806 807 { 808 .device_id = "DSTMCI", 809 .offset = 1, 810 .dst_type = DST_TYPE_IS_SAT, 811 .type_flags = DST_TYPE_HAS_TS188 | DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_FW_BUILD | DST_TYPE_HAS_INC_COUNT | DST_TYPE_HAS_VLF, 812 .dst_feature = DST_TYPE_HAS_CA | DST_TYPE_HAS_DISEQC3 | DST_TYPE_HAS_DISEQC4 813 | DST_TYPE_HAS_MOTO | DST_TYPE_HAS_MAC, 814 .tuner_type = TUNER_TYPE_MULTI 815 }, 816 817 { 818 .device_id = "DSTFCI", 819 .offset = 1, 820 .dst_type = DST_TYPE_IS_SAT, 821 .type_flags = DST_TYPE_HAS_TS188 | DST_TYPE_HAS_FW_1, 822 .dst_feature = 0, 823 .tuner_type = 0 824 }, /* unknown to vendor */ 825 826 { 827 .device_id = "DCT-CI", 828 .offset = 1, 829 .dst_type = DST_TYPE_IS_CABLE, 830 .type_flags = DST_TYPE_HAS_MULTI_FE | DST_TYPE_HAS_FW_1 | DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_VLF, 831 .dst_feature = DST_TYPE_HAS_CA, 832 .tuner_type = 0 833 }, 834 835 { 836 .device_id = "DCTNEW", 837 .offset = 1, 838 .dst_type = DST_TYPE_IS_CABLE, 839 .type_flags = DST_TYPE_HAS_TS188 | DST_TYPE_HAS_FW_3 | DST_TYPE_HAS_FW_BUILD | DST_TYPE_HAS_MULTI_FE, 840 .dst_feature = 0, 841 .tuner_type = 0 842 }, 843 844 { 845 .device_id = "DTT-CI", 846 .offset = 1, 847 .dst_type = DST_TYPE_IS_TERR, 848 .type_flags = DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_MULTI_FE | DST_TYPE_HAS_VLF, 849 .dst_feature = DST_TYPE_HAS_CA, 850 .tuner_type = 0 851 }, 852 853 { 854 .device_id = "DTTDIG", 855 .offset = 1, 856 .dst_type = DST_TYPE_IS_TERR, 857 .type_flags = DST_TYPE_HAS_FW_2, 858 .dst_feature = 0, 859 .tuner_type = 0 860 }, 861 862 { 863 .device_id = "DTTNXT", 864 .offset = 1, 865 .dst_type = DST_TYPE_IS_TERR, 866 .type_flags = DST_TYPE_HAS_FW_2, 867 .dst_feature = DST_TYPE_HAS_ANALOG, 868 .tuner_type = 0 869 }, 870 871 { 872 .device_id = "ATSCDI", 873 .offset = 1, 874 .dst_type = DST_TYPE_IS_ATSC, 875 .type_flags = DST_TYPE_HAS_FW_2, 876 .dst_feature = 0, 877 .tuner_type = 0 878 }, 879 880 { 881 .device_id = "ATSCAD", 882 .offset = 1, 883 .dst_type = DST_TYPE_IS_ATSC, 884 .type_flags = DST_TYPE_HAS_MULTI_FE | DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_FW_BUILD, 885 .dst_feature = DST_TYPE_HAS_MAC | DST_TYPE_HAS_ANALOG, 886 .tuner_type = 0 887 }, 888 889 { } 890 891 }; 892 893 static int dst_get_mac(struct dst_state *state) 894 { 895 u8 get_mac[] = { 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 896 get_mac[7] = dst_check_sum(get_mac, 7); 897 if (dst_command(state, get_mac, 8) < 0) { 898 dprintk(2, "Unsupported Command\n"); 899 return -1; 900 } 901 memset(&state->mac_address, '\0', 8); 902 memcpy(&state->mac_address, &state->rxbuffer, 6); 903 pr_err("MAC Address=[%pM]\n", state->mac_address); 904 905 return 0; 906 } 907 908 static int dst_fw_ver(struct dst_state *state) 909 { 910 u8 get_ver[] = { 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 911 get_ver[7] = dst_check_sum(get_ver, 7); 912 if (dst_command(state, get_ver, 8) < 0) { 913 dprintk(2, "Unsupported Command\n"); 914 return -1; 915 } 916 memcpy(&state->fw_version, &state->rxbuffer, 8); 917 pr_err("Firmware Ver = %x.%x Build = %02x, on %x:%x, %x-%x-20%02x\n", 918 state->fw_version[0] >> 4, state->fw_version[0] & 0x0f, 919 state->fw_version[1], 920 state->fw_version[5], state->fw_version[6], 921 state->fw_version[4], state->fw_version[3], state->fw_version[2]); 922 923 return 0; 924 } 925 926 static int dst_card_type(struct dst_state *state) 927 { 928 int j; 929 struct tuner_types *p_tuner_list = NULL; 930 931 u8 get_type[] = { 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 932 get_type[7] = dst_check_sum(get_type, 7); 933 if (dst_command(state, get_type, 8) < 0) { 934 dprintk(2, "Unsupported Command\n"); 935 return -1; 936 } 937 memset(&state->card_info, '\0', 8); 938 memcpy(&state->card_info, &state->rxbuffer, 7); 939 pr_err("Device Model=[%s]\n", &state->card_info[0]); 940 941 for (j = 0, p_tuner_list = tuner_list; j < ARRAY_SIZE(tuner_list); j++, p_tuner_list++) { 942 if (!strcmp(&state->card_info[0], p_tuner_list->board_name)) { 943 state->tuner_type = p_tuner_list->tuner_type; 944 pr_err("DST has [%s] tuner, tuner type=[%d]\n", 945 p_tuner_list->tuner_name, p_tuner_list->tuner_type); 946 } 947 } 948 949 return 0; 950 } 951 952 static int dst_get_vendor(struct dst_state *state) 953 { 954 u8 get_vendor[] = { 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 955 get_vendor[7] = dst_check_sum(get_vendor, 7); 956 if (dst_command(state, get_vendor, 8) < 0) { 957 dprintk(2, "Unsupported Command\n"); 958 return -1; 959 } 960 memset(&state->vendor, '\0', 8); 961 memcpy(&state->vendor, &state->rxbuffer, 7); 962 pr_err("Vendor=[%s]\n", &state->vendor[0]); 963 964 return 0; 965 } 966 967 static void debug_dst_buffer(struct dst_state *state) 968 { 969 dprintk(3, "%s: [ %*ph ]\n", __func__, 8, state->rxbuffer); 970 } 971 972 static int dst_check_stv0299(struct dst_state *state) 973 { 974 u8 check_stv0299[] = { 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 975 976 check_stv0299[7] = dst_check_sum(check_stv0299, 7); 977 if (dst_command(state, check_stv0299, 8) < 0) { 978 pr_err("Cmd=[0x04] failed\n"); 979 return -1; 980 } 981 debug_dst_buffer(state); 982 983 if (memcmp(&check_stv0299, &state->rxbuffer, 8)) { 984 pr_err("Found a STV0299 NIM\n"); 985 state->tuner_type = TUNER_TYPE_STV0299; 986 return 0; 987 } 988 989 return -1; 990 } 991 992 static int dst_check_mb86a15(struct dst_state *state) 993 { 994 u8 check_mb86a15[] = { 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 995 996 check_mb86a15[7] = dst_check_sum(check_mb86a15, 7); 997 if (dst_command(state, check_mb86a15, 8) < 0) { 998 pr_err("Cmd=[0x10], failed\n"); 999 return -1; 1000 } 1001 debug_dst_buffer(state); 1002 1003 if (memcmp(&check_mb86a15, &state->rxbuffer, 8) < 0) { 1004 pr_err("Found a MB86A15 NIM\n"); 1005 state->tuner_type = TUNER_TYPE_MB86A15; 1006 return 0; 1007 } 1008 1009 return -1; 1010 } 1011 1012 static int dst_get_tuner_info(struct dst_state *state) 1013 { 1014 u8 get_tuner_1[] = { 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 1015 u8 get_tuner_2[] = { 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 1016 1017 get_tuner_1[7] = dst_check_sum(get_tuner_1, 7); 1018 get_tuner_2[7] = dst_check_sum(get_tuner_2, 7); 1019 pr_err("DST TYpe = MULTI FE\n"); 1020 if (state->type_flags & DST_TYPE_HAS_MULTI_FE) { 1021 if (dst_command(state, get_tuner_1, 8) < 0) { 1022 dprintk(2, "Cmd=[0x13], Unsupported\n"); 1023 goto force; 1024 } 1025 } else { 1026 if (dst_command(state, get_tuner_2, 8) < 0) { 1027 dprintk(2, "Cmd=[0xb], Unsupported\n"); 1028 goto force; 1029 } 1030 } 1031 memcpy(&state->board_info, &state->rxbuffer, 8); 1032 if (state->type_flags & DST_TYPE_HAS_MULTI_FE) { 1033 pr_err("DST type has TS=188\n"); 1034 } 1035 if (state->board_info[0] == 0xbc) { 1036 if (state->dst_type != DST_TYPE_IS_ATSC) 1037 state->type_flags |= DST_TYPE_HAS_TS188; 1038 else 1039 state->type_flags |= DST_TYPE_HAS_NEWTUNE_2; 1040 1041 if (state->board_info[1] == 0x01) { 1042 state->dst_hw_cap |= DST_TYPE_HAS_DBOARD; 1043 pr_err("DST has Daughterboard\n"); 1044 } 1045 } 1046 1047 return 0; 1048 force: 1049 if (!strncmp(state->fw_name, "DCT-CI", 6)) { 1050 state->type_flags |= DST_TYPE_HAS_TS204; 1051 pr_err("Forcing [%s] to TS188\n", state->fw_name); 1052 } 1053 1054 return -1; 1055 } 1056 1057 static int dst_get_device_id(struct dst_state *state) 1058 { 1059 u8 reply; 1060 1061 int i, j; 1062 struct dst_types *p_dst_type = NULL; 1063 struct tuner_types *p_tuner_list = NULL; 1064 1065 u8 use_dst_type = 0; 1066 u32 use_type_flags = 0; 1067 1068 static u8 device_type[8] = {0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff}; 1069 1070 state->tuner_type = 0; 1071 device_type[7] = dst_check_sum(device_type, 7); 1072 1073 if (write_dst(state, device_type, FIXED_COMM)) 1074 return -1; /* Write failed */ 1075 if ((dst_pio_disable(state)) < 0) 1076 return -1; 1077 if (read_dst(state, &reply, GET_ACK)) 1078 return -1; /* Read failure */ 1079 if (reply != ACK) { 1080 dprintk(2, "Write not Acknowledged! [Reply=0x%02x]\n", reply); 1081 return -1; /* Unack'd write */ 1082 } 1083 if (!dst_wait_dst_ready(state, DEVICE_INIT)) 1084 return -1; /* DST not ready yet */ 1085 if (read_dst(state, state->rxbuffer, FIXED_COMM)) 1086 return -1; 1087 1088 dst_pio_disable(state); 1089 if (state->rxbuffer[7] != dst_check_sum(state->rxbuffer, 7)) { 1090 dprintk(2, "Checksum failure!\n"); 1091 return -1; /* Checksum failure */ 1092 } 1093 state->rxbuffer[7] = '\0'; 1094 1095 for (i = 0, p_dst_type = dst_tlist; i < ARRAY_SIZE(dst_tlist); i++, p_dst_type++) { 1096 if (!strncmp (&state->rxbuffer[p_dst_type->offset], p_dst_type->device_id, strlen (p_dst_type->device_id))) { 1097 use_type_flags = p_dst_type->type_flags; 1098 use_dst_type = p_dst_type->dst_type; 1099 1100 /* Card capabilities */ 1101 state->dst_hw_cap = p_dst_type->dst_feature; 1102 pr_err("Recognise [%s]\n", p_dst_type->device_id); 1103 strncpy(&state->fw_name[0], p_dst_type->device_id, 6); 1104 /* Multiple tuners */ 1105 if (p_dst_type->tuner_type & TUNER_TYPE_MULTI) { 1106 switch (use_dst_type) { 1107 case DST_TYPE_IS_SAT: 1108 /* STV0299 check */ 1109 if (dst_check_stv0299(state) < 0) { 1110 pr_err("Unsupported\n"); 1111 state->tuner_type = TUNER_TYPE_MB86A15; 1112 } 1113 break; 1114 default: 1115 break; 1116 } 1117 if (dst_check_mb86a15(state) < 0) 1118 pr_err("Unsupported\n"); 1119 /* Single tuner */ 1120 } else { 1121 state->tuner_type = p_dst_type->tuner_type; 1122 } 1123 for (j = 0, p_tuner_list = tuner_list; j < ARRAY_SIZE(tuner_list); j++, p_tuner_list++) { 1124 if (!(strncmp(p_dst_type->device_id, p_tuner_list->fw_name, 7)) && 1125 p_tuner_list->tuner_type == state->tuner_type) { 1126 pr_err("[%s] has a [%s]\n", 1127 p_dst_type->device_id, p_tuner_list->tuner_name); 1128 } 1129 } 1130 break; 1131 } 1132 } 1133 1134 if (i >= ARRAY_SIZE(dst_tlist)) { 1135 pr_err("Unable to recognize %s or %s\n", &state->rxbuffer[0], &state->rxbuffer[1]); 1136 pr_err("please email linux-dvb@linuxtv.org with this type in"); 1137 use_dst_type = DST_TYPE_IS_SAT; 1138 use_type_flags = DST_TYPE_HAS_SYMDIV; 1139 } 1140 dst_type_print(state, use_dst_type); 1141 state->type_flags = use_type_flags; 1142 state->dst_type = use_dst_type; 1143 dst_type_flags_print(state); 1144 1145 return 0; 1146 } 1147 1148 static int dst_probe(struct dst_state *state) 1149 { 1150 mutex_init(&state->dst_mutex); 1151 if (dst_addons & DST_TYPE_HAS_CA) { 1152 if ((rdc_8820_reset(state)) < 0) { 1153 pr_err("RDC 8820 RESET Failed.\n"); 1154 return -1; 1155 } 1156 msleep(4000); 1157 } else { 1158 msleep(100); 1159 } 1160 if ((dst_comm_init(state)) < 0) { 1161 pr_err("DST Initialization Failed.\n"); 1162 return -1; 1163 } 1164 msleep(100); 1165 if (dst_get_device_id(state) < 0) { 1166 pr_err("unknown device.\n"); 1167 return -1; 1168 } 1169 if (dst_get_mac(state) < 0) { 1170 dprintk(2, "MAC: Unsupported command\n"); 1171 } 1172 if ((state->type_flags & DST_TYPE_HAS_MULTI_FE) || (state->type_flags & DST_TYPE_HAS_FW_BUILD)) { 1173 if (dst_get_tuner_info(state) < 0) 1174 dprintk(2, "Tuner: Unsupported command\n"); 1175 } 1176 if (state->type_flags & DST_TYPE_HAS_TS204) { 1177 dst_packsize(state, 204); 1178 } 1179 if (state->type_flags & DST_TYPE_HAS_FW_BUILD) { 1180 if (dst_fw_ver(state) < 0) { 1181 dprintk(2, "FW: Unsupported command\n"); 1182 return 0; 1183 } 1184 if (dst_card_type(state) < 0) { 1185 dprintk(2, "Card: Unsupported command\n"); 1186 return 0; 1187 } 1188 if (dst_get_vendor(state) < 0) { 1189 dprintk(2, "Vendor: Unsupported command\n"); 1190 return 0; 1191 } 1192 } 1193 1194 return 0; 1195 } 1196 1197 static int dst_command(struct dst_state *state, u8 *data, u8 len) 1198 { 1199 u8 reply; 1200 1201 mutex_lock(&state->dst_mutex); 1202 if ((dst_comm_init(state)) < 0) { 1203 dprintk(1, "DST Communication Initialization Failed.\n"); 1204 goto error; 1205 } 1206 if (write_dst(state, data, len)) { 1207 dprintk(2, "Trying to recover..\n"); 1208 if ((dst_error_recovery(state)) < 0) { 1209 pr_err("Recovery Failed.\n"); 1210 goto error; 1211 } 1212 goto error; 1213 } 1214 if ((dst_pio_disable(state)) < 0) { 1215 pr_err("PIO Disable Failed.\n"); 1216 goto error; 1217 } 1218 if (state->type_flags & DST_TYPE_HAS_FW_1) 1219 mdelay(3); 1220 if (read_dst(state, &reply, GET_ACK)) { 1221 dprintk(3, "Trying to recover..\n"); 1222 if ((dst_error_recovery(state)) < 0) { 1223 dprintk(2, "Recovery Failed.\n"); 1224 goto error; 1225 } 1226 goto error; 1227 } 1228 if (reply != ACK) { 1229 dprintk(2, "write not acknowledged 0x%02x\n", reply); 1230 goto error; 1231 } 1232 if (len >= 2 && data[0] == 0 && (data[1] == 1 || data[1] == 3)) 1233 goto error; 1234 if (state->type_flags & DST_TYPE_HAS_FW_1) 1235 mdelay(3); 1236 else 1237 udelay(2000); 1238 if (!dst_wait_dst_ready(state, NO_DELAY)) 1239 goto error; 1240 if (read_dst(state, state->rxbuffer, FIXED_COMM)) { 1241 dprintk(3, "Trying to recover..\n"); 1242 if ((dst_error_recovery(state)) < 0) { 1243 dprintk(2, "Recovery failed.\n"); 1244 goto error; 1245 } 1246 goto error; 1247 } 1248 if (state->rxbuffer[7] != dst_check_sum(state->rxbuffer, 7)) { 1249 dprintk(2, "checksum failure\n"); 1250 goto error; 1251 } 1252 mutex_unlock(&state->dst_mutex); 1253 return 0; 1254 1255 error: 1256 mutex_unlock(&state->dst_mutex); 1257 return -EIO; 1258 1259 } 1260 1261 static int dst_get_signal(struct dst_state *state) 1262 { 1263 int retval; 1264 u8 get_signal[] = { 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb }; 1265 //dprintk("%s: Getting Signal strength and other parameters\n", __func__); 1266 if ((state->diseq_flags & ATTEMPT_TUNE) == 0) { 1267 state->decode_lock = state->decode_strength = state->decode_snr = 0; 1268 return 0; 1269 } 1270 if (0 == (state->diseq_flags & HAS_LOCK)) { 1271 state->decode_lock = state->decode_strength = state->decode_snr = 0; 1272 return 0; 1273 } 1274 if (time_after_eq(jiffies, state->cur_jiff + (HZ / 5))) { 1275 retval = dst_command(state, get_signal, 8); 1276 if (retval < 0) 1277 return retval; 1278 if (state->dst_type == DST_TYPE_IS_SAT) { 1279 state->decode_lock = ((state->rxbuffer[6] & 0x10) == 0) ? 1 : 0; 1280 state->decode_strength = state->rxbuffer[5] << 8; 1281 state->decode_snr = state->rxbuffer[2] << 8 | state->rxbuffer[3]; 1282 } else if ((state->dst_type == DST_TYPE_IS_TERR) || (state->dst_type == DST_TYPE_IS_CABLE)) { 1283 state->decode_lock = (state->rxbuffer[1]) ? 1 : 0; 1284 state->decode_strength = state->rxbuffer[4] << 8; 1285 state->decode_snr = state->rxbuffer[3] << 8; 1286 } else if (state->dst_type == DST_TYPE_IS_ATSC) { 1287 state->decode_lock = (state->rxbuffer[6] == 0x00) ? 1 : 0; 1288 state->decode_strength = state->rxbuffer[4] << 8; 1289 state->decode_snr = state->rxbuffer[2] << 8 | state->rxbuffer[3]; 1290 } 1291 state->cur_jiff = jiffies; 1292 } 1293 return 0; 1294 } 1295 1296 static int dst_tone_power_cmd(struct dst_state *state) 1297 { 1298 u8 paket[8] = { 0x00, 0x09, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00 }; 1299 1300 if (state->dst_type != DST_TYPE_IS_SAT) 1301 return -EOPNOTSUPP; 1302 paket[4] = state->tx_tuna[4]; 1303 paket[2] = state->tx_tuna[2]; 1304 paket[3] = state->tx_tuna[3]; 1305 paket[7] = dst_check_sum (paket, 7); 1306 return dst_command(state, paket, 8); 1307 } 1308 1309 static int dst_get_tuna(struct dst_state *state) 1310 { 1311 int retval; 1312 1313 if ((state->diseq_flags & ATTEMPT_TUNE) == 0) 1314 return 0; 1315 state->diseq_flags &= ~(HAS_LOCK); 1316 if (!dst_wait_dst_ready(state, NO_DELAY)) 1317 return -EIO; 1318 if ((state->type_flags & DST_TYPE_HAS_VLF) && 1319 !(state->dst_type == DST_TYPE_IS_ATSC)) 1320 1321 retval = read_dst(state, state->rx_tuna, 10); 1322 else 1323 retval = read_dst(state, &state->rx_tuna[2], FIXED_COMM); 1324 if (retval < 0) { 1325 dprintk(3, "read not successful\n"); 1326 return retval; 1327 } 1328 if ((state->type_flags & DST_TYPE_HAS_VLF) && 1329 !(state->dst_type == DST_TYPE_IS_ATSC)) { 1330 1331 if (state->rx_tuna[9] != dst_check_sum(&state->rx_tuna[0], 9)) { 1332 dprintk(2, "checksum failure ?\n"); 1333 return -EIO; 1334 } 1335 } else { 1336 if (state->rx_tuna[9] != dst_check_sum(&state->rx_tuna[2], 7)) { 1337 dprintk(2, "checksum failure?\n"); 1338 return -EIO; 1339 } 1340 } 1341 if (state->rx_tuna[2] == 0 && state->rx_tuna[3] == 0) 1342 return 0; 1343 if (state->dst_type == DST_TYPE_IS_SAT) { 1344 state->decode_freq = ((state->rx_tuna[2] & 0x7f) << 8) + state->rx_tuna[3]; 1345 } else { 1346 state->decode_freq = ((state->rx_tuna[2] & 0x7f) << 16) + (state->rx_tuna[3] << 8) + state->rx_tuna[4]; 1347 } 1348 state->decode_freq = state->decode_freq * 1000; 1349 state->decode_lock = 1; 1350 state->diseq_flags |= HAS_LOCK; 1351 1352 return 1; 1353 } 1354 1355 static int dst_set_voltage(struct dvb_frontend *fe, 1356 enum fe_sec_voltage voltage); 1357 1358 static int dst_write_tuna(struct dvb_frontend *fe) 1359 { 1360 struct dst_state *state = fe->demodulator_priv; 1361 int retval; 1362 u8 reply; 1363 1364 dprintk(2, "type_flags 0x%x\n", state->type_flags); 1365 state->decode_freq = 0; 1366 state->decode_lock = state->decode_strength = state->decode_snr = 0; 1367 if (state->dst_type == DST_TYPE_IS_SAT) { 1368 if (!(state->diseq_flags & HAS_POWER)) 1369 dst_set_voltage(fe, SEC_VOLTAGE_13); 1370 } 1371 state->diseq_flags &= ~(HAS_LOCK | ATTEMPT_TUNE); 1372 mutex_lock(&state->dst_mutex); 1373 if ((dst_comm_init(state)) < 0) { 1374 dprintk(3, "DST Communication initialization failed.\n"); 1375 goto error; 1376 } 1377 // if (state->type_flags & DST_TYPE_HAS_NEWTUNE) { 1378 if ((state->type_flags & DST_TYPE_HAS_VLF) && 1379 (!(state->dst_type == DST_TYPE_IS_ATSC))) { 1380 1381 state->tx_tuna[9] = dst_check_sum(&state->tx_tuna[0], 9); 1382 retval = write_dst(state, &state->tx_tuna[0], 10); 1383 } else { 1384 state->tx_tuna[9] = dst_check_sum(&state->tx_tuna[2], 7); 1385 retval = write_dst(state, &state->tx_tuna[2], FIXED_COMM); 1386 } 1387 if (retval < 0) { 1388 dst_pio_disable(state); 1389 dprintk(3, "write not successful\n"); 1390 goto werr; 1391 } 1392 if ((dst_pio_disable(state)) < 0) { 1393 dprintk(3, "DST PIO disable failed !\n"); 1394 goto error; 1395 } 1396 if ((read_dst(state, &reply, GET_ACK) < 0)) { 1397 dprintk(3, "read verify not successful.\n"); 1398 goto error; 1399 } 1400 if (reply != ACK) { 1401 dprintk(3, "write not acknowledged 0x%02x\n", reply); 1402 goto error; 1403 } 1404 state->diseq_flags |= ATTEMPT_TUNE; 1405 retval = dst_get_tuna(state); 1406 werr: 1407 mutex_unlock(&state->dst_mutex); 1408 return retval; 1409 1410 error: 1411 mutex_unlock(&state->dst_mutex); 1412 return -EIO; 1413 } 1414 1415 /* 1416 * line22k0 0x00, 0x09, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00 1417 * line22k1 0x00, 0x09, 0x01, 0xff, 0x01, 0x00, 0x00, 0x00 1418 * line22k2 0x00, 0x09, 0x02, 0xff, 0x01, 0x00, 0x00, 0x00 1419 * tone 0x00, 0x09, 0xff, 0x00, 0x01, 0x00, 0x00, 0x00 1420 * data 0x00, 0x09, 0xff, 0x01, 0x01, 0x00, 0x00, 0x00 1421 * power_off 0x00, 0x09, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 1422 * power_on 0x00, 0x09, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00 1423 * Diseqc 1 0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xf0, 0xec 1424 * Diseqc 2 0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xf4, 0xe8 1425 * Diseqc 3 0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xf8, 0xe4 1426 * Diseqc 4 0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xfc, 0xe0 1427 */ 1428 1429 static int dst_set_diseqc(struct dvb_frontend *fe, struct dvb_diseqc_master_cmd *cmd) 1430 { 1431 struct dst_state *state = fe->demodulator_priv; 1432 u8 paket[8] = { 0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xf0, 0xec }; 1433 1434 if (state->dst_type != DST_TYPE_IS_SAT) 1435 return -EOPNOTSUPP; 1436 if (cmd->msg_len > 0 && cmd->msg_len < 5) 1437 memcpy(&paket[3], cmd->msg, cmd->msg_len); 1438 else if (cmd->msg_len == 5 && state->dst_hw_cap & DST_TYPE_HAS_DISEQC5) 1439 memcpy(&paket[2], cmd->msg, cmd->msg_len); 1440 else 1441 return -EINVAL; 1442 paket[7] = dst_check_sum(&paket[0], 7); 1443 return dst_command(state, paket, 8); 1444 } 1445 1446 static int dst_set_voltage(struct dvb_frontend *fe, enum fe_sec_voltage voltage) 1447 { 1448 int need_cmd, retval = 0; 1449 struct dst_state *state = fe->demodulator_priv; 1450 1451 state->voltage = voltage; 1452 if (state->dst_type != DST_TYPE_IS_SAT) 1453 return -EOPNOTSUPP; 1454 1455 need_cmd = 0; 1456 1457 switch (voltage) { 1458 case SEC_VOLTAGE_13: 1459 case SEC_VOLTAGE_18: 1460 if ((state->diseq_flags & HAS_POWER) == 0) 1461 need_cmd = 1; 1462 state->diseq_flags |= HAS_POWER; 1463 state->tx_tuna[4] = 0x01; 1464 break; 1465 case SEC_VOLTAGE_OFF: 1466 need_cmd = 1; 1467 state->diseq_flags &= ~(HAS_POWER | HAS_LOCK | ATTEMPT_TUNE); 1468 state->tx_tuna[4] = 0x00; 1469 break; 1470 default: 1471 return -EINVAL; 1472 } 1473 1474 if (need_cmd) 1475 retval = dst_tone_power_cmd(state); 1476 1477 return retval; 1478 } 1479 1480 static int dst_set_tone(struct dvb_frontend *fe, enum fe_sec_tone_mode tone) 1481 { 1482 struct dst_state *state = fe->demodulator_priv; 1483 1484 state->tone = tone; 1485 if (state->dst_type != DST_TYPE_IS_SAT) 1486 return -EOPNOTSUPP; 1487 1488 switch (tone) { 1489 case SEC_TONE_OFF: 1490 if (state->type_flags & DST_TYPE_HAS_OBS_REGS) 1491 state->tx_tuna[2] = 0x00; 1492 else 1493 state->tx_tuna[2] = 0xff; 1494 break; 1495 1496 case SEC_TONE_ON: 1497 state->tx_tuna[2] = 0x02; 1498 break; 1499 default: 1500 return -EINVAL; 1501 } 1502 return dst_tone_power_cmd(state); 1503 } 1504 1505 static int dst_send_burst(struct dvb_frontend *fe, enum fe_sec_mini_cmd minicmd) 1506 { 1507 struct dst_state *state = fe->demodulator_priv; 1508 1509 if (state->dst_type != DST_TYPE_IS_SAT) 1510 return -EOPNOTSUPP; 1511 state->minicmd = minicmd; 1512 switch (minicmd) { 1513 case SEC_MINI_A: 1514 state->tx_tuna[3] = 0x02; 1515 break; 1516 case SEC_MINI_B: 1517 state->tx_tuna[3] = 0xff; 1518 break; 1519 } 1520 return dst_tone_power_cmd(state); 1521 } 1522 1523 1524 static int bt8xx_dst_init(struct dvb_frontend *fe) 1525 { 1526 struct dst_state *state = fe->demodulator_priv; 1527 1528 static u8 sat_tuna_188[] = { 0x09, 0x00, 0x03, 0xb6, 0x01, 0x00, 0x73, 0x21, 0x00, 0x00 }; 1529 static u8 sat_tuna_204[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x55, 0xbd, 0x50, 0x00, 0x00 }; 1530 static u8 ter_tuna_188[] = { 0x09, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 }; 1531 static u8 ter_tuna_204[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 }; 1532 static u8 cab_tuna_188[] = { 0x09, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 }; 1533 static u8 cab_tuna_204[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 }; 1534 static u8 atsc_tuner[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 }; 1535 1536 state->inversion = INVERSION_OFF; 1537 state->voltage = SEC_VOLTAGE_13; 1538 state->tone = SEC_TONE_OFF; 1539 state->diseq_flags = 0; 1540 state->k22 = 0x02; 1541 state->bandwidth = 7000000; 1542 state->cur_jiff = jiffies; 1543 if (state->dst_type == DST_TYPE_IS_SAT) 1544 memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_VLF) ? sat_tuna_188 : sat_tuna_204), sizeof (sat_tuna_204)); 1545 else if (state->dst_type == DST_TYPE_IS_TERR) 1546 memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_VLF) ? ter_tuna_188 : ter_tuna_204), sizeof (ter_tuna_204)); 1547 else if (state->dst_type == DST_TYPE_IS_CABLE) 1548 memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_VLF) ? cab_tuna_188 : cab_tuna_204), sizeof (cab_tuna_204)); 1549 else if (state->dst_type == DST_TYPE_IS_ATSC) 1550 memcpy(state->tx_tuna, atsc_tuner, sizeof (atsc_tuner)); 1551 1552 return 0; 1553 } 1554 1555 static int dst_read_status(struct dvb_frontend *fe, enum fe_status *status) 1556 { 1557 struct dst_state *state = fe->demodulator_priv; 1558 1559 *status = 0; 1560 if (state->diseq_flags & HAS_LOCK) { 1561 // dst_get_signal(state); // don't require(?) to ask MCU 1562 if (state->decode_lock) 1563 *status |= FE_HAS_LOCK | FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_SYNC | FE_HAS_VITERBI; 1564 } 1565 1566 return 0; 1567 } 1568 1569 static int dst_read_signal_strength(struct dvb_frontend *fe, u16 *strength) 1570 { 1571 struct dst_state *state = fe->demodulator_priv; 1572 1573 int retval = dst_get_signal(state); 1574 *strength = state->decode_strength; 1575 1576 return retval; 1577 } 1578 1579 static int dst_read_snr(struct dvb_frontend *fe, u16 *snr) 1580 { 1581 struct dst_state *state = fe->demodulator_priv; 1582 1583 int retval = dst_get_signal(state); 1584 *snr = state->decode_snr; 1585 1586 return retval; 1587 } 1588 1589 static int dst_set_frontend(struct dvb_frontend *fe) 1590 { 1591 struct dtv_frontend_properties *p = &fe->dtv_property_cache; 1592 int retval = -EINVAL; 1593 struct dst_state *state = fe->demodulator_priv; 1594 1595 if (p != NULL) { 1596 retval = dst_set_freq(state, p->frequency); 1597 if(retval != 0) 1598 return retval; 1599 dprintk(3, "Set Frequency=[%d]\n", p->frequency); 1600 1601 if (state->dst_type == DST_TYPE_IS_SAT) { 1602 if (state->type_flags & DST_TYPE_HAS_OBS_REGS) 1603 dst_set_inversion(state, p->inversion); 1604 dst_set_fec(state, p->fec_inner); 1605 dst_set_symbolrate(state, p->symbol_rate); 1606 dst_set_polarization(state); 1607 dprintk(3, "Set Symbolrate=[%d]\n", p->symbol_rate); 1608 1609 } else if (state->dst_type == DST_TYPE_IS_TERR) 1610 dst_set_bandwidth(state, p->bandwidth_hz); 1611 else if (state->dst_type == DST_TYPE_IS_CABLE) { 1612 dst_set_fec(state, p->fec_inner); 1613 dst_set_symbolrate(state, p->symbol_rate); 1614 dst_set_modulation(state, p->modulation); 1615 } 1616 retval = dst_write_tuna(fe); 1617 } 1618 1619 return retval; 1620 } 1621 1622 static int dst_tune_frontend(struct dvb_frontend* fe, 1623 bool re_tune, 1624 unsigned int mode_flags, 1625 unsigned int *delay, 1626 enum fe_status *status) 1627 { 1628 struct dst_state *state = fe->demodulator_priv; 1629 struct dtv_frontend_properties *p = &fe->dtv_property_cache; 1630 1631 if (re_tune) { 1632 dst_set_freq(state, p->frequency); 1633 dprintk(3, "Set Frequency=[%d]\n", p->frequency); 1634 1635 if (state->dst_type == DST_TYPE_IS_SAT) { 1636 if (state->type_flags & DST_TYPE_HAS_OBS_REGS) 1637 dst_set_inversion(state, p->inversion); 1638 dst_set_fec(state, p->fec_inner); 1639 dst_set_symbolrate(state, p->symbol_rate); 1640 dst_set_polarization(state); 1641 dprintk(3, "Set Symbolrate=[%d]\n", p->symbol_rate); 1642 1643 } else if (state->dst_type == DST_TYPE_IS_TERR) 1644 dst_set_bandwidth(state, p->bandwidth_hz); 1645 else if (state->dst_type == DST_TYPE_IS_CABLE) { 1646 dst_set_fec(state, p->fec_inner); 1647 dst_set_symbolrate(state, p->symbol_rate); 1648 dst_set_modulation(state, p->modulation); 1649 } 1650 dst_write_tuna(fe); 1651 } 1652 1653 if (!(mode_flags & FE_TUNE_MODE_ONESHOT)) 1654 dst_read_status(fe, status); 1655 1656 *delay = HZ/10; 1657 return 0; 1658 } 1659 1660 static int dst_get_tuning_algo(struct dvb_frontend *fe) 1661 { 1662 return dst_algo ? DVBFE_ALGO_HW : DVBFE_ALGO_SW; 1663 } 1664 1665 static int dst_get_frontend(struct dvb_frontend *fe, 1666 struct dtv_frontend_properties *p) 1667 { 1668 struct dst_state *state = fe->demodulator_priv; 1669 1670 p->frequency = state->decode_freq; 1671 if (state->dst_type == DST_TYPE_IS_SAT) { 1672 if (state->type_flags & DST_TYPE_HAS_OBS_REGS) 1673 p->inversion = state->inversion; 1674 p->symbol_rate = state->symbol_rate; 1675 p->fec_inner = dst_get_fec(state); 1676 } else if (state->dst_type == DST_TYPE_IS_TERR) { 1677 p->bandwidth_hz = state->bandwidth; 1678 } else if (state->dst_type == DST_TYPE_IS_CABLE) { 1679 p->symbol_rate = state->symbol_rate; 1680 p->fec_inner = dst_get_fec(state); 1681 p->modulation = dst_get_modulation(state); 1682 } 1683 1684 return 0; 1685 } 1686 1687 static void bt8xx_dst_release(struct dvb_frontend *fe) 1688 { 1689 struct dst_state *state = fe->demodulator_priv; 1690 if (state->dst_ca) { 1691 dvb_unregister_device(state->dst_ca); 1692 #ifdef CONFIG_MEDIA_ATTACH 1693 symbol_put(dst_ca_attach); 1694 #endif 1695 } 1696 kfree(state); 1697 } 1698 1699 static const struct dvb_frontend_ops dst_dvbt_ops; 1700 static const struct dvb_frontend_ops dst_dvbs_ops; 1701 static const struct dvb_frontend_ops dst_dvbc_ops; 1702 static const struct dvb_frontend_ops dst_atsc_ops; 1703 1704 struct dst_state *dst_attach(struct dst_state *state, struct dvb_adapter *dvb_adapter) 1705 { 1706 /* check if the ASIC is there */ 1707 if (dst_probe(state) < 0) { 1708 kfree(state); 1709 return NULL; 1710 } 1711 /* determine settings based on type */ 1712 /* create dvb_frontend */ 1713 switch (state->dst_type) { 1714 case DST_TYPE_IS_TERR: 1715 memcpy(&state->frontend.ops, &dst_dvbt_ops, sizeof(struct dvb_frontend_ops)); 1716 break; 1717 case DST_TYPE_IS_CABLE: 1718 memcpy(&state->frontend.ops, &dst_dvbc_ops, sizeof(struct dvb_frontend_ops)); 1719 break; 1720 case DST_TYPE_IS_SAT: 1721 memcpy(&state->frontend.ops, &dst_dvbs_ops, sizeof(struct dvb_frontend_ops)); 1722 break; 1723 case DST_TYPE_IS_ATSC: 1724 memcpy(&state->frontend.ops, &dst_atsc_ops, sizeof(struct dvb_frontend_ops)); 1725 break; 1726 default: 1727 pr_err("unknown DST type. please report to the LinuxTV.org DVB mailinglist.\n"); 1728 kfree(state); 1729 return NULL; 1730 } 1731 state->frontend.demodulator_priv = state; 1732 1733 return state; /* Manu (DST is a card not a frontend) */ 1734 } 1735 1736 EXPORT_SYMBOL(dst_attach); 1737 1738 static const struct dvb_frontend_ops dst_dvbt_ops = { 1739 .delsys = { SYS_DVBT }, 1740 .info = { 1741 .name = "DST DVB-T", 1742 .frequency_min = 137000000, 1743 .frequency_max = 858000000, 1744 .frequency_stepsize = 166667, 1745 .caps = FE_CAN_FEC_AUTO | 1746 FE_CAN_QAM_AUTO | 1747 FE_CAN_QAM_16 | 1748 FE_CAN_QAM_32 | 1749 FE_CAN_QAM_64 | 1750 FE_CAN_QAM_128 | 1751 FE_CAN_QAM_256 | 1752 FE_CAN_TRANSMISSION_MODE_AUTO | 1753 FE_CAN_GUARD_INTERVAL_AUTO 1754 }, 1755 1756 .release = bt8xx_dst_release, 1757 .init = bt8xx_dst_init, 1758 .tune = dst_tune_frontend, 1759 .set_frontend = dst_set_frontend, 1760 .get_frontend = dst_get_frontend, 1761 .get_frontend_algo = dst_get_tuning_algo, 1762 .read_status = dst_read_status, 1763 .read_signal_strength = dst_read_signal_strength, 1764 .read_snr = dst_read_snr, 1765 }; 1766 1767 static const struct dvb_frontend_ops dst_dvbs_ops = { 1768 .delsys = { SYS_DVBS }, 1769 .info = { 1770 .name = "DST DVB-S", 1771 .frequency_min = 950000, 1772 .frequency_max = 2150000, 1773 .frequency_stepsize = 1000, /* kHz for QPSK frontends */ 1774 .frequency_tolerance = 29500, 1775 .symbol_rate_min = 1000000, 1776 .symbol_rate_max = 45000000, 1777 /* . symbol_rate_tolerance = ???,*/ 1778 .caps = FE_CAN_FEC_AUTO | FE_CAN_QPSK 1779 }, 1780 1781 .release = bt8xx_dst_release, 1782 .init = bt8xx_dst_init, 1783 .tune = dst_tune_frontend, 1784 .set_frontend = dst_set_frontend, 1785 .get_frontend = dst_get_frontend, 1786 .get_frontend_algo = dst_get_tuning_algo, 1787 .read_status = dst_read_status, 1788 .read_signal_strength = dst_read_signal_strength, 1789 .read_snr = dst_read_snr, 1790 .diseqc_send_burst = dst_send_burst, 1791 .diseqc_send_master_cmd = dst_set_diseqc, 1792 .set_voltage = dst_set_voltage, 1793 .set_tone = dst_set_tone, 1794 }; 1795 1796 static const struct dvb_frontend_ops dst_dvbc_ops = { 1797 .delsys = { SYS_DVBC_ANNEX_A }, 1798 .info = { 1799 .name = "DST DVB-C", 1800 .frequency_stepsize = 62500, 1801 .frequency_min = 51000000, 1802 .frequency_max = 858000000, 1803 .symbol_rate_min = 1000000, 1804 .symbol_rate_max = 45000000, 1805 .caps = FE_CAN_FEC_AUTO | 1806 FE_CAN_QAM_AUTO | 1807 FE_CAN_QAM_16 | 1808 FE_CAN_QAM_32 | 1809 FE_CAN_QAM_64 | 1810 FE_CAN_QAM_128 | 1811 FE_CAN_QAM_256 1812 }, 1813 1814 .release = bt8xx_dst_release, 1815 .init = bt8xx_dst_init, 1816 .tune = dst_tune_frontend, 1817 .set_frontend = dst_set_frontend, 1818 .get_frontend = dst_get_frontend, 1819 .get_frontend_algo = dst_get_tuning_algo, 1820 .read_status = dst_read_status, 1821 .read_signal_strength = dst_read_signal_strength, 1822 .read_snr = dst_read_snr, 1823 }; 1824 1825 static const struct dvb_frontend_ops dst_atsc_ops = { 1826 .delsys = { SYS_ATSC }, 1827 .info = { 1828 .name = "DST ATSC", 1829 .frequency_stepsize = 62500, 1830 .frequency_min = 510000000, 1831 .frequency_max = 858000000, 1832 .symbol_rate_min = 1000000, 1833 .symbol_rate_max = 45000000, 1834 .caps = FE_CAN_FEC_AUTO | FE_CAN_QAM_AUTO | FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB 1835 }, 1836 1837 .release = bt8xx_dst_release, 1838 .init = bt8xx_dst_init, 1839 .tune = dst_tune_frontend, 1840 .set_frontend = dst_set_frontend, 1841 .get_frontend = dst_get_frontend, 1842 .get_frontend_algo = dst_get_tuning_algo, 1843 .read_status = dst_read_status, 1844 .read_signal_strength = dst_read_signal_strength, 1845 .read_snr = dst_read_snr, 1846 }; 1847 1848 MODULE_DESCRIPTION("DST DVB-S/T/C/ATSC Combo Frontend driver"); 1849 MODULE_AUTHOR("Jamie Honan, Manu Abraham"); 1850 MODULE_LICENSE("GPL"); 1851