.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * Montage Technology M88DS3103/M88RS6000 demodulator driver |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright (C) 2013 Antti Palosaari <crope@iki.fi> |
---|
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 | 6 | */ |
---|
16 | 7 | |
---|
17 | 8 | #include "m88ds3103_priv.h" |
---|
.. | .. |
---|
71 | 62 | err: |
---|
72 | 63 | dev_dbg(&client->dev, "failed=%d\n", ret); |
---|
73 | 64 | return ret; |
---|
| 65 | +} |
---|
| 66 | + |
---|
| 67 | +/* |
---|
| 68 | + * m88ds3103b demod has an internal device related to clocking. First the i2c |
---|
| 69 | + * gate must be opened, for one transaction, then writes will be allowed. |
---|
| 70 | + */ |
---|
| 71 | +static int m88ds3103b_dt_write(struct m88ds3103_dev *dev, int reg, int data) |
---|
| 72 | +{ |
---|
| 73 | + struct i2c_client *client = dev->client; |
---|
| 74 | + u8 buf[] = {reg, data}; |
---|
| 75 | + u8 val; |
---|
| 76 | + int ret; |
---|
| 77 | + struct i2c_msg msg = { |
---|
| 78 | + .addr = dev->dt_addr, .flags = 0, .buf = buf, .len = 2 |
---|
| 79 | + }; |
---|
| 80 | + |
---|
| 81 | + m88ds3103_update_bits(dev, 0x11, 0x01, 0x00); |
---|
| 82 | + |
---|
| 83 | + val = 0x11; |
---|
| 84 | + ret = regmap_write(dev->regmap, 0x03, val); |
---|
| 85 | + if (ret) |
---|
| 86 | + dev_dbg(&client->dev, "fail=%d\n", ret); |
---|
| 87 | + |
---|
| 88 | + ret = i2c_transfer(dev->dt_client->adapter, &msg, 1); |
---|
| 89 | + if (ret != 1) { |
---|
| 90 | + dev_err(&client->dev, "0x%02x (ret=%i, reg=0x%02x, value=0x%02x)\n", |
---|
| 91 | + dev->dt_addr, ret, reg, data); |
---|
| 92 | + |
---|
| 93 | + m88ds3103_update_bits(dev, 0x11, 0x01, 0x01); |
---|
| 94 | + return -EREMOTEIO; |
---|
| 95 | + } |
---|
| 96 | + m88ds3103_update_bits(dev, 0x11, 0x01, 0x01); |
---|
| 97 | + |
---|
| 98 | + dev_dbg(&client->dev, "0x%02x reg 0x%02x, value 0x%02x\n", |
---|
| 99 | + dev->dt_addr, reg, data); |
---|
| 100 | + |
---|
| 101 | + return 0; |
---|
| 102 | +} |
---|
| 103 | + |
---|
| 104 | +/* |
---|
| 105 | + * m88ds3103b demod has an internal device related to clocking. First the i2c |
---|
| 106 | + * gate must be opened, for two transactions, then reads will be allowed. |
---|
| 107 | + */ |
---|
| 108 | +static int m88ds3103b_dt_read(struct m88ds3103_dev *dev, u8 reg) |
---|
| 109 | +{ |
---|
| 110 | + struct i2c_client *client = dev->client; |
---|
| 111 | + int ret; |
---|
| 112 | + u8 val; |
---|
| 113 | + u8 b0[] = { reg }; |
---|
| 114 | + u8 b1[] = { 0 }; |
---|
| 115 | + struct i2c_msg msg[] = { |
---|
| 116 | + { |
---|
| 117 | + .addr = dev->dt_addr, |
---|
| 118 | + .flags = 0, |
---|
| 119 | + .buf = b0, |
---|
| 120 | + .len = 1 |
---|
| 121 | + }, |
---|
| 122 | + { |
---|
| 123 | + .addr = dev->dt_addr, |
---|
| 124 | + .flags = I2C_M_RD, |
---|
| 125 | + .buf = b1, |
---|
| 126 | + .len = 1 |
---|
| 127 | + } |
---|
| 128 | + }; |
---|
| 129 | + |
---|
| 130 | + m88ds3103_update_bits(dev, 0x11, 0x01, 0x00); |
---|
| 131 | + |
---|
| 132 | + val = 0x12; |
---|
| 133 | + ret = regmap_write(dev->regmap, 0x03, val); |
---|
| 134 | + if (ret) |
---|
| 135 | + dev_dbg(&client->dev, "fail=%d\n", ret); |
---|
| 136 | + |
---|
| 137 | + ret = i2c_transfer(dev->dt_client->adapter, msg, 2); |
---|
| 138 | + if (ret != 2) { |
---|
| 139 | + dev_err(&client->dev, "0x%02x (ret=%d, reg=0x%02x)\n", |
---|
| 140 | + dev->dt_addr, ret, reg); |
---|
| 141 | + |
---|
| 142 | + m88ds3103_update_bits(dev, 0x11, 0x01, 0x01); |
---|
| 143 | + return -EREMOTEIO; |
---|
| 144 | + } |
---|
| 145 | + m88ds3103_update_bits(dev, 0x11, 0x01, 0x01); |
---|
| 146 | + |
---|
| 147 | + dev_dbg(&client->dev, "0x%02x reg 0x%02x, value 0x%02x\n", |
---|
| 148 | + dev->dt_addr, reg, b1[0]); |
---|
| 149 | + |
---|
| 150 | + return b1[0]; |
---|
74 | 151 | } |
---|
75 | 152 | |
---|
76 | 153 | /* |
---|
.. | .. |
---|
297 | 374 | return ret; |
---|
298 | 375 | } |
---|
299 | 376 | |
---|
| 377 | +static int m88ds3103b_select_mclk(struct m88ds3103_dev *dev) |
---|
| 378 | +{ |
---|
| 379 | + struct i2c_client *client = dev->client; |
---|
| 380 | + struct dtv_frontend_properties *c = &dev->fe.dtv_property_cache; |
---|
| 381 | + u32 adc_Freq_MHz[3] = {96, 93, 99}; |
---|
| 382 | + u8 reg16_list[3] = {96, 92, 100}, reg16, reg15; |
---|
| 383 | + u32 offset_MHz[3]; |
---|
| 384 | + u32 max_offset = 0; |
---|
| 385 | + u32 old_setting = dev->mclk; |
---|
| 386 | + u32 tuner_freq_MHz = c->frequency / 1000; |
---|
| 387 | + u8 i; |
---|
| 388 | + char big_symbol = 0; |
---|
| 389 | + |
---|
| 390 | + big_symbol = (c->symbol_rate > 45010000) ? 1 : 0; |
---|
| 391 | + |
---|
| 392 | + if (big_symbol) { |
---|
| 393 | + reg16 = 115; |
---|
| 394 | + } else { |
---|
| 395 | + reg16 = 96; |
---|
| 396 | + |
---|
| 397 | + /* TODO: IS THIS NECESSARY ? */ |
---|
| 398 | + for (i = 0; i < 3; i++) { |
---|
| 399 | + offset_MHz[i] = tuner_freq_MHz % adc_Freq_MHz[i]; |
---|
| 400 | + |
---|
| 401 | + if (offset_MHz[i] > (adc_Freq_MHz[i] / 2)) |
---|
| 402 | + offset_MHz[i] = adc_Freq_MHz[i] - offset_MHz[i]; |
---|
| 403 | + |
---|
| 404 | + if (offset_MHz[i] > max_offset) { |
---|
| 405 | + max_offset = offset_MHz[i]; |
---|
| 406 | + reg16 = reg16_list[i]; |
---|
| 407 | + dev->mclk = adc_Freq_MHz[i] * 1000 * 1000; |
---|
| 408 | + |
---|
| 409 | + if (big_symbol) |
---|
| 410 | + dev->mclk /= 2; |
---|
| 411 | + |
---|
| 412 | + dev_dbg(&client->dev, "modifying mclk %u -> %u\n", |
---|
| 413 | + old_setting, dev->mclk); |
---|
| 414 | + } |
---|
| 415 | + } |
---|
| 416 | + } |
---|
| 417 | + |
---|
| 418 | + if (dev->mclk == 93000000) |
---|
| 419 | + regmap_write(dev->regmap, 0xA0, 0x42); |
---|
| 420 | + else if (dev->mclk == 96000000) |
---|
| 421 | + regmap_write(dev->regmap, 0xA0, 0x44); |
---|
| 422 | + else if (dev->mclk == 99000000) |
---|
| 423 | + regmap_write(dev->regmap, 0xA0, 0x46); |
---|
| 424 | + else if (dev->mclk == 110250000) |
---|
| 425 | + regmap_write(dev->regmap, 0xA0, 0x4E); |
---|
| 426 | + else |
---|
| 427 | + regmap_write(dev->regmap, 0xA0, 0x44); |
---|
| 428 | + |
---|
| 429 | + reg15 = m88ds3103b_dt_read(dev, 0x15); |
---|
| 430 | + |
---|
| 431 | + m88ds3103b_dt_write(dev, 0x05, 0x40); |
---|
| 432 | + m88ds3103b_dt_write(dev, 0x11, 0x08); |
---|
| 433 | + |
---|
| 434 | + if (big_symbol) |
---|
| 435 | + reg15 |= 0x02; |
---|
| 436 | + else |
---|
| 437 | + reg15 &= ~0x02; |
---|
| 438 | + |
---|
| 439 | + m88ds3103b_dt_write(dev, 0x15, reg15); |
---|
| 440 | + m88ds3103b_dt_write(dev, 0x16, reg16); |
---|
| 441 | + |
---|
| 442 | + usleep_range(5000, 5500); |
---|
| 443 | + |
---|
| 444 | + m88ds3103b_dt_write(dev, 0x05, 0x00); |
---|
| 445 | + m88ds3103b_dt_write(dev, 0x11, (u8)(big_symbol ? 0x0E : 0x0A)); |
---|
| 446 | + |
---|
| 447 | + usleep_range(5000, 5500); |
---|
| 448 | + |
---|
| 449 | + return 0; |
---|
| 450 | +} |
---|
| 451 | + |
---|
| 452 | +static int m88ds3103b_set_mclk(struct m88ds3103_dev *dev, u32 mclk_khz) |
---|
| 453 | +{ |
---|
| 454 | + u8 reg11 = 0x0A, reg15, reg16, reg1D, reg1E, reg1F, tmp; |
---|
| 455 | + u8 sm, f0 = 0, f1 = 0, f2 = 0, f3 = 0; |
---|
| 456 | + u16 pll_div_fb, N; |
---|
| 457 | + u32 div; |
---|
| 458 | + |
---|
| 459 | + reg15 = m88ds3103b_dt_read(dev, 0x15); |
---|
| 460 | + reg16 = m88ds3103b_dt_read(dev, 0x16); |
---|
| 461 | + reg1D = m88ds3103b_dt_read(dev, 0x1D); |
---|
| 462 | + |
---|
| 463 | + if (dev->cfg->ts_mode != M88DS3103_TS_SERIAL) { |
---|
| 464 | + if (reg16 == 92) |
---|
| 465 | + tmp = 93; |
---|
| 466 | + else if (reg16 == 100) |
---|
| 467 | + tmp = 99; |
---|
| 468 | + else |
---|
| 469 | + tmp = 96; |
---|
| 470 | + |
---|
| 471 | + mclk_khz *= tmp; |
---|
| 472 | + mclk_khz /= 96; |
---|
| 473 | + } |
---|
| 474 | + |
---|
| 475 | + pll_div_fb = (reg15 & 0x01) << 8; |
---|
| 476 | + pll_div_fb += reg16; |
---|
| 477 | + pll_div_fb += 32; |
---|
| 478 | + |
---|
| 479 | + div = 9000 * pll_div_fb * 4; |
---|
| 480 | + div /= mclk_khz; |
---|
| 481 | + |
---|
| 482 | + if (dev->cfg->ts_mode == M88DS3103_TS_SERIAL) { |
---|
| 483 | + reg11 |= 0x02; |
---|
| 484 | + |
---|
| 485 | + if (div <= 32) { |
---|
| 486 | + N = 2; |
---|
| 487 | + |
---|
| 488 | + f0 = 0; |
---|
| 489 | + f1 = div / N; |
---|
| 490 | + f2 = div - f1; |
---|
| 491 | + f3 = 0; |
---|
| 492 | + } else if (div <= 34) { |
---|
| 493 | + N = 3; |
---|
| 494 | + |
---|
| 495 | + f0 = div / N; |
---|
| 496 | + f1 = (div - f0) / (N - 1); |
---|
| 497 | + f2 = div - f0 - f1; |
---|
| 498 | + f3 = 0; |
---|
| 499 | + } else if (div <= 64) { |
---|
| 500 | + N = 4; |
---|
| 501 | + |
---|
| 502 | + f0 = div / N; |
---|
| 503 | + f1 = (div - f0) / (N - 1); |
---|
| 504 | + f2 = (div - f0 - f1) / (N - 2); |
---|
| 505 | + f3 = div - f0 - f1 - f2; |
---|
| 506 | + } else { |
---|
| 507 | + N = 4; |
---|
| 508 | + |
---|
| 509 | + f0 = 16; |
---|
| 510 | + f1 = 16; |
---|
| 511 | + f2 = 16; |
---|
| 512 | + f3 = 16; |
---|
| 513 | + } |
---|
| 514 | + |
---|
| 515 | + if (f0 == 16) |
---|
| 516 | + f0 = 0; |
---|
| 517 | + else if ((f0 < 8) && (f0 != 0)) |
---|
| 518 | + f0 = 8; |
---|
| 519 | + |
---|
| 520 | + if (f1 == 16) |
---|
| 521 | + f1 = 0; |
---|
| 522 | + else if ((f1 < 8) && (f1 != 0)) |
---|
| 523 | + f1 = 8; |
---|
| 524 | + |
---|
| 525 | + if (f2 == 16) |
---|
| 526 | + f2 = 0; |
---|
| 527 | + else if ((f2 < 8) && (f2 != 0)) |
---|
| 528 | + f2 = 8; |
---|
| 529 | + |
---|
| 530 | + if (f3 == 16) |
---|
| 531 | + f3 = 0; |
---|
| 532 | + else if ((f3 < 8) && (f3 != 0)) |
---|
| 533 | + f3 = 8; |
---|
| 534 | + } else { |
---|
| 535 | + reg11 &= ~0x02; |
---|
| 536 | + |
---|
| 537 | + if (div <= 32) { |
---|
| 538 | + N = 2; |
---|
| 539 | + |
---|
| 540 | + f0 = 0; |
---|
| 541 | + f1 = div / N; |
---|
| 542 | + f2 = div - f1; |
---|
| 543 | + f3 = 0; |
---|
| 544 | + } else if (div <= 48) { |
---|
| 545 | + N = 3; |
---|
| 546 | + |
---|
| 547 | + f0 = div / N; |
---|
| 548 | + f1 = (div - f0) / (N - 1); |
---|
| 549 | + f2 = div - f0 - f1; |
---|
| 550 | + f3 = 0; |
---|
| 551 | + } else if (div <= 64) { |
---|
| 552 | + N = 4; |
---|
| 553 | + |
---|
| 554 | + f0 = div / N; |
---|
| 555 | + f1 = (div - f0) / (N - 1); |
---|
| 556 | + f2 = (div - f0 - f1) / (N - 2); |
---|
| 557 | + f3 = div - f0 - f1 - f2; |
---|
| 558 | + } else { |
---|
| 559 | + N = 4; |
---|
| 560 | + |
---|
| 561 | + f0 = 16; |
---|
| 562 | + f1 = 16; |
---|
| 563 | + f2 = 16; |
---|
| 564 | + f3 = 16; |
---|
| 565 | + } |
---|
| 566 | + |
---|
| 567 | + if (f0 == 16) |
---|
| 568 | + f0 = 0; |
---|
| 569 | + else if ((f0 < 9) && (f0 != 0)) |
---|
| 570 | + f0 = 9; |
---|
| 571 | + |
---|
| 572 | + if (f1 == 16) |
---|
| 573 | + f1 = 0; |
---|
| 574 | + else if ((f1 < 9) && (f1 != 0)) |
---|
| 575 | + f1 = 9; |
---|
| 576 | + |
---|
| 577 | + if (f2 == 16) |
---|
| 578 | + f2 = 0; |
---|
| 579 | + else if ((f2 < 9) && (f2 != 0)) |
---|
| 580 | + f2 = 9; |
---|
| 581 | + |
---|
| 582 | + if (f3 == 16) |
---|
| 583 | + f3 = 0; |
---|
| 584 | + else if ((f3 < 9) && (f3 != 0)) |
---|
| 585 | + f3 = 9; |
---|
| 586 | + } |
---|
| 587 | + |
---|
| 588 | + sm = N - 1; |
---|
| 589 | + |
---|
| 590 | + /* Write to registers */ |
---|
| 591 | + //reg15 &= 0x01; |
---|
| 592 | + //reg15 |= (pll_div_fb >> 8) & 0x01; |
---|
| 593 | + |
---|
| 594 | + //reg16 = pll_div_fb & 0xFF; |
---|
| 595 | + |
---|
| 596 | + reg1D &= ~0x03; |
---|
| 597 | + reg1D |= sm; |
---|
| 598 | + reg1D |= 0x80; |
---|
| 599 | + |
---|
| 600 | + reg1E = ((f3 << 4) + f2) & 0xFF; |
---|
| 601 | + reg1F = ((f1 << 4) + f0) & 0xFF; |
---|
| 602 | + |
---|
| 603 | + m88ds3103b_dt_write(dev, 0x05, 0x40); |
---|
| 604 | + m88ds3103b_dt_write(dev, 0x11, 0x08); |
---|
| 605 | + m88ds3103b_dt_write(dev, 0x1D, reg1D); |
---|
| 606 | + m88ds3103b_dt_write(dev, 0x1E, reg1E); |
---|
| 607 | + m88ds3103b_dt_write(dev, 0x1F, reg1F); |
---|
| 608 | + |
---|
| 609 | + m88ds3103b_dt_write(dev, 0x17, 0xc1); |
---|
| 610 | + m88ds3103b_dt_write(dev, 0x17, 0x81); |
---|
| 611 | + |
---|
| 612 | + usleep_range(5000, 5500); |
---|
| 613 | + |
---|
| 614 | + m88ds3103b_dt_write(dev, 0x05, 0x00); |
---|
| 615 | + m88ds3103b_dt_write(dev, 0x11, 0x0A); |
---|
| 616 | + |
---|
| 617 | + usleep_range(5000, 5500); |
---|
| 618 | + |
---|
| 619 | + return 0; |
---|
| 620 | +} |
---|
| 621 | + |
---|
300 | 622 | static int m88ds3103_set_frontend(struct dvb_frontend *fe) |
---|
301 | 623 | { |
---|
302 | 624 | struct m88ds3103_dev *dev = fe->demodulator_priv; |
---|
.. | .. |
---|
307 | 629 | u8 u8tmp, u8tmp1 = 0, u8tmp2 = 0; /* silence compiler warning */ |
---|
308 | 630 | u8 buf[3]; |
---|
309 | 631 | u16 u16tmp; |
---|
310 | | - u32 tuner_frequency_khz, target_mclk; |
---|
| 632 | + u32 tuner_frequency_khz, target_mclk, u32tmp; |
---|
311 | 633 | s32 s32tmp; |
---|
312 | 634 | static const struct reg_sequence reset_buf[] = { |
---|
313 | 635 | {0x07, 0x80}, {0x07, 0x00} |
---|
.. | .. |
---|
330 | 652 | |
---|
331 | 653 | /* Disable demod clock path */ |
---|
332 | 654 | if (dev->chip_id == M88RS6000_CHIP_ID) { |
---|
| 655 | + if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) { |
---|
| 656 | + ret = regmap_read(dev->regmap, 0xb2, &u32tmp); |
---|
| 657 | + if (ret) |
---|
| 658 | + goto err; |
---|
| 659 | + if (u32tmp == 0x01) { |
---|
| 660 | + ret = regmap_write(dev->regmap, 0x00, 0x00); |
---|
| 661 | + if (ret) |
---|
| 662 | + goto err; |
---|
| 663 | + ret = regmap_write(dev->regmap, 0xb2, 0x00); |
---|
| 664 | + if (ret) |
---|
| 665 | + goto err; |
---|
| 666 | + } |
---|
| 667 | + } |
---|
| 668 | + |
---|
333 | 669 | ret = regmap_write(dev->regmap, 0x06, 0xe0); |
---|
334 | 670 | if (ret) |
---|
335 | 671 | goto err; |
---|
.. | .. |
---|
355 | 691 | tuner_frequency_khz = c->frequency; |
---|
356 | 692 | } |
---|
357 | 693 | |
---|
358 | | - /* select M88RS6000 demod main mclk and ts mclk from tuner die. */ |
---|
| 694 | + /* set M88RS6000/DS3103B demod main mclk and ts mclk from tuner die */ |
---|
359 | 695 | if (dev->chip_id == M88RS6000_CHIP_ID) { |
---|
360 | 696 | if (c->symbol_rate > 45010000) |
---|
361 | 697 | dev->mclk = 110250000; |
---|
.. | .. |
---|
366 | 702 | target_mclk = 96000000; |
---|
367 | 703 | else |
---|
368 | 704 | target_mclk = 144000000; |
---|
| 705 | + |
---|
| 706 | + if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) { |
---|
| 707 | + m88ds3103b_select_mclk(dev); |
---|
| 708 | + m88ds3103b_set_mclk(dev, target_mclk / 1000); |
---|
| 709 | + } |
---|
369 | 710 | |
---|
370 | 711 | /* Enable demod clock path */ |
---|
371 | 712 | ret = regmap_write(dev->regmap, 0x06, 0x00); |
---|
.. | .. |
---|
478 | 819 | ret = m88ds3103_update_bits(dev, 0x9d, 0x08, 0x08); |
---|
479 | 820 | if (ret) |
---|
480 | 821 | goto err; |
---|
| 822 | + |
---|
| 823 | + if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) { |
---|
| 824 | + buf[0] = m88ds3103b_dt_read(dev, 0x15); |
---|
| 825 | + buf[1] = m88ds3103b_dt_read(dev, 0x16); |
---|
| 826 | + |
---|
| 827 | + if (c->symbol_rate > 45010000) { |
---|
| 828 | + buf[0] &= ~0x03; |
---|
| 829 | + buf[0] |= 0x02; |
---|
| 830 | + buf[0] |= ((147 - 32) >> 8) & 0x01; |
---|
| 831 | + buf[1] = (147 - 32) & 0xFF; |
---|
| 832 | + |
---|
| 833 | + dev->mclk = 110250 * 1000; |
---|
| 834 | + } else { |
---|
| 835 | + buf[0] &= ~0x03; |
---|
| 836 | + buf[0] |= ((128 - 32) >> 8) & 0x01; |
---|
| 837 | + buf[1] = (128 - 32) & 0xFF; |
---|
| 838 | + |
---|
| 839 | + dev->mclk = 96000 * 1000; |
---|
| 840 | + } |
---|
| 841 | + m88ds3103b_dt_write(dev, 0x15, buf[0]); |
---|
| 842 | + m88ds3103b_dt_write(dev, 0x16, buf[1]); |
---|
| 843 | + |
---|
| 844 | + regmap_read(dev->regmap, 0x30, &u32tmp); |
---|
| 845 | + u32tmp &= ~0x80; |
---|
| 846 | + regmap_write(dev->regmap, 0x30, u32tmp & 0xff); |
---|
| 847 | + } |
---|
| 848 | + |
---|
481 | 849 | ret = regmap_write(dev->regmap, 0xf1, 0x01); |
---|
482 | 850 | if (ret) |
---|
483 | 851 | goto err; |
---|
484 | | - ret = m88ds3103_update_bits(dev, 0x30, 0x80, 0x80); |
---|
485 | | - if (ret) |
---|
486 | | - goto err; |
---|
| 852 | + |
---|
| 853 | + if (dev->chiptype != M88DS3103_CHIPTYPE_3103B) { |
---|
| 854 | + ret = m88ds3103_update_bits(dev, 0x30, 0x80, 0x80); |
---|
| 855 | + if (ret) |
---|
| 856 | + goto err; |
---|
| 857 | + } |
---|
487 | 858 | } |
---|
488 | 859 | |
---|
489 | 860 | switch (dev->cfg->ts_mode) { |
---|
.. | .. |
---|
497 | 868 | break; |
---|
498 | 869 | case M88DS3103_TS_PARALLEL: |
---|
499 | 870 | u8tmp = 0x02; |
---|
| 871 | + if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) { |
---|
| 872 | + u8tmp = 0x01; |
---|
| 873 | + u8tmp1 = 0x01; |
---|
| 874 | + } |
---|
500 | 875 | break; |
---|
501 | 876 | case M88DS3103_TS_CI: |
---|
502 | 877 | u8tmp = 0x03; |
---|
.. | .. |
---|
525 | 900 | u8tmp1 = 0x3f; |
---|
526 | 901 | u8tmp2 = 0x3f; |
---|
527 | 902 | break; |
---|
| 903 | + case M88DS3103_TS_PARALLEL: |
---|
| 904 | + if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) { |
---|
| 905 | + ret = m88ds3103_update_bits(dev, 0x29, 0x01, u8tmp1); |
---|
| 906 | + if (ret) |
---|
| 907 | + goto err; |
---|
| 908 | + } |
---|
| 909 | + fallthrough; |
---|
528 | 910 | default: |
---|
529 | 911 | u16tmp = DIV_ROUND_UP(target_mclk, dev->cfg->ts_clk); |
---|
530 | 912 | u8tmp1 = u16tmp / 2 - 1; |
---|
.. | .. |
---|
551 | 933 | u8tmp = 0x10; |
---|
552 | 934 | else |
---|
553 | 935 | u8tmp = 0x06; |
---|
| 936 | + |
---|
| 937 | + if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) |
---|
| 938 | + m88ds3103b_set_mclk(dev, target_mclk / 1000); |
---|
554 | 939 | |
---|
555 | 940 | ret = regmap_write(dev->regmap, 0xc3, 0x08); |
---|
556 | 941 | if (ret) |
---|
.. | .. |
---|
586 | 971 | ret = regmap_write(dev->regmap, 0x33, dev->cfg->agc); |
---|
587 | 972 | if (ret) |
---|
588 | 973 | goto err; |
---|
| 974 | + |
---|
| 975 | + if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) { |
---|
| 976 | + /* enable/disable 192M LDPC clock */ |
---|
| 977 | + ret = m88ds3103_update_bits(dev, 0x29, 0x10, |
---|
| 978 | + (c->delivery_system == SYS_DVBS) ? 0x10 : 0x0); |
---|
| 979 | + if (ret) |
---|
| 980 | + goto err; |
---|
| 981 | + |
---|
| 982 | + ret = m88ds3103_update_bits(dev, 0xc9, 0x08, 0x08); |
---|
| 983 | + if (ret) |
---|
| 984 | + goto err; |
---|
| 985 | + } |
---|
589 | 986 | |
---|
590 | 987 | dev_dbg(&client->dev, "carrier offset=%d\n", |
---|
591 | 988 | (tuner_frequency_khz - c->frequency)); |
---|
.. | .. |
---|
651 | 1048 | if (utmp) |
---|
652 | 1049 | goto warm; |
---|
653 | 1050 | |
---|
654 | | - /* global reset, global diseqc reset, golbal fec reset */ |
---|
| 1051 | + /* global reset, global diseqc reset, global fec reset */ |
---|
655 | 1052 | ret = regmap_write(dev->regmap, 0x07, 0xe0); |
---|
656 | 1053 | if (ret) |
---|
657 | 1054 | goto err; |
---|
.. | .. |
---|
661 | 1058 | |
---|
662 | 1059 | /* cold state - try to download firmware */ |
---|
663 | 1060 | dev_info(&client->dev, "found a '%s' in cold state\n", |
---|
664 | | - m88ds3103_ops.info.name); |
---|
| 1061 | + dev->fe.ops.info.name); |
---|
665 | 1062 | |
---|
666 | | - if (dev->chip_id == M88RS6000_CHIP_ID) |
---|
| 1063 | + if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) |
---|
| 1064 | + name = M88DS3103B_FIRMWARE; |
---|
| 1065 | + else if (dev->chip_id == M88RS6000_CHIP_ID) |
---|
667 | 1066 | name = M88RS6000_FIRMWARE; |
---|
668 | 1067 | else |
---|
669 | 1068 | name = M88DS3103_FIRMWARE; |
---|
| 1069 | + |
---|
670 | 1070 | /* request the firmware, this will block and timeout */ |
---|
671 | 1071 | ret = request_firmware(&firmware, name, &client->dev); |
---|
672 | 1072 | if (ret) { |
---|
.. | .. |
---|
709 | 1109 | } |
---|
710 | 1110 | |
---|
711 | 1111 | dev_info(&client->dev, "found a '%s' in warm state\n", |
---|
712 | | - m88ds3103_ops.info.name); |
---|
| 1112 | + dev->fe.ops.info.name); |
---|
713 | 1113 | dev_info(&client->dev, "firmware version: %X.%X\n", |
---|
714 | 1114 | (utmp >> 4) & 0xf, (utmp >> 0 & 0xf)); |
---|
715 | 1115 | |
---|
| 1116 | + if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) { |
---|
| 1117 | + m88ds3103b_dt_write(dev, 0x21, 0x92); |
---|
| 1118 | + m88ds3103b_dt_write(dev, 0x15, 0x6C); |
---|
| 1119 | + m88ds3103b_dt_write(dev, 0x17, 0xC1); |
---|
| 1120 | + m88ds3103b_dt_write(dev, 0x17, 0x81); |
---|
| 1121 | + } |
---|
716 | 1122 | warm: |
---|
717 | 1123 | /* warm state */ |
---|
718 | 1124 | dev->warm = true; |
---|
.. | .. |
---|
1283 | 1689 | pdata.attach_in_use = true; |
---|
1284 | 1690 | |
---|
1285 | 1691 | memset(&board_info, 0, sizeof(board_info)); |
---|
1286 | | - strlcpy(board_info.type, "m88ds3103", I2C_NAME_SIZE); |
---|
| 1692 | + strscpy(board_info.type, "m88ds3103", I2C_NAME_SIZE); |
---|
1287 | 1693 | board_info.addr = cfg->i2c_addr; |
---|
1288 | 1694 | board_info.platform_data = &pdata; |
---|
1289 | | - client = i2c_new_device(i2c, &board_info); |
---|
1290 | | - if (!client || !client->dev.driver) |
---|
| 1695 | + client = i2c_new_client_device(i2c, &board_info); |
---|
| 1696 | + if (!i2c_client_has_driver(client)) |
---|
1291 | 1697 | return NULL; |
---|
1292 | 1698 | |
---|
1293 | 1699 | *tuner_i2c_adapter = pdata.get_i2c_adapter(client); |
---|
.. | .. |
---|
1402 | 1808 | goto err_kfree; |
---|
1403 | 1809 | |
---|
1404 | 1810 | dev->chip_id = utmp >> 1; |
---|
| 1811 | + dev->chiptype = (u8)id->driver_data; |
---|
| 1812 | + |
---|
1405 | 1813 | dev_dbg(&client->dev, "chip_id=%02x\n", dev->chip_id); |
---|
1406 | 1814 | |
---|
1407 | 1815 | switch (dev->chip_id) { |
---|
.. | .. |
---|
1468 | 1876 | |
---|
1469 | 1877 | /* create dvb_frontend */ |
---|
1470 | 1878 | memcpy(&dev->fe.ops, &m88ds3103_ops, sizeof(struct dvb_frontend_ops)); |
---|
1471 | | - if (dev->chip_id == M88RS6000_CHIP_ID) |
---|
1472 | | - strncpy(dev->fe.ops.info.name, "Montage Technology M88RS6000", |
---|
| 1879 | + if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) |
---|
| 1880 | + strscpy(dev->fe.ops.info.name, "Montage Technology M88DS3103B", |
---|
| 1881 | + sizeof(dev->fe.ops.info.name)); |
---|
| 1882 | + else if (dev->chip_id == M88RS6000_CHIP_ID) |
---|
| 1883 | + strscpy(dev->fe.ops.info.name, "Montage Technology M88RS6000", |
---|
1473 | 1884 | sizeof(dev->fe.ops.info.name)); |
---|
1474 | 1885 | if (!pdata->attach_in_use) |
---|
1475 | 1886 | dev->fe.ops.release = NULL; |
---|
.. | .. |
---|
1479 | 1890 | /* setup callbacks */ |
---|
1480 | 1891 | pdata->get_dvb_frontend = m88ds3103_get_dvb_frontend; |
---|
1481 | 1892 | pdata->get_i2c_adapter = m88ds3103_get_i2c_adapter; |
---|
| 1893 | + |
---|
| 1894 | + if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) { |
---|
| 1895 | + /* enable i2c repeater for tuner */ |
---|
| 1896 | + m88ds3103_update_bits(dev, 0x11, 0x01, 0x01); |
---|
| 1897 | + |
---|
| 1898 | + /* get frontend address */ |
---|
| 1899 | + ret = regmap_read(dev->regmap, 0x29, &utmp); |
---|
| 1900 | + if (ret) |
---|
| 1901 | + goto err_kfree; |
---|
| 1902 | + dev->dt_addr = ((utmp & 0x80) == 0) ? 0x42 >> 1 : 0x40 >> 1; |
---|
| 1903 | + dev_dbg(&client->dev, "dt addr is 0x%02x\n", dev->dt_addr); |
---|
| 1904 | + |
---|
| 1905 | + dev->dt_client = i2c_new_dummy_device(client->adapter, |
---|
| 1906 | + dev->dt_addr); |
---|
| 1907 | + if (IS_ERR(dev->dt_client)) { |
---|
| 1908 | + ret = PTR_ERR(dev->dt_client); |
---|
| 1909 | + goto err_kfree; |
---|
| 1910 | + } |
---|
| 1911 | + } |
---|
| 1912 | + |
---|
1482 | 1913 | return 0; |
---|
1483 | 1914 | err_kfree: |
---|
1484 | 1915 | kfree(dev); |
---|
.. | .. |
---|
1493 | 1924 | |
---|
1494 | 1925 | dev_dbg(&client->dev, "\n"); |
---|
1495 | 1926 | |
---|
| 1927 | + if (dev->dt_client) |
---|
| 1928 | + i2c_unregister_device(dev->dt_client); |
---|
| 1929 | + |
---|
1496 | 1930 | i2c_mux_del_adapters(dev->muxc); |
---|
1497 | 1931 | |
---|
1498 | 1932 | kfree(dev); |
---|
.. | .. |
---|
1500 | 1934 | } |
---|
1501 | 1935 | |
---|
1502 | 1936 | static const struct i2c_device_id m88ds3103_id_table[] = { |
---|
1503 | | - {"m88ds3103", 0}, |
---|
| 1937 | + {"m88ds3103", M88DS3103_CHIPTYPE_3103}, |
---|
| 1938 | + {"m88rs6000", M88DS3103_CHIPTYPE_RS6000}, |
---|
| 1939 | + {"m88ds3103b", M88DS3103_CHIPTYPE_3103B}, |
---|
1504 | 1940 | {} |
---|
1505 | 1941 | }; |
---|
1506 | 1942 | MODULE_DEVICE_TABLE(i2c, m88ds3103_id_table); |
---|
.. | .. |
---|
1522 | 1958 | MODULE_LICENSE("GPL"); |
---|
1523 | 1959 | MODULE_FIRMWARE(M88DS3103_FIRMWARE); |
---|
1524 | 1960 | MODULE_FIRMWARE(M88RS6000_FIRMWARE); |
---|
| 1961 | +MODULE_FIRMWARE(M88DS3103B_FIRMWARE); |
---|