Message ID | 20200201214826.22873-2-brad@nextdimension.cc (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | m88ds3103: Add support for Montage 3103b DVB-S demod | expand |
Hi Brad, Thank you for the patch! Perhaps something to improve: [auto build test WARNING on linuxtv-media/master] [also build test WARNING on v5.5 next-20200203] [if your patch is applied to the wrong git tree, please drop us a note to help improve the system. BTW, we also suggest to use '--base' option to specify the base tree in git format-patch, please see https://stackoverflow.com/a/37406982] url: https://github.com/0day-ci/linux/commits/Brad-Love/m88ds3103-Add-support-for-Montage-3103b-DVB-S-demod/20200203-135639 base: git://linuxtv.org/media_tree.git master config: i386-randconfig-b001-20200202 (attached as .config) compiler: gcc-7 (Debian 7.5.0-3) 7.5.0 reproduce: # save the attached .config to linux build tree make ARCH=i386 If you fix the issue, kindly add following tag Reported-by: kbuild test robot <lkp@intel.com> All warnings (new ones prefixed by >>): drivers/media/dvb-frontends/m88ds3103.c: In function 'm88ds3103_set_frontend': >> drivers/media/dvb-frontends/m88ds3103.c:906:6: warning: this statement may fall through [-Wimplicit-fallthrough=] if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) { ^ drivers/media/dvb-frontends/m88ds3103.c:911:2: note: here default: ^~~~~~~ vim +906 drivers/media/dvb-frontends/m88ds3103.c 623 624 static int m88ds3103_set_frontend(struct dvb_frontend *fe) 625 { 626 struct m88ds3103_dev *dev = fe->demodulator_priv; 627 struct i2c_client *client = dev->client; 628 struct dtv_frontend_properties *c = &fe->dtv_property_cache; 629 int ret, len; 630 const struct m88ds3103_reg_val *init; 631 u8 u8tmp, u8tmp1 = 0, u8tmp2 = 0; /* silence compiler warning */ 632 u8 buf[3]; 633 u16 u16tmp; 634 u32 tuner_frequency_khz, target_mclk, u32tmp; 635 s32 s32tmp; 636 static const struct reg_sequence reset_buf[] = { 637 {0x07, 0x80}, {0x07, 0x00} 638 }; 639 640 dev_dbg(&client->dev, 641 "delivery_system=%d modulation=%d frequency=%u symbol_rate=%d inversion=%d pilot=%d rolloff=%d\n", 642 c->delivery_system, c->modulation, c->frequency, c->symbol_rate, 643 c->inversion, c->pilot, c->rolloff); 644 645 if (!dev->warm) { 646 ret = -EAGAIN; 647 goto err; 648 } 649 650 /* reset */ 651 ret = regmap_multi_reg_write(dev->regmap, reset_buf, 2); 652 if (ret) 653 goto err; 654 655 /* Disable demod clock path */ 656 if (dev->chip_id == M88RS6000_CHIP_ID) { 657 if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) { 658 ret = regmap_read(dev->regmap, 0xb2, &u32tmp); 659 if (ret) 660 goto err; 661 if (u32tmp == 0x01) { 662 ret = regmap_write(dev->regmap, 0x00, 0x00); 663 if (ret) 664 goto err; 665 ret = regmap_write(dev->regmap, 0xb2, 0x00); 666 if (ret) 667 goto err; 668 } 669 } 670 671 ret = regmap_write(dev->regmap, 0x06, 0xe0); 672 if (ret) 673 goto err; 674 } 675 676 /* program tuner */ 677 if (fe->ops.tuner_ops.set_params) { 678 ret = fe->ops.tuner_ops.set_params(fe); 679 if (ret) 680 goto err; 681 } 682 683 if (fe->ops.tuner_ops.get_frequency) { 684 ret = fe->ops.tuner_ops.get_frequency(fe, &tuner_frequency_khz); 685 if (ret) 686 goto err; 687 } else { 688 /* 689 * Use nominal target frequency as tuner driver does not provide 690 * actual frequency used. Carrier offset calculation is not 691 * valid. 692 */ 693 tuner_frequency_khz = c->frequency; 694 } 695 696 /* set M88RS6000/DS3103B demod main mclk and ts mclk from tuner die */ 697 if (dev->chip_id == M88RS6000_CHIP_ID) { 698 if (c->symbol_rate > 45010000) 699 dev->mclk = 110250000; 700 else 701 dev->mclk = 96000000; 702 703 if (c->delivery_system == SYS_DVBS) 704 target_mclk = 96000000; 705 else 706 target_mclk = 144000000; 707 708 if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) { 709 m88ds3103b_select_mclk(dev); 710 m88ds3103b_set_mclk(dev, target_mclk / 1000); 711 } 712 713 /* Enable demod clock path */ 714 ret = regmap_write(dev->regmap, 0x06, 0x00); 715 if (ret) 716 goto err; 717 usleep_range(10000, 20000); 718 } else { 719 /* set M88DS3103 mclk and ts mclk. */ 720 dev->mclk = 96000000; 721 722 switch (dev->cfg->ts_mode) { 723 case M88DS3103_TS_SERIAL: 724 case M88DS3103_TS_SERIAL_D7: 725 target_mclk = dev->cfg->ts_clk; 726 break; 727 case M88DS3103_TS_PARALLEL: 728 case M88DS3103_TS_CI: 729 if (c->delivery_system == SYS_DVBS) 730 target_mclk = 96000000; 731 else { 732 if (c->symbol_rate < 18000000) 733 target_mclk = 96000000; 734 else if (c->symbol_rate < 28000000) 735 target_mclk = 144000000; 736 else 737 target_mclk = 192000000; 738 } 739 break; 740 default: 741 dev_dbg(&client->dev, "invalid ts_mode\n"); 742 ret = -EINVAL; 743 goto err; 744 } 745 746 switch (target_mclk) { 747 case 96000000: 748 u8tmp1 = 0x02; /* 0b10 */ 749 u8tmp2 = 0x01; /* 0b01 */ 750 break; 751 case 144000000: 752 u8tmp1 = 0x00; /* 0b00 */ 753 u8tmp2 = 0x01; /* 0b01 */ 754 break; 755 case 192000000: 756 u8tmp1 = 0x03; /* 0b11 */ 757 u8tmp2 = 0x00; /* 0b00 */ 758 break; 759 } 760 ret = m88ds3103_update_bits(dev, 0x22, 0xc0, u8tmp1 << 6); 761 if (ret) 762 goto err; 763 ret = m88ds3103_update_bits(dev, 0x24, 0xc0, u8tmp2 << 6); 764 if (ret) 765 goto err; 766 } 767 768 ret = regmap_write(dev->regmap, 0xb2, 0x01); 769 if (ret) 770 goto err; 771 772 ret = regmap_write(dev->regmap, 0x00, 0x01); 773 if (ret) 774 goto err; 775 776 switch (c->delivery_system) { 777 case SYS_DVBS: 778 if (dev->chip_id == M88RS6000_CHIP_ID) { 779 len = ARRAY_SIZE(m88rs6000_dvbs_init_reg_vals); 780 init = m88rs6000_dvbs_init_reg_vals; 781 } else { 782 len = ARRAY_SIZE(m88ds3103_dvbs_init_reg_vals); 783 init = m88ds3103_dvbs_init_reg_vals; 784 } 785 break; 786 case SYS_DVBS2: 787 if (dev->chip_id == M88RS6000_CHIP_ID) { 788 len = ARRAY_SIZE(m88rs6000_dvbs2_init_reg_vals); 789 init = m88rs6000_dvbs2_init_reg_vals; 790 } else { 791 len = ARRAY_SIZE(m88ds3103_dvbs2_init_reg_vals); 792 init = m88ds3103_dvbs2_init_reg_vals; 793 } 794 break; 795 default: 796 dev_dbg(&client->dev, "invalid delivery_system\n"); 797 ret = -EINVAL; 798 goto err; 799 } 800 801 /* program init table */ 802 if (c->delivery_system != dev->delivery_system) { 803 ret = m88ds3103_wr_reg_val_tab(dev, init, len); 804 if (ret) 805 goto err; 806 } 807 808 if (dev->chip_id == M88RS6000_CHIP_ID) { 809 if (c->delivery_system == SYS_DVBS2 && 810 c->symbol_rate <= 5000000) { 811 ret = regmap_write(dev->regmap, 0xc0, 0x04); 812 if (ret) 813 goto err; 814 buf[0] = 0x09; 815 buf[1] = 0x22; 816 buf[2] = 0x88; 817 ret = regmap_bulk_write(dev->regmap, 0x8a, buf, 3); 818 if (ret) 819 goto err; 820 } 821 ret = m88ds3103_update_bits(dev, 0x9d, 0x08, 0x08); 822 if (ret) 823 goto err; 824 825 if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) { 826 buf[0] = m88ds3103b_dt_read(dev, 0x15); 827 buf[1] = m88ds3103b_dt_read(dev, 0x16); 828 829 if (c->symbol_rate > 45010000) { 830 buf[0] &= ~0x03; 831 buf[0] |= 0x02; 832 buf[0] |= ((147 - 32) >> 8) & 0x01; 833 buf[1] = (147 - 32) & 0xFF; 834 835 dev->mclk = 110250 * 1000; 836 } else { 837 buf[0] &= ~0x03; 838 buf[0] |= ((128 - 32) >> 8) & 0x01; 839 buf[1] = (128 - 32) & 0xFF; 840 841 dev->mclk = 96000 * 1000; 842 } 843 m88ds3103b_dt_write(dev, 0x15, buf[0]); 844 m88ds3103b_dt_write(dev, 0x16, buf[1]); 845 846 regmap_read(dev->regmap, 0x30, &u32tmp); 847 u32tmp &= ~0x80; 848 regmap_write(dev->regmap, 0x30, u32tmp & 0xff); 849 } 850 851 ret = regmap_write(dev->regmap, 0xf1, 0x01); 852 if (ret) 853 goto err; 854 855 if (dev->chiptype != M88DS3103_CHIPTYPE_3103B) { 856 ret = m88ds3103_update_bits(dev, 0x30, 0x80, 0x80); 857 if (ret) 858 goto err; 859 } 860 } 861 862 switch (dev->cfg->ts_mode) { 863 case M88DS3103_TS_SERIAL: 864 u8tmp1 = 0x00; 865 u8tmp = 0x06; 866 break; 867 case M88DS3103_TS_SERIAL_D7: 868 u8tmp1 = 0x20; 869 u8tmp = 0x06; 870 break; 871 case M88DS3103_TS_PARALLEL: 872 u8tmp = 0x02; 873 if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) { 874 u8tmp = 0x01; 875 u8tmp1 = 0x01; 876 } 877 break; 878 case M88DS3103_TS_CI: 879 u8tmp = 0x03; 880 break; 881 default: 882 dev_dbg(&client->dev, "invalid ts_mode\n"); 883 ret = -EINVAL; 884 goto err; 885 } 886 887 if (dev->cfg->ts_clk_pol) 888 u8tmp |= 0x40; 889 890 /* TS mode */ 891 ret = regmap_write(dev->regmap, 0xfd, u8tmp); 892 if (ret) 893 goto err; 894 895 switch (dev->cfg->ts_mode) { 896 case M88DS3103_TS_SERIAL: 897 case M88DS3103_TS_SERIAL_D7: 898 ret = m88ds3103_update_bits(dev, 0x29, 0x20, u8tmp1); 899 if (ret) 900 goto err; 901 u16tmp = 0; 902 u8tmp1 = 0x3f; 903 u8tmp2 = 0x3f; 904 break; 905 case M88DS3103_TS_PARALLEL: > 906 if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) { 907 ret = m88ds3103_update_bits(dev, 0x29, 0x01, u8tmp1); 908 if (ret) 909 goto err; 910 } 911 default: 912 u16tmp = DIV_ROUND_UP(target_mclk, dev->cfg->ts_clk); 913 u8tmp1 = u16tmp / 2 - 1; 914 u8tmp2 = DIV_ROUND_UP(u16tmp, 2) - 1; 915 } 916 917 dev_dbg(&client->dev, "target_mclk=%u ts_clk=%u ts_clk_divide_ratio=%u\n", 918 target_mclk, dev->cfg->ts_clk, u16tmp); 919 920 /* u8tmp1[5:2] => fe[3:0], u8tmp1[1:0] => ea[7:6] */ 921 /* u8tmp2[5:0] => ea[5:0] */ 922 u8tmp = (u8tmp1 >> 2) & 0x0f; 923 ret = regmap_update_bits(dev->regmap, 0xfe, 0x0f, u8tmp); 924 if (ret) 925 goto err; 926 u8tmp = ((u8tmp1 & 0x03) << 6) | u8tmp2 >> 0; 927 ret = regmap_write(dev->regmap, 0xea, u8tmp); 928 if (ret) 929 goto err; 930 931 if (c->symbol_rate <= 3000000) 932 u8tmp = 0x20; 933 else if (c->symbol_rate <= 10000000) 934 u8tmp = 0x10; 935 else 936 u8tmp = 0x06; 937 938 if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) 939 m88ds3103b_set_mclk(dev, target_mclk / 1000); 940 941 ret = regmap_write(dev->regmap, 0xc3, 0x08); 942 if (ret) 943 goto err; 944 945 ret = regmap_write(dev->regmap, 0xc8, u8tmp); 946 if (ret) 947 goto err; 948 949 ret = regmap_write(dev->regmap, 0xc4, 0x08); 950 if (ret) 951 goto err; 952 953 ret = regmap_write(dev->regmap, 0xc7, 0x00); 954 if (ret) 955 goto err; 956 957 u16tmp = DIV_ROUND_CLOSEST_ULL((u64)c->symbol_rate * 0x10000, dev->mclk); 958 buf[0] = (u16tmp >> 0) & 0xff; 959 buf[1] = (u16tmp >> 8) & 0xff; 960 ret = regmap_bulk_write(dev->regmap, 0x61, buf, 2); 961 if (ret) 962 goto err; 963 964 ret = m88ds3103_update_bits(dev, 0x4d, 0x02, dev->cfg->spec_inv << 1); 965 if (ret) 966 goto err; 967 968 ret = m88ds3103_update_bits(dev, 0x30, 0x10, dev->cfg->agc_inv << 4); 969 if (ret) 970 goto err; 971 972 ret = regmap_write(dev->regmap, 0x33, dev->cfg->agc); 973 if (ret) 974 goto err; 975 976 if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) { 977 /* enable/disable 192M LDPC clock */ 978 ret = m88ds3103_update_bits(dev, 0x29, 0x10, 979 (c->delivery_system == SYS_DVBS) ? 0x10 : 0x0); 980 if (ret) 981 goto err; 982 983 ret = m88ds3103_update_bits(dev, 0xc9, 0x08, 0x08); 984 } 985 986 dev_dbg(&client->dev, "carrier offset=%d\n", 987 (tuner_frequency_khz - c->frequency)); 988 989 /* Use 32-bit calc as there is no s64 version of DIV_ROUND_CLOSEST() */ 990 s32tmp = 0x10000 * (tuner_frequency_khz - c->frequency); 991 s32tmp = DIV_ROUND_CLOSEST(s32tmp, dev->mclk / 1000); 992 buf[0] = (s32tmp >> 0) & 0xff; 993 buf[1] = (s32tmp >> 8) & 0xff; 994 ret = regmap_bulk_write(dev->regmap, 0x5e, buf, 2); 995 if (ret) 996 goto err; 997 998 ret = regmap_write(dev->regmap, 0x00, 0x00); 999 if (ret) 1000 goto err; 1001 1002 ret = regmap_write(dev->regmap, 0xb2, 0x00); 1003 if (ret) 1004 goto err; 1005 1006 dev->delivery_system = c->delivery_system; 1007 1008 return 0; 1009 err: 1010 dev_dbg(&client->dev, "failed=%d\n", ret); 1011 return ret; 1012 } 1013 --- 0-DAY kernel test infrastructure Open Source Technology Center https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org Intel Corporation
Hi Brad, Thank you for the patch! Perhaps something to improve: [auto build test WARNING on linuxtv-media/master] [also build test WARNING on v5.5 next-20200203] [if your patch is applied to the wrong git tree, please drop us a note to help improve the system. BTW, we also suggest to use '--base' option to specify the base tree in git format-patch, please see https://stackoverflow.com/a/37406982] url: https://github.com/0day-ci/linux/commits/Brad-Love/m88ds3103-Add-support-for-Montage-3103b-DVB-S-demod/20200203-135639 base: git://linuxtv.org/media_tree.git master config: x86_64-randconfig-d002-20200202 (attached as .config) compiler: gcc-7 (Debian 7.5.0-3) 7.5.0 reproduce: # save the attached .config to linux build tree make ARCH=x86_64 If you fix the issue, kindly add following tag Reported-by: kbuild test robot <lkp@intel.com> All warnings (new ones prefixed by >>): In file included from arch/x86/include/asm/current.h:5:0, from include/linux/sched.h:12, from include/media/dvb_frontend.h:36, from drivers/media/dvb-frontends/m88ds3103_priv.h:11, from drivers/media/dvb-frontends/m88ds3103.c:8: drivers/media/dvb-frontends/m88ds3103.c: In function 'm88ds3103_set_frontend': include/linux/compiler.h:56:26: warning: this statement may fall through [-Wimplicit-fallthrough=] #define if(cond, ...) if ( __trace_if_var( !!(cond , ## __VA_ARGS__) ) ) ^ >> drivers/media/dvb-frontends/m88ds3103.c:906:3: note: in expansion of macro 'if' if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) { ^~ drivers/media/dvb-frontends/m88ds3103.c:911:2: note: here default: ^~~~~~~ Cyclomatic Complexity 1 arch/x86/include/asm/bitops.h:fls64 Cyclomatic Complexity 1 include/linux/log2.h:__ilog2_u64 Cyclomatic Complexity 1 include/linux/math64.h:div_u64_rem Cyclomatic Complexity 1 include/linux/math64.h:div_s64_rem Cyclomatic Complexity 1 include/linux/math64.h:div_u64 Cyclomatic Complexity 1 include/linux/math64.h:div_s64 Cyclomatic Complexity 1 include/linux/err.h:PTR_ERR Cyclomatic Complexity 1 include/linux/jiffies.h:_msecs_to_jiffies Cyclomatic Complexity 7 include/linux/jiffies.h:msecs_to_jiffies Cyclomatic Complexity 4 include/linux/slab.h:kmalloc_type Cyclomatic Complexity 84 include/linux/slab.h:kmalloc_index Cyclomatic Complexity 1 include/linux/slab.h:kmalloc_large Cyclomatic Complexity 10 include/linux/slab.h:kmalloc Cyclomatic Complexity 1 include/linux/slab.h:kzalloc Cyclomatic Complexity 1 include/linux/device.h:dev_get_drvdata Cyclomatic Complexity 1 include/linux/device.h:dev_set_drvdata Cyclomatic Complexity 1 include/linux/i2c.h:i2c_get_clientdata Cyclomatic Complexity 1 include/linux/i2c.h:i2c_set_clientdata Cyclomatic Complexity 1 include/linux/i2c-mux.h:i2c_mux_priv Cyclomatic Complexity 1 drivers/media/dvb-frontends/m88ds3103.c:m88ds3103_read_ber Cyclomatic Complexity 1 drivers/media/dvb-frontends/m88ds3103.c:m88ds3103_get_tune_settings Cyclomatic Complexity 1 drivers/media/dvb-frontends/m88ds3103.c:m88ds3103_get_dvb_frontend Cyclomatic Complexity 1 drivers/media/dvb-frontends/m88ds3103.c:m88ds3103_get_i2c_adapter Cyclomatic Complexity 4 drivers/media/dvb-frontends/m88ds3103.c:m88ds3103_get_agc_pwm Cyclomatic Complexity 4 drivers/media/dvb-frontends/m88ds3103.c:m88ds3103_read_snr Cyclomatic Complexity 74 include/asm-generic/getorder.h:get_order Cyclomatic Complexity 3 include/linux/err.h:IS_ERR_OR_NULL Cyclomatic Complexity 3 include/linux/i2c.h:i2c_client_has_driver Cyclomatic Complexity 3 drivers/media/dvb-frontends/m88ds3103.c:m88ds3103_attach Cyclomatic Complexity 1 include/linux/err.h:IS_ERR Cyclomatic Complexity 1 drivers/media/dvb-frontends/m88ds3103.c:m88ds3103_driver_init Cyclomatic Complexity 1 drivers/media/dvb-frontends/m88ds3103.c:m88ds3103_release Cyclomatic Complexity 4 drivers/media/dvb-frontends/m88ds3103.c:m88ds3103_remove Cyclomatic Complexity 19 drivers/media/dvb-frontends/m88ds3103.c:m88ds3103_wr_reg_val_tab Cyclomatic Complexity 56 drivers/media/dvb-frontends/m88ds3103.c:m88ds3103_get_frontend Cyclomatic Complexity 7 drivers/media/dvb-frontends/m88ds3103.c:m88ds3103_update_bits Cyclomatic Complexity 56 drivers/media/dvb-frontends/m88ds3103.c:m88ds3103_probe Cyclomatic Complexity 10 drivers/media/dvb-frontends/m88ds3103.c:m88ds3103_set_voltage Cyclomatic Complexity 12 drivers/media/dvb-frontends/m88ds3103.c:m88ds3103_set_tone Cyclomatic Complexity 31 drivers/media/dvb-frontends/m88ds3103.c:m88ds3103_diseqc_send_burst Cyclomatic Complexity 35 drivers/media/dvb-frontends/m88ds3103.c:m88ds3103_diseqc_send_master_cmd Cyclomatic Complexity 16 drivers/media/dvb-frontends/m88ds3103.c:m88ds3103_sleep Cyclomatic Complexity 82 drivers/media/dvb-frontends/m88ds3103.c:m88ds3103_read_status Cyclomatic Complexity 6 drivers/media/dvb-frontends/m88ds3103.c:m88ds3103b_dt_read Cyclomatic Complexity 6 drivers/media/dvb-frontends/m88ds3103.c:m88ds3103b_dt_write Cyclomatic Complexity 30 drivers/media/dvb-frontends/m88ds3103.c:m88ds3103b_select_mclk Cyclomatic Complexity 79 drivers/media/dvb-frontends/m88ds3103.c:m88ds3103b_set_mclk Cyclomatic Complexity 210 drivers/media/dvb-frontends/m88ds3103.c:m88ds3103_set_frontend Cyclomatic Complexity 50 drivers/media/dvb-frontends/m88ds3103.c:m88ds3103_init Cyclomatic Complexity 7 drivers/media/dvb-frontends/m88ds3103.c:m88ds3103_select Cyclomatic Complexity 1 drivers/media/dvb-frontends/m88ds3103.c:m88ds3103_driver_exit vim +/if +906 drivers/media/dvb-frontends/m88ds3103.c 623 624 static int m88ds3103_set_frontend(struct dvb_frontend *fe) 625 { 626 struct m88ds3103_dev *dev = fe->demodulator_priv; 627 struct i2c_client *client = dev->client; 628 struct dtv_frontend_properties *c = &fe->dtv_property_cache; 629 int ret, len; 630 const struct m88ds3103_reg_val *init; 631 u8 u8tmp, u8tmp1 = 0, u8tmp2 = 0; /* silence compiler warning */ 632 u8 buf[3]; 633 u16 u16tmp; 634 u32 tuner_frequency_khz, target_mclk, u32tmp; 635 s32 s32tmp; 636 static const struct reg_sequence reset_buf[] = { 637 {0x07, 0x80}, {0x07, 0x00} 638 }; 639 640 dev_dbg(&client->dev, 641 "delivery_system=%d modulation=%d frequency=%u symbol_rate=%d inversion=%d pilot=%d rolloff=%d\n", 642 c->delivery_system, c->modulation, c->frequency, c->symbol_rate, 643 c->inversion, c->pilot, c->rolloff); 644 645 if (!dev->warm) { 646 ret = -EAGAIN; 647 goto err; 648 } 649 650 /* reset */ 651 ret = regmap_multi_reg_write(dev->regmap, reset_buf, 2); 652 if (ret) 653 goto err; 654 655 /* Disable demod clock path */ 656 if (dev->chip_id == M88RS6000_CHIP_ID) { 657 if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) { 658 ret = regmap_read(dev->regmap, 0xb2, &u32tmp); 659 if (ret) 660 goto err; 661 if (u32tmp == 0x01) { 662 ret = regmap_write(dev->regmap, 0x00, 0x00); 663 if (ret) 664 goto err; 665 ret = regmap_write(dev->regmap, 0xb2, 0x00); 666 if (ret) 667 goto err; 668 } 669 } 670 671 ret = regmap_write(dev->regmap, 0x06, 0xe0); 672 if (ret) 673 goto err; 674 } 675 676 /* program tuner */ 677 if (fe->ops.tuner_ops.set_params) { 678 ret = fe->ops.tuner_ops.set_params(fe); 679 if (ret) 680 goto err; 681 } 682 683 if (fe->ops.tuner_ops.get_frequency) { 684 ret = fe->ops.tuner_ops.get_frequency(fe, &tuner_frequency_khz); 685 if (ret) 686 goto err; 687 } else { 688 /* 689 * Use nominal target frequency as tuner driver does not provide 690 * actual frequency used. Carrier offset calculation is not 691 * valid. 692 */ 693 tuner_frequency_khz = c->frequency; 694 } 695 696 /* set M88RS6000/DS3103B demod main mclk and ts mclk from tuner die */ 697 if (dev->chip_id == M88RS6000_CHIP_ID) { 698 if (c->symbol_rate > 45010000) 699 dev->mclk = 110250000; 700 else 701 dev->mclk = 96000000; 702 703 if (c->delivery_system == SYS_DVBS) 704 target_mclk = 96000000; 705 else 706 target_mclk = 144000000; 707 708 if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) { 709 m88ds3103b_select_mclk(dev); 710 m88ds3103b_set_mclk(dev, target_mclk / 1000); 711 } 712 713 /* Enable demod clock path */ 714 ret = regmap_write(dev->regmap, 0x06, 0x00); 715 if (ret) 716 goto err; 717 usleep_range(10000, 20000); 718 } else { 719 /* set M88DS3103 mclk and ts mclk. */ 720 dev->mclk = 96000000; 721 722 switch (dev->cfg->ts_mode) { 723 case M88DS3103_TS_SERIAL: 724 case M88DS3103_TS_SERIAL_D7: 725 target_mclk = dev->cfg->ts_clk; 726 break; 727 case M88DS3103_TS_PARALLEL: 728 case M88DS3103_TS_CI: 729 if (c->delivery_system == SYS_DVBS) 730 target_mclk = 96000000; 731 else { 732 if (c->symbol_rate < 18000000) 733 target_mclk = 96000000; 734 else if (c->symbol_rate < 28000000) 735 target_mclk = 144000000; 736 else 737 target_mclk = 192000000; 738 } 739 break; 740 default: 741 dev_dbg(&client->dev, "invalid ts_mode\n"); 742 ret = -EINVAL; 743 goto err; 744 } 745 746 switch (target_mclk) { 747 case 96000000: 748 u8tmp1 = 0x02; /* 0b10 */ 749 u8tmp2 = 0x01; /* 0b01 */ 750 break; 751 case 144000000: 752 u8tmp1 = 0x00; /* 0b00 */ 753 u8tmp2 = 0x01; /* 0b01 */ 754 break; 755 case 192000000: 756 u8tmp1 = 0x03; /* 0b11 */ 757 u8tmp2 = 0x00; /* 0b00 */ 758 break; 759 } 760 ret = m88ds3103_update_bits(dev, 0x22, 0xc0, u8tmp1 << 6); 761 if (ret) 762 goto err; 763 ret = m88ds3103_update_bits(dev, 0x24, 0xc0, u8tmp2 << 6); 764 if (ret) 765 goto err; 766 } 767 768 ret = regmap_write(dev->regmap, 0xb2, 0x01); 769 if (ret) 770 goto err; 771 772 ret = regmap_write(dev->regmap, 0x00, 0x01); 773 if (ret) 774 goto err; 775 776 switch (c->delivery_system) { 777 case SYS_DVBS: 778 if (dev->chip_id == M88RS6000_CHIP_ID) { 779 len = ARRAY_SIZE(m88rs6000_dvbs_init_reg_vals); 780 init = m88rs6000_dvbs_init_reg_vals; 781 } else { 782 len = ARRAY_SIZE(m88ds3103_dvbs_init_reg_vals); 783 init = m88ds3103_dvbs_init_reg_vals; 784 } 785 break; 786 case SYS_DVBS2: 787 if (dev->chip_id == M88RS6000_CHIP_ID) { 788 len = ARRAY_SIZE(m88rs6000_dvbs2_init_reg_vals); 789 init = m88rs6000_dvbs2_init_reg_vals; 790 } else { 791 len = ARRAY_SIZE(m88ds3103_dvbs2_init_reg_vals); 792 init = m88ds3103_dvbs2_init_reg_vals; 793 } 794 break; 795 default: 796 dev_dbg(&client->dev, "invalid delivery_system\n"); 797 ret = -EINVAL; 798 goto err; 799 } 800 801 /* program init table */ 802 if (c->delivery_system != dev->delivery_system) { 803 ret = m88ds3103_wr_reg_val_tab(dev, init, len); 804 if (ret) 805 goto err; 806 } 807 808 if (dev->chip_id == M88RS6000_CHIP_ID) { 809 if (c->delivery_system == SYS_DVBS2 && 810 c->symbol_rate <= 5000000) { 811 ret = regmap_write(dev->regmap, 0xc0, 0x04); 812 if (ret) 813 goto err; 814 buf[0] = 0x09; 815 buf[1] = 0x22; 816 buf[2] = 0x88; 817 ret = regmap_bulk_write(dev->regmap, 0x8a, buf, 3); 818 if (ret) 819 goto err; 820 } 821 ret = m88ds3103_update_bits(dev, 0x9d, 0x08, 0x08); 822 if (ret) 823 goto err; 824 825 if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) { 826 buf[0] = m88ds3103b_dt_read(dev, 0x15); 827 buf[1] = m88ds3103b_dt_read(dev, 0x16); 828 829 if (c->symbol_rate > 45010000) { 830 buf[0] &= ~0x03; 831 buf[0] |= 0x02; 832 buf[0] |= ((147 - 32) >> 8) & 0x01; 833 buf[1] = (147 - 32) & 0xFF; 834 835 dev->mclk = 110250 * 1000; 836 } else { 837 buf[0] &= ~0x03; 838 buf[0] |= ((128 - 32) >> 8) & 0x01; 839 buf[1] = (128 - 32) & 0xFF; 840 841 dev->mclk = 96000 * 1000; 842 } 843 m88ds3103b_dt_write(dev, 0x15, buf[0]); 844 m88ds3103b_dt_write(dev, 0x16, buf[1]); 845 846 regmap_read(dev->regmap, 0x30, &u32tmp); 847 u32tmp &= ~0x80; 848 regmap_write(dev->regmap, 0x30, u32tmp & 0xff); 849 } 850 851 ret = regmap_write(dev->regmap, 0xf1, 0x01); 852 if (ret) 853 goto err; 854 855 if (dev->chiptype != M88DS3103_CHIPTYPE_3103B) { 856 ret = m88ds3103_update_bits(dev, 0x30, 0x80, 0x80); 857 if (ret) 858 goto err; 859 } 860 } 861 862 switch (dev->cfg->ts_mode) { 863 case M88DS3103_TS_SERIAL: 864 u8tmp1 = 0x00; 865 u8tmp = 0x06; 866 break; 867 case M88DS3103_TS_SERIAL_D7: 868 u8tmp1 = 0x20; 869 u8tmp = 0x06; 870 break; 871 case M88DS3103_TS_PARALLEL: 872 u8tmp = 0x02; 873 if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) { 874 u8tmp = 0x01; 875 u8tmp1 = 0x01; 876 } 877 break; 878 case M88DS3103_TS_CI: 879 u8tmp = 0x03; 880 break; 881 default: 882 dev_dbg(&client->dev, "invalid ts_mode\n"); 883 ret = -EINVAL; 884 goto err; 885 } 886 887 if (dev->cfg->ts_clk_pol) 888 u8tmp |= 0x40; 889 890 /* TS mode */ 891 ret = regmap_write(dev->regmap, 0xfd, u8tmp); 892 if (ret) 893 goto err; 894 895 switch (dev->cfg->ts_mode) { 896 case M88DS3103_TS_SERIAL: 897 case M88DS3103_TS_SERIAL_D7: 898 ret = m88ds3103_update_bits(dev, 0x29, 0x20, u8tmp1); 899 if (ret) 900 goto err; 901 u16tmp = 0; 902 u8tmp1 = 0x3f; 903 u8tmp2 = 0x3f; 904 break; 905 case M88DS3103_TS_PARALLEL: > 906 if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) { 907 ret = m88ds3103_update_bits(dev, 0x29, 0x01, u8tmp1); 908 if (ret) 909 goto err; 910 } 911 default: 912 u16tmp = DIV_ROUND_UP(target_mclk, dev->cfg->ts_clk); 913 u8tmp1 = u16tmp / 2 - 1; 914 u8tmp2 = DIV_ROUND_UP(u16tmp, 2) - 1; 915 } 916 917 dev_dbg(&client->dev, "target_mclk=%u ts_clk=%u ts_clk_divide_ratio=%u\n", 918 target_mclk, dev->cfg->ts_clk, u16tmp); 919 920 /* u8tmp1[5:2] => fe[3:0], u8tmp1[1:0] => ea[7:6] */ 921 /* u8tmp2[5:0] => ea[5:0] */ 922 u8tmp = (u8tmp1 >> 2) & 0x0f; 923 ret = regmap_update_bits(dev->regmap, 0xfe, 0x0f, u8tmp); 924 if (ret) 925 goto err; 926 u8tmp = ((u8tmp1 & 0x03) << 6) | u8tmp2 >> 0; 927 ret = regmap_write(dev->regmap, 0xea, u8tmp); 928 if (ret) 929 goto err; 930 931 if (c->symbol_rate <= 3000000) 932 u8tmp = 0x20; 933 else if (c->symbol_rate <= 10000000) 934 u8tmp = 0x10; 935 else 936 u8tmp = 0x06; 937 938 if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) 939 m88ds3103b_set_mclk(dev, target_mclk / 1000); 940 941 ret = regmap_write(dev->regmap, 0xc3, 0x08); 942 if (ret) 943 goto err; 944 945 ret = regmap_write(dev->regmap, 0xc8, u8tmp); 946 if (ret) 947 goto err; 948 949 ret = regmap_write(dev->regmap, 0xc4, 0x08); 950 if (ret) 951 goto err; 952 953 ret = regmap_write(dev->regmap, 0xc7, 0x00); 954 if (ret) 955 goto err; 956 957 u16tmp = DIV_ROUND_CLOSEST_ULL((u64)c->symbol_rate * 0x10000, dev->mclk); 958 buf[0] = (u16tmp >> 0) & 0xff; 959 buf[1] = (u16tmp >> 8) & 0xff; 960 ret = regmap_bulk_write(dev->regmap, 0x61, buf, 2); 961 if (ret) 962 goto err; 963 964 ret = m88ds3103_update_bits(dev, 0x4d, 0x02, dev->cfg->spec_inv << 1); 965 if (ret) 966 goto err; 967 968 ret = m88ds3103_update_bits(dev, 0x30, 0x10, dev->cfg->agc_inv << 4); 969 if (ret) 970 goto err; 971 972 ret = regmap_write(dev->regmap, 0x33, dev->cfg->agc); 973 if (ret) 974 goto err; 975 976 if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) { 977 /* enable/disable 192M LDPC clock */ 978 ret = m88ds3103_update_bits(dev, 0x29, 0x10, 979 (c->delivery_system == SYS_DVBS) ? 0x10 : 0x0); 980 if (ret) 981 goto err; 982 983 ret = m88ds3103_update_bits(dev, 0xc9, 0x08, 0x08); 984 } 985 986 dev_dbg(&client->dev, "carrier offset=%d\n", 987 (tuner_frequency_khz - c->frequency)); 988 989 /* Use 32-bit calc as there is no s64 version of DIV_ROUND_CLOSEST() */ 990 s32tmp = 0x10000 * (tuner_frequency_khz - c->frequency); 991 s32tmp = DIV_ROUND_CLOSEST(s32tmp, dev->mclk / 1000); 992 buf[0] = (s32tmp >> 0) & 0xff; 993 buf[1] = (s32tmp >> 8) & 0xff; 994 ret = regmap_bulk_write(dev->regmap, 0x5e, buf, 2); 995 if (ret) 996 goto err; 997 998 ret = regmap_write(dev->regmap, 0x00, 0x00); 999 if (ret) 1000 goto err; 1001 1002 ret = regmap_write(dev->regmap, 0xb2, 0x00); 1003 if (ret) 1004 goto err; 1005 1006 dev->delivery_system = c->delivery_system; 1007 1008 return 0; 1009 err: 1010 dev_dbg(&client->dev, "failed=%d\n", ret); 1011 return ret; 1012 } 1013 --- 0-DAY kernel test infrastructure Open Source Technology Center https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org Intel Corporation
diff --git a/drivers/media/dvb-frontends/m88ds3103.c b/drivers/media/dvb-frontends/m88ds3103.c index c96f05ff5f2f..baf21b999ccc 100644 --- a/drivers/media/dvb-frontends/m88ds3103.c +++ b/drivers/media/dvb-frontends/m88ds3103.c @@ -64,6 +64,92 @@ static int m88ds3103_wr_reg_val_tab(struct m88ds3103_dev *dev, return ret; } +/* + * m88ds3103b demod has an internal device related to clocking. First the i2c + * gate must be opened, for one transaction, then writes will be allowed. + */ +static int m88ds3103b_dt_write(struct m88ds3103_dev *dev, int reg, int data) +{ + struct i2c_client *client = dev->client; + u8 buf[] = {reg, data}; + u8 val; + int ret; + struct i2c_msg msg = { + .addr = dev->dt_addr, .flags = 0, .buf = buf, .len = 2 + }; + + m88ds3103_update_bits(dev, 0x11, 0x01, 0x00); + + val = 0x11; + ret = regmap_write(dev->regmap, 0x03, val); + if (ret) + dev_dbg(&client->dev, "fail=%d\n", ret); + + ret = i2c_transfer(dev->dt_client->adapter, &msg, 1); + if (ret != 1) { + dev_err(&client->dev, "0x%02x (ret=%i, reg=0x%02x, value=0x%02x)\n", + dev->dt_addr, ret, reg, data); + + m88ds3103_update_bits(dev, 0x11, 0x01, 0x01); + return -EREMOTEIO; + } + m88ds3103_update_bits(dev, 0x11, 0x01, 0x01); + + dev_dbg(&client->dev, "0x%02x reg 0x%02x, value 0x%02x\n", + dev->dt_addr, reg, data); + + return 0; +} + +/* + * m88ds3103b demod has an internal device related to clocking. First the i2c + * gate must be opened, for two transactions, then reads will be allowed. + */ +static int m88ds3103b_dt_read(struct m88ds3103_dev *dev, u8 reg) +{ + struct i2c_client *client = dev->client; + int ret; + u8 val; + u8 b0[] = { reg }; + u8 b1[] = { 0 }; + struct i2c_msg msg[] = { + { + .addr = dev->dt_addr, + .flags = 0, + .buf = b0, + .len = 1 + }, + { + .addr = dev->dt_addr, + .flags = I2C_M_RD, + .buf = b1, + .len = 1 + } + }; + + m88ds3103_update_bits(dev, 0x11, 0x01, 0x00); + + val = 0x12; + ret = regmap_write(dev->regmap, 0x03, val); + if (ret) + dev_dbg(&client->dev, "fail=%d\n", ret); + + ret = i2c_transfer(dev->dt_client->adapter, msg, 2); + if (ret != 2) { + dev_err(&client->dev, "0x%02x (ret=%d, reg=0x%02x)\n", + dev->dt_addr, ret, reg); + + m88ds3103_update_bits(dev, 0x11, 0x01, 0x01); + return -EREMOTEIO; + } + m88ds3103_update_bits(dev, 0x11, 0x01, 0x01); + + dev_dbg(&client->dev, "0x%02x reg 0x%02x, value 0x%02x\n", + dev->dt_addr, reg, b1[0]); + + return b1[0]; +} + /* * Get the demodulator AGC PWM voltage setting supplied to the tuner. */ @@ -288,6 +374,253 @@ static int m88ds3103_read_status(struct dvb_frontend *fe, return ret; } +static int m88ds3103b_select_mclk(struct m88ds3103_dev *dev) +{ + struct i2c_client *client = dev->client; + struct dtv_frontend_properties *c = &dev->fe.dtv_property_cache; + u32 adc_Freq_MHz[3] = {96, 93, 99}; + u8 reg16_list[3] = {96, 92, 100}, reg16, reg15; + u32 offset_MHz[3]; + u32 max_offset = 0; + u32 old_setting = dev->mclk; + u32 tuner_freq_MHz = c->frequency / 1000; + u8 i; + char big_symbol = 0; + + big_symbol = (c->symbol_rate > 45010000) ? 1 : 0; + + if (big_symbol) { + reg16 = 115; + } else { + reg16 = 96; + + /* TODO: IS THIS NECESSARY ? */ + for (i = 0; i < 3; i++) { + offset_MHz[i] = tuner_freq_MHz % adc_Freq_MHz[i]; + + if (offset_MHz[i] > (adc_Freq_MHz[i] / 2)) + offset_MHz[i] = adc_Freq_MHz[i] - offset_MHz[i]; + + if (offset_MHz[i] > max_offset) { + max_offset = offset_MHz[i]; + reg16 = reg16_list[i]; + dev->mclk = adc_Freq_MHz[i] * 1000 * 1000; + + if (big_symbol) + dev->mclk /= 2; + + dev_dbg(&client->dev, "modifying mclk %u -> %u\n", + old_setting, dev->mclk); + } + } + } + + if (dev->mclk == 93000000) + regmap_write(dev->regmap, 0xA0, 0x42); + else if (dev->mclk == 96000000) + regmap_write(dev->regmap, 0xA0, 0x44); + else if (dev->mclk == 99000000) + regmap_write(dev->regmap, 0xA0, 0x46); + else if (dev->mclk == 110250000) + regmap_write(dev->regmap, 0xA0, 0x4E); + else + regmap_write(dev->regmap, 0xA0, 0x44); + + reg15 = m88ds3103b_dt_read(dev, 0x15); + + m88ds3103b_dt_write(dev, 0x05, 0x40); + m88ds3103b_dt_write(dev, 0x11, 0x08); + + if (big_symbol) + reg15 |= 0x02; + else + reg15 &= ~0x02; + + m88ds3103b_dt_write(dev, 0x15, reg15); + m88ds3103b_dt_write(dev, 0x16, reg16); + + usleep_range(5000, 5500); + + m88ds3103b_dt_write(dev, 0x05, 0x00); + m88ds3103b_dt_write(dev, 0x11, (u8)(big_symbol ? 0x0E : 0x0A)); + + usleep_range(5000, 5500); + + return 0; +} + +static int m88ds3103b_set_mclk(struct m88ds3103_dev *dev, u32 mclk_khz) +{ + u8 reg11 = 0x0A, reg15, reg16, reg1D, reg1E, reg1F, tmp; + u8 sm, f0 = 0, f1 = 0, f2 = 0, f3 = 0, pll_ldpc_mode; + u16 pll_div_fb, N; + u32 div; + + reg15 = m88ds3103b_dt_read(dev, 0x15); + reg16 = m88ds3103b_dt_read(dev, 0x16); + reg1D = m88ds3103b_dt_read(dev, 0x1D); + + if (dev->cfg->ts_mode != M88DS3103_TS_SERIAL) { + if (reg16 == 92) + tmp = 93; + else if (reg16 == 100) + tmp = 99; + else + tmp = 96; + + mclk_khz *= tmp; + mclk_khz /= 96; + } + + pll_ldpc_mode = (reg15 >> 1) & 0x01; + + pll_div_fb = (reg15 & 0x01) << 8; + pll_div_fb += reg16; + pll_div_fb += 32; + + div = 9000 * pll_div_fb * 4; + div /= mclk_khz; + + if (dev->cfg->ts_mode == M88DS3103_TS_SERIAL) { + reg11 |= 0x02; + + if (div <= 32) { + N = 2; + + f0 = 0; + f1 = div / N; + f2 = div - f1; + f3 = 0; + } else if (div <= 34) { + N = 3; + + f0 = div / N; + f1 = (div - f0) / (N - 1); + f2 = div - f0 - f1; + f3 = 0; + } else if (div <= 64) { + N = 4; + + f0 = div / N; + f1 = (div - f0) / (N - 1); + f2 = (div - f0 - f1) / (N - 2); + f3 = div - f0 - f1 - f2; + } else { + N = 4; + + f0 = 16; + f1 = 16; + f2 = 16; + f3 = 16; + } + + if (f0 == 16) + f0 = 0; + else if ((f0 < 8) && (f0 != 0)) + f0 = 8; + + if (f1 == 16) + f1 = 0; + else if ((f1 < 8) && (f1 != 0)) + f1 = 8; + + if (f2 == 16) + f2 = 0; + else if ((f2 < 8) && (f2 != 0)) + f2 = 8; + + if (f3 == 16) + f3 = 0; + else if ((f3 < 8) && (f3 != 0)) + f3 = 8; + } else { + reg11 &= ~0x02; + + if (div <= 32) { + N = 2; + + f0 = 0; + f1 = div / N; + f2 = div - f1; + f3 = 0; + } else if (div <= 48) { + N = 3; + + f0 = div / N; + f1 = (div - f0) / (N - 1); + f2 = div - f0 - f1; + f3 = 0; + } else if (div <= 64) { + N = 4; + + f0 = div / N; + f1 = (div - f0) / (N - 1); + f2 = (div - f0 - f1) / (N - 2); + f3 = div - f0 - f1 - f2; + } else { + N = 4; + + f0 = 16; + f1 = 16; + f2 = 16; + f3 = 16; + } + + if (f0 == 16) + f0 = 0; + else if ((f0 < 9) && (f0 != 0)) + f0 = 9; + + if (f1 == 16) + f1 = 0; + else if ((f1 < 9) && (f1 != 0)) + f1 = 9; + + if (f2 == 16) + f2 = 0; + else if ((f2 < 9) && (f2 != 0)) + f2 = 9; + + if (f3 == 16) + f3 = 0; + else if ((f3 < 9) && (f3 != 0)) + f3 = 9; + } + + sm = N - 1; + + /* Write to registers */ + //reg15 &= 0x01; + //reg15 |= (pll_div_fb >> 8) & 0x01; + + //reg16 = pll_div_fb & 0xFF; + + reg1D &= ~0x03; + reg1D |= sm; + reg1D |= 0x80; + + reg1E = ((f3 << 4) + f2) & 0xFF; + reg1F = ((f1 << 4) + f0) & 0xFF; + + m88ds3103b_dt_write(dev, 0x05, 0x40); + m88ds3103b_dt_write(dev, 0x11, 0x08); + m88ds3103b_dt_write(dev, 0x1D, reg1D); + m88ds3103b_dt_write(dev, 0x1E, reg1E); + m88ds3103b_dt_write(dev, 0x1F, reg1F); + + m88ds3103b_dt_write(dev, 0x17, 0xc1); + m88ds3103b_dt_write(dev, 0x17, 0x81); + + usleep_range(5000, 5500); + + m88ds3103b_dt_write(dev, 0x05, 0x00); + m88ds3103b_dt_write(dev, 0x11, 0x0A); + + usleep_range(5000, 5500); + + return 0; +} + static int m88ds3103_set_frontend(struct dvb_frontend *fe) { struct m88ds3103_dev *dev = fe->demodulator_priv; @@ -298,7 +631,7 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe) u8 u8tmp, u8tmp1 = 0, u8tmp2 = 0; /* silence compiler warning */ u8 buf[3]; u16 u16tmp; - u32 tuner_frequency_khz, target_mclk; + u32 tuner_frequency_khz, target_mclk, u32tmp; s32 s32tmp; static const struct reg_sequence reset_buf[] = { {0x07, 0x80}, {0x07, 0x00} @@ -321,6 +654,20 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe) /* Disable demod clock path */ if (dev->chip_id == M88RS6000_CHIP_ID) { + if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) { + ret = regmap_read(dev->regmap, 0xb2, &u32tmp); + if (ret) + goto err; + if (u32tmp == 0x01) { + ret = regmap_write(dev->regmap, 0x00, 0x00); + if (ret) + goto err; + ret = regmap_write(dev->regmap, 0xb2, 0x00); + if (ret) + goto err; + } + } + ret = regmap_write(dev->regmap, 0x06, 0xe0); if (ret) goto err; @@ -346,7 +693,7 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe) tuner_frequency_khz = c->frequency; } - /* select M88RS6000 demod main mclk and ts mclk from tuner die. */ + /* set M88RS6000/DS3103B demod main mclk and ts mclk from tuner die */ if (dev->chip_id == M88RS6000_CHIP_ID) { if (c->symbol_rate > 45010000) dev->mclk = 110250000; @@ -358,6 +705,11 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe) else target_mclk = 144000000; + if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) { + m88ds3103b_select_mclk(dev); + m88ds3103b_set_mclk(dev, target_mclk / 1000); + } + /* Enable demod clock path */ ret = regmap_write(dev->regmap, 0x06, 0x00); if (ret) @@ -469,12 +821,42 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe) ret = m88ds3103_update_bits(dev, 0x9d, 0x08, 0x08); if (ret) goto err; + + if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) { + buf[0] = m88ds3103b_dt_read(dev, 0x15); + buf[1] = m88ds3103b_dt_read(dev, 0x16); + + if (c->symbol_rate > 45010000) { + buf[0] &= ~0x03; + buf[0] |= 0x02; + buf[0] |= ((147 - 32) >> 8) & 0x01; + buf[1] = (147 - 32) & 0xFF; + + dev->mclk = 110250 * 1000; + } else { + buf[0] &= ~0x03; + buf[0] |= ((128 - 32) >> 8) & 0x01; + buf[1] = (128 - 32) & 0xFF; + + dev->mclk = 96000 * 1000; + } + m88ds3103b_dt_write(dev, 0x15, buf[0]); + m88ds3103b_dt_write(dev, 0x16, buf[1]); + + regmap_read(dev->regmap, 0x30, &u32tmp); + u32tmp &= ~0x80; + regmap_write(dev->regmap, 0x30, u32tmp & 0xff); + } + ret = regmap_write(dev->regmap, 0xf1, 0x01); if (ret) goto err; - ret = m88ds3103_update_bits(dev, 0x30, 0x80, 0x80); - if (ret) - goto err; + + if (dev->chiptype != M88DS3103_CHIPTYPE_3103B) { + ret = m88ds3103_update_bits(dev, 0x30, 0x80, 0x80); + if (ret) + goto err; + } } switch (dev->cfg->ts_mode) { @@ -488,6 +870,10 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe) break; case M88DS3103_TS_PARALLEL: u8tmp = 0x02; + if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) { + u8tmp = 0x01; + u8tmp1 = 0x01; + } break; case M88DS3103_TS_CI: u8tmp = 0x03; @@ -516,6 +902,12 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe) u8tmp1 = 0x3f; u8tmp2 = 0x3f; break; + case M88DS3103_TS_PARALLEL: + if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) { + ret = m88ds3103_update_bits(dev, 0x29, 0x01, u8tmp1); + if (ret) + goto err; + } default: u16tmp = DIV_ROUND_UP(target_mclk, dev->cfg->ts_clk); u8tmp1 = u16tmp / 2 - 1; @@ -543,6 +935,9 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe) else u8tmp = 0x06; + if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) + m88ds3103b_set_mclk(dev, target_mclk / 1000); + ret = regmap_write(dev->regmap, 0xc3, 0x08); if (ret) goto err; @@ -578,6 +973,16 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe) if (ret) goto err; + if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) { + /* enable/disable 192M LDPC clock */ + ret = m88ds3103_update_bits(dev, 0x29, 0x10, + (c->delivery_system == SYS_DVBS) ? 0x10 : 0x0); + if (ret) + goto err; + + ret = m88ds3103_update_bits(dev, 0xc9, 0x08, 0x08); + } + dev_dbg(&client->dev, "carrier offset=%d\n", (tuner_frequency_khz - c->frequency)); @@ -642,7 +1047,7 @@ static int m88ds3103_init(struct dvb_frontend *fe) if (utmp) goto warm; - /* global reset, global diseqc reset, golbal fec reset */ + /* global reset, global diseqc reset, global fec reset */ ret = regmap_write(dev->regmap, 0x07, 0xe0); if (ret) goto err; @@ -652,12 +1057,15 @@ static int m88ds3103_init(struct dvb_frontend *fe) /* cold state - try to download firmware */ dev_info(&client->dev, "found a '%s' in cold state\n", - m88ds3103_ops.info.name); + dev->fe.ops.info.name); - if (dev->chip_id == M88RS6000_CHIP_ID) + if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) + name = M88DS3103B_FIRMWARE; + else if (dev->chip_id == M88RS6000_CHIP_ID) name = M88RS6000_FIRMWARE; else name = M88DS3103_FIRMWARE; + /* request the firmware, this will block and timeout */ ret = request_firmware(&firmware, name, &client->dev); if (ret) { @@ -700,10 +1108,16 @@ static int m88ds3103_init(struct dvb_frontend *fe) } dev_info(&client->dev, "found a '%s' in warm state\n", - m88ds3103_ops.info.name); + dev->fe.ops.info.name); dev_info(&client->dev, "firmware version: %X.%X\n", (utmp >> 4) & 0xf, (utmp >> 0 & 0xf)); + if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) { + m88ds3103b_dt_write(dev, 0x21, 0x92); + m88ds3103b_dt_write(dev, 0x15, 0x6C); + m88ds3103b_dt_write(dev, 0x17, 0xC1); + m88ds3103b_dt_write(dev, 0x17, 0x81); + } warm: /* warm state */ dev->warm = true; @@ -1393,6 +1807,8 @@ static int m88ds3103_probe(struct i2c_client *client, goto err_kfree; dev->chip_id = utmp >> 1; + dev->chiptype = (u8)id->driver_data; + dev_dbg(&client->dev, "chip_id=%02x\n", dev->chip_id); switch (dev->chip_id) { @@ -1459,7 +1875,10 @@ static int m88ds3103_probe(struct i2c_client *client, /* create dvb_frontend */ memcpy(&dev->fe.ops, &m88ds3103_ops, sizeof(struct dvb_frontend_ops)); - if (dev->chip_id == M88RS6000_CHIP_ID) + if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) + strscpy(dev->fe.ops.info.name, "Montage Technology M88DS3103B", + sizeof(dev->fe.ops.info.name)); + else if (dev->chip_id == M88RS6000_CHIP_ID) strscpy(dev->fe.ops.info.name, "Montage Technology M88RS6000", sizeof(dev->fe.ops.info.name)); if (!pdata->attach_in_use) @@ -1470,6 +1889,25 @@ static int m88ds3103_probe(struct i2c_client *client, /* setup callbacks */ pdata->get_dvb_frontend = m88ds3103_get_dvb_frontend; pdata->get_i2c_adapter = m88ds3103_get_i2c_adapter; + + if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) { + /* enable i2c repeater for tuner */ + m88ds3103_update_bits(dev, 0x11, 0x01, 0x01); + + /* get frontend address */ + ret = regmap_read(dev->regmap, 0x29, &utmp); + if (ret) + goto err_kfree; + dev->dt_addr = ((utmp & 0x80) == 0) ? 0x42 >> 1 : 0x40 >> 1; + dev_err(&client->dev, "dt addr is 0x%02x", dev->dt_addr); + + dev->dt_client = i2c_new_dummy_device(client->adapter, dev->dt_addr); + if (!dev->dt_client) { + ret = -ENODEV; + goto err_kfree; + } + } + return 0; err_kfree: kfree(dev); @@ -1484,6 +1922,9 @@ static int m88ds3103_remove(struct i2c_client *client) dev_dbg(&client->dev, "\n"); + if (dev->dt_client) + i2c_unregister_device(dev->dt_client); + i2c_mux_del_adapters(dev->muxc); kfree(dev); @@ -1491,7 +1932,9 @@ static int m88ds3103_remove(struct i2c_client *client) } static const struct i2c_device_id m88ds3103_id_table[] = { - {"m88ds3103", 0}, + {"m88ds3103", M88DS3103_CHIPTYPE_3103}, + {"m88rs6000", M88DS3103_CHIPTYPE_RS6000}, + {"m88ds3103b", M88DS3103_CHIPTYPE_3103B}, {} }; MODULE_DEVICE_TABLE(i2c, m88ds3103_id_table); @@ -1513,3 +1956,4 @@ MODULE_DESCRIPTION("Montage Technology M88DS3103 DVB-S/S2 demodulator driver"); MODULE_LICENSE("GPL"); MODULE_FIRMWARE(M88DS3103_FIRMWARE); MODULE_FIRMWARE(M88RS6000_FIRMWARE); +MODULE_FIRMWARE(M88DS3103B_FIRMWARE); diff --git a/drivers/media/dvb-frontends/m88ds3103_priv.h b/drivers/media/dvb-frontends/m88ds3103_priv.h index c825032f07ab..aa5306f40201 100644 --- a/drivers/media/dvb-frontends/m88ds3103_priv.h +++ b/drivers/media/dvb-frontends/m88ds3103_priv.h @@ -16,13 +16,20 @@ #include <linux/regmap.h> #include <linux/math64.h> -#define M88DS3103_FIRMWARE "dvb-demod-m88ds3103.fw" -#define M88RS6000_FIRMWARE "dvb-demod-m88rs6000.fw" +#define M88DS3103B_FIRMWARE "dvb-demod-m88ds3103b.fw" +#define M88DS3103_FIRMWARE "dvb-demod-m88ds3103.fw" +#define M88RS6000_FIRMWARE "dvb-demod-m88rs6000.fw" + #define M88RS6000_CHIP_ID 0x74 #define M88DS3103_CHIP_ID 0x70 +#define M88DS3103_CHIPTYPE_3103 0 +#define M88DS3103_CHIPTYPE_RS6000 1 +#define M88DS3103_CHIPTYPE_3103B 2 + struct m88ds3103_dev { struct i2c_client *client; + struct i2c_client *dt_client; struct regmap_config regmap_config; struct regmap *regmap; struct m88ds3103_config config; @@ -35,10 +42,13 @@ struct m88ds3103_dev { struct i2c_mux_core *muxc; /* auto detect chip id to do different config */ u8 chip_id; + /* chip type to differentiate m88rs6000 from m88ds3103b */ + u8 chiptype; /* main mclk is calculated for M88RS6000 dynamically */ s32 mclk; u64 post_bit_error; u64 post_bit_count; + u8 dt_addr; }; struct m88ds3103_reg_val {
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> --- drivers/media/dvb-frontends/m88ds3103.c | 466 ++++++++++++++++++- drivers/media/dvb-frontends/m88ds3103_priv.h | 14 +- 2 files changed, 467 insertions(+), 13 deletions(-)