1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * PCTV 452e DVB driver 4 * 5 * Copyright (c) 2006-2008 Dominik Kuhlen <dkuhlen@gmx.net> 6 * 7 * TT connect S2-3650-CI Common Interface support, MAC readout 8 * Copyright (C) 2008 Michael H. Schimek <mschimek@gmx.at> 9 */ 10 11 /* dvb usb framework */ 12 #define DVB_USB_LOG_PREFIX "pctv452e" 13 #include "dvb-usb.h" 14 15 /* Demodulator */ 16 #include "stb0899_drv.h" 17 #include "stb0899_reg.h" 18 #include "stb0899_cfg.h" 19 /* Tuner */ 20 #include "stb6100.h" 21 #include "stb6100_cfg.h" 22 /* FE Power */ 23 #include "lnbp22.h" 24 25 #include <media/dvb_ca_en50221.h> 26 #include "ttpci-eeprom.h" 27 28 static int debug; 29 module_param(debug, int, 0644); 30 MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off)."); 31 32 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); 33 34 #define ISOC_INTERFACE_ALTERNATIVE 3 35 36 #define SYNC_BYTE_OUT 0xaa 37 #define SYNC_BYTE_IN 0x55 38 39 /* guessed: (copied from ttusb-budget) */ 40 #define PCTV_CMD_RESET 0x15 41 /* command to poll IR receiver */ 42 #define PCTV_CMD_IR 0x1b 43 /* command to send I2C */ 44 #define PCTV_CMD_I2C 0x31 45 46 #define I2C_ADDR_STB0899 (0xd0 >> 1) 47 #define I2C_ADDR_STB6100 (0xc0 >> 1) 48 #define I2C_ADDR_LNBP22 (0x10 >> 1) 49 #define I2C_ADDR_24C16 (0xa0 >> 1) 50 #define I2C_ADDR_24C64 (0xa2 >> 1) 51 52 53 /* pctv452e sends us this amount of data for each issued usb-command */ 54 #define PCTV_ANSWER_LEN 64 55 /* Wait up to 1000ms for device */ 56 #define PCTV_TIMEOUT 1000 57 58 59 #define PCTV_LED_GPIO STB0899_GPIO01 60 #define PCTV_LED_GREEN 0x82 61 #define PCTV_LED_ORANGE 0x02 62 63 #define ci_dbg(format, arg...) \ 64 do { \ 65 if (0) \ 66 printk(KERN_DEBUG DVB_USB_LOG_PREFIX \ 67 ": " format "\n" , ## arg); \ 68 } while (0) 69 70 enum { 71 TT3650_CMD_CI_TEST = 0x40, 72 TT3650_CMD_CI_RD_CTRL, 73 TT3650_CMD_CI_WR_CTRL, 74 TT3650_CMD_CI_RD_ATTR, 75 TT3650_CMD_CI_WR_ATTR, 76 TT3650_CMD_CI_RESET, 77 TT3650_CMD_CI_SET_VIDEO_PORT 78 }; 79 80 81 static struct stb0899_postproc pctv45e_postproc[] = { 82 { PCTV_LED_GPIO, STB0899_GPIOPULLUP }, 83 { 0, 0 } 84 }; 85 86 /* 87 * stores all private variables for communication with the PCTV452e DVB-S2 88 */ 89 struct pctv452e_state { 90 struct dvb_ca_en50221 ca; 91 struct mutex ca_mutex; 92 93 u8 c; /* transaction counter, wraps around... */ 94 u8 initialized; /* set to 1 if 0x15 has been sent */ 95 u16 last_rc_key; 96 }; 97 98 static int tt3650_ci_msg(struct dvb_usb_device *d, u8 cmd, u8 *data, 99 unsigned int write_len, unsigned int read_len) 100 { 101 struct pctv452e_state *state = (struct pctv452e_state *)d->priv; 102 u8 *buf; 103 u8 id; 104 unsigned int rlen; 105 int ret; 106 107 if (!data || (write_len > 64 - 4) || (read_len > 64 - 4)) { 108 err("%s: transfer data invalid", __func__); 109 return -EIO; 110 } 111 112 buf = kmalloc(64, GFP_KERNEL); 113 if (!buf) 114 return -ENOMEM; 115 116 id = state->c++; 117 118 buf[0] = SYNC_BYTE_OUT; 119 buf[1] = id; 120 buf[2] = cmd; 121 buf[3] = write_len; 122 123 memcpy(buf + 4, data, write_len); 124 125 rlen = (read_len > 0) ? 64 : 0; 126 ret = dvb_usb_generic_rw(d, buf, 4 + write_len, 127 buf, rlen, /* delay_ms */ 0); 128 if (0 != ret) 129 goto failed; 130 131 ret = -EIO; 132 if (SYNC_BYTE_IN != buf[0] || id != buf[1]) 133 goto failed; 134 135 memcpy(data, buf + 4, read_len); 136 137 kfree(buf); 138 return 0; 139 140 failed: 141 err("CI error %d; %02X %02X %02X -> %*ph.", 142 ret, SYNC_BYTE_OUT, id, cmd, 3, buf); 143 144 kfree(buf); 145 return ret; 146 } 147 148 static int tt3650_ci_msg_locked(struct dvb_ca_en50221 *ca, 149 u8 cmd, u8 *data, unsigned int write_len, 150 unsigned int read_len) 151 { 152 struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; 153 struct pctv452e_state *state = (struct pctv452e_state *)d->priv; 154 int ret; 155 156 mutex_lock(&state->ca_mutex); 157 ret = tt3650_ci_msg(d, cmd, data, write_len, read_len); 158 mutex_unlock(&state->ca_mutex); 159 160 return ret; 161 } 162 163 static int tt3650_ci_read_attribute_mem(struct dvb_ca_en50221 *ca, 164 int slot, int address) 165 { 166 u8 buf[3]; 167 int ret; 168 169 if (0 != slot) 170 return -EINVAL; 171 172 buf[0] = (address >> 8) & 0x0F; 173 buf[1] = address; 174 175 ret = tt3650_ci_msg_locked(ca, TT3650_CMD_CI_RD_ATTR, buf, 2, 3); 176 177 ci_dbg("%s %04x -> %d 0x%02x", 178 __func__, address, ret, buf[2]); 179 180 if (ret < 0) 181 return ret; 182 183 return buf[2]; 184 } 185 186 static int tt3650_ci_write_attribute_mem(struct dvb_ca_en50221 *ca, 187 int slot, int address, u8 value) 188 { 189 u8 buf[3]; 190 191 ci_dbg("%s %d 0x%04x 0x%02x", 192 __func__, slot, address, value); 193 194 if (0 != slot) 195 return -EINVAL; 196 197 buf[0] = (address >> 8) & 0x0F; 198 buf[1] = address; 199 buf[2] = value; 200 201 return tt3650_ci_msg_locked(ca, TT3650_CMD_CI_WR_ATTR, buf, 3, 3); 202 } 203 204 static int tt3650_ci_read_cam_control(struct dvb_ca_en50221 *ca, 205 int slot, 206 u8 address) 207 { 208 u8 buf[2]; 209 int ret; 210 211 if (0 != slot) 212 return -EINVAL; 213 214 buf[0] = address & 3; 215 216 ret = tt3650_ci_msg_locked(ca, TT3650_CMD_CI_RD_CTRL, buf, 1, 2); 217 218 ci_dbg("%s 0x%02x -> %d 0x%02x", 219 __func__, address, ret, buf[1]); 220 221 if (ret < 0) 222 return ret; 223 224 return buf[1]; 225 } 226 227 static int tt3650_ci_write_cam_control(struct dvb_ca_en50221 *ca, 228 int slot, 229 u8 address, 230 u8 value) 231 { 232 u8 buf[2]; 233 234 ci_dbg("%s %d 0x%02x 0x%02x", 235 __func__, slot, address, value); 236 237 if (0 != slot) 238 return -EINVAL; 239 240 buf[0] = address; 241 buf[1] = value; 242 243 return tt3650_ci_msg_locked(ca, TT3650_CMD_CI_WR_CTRL, buf, 2, 2); 244 } 245 246 static int tt3650_ci_set_video_port(struct dvb_ca_en50221 *ca, 247 int slot, 248 int enable) 249 { 250 u8 buf[1]; 251 int ret; 252 253 ci_dbg("%s %d %d", __func__, slot, enable); 254 255 if (0 != slot) 256 return -EINVAL; 257 258 enable = !!enable; 259 buf[0] = enable; 260 261 ret = tt3650_ci_msg_locked(ca, TT3650_CMD_CI_SET_VIDEO_PORT, buf, 1, 1); 262 if (ret < 0) 263 return ret; 264 265 if (enable != buf[0]) { 266 err("CI not %sabled.", enable ? "en" : "dis"); 267 return -EIO; 268 } 269 270 return 0; 271 } 272 273 static int tt3650_ci_slot_shutdown(struct dvb_ca_en50221 *ca, int slot) 274 { 275 return tt3650_ci_set_video_port(ca, slot, /* enable */ 0); 276 } 277 278 static int tt3650_ci_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot) 279 { 280 return tt3650_ci_set_video_port(ca, slot, /* enable */ 1); 281 } 282 283 static int tt3650_ci_slot_reset(struct dvb_ca_en50221 *ca, int slot) 284 { 285 struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; 286 struct pctv452e_state *state = (struct pctv452e_state *)d->priv; 287 u8 buf[1]; 288 int ret; 289 290 ci_dbg("%s %d", __func__, slot); 291 292 if (0 != slot) 293 return -EINVAL; 294 295 buf[0] = 0; 296 297 mutex_lock(&state->ca_mutex); 298 299 ret = tt3650_ci_msg(d, TT3650_CMD_CI_RESET, buf, 1, 1); 300 if (0 != ret) 301 goto failed; 302 303 msleep(500); 304 305 buf[0] = 1; 306 307 ret = tt3650_ci_msg(d, TT3650_CMD_CI_RESET, buf, 1, 1); 308 if (0 != ret) 309 goto failed; 310 311 msleep(500); 312 313 buf[0] = 0; /* FTA */ 314 315 ret = tt3650_ci_msg(d, TT3650_CMD_CI_SET_VIDEO_PORT, buf, 1, 1); 316 317 failed: 318 mutex_unlock(&state->ca_mutex); 319 320 return ret; 321 } 322 323 static int tt3650_ci_poll_slot_status(struct dvb_ca_en50221 *ca, 324 int slot, 325 int open) 326 { 327 u8 buf[1]; 328 int ret; 329 330 if (0 != slot) 331 return -EINVAL; 332 333 ret = tt3650_ci_msg_locked(ca, TT3650_CMD_CI_TEST, buf, 0, 1); 334 if (0 != ret) 335 return ret; 336 337 if (1 == buf[0]) 338 return DVB_CA_EN50221_POLL_CAM_PRESENT | 339 DVB_CA_EN50221_POLL_CAM_READY; 340 341 return 0; 342 343 } 344 345 static void tt3650_ci_uninit(struct dvb_usb_device *d) 346 { 347 struct pctv452e_state *state; 348 349 ci_dbg("%s", __func__); 350 351 if (NULL == d) 352 return; 353 354 state = (struct pctv452e_state *)d->priv; 355 if (NULL == state) 356 return; 357 358 if (NULL == state->ca.data) 359 return; 360 361 /* Error ignored. */ 362 tt3650_ci_set_video_port(&state->ca, /* slot */ 0, /* enable */ 0); 363 364 dvb_ca_en50221_release(&state->ca); 365 366 memset(&state->ca, 0, sizeof(state->ca)); 367 } 368 369 static int tt3650_ci_init(struct dvb_usb_adapter *a) 370 { 371 struct dvb_usb_device *d = a->dev; 372 struct pctv452e_state *state = (struct pctv452e_state *)d->priv; 373 int ret; 374 375 ci_dbg("%s", __func__); 376 377 mutex_init(&state->ca_mutex); 378 379 state->ca.owner = THIS_MODULE; 380 state->ca.read_attribute_mem = tt3650_ci_read_attribute_mem; 381 state->ca.write_attribute_mem = tt3650_ci_write_attribute_mem; 382 state->ca.read_cam_control = tt3650_ci_read_cam_control; 383 state->ca.write_cam_control = tt3650_ci_write_cam_control; 384 state->ca.slot_reset = tt3650_ci_slot_reset; 385 state->ca.slot_shutdown = tt3650_ci_slot_shutdown; 386 state->ca.slot_ts_enable = tt3650_ci_slot_ts_enable; 387 state->ca.poll_slot_status = tt3650_ci_poll_slot_status; 388 state->ca.data = d; 389 390 ret = dvb_ca_en50221_init(&a->dvb_adap, 391 &state->ca, 392 /* flags */ 0, 393 /* n_slots */ 1); 394 if (0 != ret) { 395 err("Cannot initialize CI: Error %d.", ret); 396 memset(&state->ca, 0, sizeof(state->ca)); 397 return ret; 398 } 399 400 info("CI initialized."); 401 402 return 0; 403 } 404 405 #define CMD_BUFFER_SIZE 0x28 406 static int pctv452e_i2c_msg(struct dvb_usb_device *d, u8 addr, 407 const u8 *snd_buf, u8 snd_len, 408 u8 *rcv_buf, u8 rcv_len) 409 { 410 struct pctv452e_state *state = (struct pctv452e_state *)d->priv; 411 u8 *buf; 412 u8 id; 413 int ret; 414 415 buf = kmalloc(64, GFP_KERNEL); 416 if (!buf) 417 return -ENOMEM; 418 419 id = state->c++; 420 421 ret = -EINVAL; 422 if (snd_len > 64 - 7 || rcv_len > 64 - 7) 423 goto failed; 424 425 buf[0] = SYNC_BYTE_OUT; 426 buf[1] = id; 427 buf[2] = PCTV_CMD_I2C; 428 buf[3] = snd_len + 3; 429 buf[4] = addr << 1; 430 buf[5] = snd_len; 431 buf[6] = rcv_len; 432 433 memcpy(buf + 7, snd_buf, snd_len); 434 435 ret = dvb_usb_generic_rw(d, buf, 7 + snd_len, 436 buf, /* rcv_len */ 64, 437 /* delay_ms */ 0); 438 if (ret < 0) 439 goto failed; 440 441 /* TT USB protocol error. */ 442 ret = -EIO; 443 if (SYNC_BYTE_IN != buf[0] || id != buf[1]) 444 goto failed; 445 446 /* I2C device didn't respond as expected. */ 447 ret = -EREMOTEIO; 448 if (buf[5] < snd_len || buf[6] < rcv_len) 449 goto failed; 450 451 memcpy(rcv_buf, buf + 7, rcv_len); 452 453 kfree(buf); 454 return rcv_len; 455 456 failed: 457 err("I2C error %d; %02X %02X %02X %02X %02X -> %*ph", 458 ret, SYNC_BYTE_OUT, id, addr << 1, snd_len, rcv_len, 459 7, buf); 460 461 kfree(buf); 462 return ret; 463 } 464 465 static int pctv452e_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msg, 466 int num) 467 { 468 struct dvb_usb_device *d = i2c_get_adapdata(adapter); 469 int i; 470 471 if (mutex_lock_interruptible(&d->i2c_mutex) < 0) 472 return -EAGAIN; 473 474 for (i = 0; i < num; i++) { 475 u8 addr, snd_len, rcv_len, *snd_buf, *rcv_buf; 476 int ret; 477 478 if (msg[i].flags & I2C_M_RD) { 479 addr = msg[i].addr; 480 snd_buf = NULL; 481 snd_len = 0; 482 rcv_buf = msg[i].buf; 483 rcv_len = msg[i].len; 484 } else { 485 addr = msg[i].addr; 486 snd_buf = msg[i].buf; 487 snd_len = msg[i].len; 488 rcv_buf = NULL; 489 rcv_len = 0; 490 } 491 492 ret = pctv452e_i2c_msg(d, addr, snd_buf, snd_len, rcv_buf, 493 rcv_len); 494 if (ret < rcv_len) 495 break; 496 } 497 498 mutex_unlock(&d->i2c_mutex); 499 return i; 500 } 501 502 static u32 pctv452e_i2c_func(struct i2c_adapter *adapter) 503 { 504 return I2C_FUNC_I2C; 505 } 506 507 static int pctv452e_power_ctrl(struct dvb_usb_device *d, int i) 508 { 509 struct pctv452e_state *state = (struct pctv452e_state *)d->priv; 510 u8 *b0, *rx; 511 int ret; 512 513 info("%s: %d\n", __func__, i); 514 515 if (!i) 516 return 0; 517 518 if (state->initialized) 519 return 0; 520 521 b0 = kmalloc(5 + PCTV_ANSWER_LEN, GFP_KERNEL); 522 if (!b0) 523 return -ENOMEM; 524 525 rx = b0 + 5; 526 527 /* hmm where should this should go? */ 528 ret = usb_set_interface(d->udev, 0, ISOC_INTERFACE_ALTERNATIVE); 529 if (ret != 0) 530 info("%s: Warning set interface returned: %d\n", 531 __func__, ret); 532 533 /* this is a one-time initialization, don't know where to put */ 534 b0[0] = 0xaa; 535 b0[1] = state->c++; 536 b0[2] = PCTV_CMD_RESET; 537 b0[3] = 1; 538 b0[4] = 0; 539 /* reset board */ 540 ret = dvb_usb_generic_rw(d, b0, 5, rx, PCTV_ANSWER_LEN, 0); 541 if (ret) 542 goto ret; 543 544 b0[1] = state->c++; 545 b0[4] = 1; 546 /* reset board (again?) */ 547 ret = dvb_usb_generic_rw(d, b0, 5, rx, PCTV_ANSWER_LEN, 0); 548 if (ret) 549 goto ret; 550 551 state->initialized = 1; 552 553 ret: 554 kfree(b0); 555 return ret; 556 } 557 558 static int pctv452e_rc_query(struct dvb_usb_device *d) 559 { 560 struct pctv452e_state *state = (struct pctv452e_state *)d->priv; 561 u8 *b, *rx; 562 int ret, i; 563 u8 id; 564 565 b = kmalloc(CMD_BUFFER_SIZE + PCTV_ANSWER_LEN, GFP_KERNEL); 566 if (!b) 567 return -ENOMEM; 568 569 rx = b + CMD_BUFFER_SIZE; 570 571 id = state->c++; 572 573 /* prepare command header */ 574 b[0] = SYNC_BYTE_OUT; 575 b[1] = id; 576 b[2] = PCTV_CMD_IR; 577 b[3] = 0; 578 579 /* send ir request */ 580 ret = dvb_usb_generic_rw(d, b, 4, rx, PCTV_ANSWER_LEN, 0); 581 if (ret != 0) 582 goto ret; 583 584 if (debug > 3) { 585 info("%s: read: %2d: %*ph: ", __func__, ret, 3, rx); 586 for (i = 0; (i < rx[3]) && ((i+3) < PCTV_ANSWER_LEN); i++) 587 info(" %02x", rx[i+3]); 588 589 info("\n"); 590 } 591 592 if ((rx[3] == 9) && (rx[12] & 0x01)) { 593 /* got a "press" event */ 594 state->last_rc_key = RC_SCANCODE_RC5(rx[7], rx[6]); 595 if (debug > 2) 596 info("%s: cmd=0x%02x sys=0x%02x\n", 597 __func__, rx[6], rx[7]); 598 599 rc_keydown(d->rc_dev, RC_PROTO_RC5, state->last_rc_key, 0); 600 } else if (state->last_rc_key) { 601 rc_keyup(d->rc_dev); 602 state->last_rc_key = 0; 603 } 604 ret: 605 kfree(b); 606 return ret; 607 } 608 609 static int pctv452e_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) 610 { 611 const u8 mem_addr[] = { 0x1f, 0xcc }; 612 u8 encoded_mac[20]; 613 int ret; 614 615 ret = -EAGAIN; 616 if (mutex_lock_interruptible(&d->i2c_mutex) < 0) 617 goto failed; 618 619 ret = pctv452e_i2c_msg(d, I2C_ADDR_24C16, 620 mem_addr + 1, /* snd_len */ 1, 621 encoded_mac, /* rcv_len */ 20); 622 if (-EREMOTEIO == ret) 623 /* Caution! A 24C16 interprets 0xA2 0x1F 0xCC as a 624 byte write if /WC is low. */ 625 ret = pctv452e_i2c_msg(d, I2C_ADDR_24C64, 626 mem_addr, 2, 627 encoded_mac, 20); 628 629 mutex_unlock(&d->i2c_mutex); 630 631 if (20 != ret) 632 goto failed; 633 634 ret = ttpci_eeprom_decode_mac(mac, encoded_mac); 635 if (0 != ret) 636 goto failed; 637 638 return 0; 639 640 failed: 641 eth_zero_addr(mac); 642 643 return ret; 644 } 645 646 static const struct stb0899_s1_reg pctv452e_init_dev[] = { 647 { STB0899_DISCNTRL1, 0x26 }, 648 { STB0899_DISCNTRL2, 0x80 }, 649 { STB0899_DISRX_ST0, 0x04 }, 650 { STB0899_DISRX_ST1, 0x20 }, 651 { STB0899_DISPARITY, 0x00 }, 652 { STB0899_DISFIFO, 0x00 }, 653 { STB0899_DISF22, 0x99 }, 654 { STB0899_DISF22RX, 0x85 }, /* 0xa8 */ 655 { STB0899_ACRPRESC, 0x11 }, 656 { STB0899_ACRDIV1, 0x0a }, 657 { STB0899_ACRDIV2, 0x05 }, 658 { STB0899_DACR1 , 0x00 }, 659 { STB0899_DACR2 , 0x00 }, 660 { STB0899_OUTCFG, 0x00 }, 661 { STB0899_MODECFG, 0x00 }, /* Inversion */ 662 { STB0899_IRQMSK_3, 0xf3 }, 663 { STB0899_IRQMSK_2, 0xfc }, 664 { STB0899_IRQMSK_1, 0xff }, 665 { STB0899_IRQMSK_0, 0xff }, 666 { STB0899_I2CCFG, 0x88 }, 667 { STB0899_I2CRPT, 0x58 }, 668 { STB0899_GPIO00CFG, 0x82 }, 669 { STB0899_GPIO01CFG, 0x82 }, /* LED: 0x02 green, 0x82 orange */ 670 { STB0899_GPIO02CFG, 0x82 }, 671 { STB0899_GPIO03CFG, 0x82 }, 672 { STB0899_GPIO04CFG, 0x82 }, 673 { STB0899_GPIO05CFG, 0x82 }, 674 { STB0899_GPIO06CFG, 0x82 }, 675 { STB0899_GPIO07CFG, 0x82 }, 676 { STB0899_GPIO08CFG, 0x82 }, 677 { STB0899_GPIO09CFG, 0x82 }, 678 { STB0899_GPIO10CFG, 0x82 }, 679 { STB0899_GPIO11CFG, 0x82 }, 680 { STB0899_GPIO12CFG, 0x82 }, 681 { STB0899_GPIO13CFG, 0x82 }, 682 { STB0899_GPIO14CFG, 0x82 }, 683 { STB0899_GPIO15CFG, 0x82 }, 684 { STB0899_GPIO16CFG, 0x82 }, 685 { STB0899_GPIO17CFG, 0x82 }, 686 { STB0899_GPIO18CFG, 0x82 }, 687 { STB0899_GPIO19CFG, 0x82 }, 688 { STB0899_GPIO20CFG, 0x82 }, 689 { STB0899_SDATCFG, 0xb8 }, 690 { STB0899_SCLTCFG, 0xba }, 691 { STB0899_AGCRFCFG, 0x1c }, /* 0x11 DVB-S; 0x1c DVB-S2 (1c, rjkm) */ 692 { STB0899_GPIO22, 0x82 }, 693 { STB0899_GPIO21, 0x91 }, 694 { STB0899_DIRCLKCFG, 0x82 }, 695 { STB0899_CLKOUT27CFG, 0x7e }, 696 { STB0899_STDBYCFG, 0x82 }, 697 { STB0899_CS0CFG, 0x82 }, 698 { STB0899_CS1CFG, 0x82 }, 699 { STB0899_DISEQCOCFG, 0x20 }, 700 { STB0899_NCOARSE, 0x15 }, /* 0x15 27Mhz, F/3 198MHz, F/6 108MHz */ 701 { STB0899_SYNTCTRL, 0x00 }, /* 0x00 CLKI, 0x02 XTALI */ 702 { STB0899_FILTCTRL, 0x00 }, 703 { STB0899_SYSCTRL, 0x00 }, 704 { STB0899_STOPCLK1, 0x20 }, /* orig: 0x00 budget-ci: 0x20 */ 705 { STB0899_STOPCLK2, 0x00 }, 706 { STB0899_INTBUFCTRL, 0x0a }, 707 { STB0899_AGC2I1, 0x00 }, 708 { STB0899_AGC2I2, 0x00 }, 709 { STB0899_AGCIQIN, 0x00 }, 710 { STB0899_TSTRES, 0x40 }, /* rjkm */ 711 { 0xffff, 0xff }, 712 }; 713 714 static const struct stb0899_s1_reg pctv452e_init_s1_demod[] = { 715 { STB0899_DEMOD, 0x00 }, 716 { STB0899_RCOMPC, 0xc9 }, 717 { STB0899_AGC1CN, 0x01 }, 718 { STB0899_AGC1REF, 0x10 }, 719 { STB0899_RTC, 0x23 }, 720 { STB0899_TMGCFG, 0x4e }, 721 { STB0899_AGC2REF, 0x34 }, 722 { STB0899_TLSR, 0x84 }, 723 { STB0899_CFD, 0xf7 }, 724 { STB0899_ACLC, 0x87 }, 725 { STB0899_BCLC, 0x94 }, 726 { STB0899_EQON, 0x41 }, 727 { STB0899_LDT, 0xf1 }, 728 { STB0899_LDT2, 0xe3 }, 729 { STB0899_EQUALREF, 0xb4 }, 730 { STB0899_TMGRAMP, 0x10 }, 731 { STB0899_TMGTHD, 0x30 }, 732 { STB0899_IDCCOMP, 0xfd }, 733 { STB0899_QDCCOMP, 0xff }, 734 { STB0899_POWERI, 0x0c }, 735 { STB0899_POWERQ, 0x0f }, 736 { STB0899_RCOMP, 0x6c }, 737 { STB0899_AGCIQIN, 0x80 }, 738 { STB0899_AGC2I1, 0x06 }, 739 { STB0899_AGC2I2, 0x00 }, 740 { STB0899_TLIR, 0x30 }, 741 { STB0899_RTF, 0x7f }, 742 { STB0899_DSTATUS, 0x00 }, 743 { STB0899_LDI, 0xbc }, 744 { STB0899_CFRM, 0xea }, 745 { STB0899_CFRL, 0x31 }, 746 { STB0899_NIRM, 0x2b }, 747 { STB0899_NIRL, 0x80 }, 748 { STB0899_ISYMB, 0x1d }, 749 { STB0899_QSYMB, 0xa6 }, 750 { STB0899_SFRH, 0x2f }, 751 { STB0899_SFRM, 0x68 }, 752 { STB0899_SFRL, 0x40 }, 753 { STB0899_SFRUPH, 0x2f }, 754 { STB0899_SFRUPM, 0x68 }, 755 { STB0899_SFRUPL, 0x40 }, 756 { STB0899_EQUAI1, 0x02 }, 757 { STB0899_EQUAQ1, 0xff }, 758 { STB0899_EQUAI2, 0x04 }, 759 { STB0899_EQUAQ2, 0x05 }, 760 { STB0899_EQUAI3, 0x02 }, 761 { STB0899_EQUAQ3, 0xfd }, 762 { STB0899_EQUAI4, 0x03 }, 763 { STB0899_EQUAQ4, 0x07 }, 764 { STB0899_EQUAI5, 0x08 }, 765 { STB0899_EQUAQ5, 0xf5 }, 766 { STB0899_DSTATUS2, 0x00 }, 767 { STB0899_VSTATUS, 0x00 }, 768 { STB0899_VERROR, 0x86 }, 769 { STB0899_IQSWAP, 0x2a }, 770 { STB0899_ECNT1M, 0x00 }, 771 { STB0899_ECNT1L, 0x00 }, 772 { STB0899_ECNT2M, 0x00 }, 773 { STB0899_ECNT2L, 0x00 }, 774 { STB0899_ECNT3M, 0x0a }, 775 { STB0899_ECNT3L, 0xad }, 776 { STB0899_FECAUTO1, 0x06 }, 777 { STB0899_FECM, 0x01 }, 778 { STB0899_VTH12, 0xb0 }, 779 { STB0899_VTH23, 0x7a }, 780 { STB0899_VTH34, 0x58 }, 781 { STB0899_VTH56, 0x38 }, 782 { STB0899_VTH67, 0x34 }, 783 { STB0899_VTH78, 0x24 }, 784 { STB0899_PRVIT, 0xff }, 785 { STB0899_VITSYNC, 0x19 }, 786 { STB0899_RSULC, 0xb1 }, /* DVB = 0xb1, DSS = 0xa1 */ 787 { STB0899_TSULC, 0x42 }, 788 { STB0899_RSLLC, 0x41 }, 789 { STB0899_TSLPL, 0x12 }, 790 { STB0899_TSCFGH, 0x0c }, 791 { STB0899_TSCFGM, 0x00 }, 792 { STB0899_TSCFGL, 0x00 }, 793 { STB0899_TSOUT, 0x69 }, /* 0x0d for CAM */ 794 { STB0899_RSSYNCDEL, 0x00 }, 795 { STB0899_TSINHDELH, 0x02 }, 796 { STB0899_TSINHDELM, 0x00 }, 797 { STB0899_TSINHDELL, 0x00 }, 798 { STB0899_TSLLSTKM, 0x1b }, 799 { STB0899_TSLLSTKL, 0xb3 }, 800 { STB0899_TSULSTKM, 0x00 }, 801 { STB0899_TSULSTKL, 0x00 }, 802 { STB0899_PCKLENUL, 0xbc }, 803 { STB0899_PCKLENLL, 0xcc }, 804 { STB0899_RSPCKLEN, 0xbd }, 805 { STB0899_TSSTATUS, 0x90 }, 806 { STB0899_ERRCTRL1, 0xb6 }, 807 { STB0899_ERRCTRL2, 0x95 }, 808 { STB0899_ERRCTRL3, 0x8d }, 809 { STB0899_DMONMSK1, 0x27 }, 810 { STB0899_DMONMSK0, 0x03 }, 811 { STB0899_DEMAPVIT, 0x5c }, 812 { STB0899_PLPARM, 0x19 }, 813 { STB0899_PDELCTRL, 0x48 }, 814 { STB0899_PDELCTRL2, 0x00 }, 815 { STB0899_BBHCTRL1, 0x00 }, 816 { STB0899_BBHCTRL2, 0x00 }, 817 { STB0899_HYSTTHRESH, 0x77 }, 818 { STB0899_MATCSTM, 0x00 }, 819 { STB0899_MATCSTL, 0x00 }, 820 { STB0899_UPLCSTM, 0x00 }, 821 { STB0899_UPLCSTL, 0x00 }, 822 { STB0899_DFLCSTM, 0x00 }, 823 { STB0899_DFLCSTL, 0x00 }, 824 { STB0899_SYNCCST, 0x00 }, 825 { STB0899_SYNCDCSTM, 0x00 }, 826 { STB0899_SYNCDCSTL, 0x00 }, 827 { STB0899_ISI_ENTRY, 0x00 }, 828 { STB0899_ISI_BIT_EN, 0x00 }, 829 { STB0899_MATSTRM, 0xf0 }, 830 { STB0899_MATSTRL, 0x02 }, 831 { STB0899_UPLSTRM, 0x45 }, 832 { STB0899_UPLSTRL, 0x60 }, 833 { STB0899_DFLSTRM, 0xe3 }, 834 { STB0899_DFLSTRL, 0x00 }, 835 { STB0899_SYNCSTR, 0x47 }, 836 { STB0899_SYNCDSTRM, 0x05 }, 837 { STB0899_SYNCDSTRL, 0x18 }, 838 { STB0899_CFGPDELSTATUS1, 0x19 }, 839 { STB0899_CFGPDELSTATUS2, 0x2b }, 840 { STB0899_BBFERRORM, 0x00 }, 841 { STB0899_BBFERRORL, 0x01 }, 842 { STB0899_UPKTERRORM, 0x00 }, 843 { STB0899_UPKTERRORL, 0x00 }, 844 { 0xffff, 0xff }, 845 }; 846 847 static struct stb0899_config stb0899_config = { 848 .init_dev = pctv452e_init_dev, 849 .init_s2_demod = stb0899_s2_init_2, 850 .init_s1_demod = pctv452e_init_s1_demod, 851 .init_s2_fec = stb0899_s2_init_4, 852 .init_tst = stb0899_s1_init_5, 853 854 .demod_address = I2C_ADDR_STB0899, /* I2C Address */ 855 .block_sync_mode = STB0899_SYNC_FORCED, /* ? */ 856 857 .xtal_freq = 27000000, /* Assume Hz ? */ 858 .inversion = IQ_SWAP_ON, 859 860 .lo_clk = 76500000, 861 .hi_clk = 99000000, 862 863 .ts_output_mode = 0, /* Use parallel mode */ 864 .clock_polarity = 0, 865 .data_clk_parity = 0, 866 .fec_mode = 0, 867 868 .esno_ave = STB0899_DVBS2_ESNO_AVE, 869 .esno_quant = STB0899_DVBS2_ESNO_QUANT, 870 .avframes_coarse = STB0899_DVBS2_AVFRAMES_COARSE, 871 .avframes_fine = STB0899_DVBS2_AVFRAMES_FINE, 872 .miss_threshold = STB0899_DVBS2_MISS_THRESHOLD, 873 .uwp_threshold_acq = STB0899_DVBS2_UWP_THRESHOLD_ACQ, 874 .uwp_threshold_track = STB0899_DVBS2_UWP_THRESHOLD_TRACK, 875 .uwp_threshold_sof = STB0899_DVBS2_UWP_THRESHOLD_SOF, 876 .sof_search_timeout = STB0899_DVBS2_SOF_SEARCH_TIMEOUT, 877 878 .btr_nco_bits = STB0899_DVBS2_BTR_NCO_BITS, 879 .btr_gain_shift_offset = STB0899_DVBS2_BTR_GAIN_SHIFT_OFFSET, 880 .crl_nco_bits = STB0899_DVBS2_CRL_NCO_BITS, 881 .ldpc_max_iter = STB0899_DVBS2_LDPC_MAX_ITER, 882 883 .tuner_get_frequency = stb6100_get_frequency, 884 .tuner_set_frequency = stb6100_set_frequency, 885 .tuner_set_bandwidth = stb6100_set_bandwidth, 886 .tuner_get_bandwidth = stb6100_get_bandwidth, 887 .tuner_set_rfsiggain = NULL, 888 889 /* helper for switching LED green/orange */ 890 .postproc = pctv45e_postproc 891 }; 892 893 static struct stb6100_config stb6100_config = { 894 .tuner_address = I2C_ADDR_STB6100, 895 .refclock = 27000000 896 }; 897 898 899 static struct i2c_algorithm pctv452e_i2c_algo = { 900 .master_xfer = pctv452e_i2c_xfer, 901 .functionality = pctv452e_i2c_func 902 }; 903 904 static int pctv452e_frontend_attach(struct dvb_usb_adapter *a) 905 { 906 struct usb_device_id *id; 907 908 a->fe_adap[0].fe = dvb_attach(stb0899_attach, &stb0899_config, 909 &a->dev->i2c_adap); 910 if (!a->fe_adap[0].fe) 911 return -ENODEV; 912 if ((dvb_attach(lnbp22_attach, a->fe_adap[0].fe, 913 &a->dev->i2c_adap)) == NULL) 914 err("Cannot attach lnbp22\n"); 915 916 id = a->dev->desc->warm_ids[0]; 917 if (USB_VID_TECHNOTREND == id->idVendor 918 && USB_PID_TECHNOTREND_CONNECT_S2_3650_CI == id->idProduct) 919 /* Error ignored. */ 920 tt3650_ci_init(a); 921 922 return 0; 923 } 924 925 static int pctv452e_tuner_attach(struct dvb_usb_adapter *a) 926 { 927 if (!a->fe_adap[0].fe) 928 return -ENODEV; 929 if (dvb_attach(stb6100_attach, a->fe_adap[0].fe, &stb6100_config, 930 &a->dev->i2c_adap) == NULL) { 931 err("%s failed\n", __func__); 932 return -ENODEV; 933 } 934 935 return 0; 936 } 937 938 static struct usb_device_id pctv452e_usb_table[] = { 939 {USB_DEVICE(USB_VID_PINNACLE, USB_PID_PCTV_452E)}, 940 {USB_DEVICE(USB_VID_TECHNOTREND, USB_PID_TECHNOTREND_CONNECT_S2_3600)}, 941 {USB_DEVICE(USB_VID_TECHNOTREND, 942 USB_PID_TECHNOTREND_CONNECT_S2_3650_CI)}, 943 {} 944 }; 945 MODULE_DEVICE_TABLE(usb, pctv452e_usb_table); 946 947 static struct dvb_usb_device_properties pctv452e_properties = { 948 .caps = DVB_USB_IS_AN_I2C_ADAPTER, /* more ? */ 949 .usb_ctrl = DEVICE_SPECIFIC, 950 951 .size_of_priv = sizeof(struct pctv452e_state), 952 953 .power_ctrl = pctv452e_power_ctrl, 954 955 .rc.core = { 956 .rc_codes = RC_MAP_DIB0700_RC5_TABLE, 957 .allowed_protos = RC_PROTO_BIT_RC5, 958 .rc_query = pctv452e_rc_query, 959 .rc_interval = 100, 960 }, 961 962 .num_adapters = 1, 963 .adapter = {{ 964 .num_frontends = 1, 965 .fe = {{ 966 .frontend_attach = pctv452e_frontend_attach, 967 .tuner_attach = pctv452e_tuner_attach, 968 969 /* parameter for the MPEG2-data transfer */ 970 .stream = { 971 .type = USB_ISOC, 972 .count = 4, 973 .endpoint = 0x02, 974 .u = { 975 .isoc = { 976 .framesperurb = 4, 977 .framesize = 940, 978 .interval = 1 979 } 980 } 981 }, 982 } }, 983 } }, 984 985 .i2c_algo = &pctv452e_i2c_algo, 986 987 .generic_bulk_ctrl_endpoint = 1, /* allow generice rw function */ 988 989 .num_device_descs = 1, 990 .devices = { 991 { .name = "PCTV HDTV USB", 992 .cold_ids = { NULL, NULL }, /* this is a warm only device */ 993 .warm_ids = { &pctv452e_usb_table[0], NULL } 994 }, 995 { NULL }, 996 } 997 }; 998 999 static struct dvb_usb_device_properties tt_connect_s2_3600_properties = { 1000 .caps = DVB_USB_IS_AN_I2C_ADAPTER, /* more ? */ 1001 .usb_ctrl = DEVICE_SPECIFIC, 1002 1003 .size_of_priv = sizeof(struct pctv452e_state), 1004 1005 .power_ctrl = pctv452e_power_ctrl, 1006 .read_mac_address = pctv452e_read_mac_address, 1007 1008 .rc.core = { 1009 .rc_codes = RC_MAP_TT_1500, 1010 .allowed_protos = RC_PROTO_BIT_RC5, 1011 .rc_query = pctv452e_rc_query, 1012 .rc_interval = 100, 1013 }, 1014 1015 .num_adapters = 1, 1016 .adapter = {{ 1017 .num_frontends = 1, 1018 .fe = {{ 1019 .frontend_attach = pctv452e_frontend_attach, 1020 .tuner_attach = pctv452e_tuner_attach, 1021 1022 /* parameter for the MPEG2-data transfer */ 1023 .stream = { 1024 .type = USB_ISOC, 1025 .count = 4, 1026 .endpoint = 0x02, 1027 .u = { 1028 .isoc = { 1029 .framesperurb = 64, 1030 .framesize = 940, 1031 .interval = 1 1032 } 1033 } 1034 }, 1035 1036 } }, 1037 } }, 1038 1039 .i2c_algo = &pctv452e_i2c_algo, 1040 1041 .generic_bulk_ctrl_endpoint = 1, /* allow generic rw function*/ 1042 1043 .num_device_descs = 2, 1044 .devices = { 1045 { .name = "Technotrend TT Connect S2-3600", 1046 .cold_ids = { NULL, NULL }, /* this is a warm only device */ 1047 .warm_ids = { &pctv452e_usb_table[1], NULL } 1048 }, 1049 { .name = "Technotrend TT Connect S2-3650-CI", 1050 .cold_ids = { NULL, NULL }, 1051 .warm_ids = { &pctv452e_usb_table[2], NULL } 1052 }, 1053 { NULL }, 1054 } 1055 }; 1056 1057 static void pctv452e_usb_disconnect(struct usb_interface *intf) 1058 { 1059 struct dvb_usb_device *d = usb_get_intfdata(intf); 1060 1061 tt3650_ci_uninit(d); 1062 dvb_usb_device_exit(intf); 1063 } 1064 1065 static int pctv452e_usb_probe(struct usb_interface *intf, 1066 const struct usb_device_id *id) 1067 { 1068 if (0 == dvb_usb_device_init(intf, &pctv452e_properties, 1069 THIS_MODULE, NULL, adapter_nr) || 1070 0 == dvb_usb_device_init(intf, &tt_connect_s2_3600_properties, 1071 THIS_MODULE, NULL, adapter_nr)) 1072 return 0; 1073 1074 return -ENODEV; 1075 } 1076 1077 static struct usb_driver pctv452e_usb_driver = { 1078 .name = "pctv452e", 1079 .probe = pctv452e_usb_probe, 1080 .disconnect = pctv452e_usb_disconnect, 1081 .id_table = pctv452e_usb_table, 1082 }; 1083 1084 module_usb_driver(pctv452e_usb_driver); 1085 1086 MODULE_AUTHOR("Dominik Kuhlen <dkuhlen@gmx.net>"); 1087 MODULE_AUTHOR("Andre Weidemann <Andre.Weidemann@web.de>"); 1088 MODULE_AUTHOR("Michael H. Schimek <mschimek@gmx.at>"); 1089 MODULE_DESCRIPTION("Pinnacle PCTV HDTV USB DVB / TT connect S2-3600 Driver"); 1090 MODULE_LICENSE("GPL"); 1091