Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

media: m88ds3103: Add support for ds3103b demod

The ds3103b demodulator identifies as an m88rs600, but requires different
clock settings and firmware, along with differences in register settings.

Changes were reverse engineered using an instrumented downstream GPLv2
driver to compare i2c traffic and clocking. The mclk functions are from
the downstream GPLv2 driver.

Signed-off-by: Brad Love <brad@nextdimension.cc>
Signed-off-by: Sean Young <sean@mess.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>

authored by

Brad Love and committed by
Mauro Carvalho Chehab
e6089fec e6c6d7d4

+467 -13
+455 -11
drivers/media/dvb-frontends/m88ds3103.c
··· 65 65 } 66 66 67 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]; 151 + } 152 + 153 + /* 68 154 * Get the demodulator AGC PWM voltage setting supplied to the tuner. 69 155 */ 70 156 int m88ds3103_get_agc_pwm(struct dvb_frontend *fe, u8 *_agc_pwm) ··· 374 288 return ret; 375 289 } 376 290 291 + static int m88ds3103b_select_mclk(struct m88ds3103_dev *dev) 292 + { 293 + struct i2c_client *client = dev->client; 294 + struct dtv_frontend_properties *c = &dev->fe.dtv_property_cache; 295 + u32 adc_Freq_MHz[3] = {96, 93, 99}; 296 + u8 reg16_list[3] = {96, 92, 100}, reg16, reg15; 297 + u32 offset_MHz[3]; 298 + u32 max_offset = 0; 299 + u32 old_setting = dev->mclk; 300 + u32 tuner_freq_MHz = c->frequency / 1000; 301 + u8 i; 302 + char big_symbol = 0; 303 + 304 + big_symbol = (c->symbol_rate > 45010000) ? 1 : 0; 305 + 306 + if (big_symbol) { 307 + reg16 = 115; 308 + } else { 309 + reg16 = 96; 310 + 311 + /* TODO: IS THIS NECESSARY ? */ 312 + for (i = 0; i < 3; i++) { 313 + offset_MHz[i] = tuner_freq_MHz % adc_Freq_MHz[i]; 314 + 315 + if (offset_MHz[i] > (adc_Freq_MHz[i] / 2)) 316 + offset_MHz[i] = adc_Freq_MHz[i] - offset_MHz[i]; 317 + 318 + if (offset_MHz[i] > max_offset) { 319 + max_offset = offset_MHz[i]; 320 + reg16 = reg16_list[i]; 321 + dev->mclk = adc_Freq_MHz[i] * 1000 * 1000; 322 + 323 + if (big_symbol) 324 + dev->mclk /= 2; 325 + 326 + dev_dbg(&client->dev, "modifying mclk %u -> %u\n", 327 + old_setting, dev->mclk); 328 + } 329 + } 330 + } 331 + 332 + if (dev->mclk == 93000000) 333 + regmap_write(dev->regmap, 0xA0, 0x42); 334 + else if (dev->mclk == 96000000) 335 + regmap_write(dev->regmap, 0xA0, 0x44); 336 + else if (dev->mclk == 99000000) 337 + regmap_write(dev->regmap, 0xA0, 0x46); 338 + else if (dev->mclk == 110250000) 339 + regmap_write(dev->regmap, 0xA0, 0x4E); 340 + else 341 + regmap_write(dev->regmap, 0xA0, 0x44); 342 + 343 + reg15 = m88ds3103b_dt_read(dev, 0x15); 344 + 345 + m88ds3103b_dt_write(dev, 0x05, 0x40); 346 + m88ds3103b_dt_write(dev, 0x11, 0x08); 347 + 348 + if (big_symbol) 349 + reg15 |= 0x02; 350 + else 351 + reg15 &= ~0x02; 352 + 353 + m88ds3103b_dt_write(dev, 0x15, reg15); 354 + m88ds3103b_dt_write(dev, 0x16, reg16); 355 + 356 + usleep_range(5000, 5500); 357 + 358 + m88ds3103b_dt_write(dev, 0x05, 0x00); 359 + m88ds3103b_dt_write(dev, 0x11, (u8)(big_symbol ? 0x0E : 0x0A)); 360 + 361 + usleep_range(5000, 5500); 362 + 363 + return 0; 364 + } 365 + 366 + static int m88ds3103b_set_mclk(struct m88ds3103_dev *dev, u32 mclk_khz) 367 + { 368 + u8 reg11 = 0x0A, reg15, reg16, reg1D, reg1E, reg1F, tmp; 369 + u8 sm, f0 = 0, f1 = 0, f2 = 0, f3 = 0; 370 + u16 pll_div_fb, N; 371 + u32 div; 372 + 373 + reg15 = m88ds3103b_dt_read(dev, 0x15); 374 + reg16 = m88ds3103b_dt_read(dev, 0x16); 375 + reg1D = m88ds3103b_dt_read(dev, 0x1D); 376 + 377 + if (dev->cfg->ts_mode != M88DS3103_TS_SERIAL) { 378 + if (reg16 == 92) 379 + tmp = 93; 380 + else if (reg16 == 100) 381 + tmp = 99; 382 + else 383 + tmp = 96; 384 + 385 + mclk_khz *= tmp; 386 + mclk_khz /= 96; 387 + } 388 + 389 + pll_div_fb = (reg15 & 0x01) << 8; 390 + pll_div_fb += reg16; 391 + pll_div_fb += 32; 392 + 393 + div = 9000 * pll_div_fb * 4; 394 + div /= mclk_khz; 395 + 396 + if (dev->cfg->ts_mode == M88DS3103_TS_SERIAL) { 397 + reg11 |= 0x02; 398 + 399 + if (div <= 32) { 400 + N = 2; 401 + 402 + f0 = 0; 403 + f1 = div / N; 404 + f2 = div - f1; 405 + f3 = 0; 406 + } else if (div <= 34) { 407 + N = 3; 408 + 409 + f0 = div / N; 410 + f1 = (div - f0) / (N - 1); 411 + f2 = div - f0 - f1; 412 + f3 = 0; 413 + } else if (div <= 64) { 414 + N = 4; 415 + 416 + f0 = div / N; 417 + f1 = (div - f0) / (N - 1); 418 + f2 = (div - f0 - f1) / (N - 2); 419 + f3 = div - f0 - f1 - f2; 420 + } else { 421 + N = 4; 422 + 423 + f0 = 16; 424 + f1 = 16; 425 + f2 = 16; 426 + f3 = 16; 427 + } 428 + 429 + if (f0 == 16) 430 + f0 = 0; 431 + else if ((f0 < 8) && (f0 != 0)) 432 + f0 = 8; 433 + 434 + if (f1 == 16) 435 + f1 = 0; 436 + else if ((f1 < 8) && (f1 != 0)) 437 + f1 = 8; 438 + 439 + if (f2 == 16) 440 + f2 = 0; 441 + else if ((f2 < 8) && (f2 != 0)) 442 + f2 = 8; 443 + 444 + if (f3 == 16) 445 + f3 = 0; 446 + else if ((f3 < 8) && (f3 != 0)) 447 + f3 = 8; 448 + } else { 449 + reg11 &= ~0x02; 450 + 451 + if (div <= 32) { 452 + N = 2; 453 + 454 + f0 = 0; 455 + f1 = div / N; 456 + f2 = div - f1; 457 + f3 = 0; 458 + } else if (div <= 48) { 459 + N = 3; 460 + 461 + f0 = div / N; 462 + f1 = (div - f0) / (N - 1); 463 + f2 = div - f0 - f1; 464 + f3 = 0; 465 + } else if (div <= 64) { 466 + N = 4; 467 + 468 + f0 = div / N; 469 + f1 = (div - f0) / (N - 1); 470 + f2 = (div - f0 - f1) / (N - 2); 471 + f3 = div - f0 - f1 - f2; 472 + } else { 473 + N = 4; 474 + 475 + f0 = 16; 476 + f1 = 16; 477 + f2 = 16; 478 + f3 = 16; 479 + } 480 + 481 + if (f0 == 16) 482 + f0 = 0; 483 + else if ((f0 < 9) && (f0 != 0)) 484 + f0 = 9; 485 + 486 + if (f1 == 16) 487 + f1 = 0; 488 + else if ((f1 < 9) && (f1 != 0)) 489 + f1 = 9; 490 + 491 + if (f2 == 16) 492 + f2 = 0; 493 + else if ((f2 < 9) && (f2 != 0)) 494 + f2 = 9; 495 + 496 + if (f3 == 16) 497 + f3 = 0; 498 + else if ((f3 < 9) && (f3 != 0)) 499 + f3 = 9; 500 + } 501 + 502 + sm = N - 1; 503 + 504 + /* Write to registers */ 505 + //reg15 &= 0x01; 506 + //reg15 |= (pll_div_fb >> 8) & 0x01; 507 + 508 + //reg16 = pll_div_fb & 0xFF; 509 + 510 + reg1D &= ~0x03; 511 + reg1D |= sm; 512 + reg1D |= 0x80; 513 + 514 + reg1E = ((f3 << 4) + f2) & 0xFF; 515 + reg1F = ((f1 << 4) + f0) & 0xFF; 516 + 517 + m88ds3103b_dt_write(dev, 0x05, 0x40); 518 + m88ds3103b_dt_write(dev, 0x11, 0x08); 519 + m88ds3103b_dt_write(dev, 0x1D, reg1D); 520 + m88ds3103b_dt_write(dev, 0x1E, reg1E); 521 + m88ds3103b_dt_write(dev, 0x1F, reg1F); 522 + 523 + m88ds3103b_dt_write(dev, 0x17, 0xc1); 524 + m88ds3103b_dt_write(dev, 0x17, 0x81); 525 + 526 + usleep_range(5000, 5500); 527 + 528 + m88ds3103b_dt_write(dev, 0x05, 0x00); 529 + m88ds3103b_dt_write(dev, 0x11, 0x0A); 530 + 531 + usleep_range(5000, 5500); 532 + 533 + return 0; 534 + } 535 + 377 536 static int m88ds3103_set_frontend(struct dvb_frontend *fe) 378 537 { 379 538 struct m88ds3103_dev *dev = fe->demodulator_priv; ··· 629 298 u8 u8tmp, u8tmp1 = 0, u8tmp2 = 0; /* silence compiler warning */ 630 299 u8 buf[3]; 631 300 u16 u16tmp; 632 - u32 tuner_frequency_khz, target_mclk; 301 + u32 tuner_frequency_khz, target_mclk, u32tmp; 633 302 s32 s32tmp; 634 303 static const struct reg_sequence reset_buf[] = { 635 304 {0x07, 0x80}, {0x07, 0x00} ··· 652 321 653 322 /* Disable demod clock path */ 654 323 if (dev->chip_id == M88RS6000_CHIP_ID) { 324 + if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) { 325 + ret = regmap_read(dev->regmap, 0xb2, &u32tmp); 326 + if (ret) 327 + goto err; 328 + if (u32tmp == 0x01) { 329 + ret = regmap_write(dev->regmap, 0x00, 0x00); 330 + if (ret) 331 + goto err; 332 + ret = regmap_write(dev->regmap, 0xb2, 0x00); 333 + if (ret) 334 + goto err; 335 + } 336 + } 337 + 655 338 ret = regmap_write(dev->regmap, 0x06, 0xe0); 656 339 if (ret) 657 340 goto err; ··· 691 346 tuner_frequency_khz = c->frequency; 692 347 } 693 348 694 - /* select M88RS6000 demod main mclk and ts mclk from tuner die. */ 349 + /* set M88RS6000/DS3103B demod main mclk and ts mclk from tuner die */ 695 350 if (dev->chip_id == M88RS6000_CHIP_ID) { 696 351 if (c->symbol_rate > 45010000) 697 352 dev->mclk = 110250000; ··· 702 357 target_mclk = 96000000; 703 358 else 704 359 target_mclk = 144000000; 360 + 361 + if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) { 362 + m88ds3103b_select_mclk(dev); 363 + m88ds3103b_set_mclk(dev, target_mclk / 1000); 364 + } 705 365 706 366 /* Enable demod clock path */ 707 367 ret = regmap_write(dev->regmap, 0x06, 0x00); ··· 819 469 ret = m88ds3103_update_bits(dev, 0x9d, 0x08, 0x08); 820 470 if (ret) 821 471 goto err; 472 + 473 + if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) { 474 + buf[0] = m88ds3103b_dt_read(dev, 0x15); 475 + buf[1] = m88ds3103b_dt_read(dev, 0x16); 476 + 477 + if (c->symbol_rate > 45010000) { 478 + buf[0] &= ~0x03; 479 + buf[0] |= 0x02; 480 + buf[0] |= ((147 - 32) >> 8) & 0x01; 481 + buf[1] = (147 - 32) & 0xFF; 482 + 483 + dev->mclk = 110250 * 1000; 484 + } else { 485 + buf[0] &= ~0x03; 486 + buf[0] |= ((128 - 32) >> 8) & 0x01; 487 + buf[1] = (128 - 32) & 0xFF; 488 + 489 + dev->mclk = 96000 * 1000; 490 + } 491 + m88ds3103b_dt_write(dev, 0x15, buf[0]); 492 + m88ds3103b_dt_write(dev, 0x16, buf[1]); 493 + 494 + regmap_read(dev->regmap, 0x30, &u32tmp); 495 + u32tmp &= ~0x80; 496 + regmap_write(dev->regmap, 0x30, u32tmp & 0xff); 497 + } 498 + 822 499 ret = regmap_write(dev->regmap, 0xf1, 0x01); 823 500 if (ret) 824 501 goto err; 825 - ret = m88ds3103_update_bits(dev, 0x30, 0x80, 0x80); 826 - if (ret) 827 - goto err; 502 + 503 + if (dev->chiptype != M88DS3103_CHIPTYPE_3103B) { 504 + ret = m88ds3103_update_bits(dev, 0x30, 0x80, 0x80); 505 + if (ret) 506 + goto err; 507 + } 828 508 } 829 509 830 510 switch (dev->cfg->ts_mode) { ··· 868 488 break; 869 489 case M88DS3103_TS_PARALLEL: 870 490 u8tmp = 0x02; 491 + if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) { 492 + u8tmp = 0x01; 493 + u8tmp1 = 0x01; 494 + } 871 495 break; 872 496 case M88DS3103_TS_CI: 873 497 u8tmp = 0x03; ··· 900 516 u8tmp1 = 0x3f; 901 517 u8tmp2 = 0x3f; 902 518 break; 519 + case M88DS3103_TS_PARALLEL: 520 + if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) { 521 + ret = m88ds3103_update_bits(dev, 0x29, 0x01, u8tmp1); 522 + if (ret) 523 + goto err; 524 + } 525 + /* fall through */ 903 526 default: 904 527 u16tmp = DIV_ROUND_UP(target_mclk, dev->cfg->ts_clk); 905 528 u8tmp1 = u16tmp / 2 - 1; ··· 933 542 u8tmp = 0x10; 934 543 else 935 544 u8tmp = 0x06; 545 + 546 + if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) 547 + m88ds3103b_set_mclk(dev, target_mclk / 1000); 936 548 937 549 ret = regmap_write(dev->regmap, 0xc3, 0x08); 938 550 if (ret) ··· 971 577 ret = regmap_write(dev->regmap, 0x33, dev->cfg->agc); 972 578 if (ret) 973 579 goto err; 580 + 581 + if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) { 582 + /* enable/disable 192M LDPC clock */ 583 + ret = m88ds3103_update_bits(dev, 0x29, 0x10, 584 + (c->delivery_system == SYS_DVBS) ? 0x10 : 0x0); 585 + if (ret) 586 + goto err; 587 + 588 + ret = m88ds3103_update_bits(dev, 0xc9, 0x08, 0x08); 589 + } 974 590 975 591 dev_dbg(&client->dev, "carrier offset=%d\n", 976 592 (tuner_frequency_khz - c->frequency)); ··· 1046 642 if (utmp) 1047 643 goto warm; 1048 644 1049 - /* global reset, global diseqc reset, golbal fec reset */ 645 + /* global reset, global diseqc reset, global fec reset */ 1050 646 ret = regmap_write(dev->regmap, 0x07, 0xe0); 1051 647 if (ret) 1052 648 goto err; ··· 1056 652 1057 653 /* cold state - try to download firmware */ 1058 654 dev_info(&client->dev, "found a '%s' in cold state\n", 1059 - m88ds3103_ops.info.name); 655 + dev->fe.ops.info.name); 1060 656 1061 - if (dev->chip_id == M88RS6000_CHIP_ID) 657 + if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) 658 + name = M88DS3103B_FIRMWARE; 659 + else if (dev->chip_id == M88RS6000_CHIP_ID) 1062 660 name = M88RS6000_FIRMWARE; 1063 661 else 1064 662 name = M88DS3103_FIRMWARE; 663 + 1065 664 /* request the firmware, this will block and timeout */ 1066 665 ret = request_firmware(&firmware, name, &client->dev); 1067 666 if (ret) { ··· 1107 700 } 1108 701 1109 702 dev_info(&client->dev, "found a '%s' in warm state\n", 1110 - m88ds3103_ops.info.name); 703 + dev->fe.ops.info.name); 1111 704 dev_info(&client->dev, "firmware version: %X.%X\n", 1112 705 (utmp >> 4) & 0xf, (utmp >> 0 & 0xf)); 1113 706 707 + if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) { 708 + m88ds3103b_dt_write(dev, 0x21, 0x92); 709 + m88ds3103b_dt_write(dev, 0x15, 0x6C); 710 + m88ds3103b_dt_write(dev, 0x17, 0xC1); 711 + m88ds3103b_dt_write(dev, 0x17, 0x81); 712 + } 1114 713 warm: 1115 714 /* warm state */ 1116 715 dev->warm = true; ··· 1806 1393 goto err_kfree; 1807 1394 1808 1395 dev->chip_id = utmp >> 1; 1396 + dev->chiptype = (u8)id->driver_data; 1397 + 1809 1398 dev_dbg(&client->dev, "chip_id=%02x\n", dev->chip_id); 1810 1399 1811 1400 switch (dev->chip_id) { ··· 1874 1459 1875 1460 /* create dvb_frontend */ 1876 1461 memcpy(&dev->fe.ops, &m88ds3103_ops, sizeof(struct dvb_frontend_ops)); 1877 - if (dev->chip_id == M88RS6000_CHIP_ID) 1462 + if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) 1463 + strscpy(dev->fe.ops.info.name, "Montage Technology M88DS3103B", 1464 + sizeof(dev->fe.ops.info.name)); 1465 + else if (dev->chip_id == M88RS6000_CHIP_ID) 1878 1466 strscpy(dev->fe.ops.info.name, "Montage Technology M88RS6000", 1879 1467 sizeof(dev->fe.ops.info.name)); 1880 1468 if (!pdata->attach_in_use) ··· 1888 1470 /* setup callbacks */ 1889 1471 pdata->get_dvb_frontend = m88ds3103_get_dvb_frontend; 1890 1472 pdata->get_i2c_adapter = m88ds3103_get_i2c_adapter; 1473 + 1474 + if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) { 1475 + /* enable i2c repeater for tuner */ 1476 + m88ds3103_update_bits(dev, 0x11, 0x01, 0x01); 1477 + 1478 + /* get frontend address */ 1479 + ret = regmap_read(dev->regmap, 0x29, &utmp); 1480 + if (ret) 1481 + goto err_kfree; 1482 + dev->dt_addr = ((utmp & 0x80) == 0) ? 0x42 >> 1 : 0x40 >> 1; 1483 + dev_err(&client->dev, "dt addr is 0x%02x", dev->dt_addr); 1484 + 1485 + dev->dt_client = i2c_new_dummy_device(client->adapter, 1486 + dev->dt_addr); 1487 + if (!dev->dt_client) { 1488 + ret = -ENODEV; 1489 + goto err_kfree; 1490 + } 1491 + } 1492 + 1891 1493 return 0; 1892 1494 err_kfree: 1893 1495 kfree(dev); ··· 1922 1484 1923 1485 dev_dbg(&client->dev, "\n"); 1924 1486 1487 + if (dev->dt_client) 1488 + i2c_unregister_device(dev->dt_client); 1489 + 1925 1490 i2c_mux_del_adapters(dev->muxc); 1926 1491 1927 1492 kfree(dev); ··· 1932 1491 } 1933 1492 1934 1493 static const struct i2c_device_id m88ds3103_id_table[] = { 1935 - {"m88ds3103", 0}, 1494 + {"m88ds3103", M88DS3103_CHIPTYPE_3103}, 1495 + {"m88rs6000", M88DS3103_CHIPTYPE_RS6000}, 1496 + {"m88ds3103b", M88DS3103_CHIPTYPE_3103B}, 1936 1497 {} 1937 1498 }; 1938 1499 MODULE_DEVICE_TABLE(i2c, m88ds3103_id_table); ··· 1956 1513 MODULE_LICENSE("GPL"); 1957 1514 MODULE_FIRMWARE(M88DS3103_FIRMWARE); 1958 1515 MODULE_FIRMWARE(M88RS6000_FIRMWARE); 1516 + MODULE_FIRMWARE(M88DS3103B_FIRMWARE);
+12 -2
drivers/media/dvb-frontends/m88ds3103_priv.h
··· 16 16 #include <linux/regmap.h> 17 17 #include <linux/math64.h> 18 18 19 - #define M88DS3103_FIRMWARE "dvb-demod-m88ds3103.fw" 20 - #define M88RS6000_FIRMWARE "dvb-demod-m88rs6000.fw" 19 + #define M88DS3103B_FIRMWARE "dvb-demod-m88ds3103b.fw" 20 + #define M88DS3103_FIRMWARE "dvb-demod-m88ds3103.fw" 21 + #define M88RS6000_FIRMWARE "dvb-demod-m88rs6000.fw" 22 + 21 23 #define M88RS6000_CHIP_ID 0x74 22 24 #define M88DS3103_CHIP_ID 0x70 23 25 26 + #define M88DS3103_CHIPTYPE_3103 0 27 + #define M88DS3103_CHIPTYPE_RS6000 1 28 + #define M88DS3103_CHIPTYPE_3103B 2 29 + 24 30 struct m88ds3103_dev { 25 31 struct i2c_client *client; 32 + struct i2c_client *dt_client; 26 33 struct regmap_config regmap_config; 27 34 struct regmap *regmap; 28 35 struct m88ds3103_config config; ··· 42 35 struct i2c_mux_core *muxc; 43 36 /* auto detect chip id to do different config */ 44 37 u8 chip_id; 38 + /* chip type to differentiate m88rs6000 from m88ds3103b */ 39 + u8 chiptype; 45 40 /* main mclk is calculated for M88RS6000 dynamically */ 46 41 s32 mclk; 47 42 u64 post_bit_error; 48 43 u64 post_bit_count; 44 + u8 dt_addr; 49 45 }; 50 46 51 47 struct m88ds3103_reg_val {