diff options
Diffstat (limited to 'drivers/media/dvb-frontends')
-rw-r--r-- | drivers/media/dvb-frontends/Kconfig | 7 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/Makefile | 1 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/a8293.c | 2 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/cx24117.c | 121 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/dib8000.c | 590 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/drxk.h | 2 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/drxk_hard.c | 24 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/m88ds3103.c | 1311 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/m88ds3103.h | 114 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/m88ds3103_priv.h | 215 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/m88rs2000.c | 172 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/m88rs2000.h | 2 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/nxt200x.c | 2 |
13 files changed, 2392 insertions, 171 deletions
diff --git a/drivers/media/dvb-frontends/Kconfig b/drivers/media/dvb-frontends/Kconfig index bddbab43a2df..dd12a1ebda82 100644 --- a/drivers/media/dvb-frontends/Kconfig +++ b/drivers/media/dvb-frontends/Kconfig | |||
@@ -35,6 +35,13 @@ config DVB_STV6110x | |||
35 | help | 35 | help |
36 | A Silicon tuner that supports DVB-S and DVB-S2 modes | 36 | A Silicon tuner that supports DVB-S and DVB-S2 modes |
37 | 37 | ||
38 | config DVB_M88DS3103 | ||
39 | tristate "Montage M88DS3103" | ||
40 | depends on DVB_CORE && I2C && I2C_MUX | ||
41 | default m if !MEDIA_SUBDRV_AUTOSELECT | ||
42 | help | ||
43 | Say Y when you want to support this frontend. | ||
44 | |||
38 | comment "Multistandard (cable + terrestrial) frontends" | 45 | comment "Multistandard (cable + terrestrial) frontends" |
39 | depends on DVB_CORE | 46 | depends on DVB_CORE |
40 | 47 | ||
diff --git a/drivers/media/dvb-frontends/Makefile b/drivers/media/dvb-frontends/Makefile index f9cb43d9aed9..0c75a6aafb9d 100644 --- a/drivers/media/dvb-frontends/Makefile +++ b/drivers/media/dvb-frontends/Makefile | |||
@@ -85,6 +85,7 @@ obj-$(CONFIG_DVB_STV6110) += stv6110.o | |||
85 | obj-$(CONFIG_DVB_STV0900) += stv0900.o | 85 | obj-$(CONFIG_DVB_STV0900) += stv0900.o |
86 | obj-$(CONFIG_DVB_STV090x) += stv090x.o | 86 | obj-$(CONFIG_DVB_STV090x) += stv090x.o |
87 | obj-$(CONFIG_DVB_STV6110x) += stv6110x.o | 87 | obj-$(CONFIG_DVB_STV6110x) += stv6110x.o |
88 | obj-$(CONFIG_DVB_M88DS3103) += m88ds3103.o | ||
88 | obj-$(CONFIG_DVB_ISL6423) += isl6423.o | 89 | obj-$(CONFIG_DVB_ISL6423) += isl6423.o |
89 | obj-$(CONFIG_DVB_EC100) += ec100.o | 90 | obj-$(CONFIG_DVB_EC100) += ec100.o |
90 | obj-$(CONFIG_DVB_HD29L2) += hd29l2.o | 91 | obj-$(CONFIG_DVB_HD29L2) += hd29l2.o |
diff --git a/drivers/media/dvb-frontends/a8293.c b/drivers/media/dvb-frontends/a8293.c index 74fbb5d58bed..780da58132f1 100644 --- a/drivers/media/dvb-frontends/a8293.c +++ b/drivers/media/dvb-frontends/a8293.c | |||
@@ -96,6 +96,8 @@ static int a8293_set_voltage(struct dvb_frontend *fe, | |||
96 | if (ret) | 96 | if (ret) |
97 | goto err; | 97 | goto err; |
98 | 98 | ||
99 | usleep_range(1500, 50000); | ||
100 | |||
99 | return ret; | 101 | return ret; |
100 | err: | 102 | err: |
101 | dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); | 103 | dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); |
diff --git a/drivers/media/dvb-frontends/cx24117.c b/drivers/media/dvb-frontends/cx24117.c index 476b422ccf19..68f768a5422d 100644 --- a/drivers/media/dvb-frontends/cx24117.c +++ b/drivers/media/dvb-frontends/cx24117.c | |||
@@ -135,15 +135,33 @@ | |||
135 | 135 | ||
136 | 136 | ||
137 | enum cmds { | 137 | enum cmds { |
138 | CMD_SET_VCO = 0x10, | 138 | CMD_SET_VCOFREQ = 0x10, |
139 | CMD_TUNEREQUEST = 0x11, | 139 | CMD_TUNEREQUEST = 0x11, |
140 | CMD_MPEGCONFIG = 0x13, | 140 | CMD_GLOBAL_MPEGCFG = 0x13, |
141 | CMD_TUNERINIT = 0x14, | 141 | CMD_MPEGCFG = 0x14, |
142 | CMD_LNBSEND = 0x21, /* Formerly CMD_SEND_DISEQC */ | 142 | CMD_TUNERINIT = 0x15, |
143 | CMD_LNBDCLEVEL = 0x22, | 143 | CMD_GET_SRATE = 0x18, |
144 | CMD_SET_TONE = 0x23, | 144 | CMD_SET_GOLDCODE = 0x19, |
145 | CMD_UPDFWVERS = 0x35, | 145 | CMD_GET_AGCACC = 0x1a, |
146 | CMD_TUNERSLEEP = 0x36, | 146 | CMD_DEMODINIT = 0x1b, |
147 | CMD_GETCTLACC = 0x1c, | ||
148 | |||
149 | CMD_LNBCONFIG = 0x20, | ||
150 | CMD_LNBSEND = 0x21, | ||
151 | CMD_LNBDCLEVEL = 0x22, | ||
152 | CMD_LNBPCBCONFIG = 0x23, | ||
153 | CMD_LNBSENDTONEBST = 0x24, | ||
154 | CMD_LNBUPDREPLY = 0x25, | ||
155 | |||
156 | CMD_SET_GPIOMODE = 0x30, | ||
157 | CMD_SET_GPIOEN = 0x31, | ||
158 | CMD_SET_GPIODIR = 0x32, | ||
159 | CMD_SET_GPIOOUT = 0x33, | ||
160 | CMD_ENABLERSCORR = 0x34, | ||
161 | CMD_FWVERSION = 0x35, | ||
162 | CMD_SET_SLEEPMODE = 0x36, | ||
163 | CMD_BERCTRL = 0x3c, | ||
164 | CMD_EVENTCTRL = 0x3d, | ||
147 | }; | 165 | }; |
148 | 166 | ||
149 | static LIST_HEAD(hybrid_tuner_instance_list); | 167 | static LIST_HEAD(hybrid_tuner_instance_list); |
@@ -619,8 +637,8 @@ static int cx24117_load_firmware(struct dvb_frontend *fe, | |||
619 | cx24117_writereg(state, 0xf7, 0x0c); | 637 | cx24117_writereg(state, 0xf7, 0x0c); |
620 | cx24117_writereg(state, 0xe0, 0x00); | 638 | cx24117_writereg(state, 0xe0, 0x00); |
621 | 639 | ||
622 | /* CMD 1B */ | 640 | /* Init demodulator */ |
623 | cmd.args[0] = 0x1b; | 641 | cmd.args[0] = CMD_DEMODINIT; |
624 | cmd.args[1] = 0x00; | 642 | cmd.args[1] = 0x00; |
625 | cmd.args[2] = 0x01; | 643 | cmd.args[2] = 0x01; |
626 | cmd.args[3] = 0x00; | 644 | cmd.args[3] = 0x00; |
@@ -629,8 +647,8 @@ static int cx24117_load_firmware(struct dvb_frontend *fe, | |||
629 | if (ret != 0) | 647 | if (ret != 0) |
630 | goto error; | 648 | goto error; |
631 | 649 | ||
632 | /* CMD 10 */ | 650 | /* Set VCO frequency */ |
633 | cmd.args[0] = CMD_SET_VCO; | 651 | cmd.args[0] = CMD_SET_VCOFREQ; |
634 | cmd.args[1] = 0x06; | 652 | cmd.args[1] = 0x06; |
635 | cmd.args[2] = 0x2b; | 653 | cmd.args[2] = 0x2b; |
636 | cmd.args[3] = 0xd8; | 654 | cmd.args[3] = 0xd8; |
@@ -648,8 +666,8 @@ static int cx24117_load_firmware(struct dvb_frontend *fe, | |||
648 | if (ret != 0) | 666 | if (ret != 0) |
649 | goto error; | 667 | goto error; |
650 | 668 | ||
651 | /* CMD 15 */ | 669 | /* Tuner init */ |
652 | cmd.args[0] = 0x15; | 670 | cmd.args[0] = CMD_TUNERINIT; |
653 | cmd.args[1] = 0x00; | 671 | cmd.args[1] = 0x00; |
654 | cmd.args[2] = 0x01; | 672 | cmd.args[2] = 0x01; |
655 | cmd.args[3] = 0x00; | 673 | cmd.args[3] = 0x00; |
@@ -667,8 +685,8 @@ static int cx24117_load_firmware(struct dvb_frontend *fe, | |||
667 | if (ret != 0) | 685 | if (ret != 0) |
668 | goto error; | 686 | goto error; |
669 | 687 | ||
670 | /* CMD 13 */ | 688 | /* Global MPEG config */ |
671 | cmd.args[0] = CMD_MPEGCONFIG; | 689 | cmd.args[0] = CMD_GLOBAL_MPEGCFG; |
672 | cmd.args[1] = 0x00; | 690 | cmd.args[1] = 0x00; |
673 | cmd.args[2] = 0x00; | 691 | cmd.args[2] = 0x00; |
674 | cmd.args[3] = 0x00; | 692 | cmd.args[3] = 0x00; |
@@ -679,9 +697,9 @@ static int cx24117_load_firmware(struct dvb_frontend *fe, | |||
679 | if (ret != 0) | 697 | if (ret != 0) |
680 | goto error; | 698 | goto error; |
681 | 699 | ||
682 | /* CMD 14 */ | 700 | /* MPEG config for each demod */ |
683 | for (i = 0; i < 2; i++) { | 701 | for (i = 0; i < 2; i++) { |
684 | cmd.args[0] = CMD_TUNERINIT; | 702 | cmd.args[0] = CMD_MPEGCFG; |
685 | cmd.args[1] = (u8) i; | 703 | cmd.args[1] = (u8) i; |
686 | cmd.args[2] = 0x00; | 704 | cmd.args[2] = 0x00; |
687 | cmd.args[3] = 0x05; | 705 | cmd.args[3] = 0x05; |
@@ -699,8 +717,8 @@ static int cx24117_load_firmware(struct dvb_frontend *fe, | |||
699 | cx24117_writereg(state, 0xcf, 0x00); | 717 | cx24117_writereg(state, 0xcf, 0x00); |
700 | cx24117_writereg(state, 0xe5, 0x04); | 718 | cx24117_writereg(state, 0xe5, 0x04); |
701 | 719 | ||
702 | /* Firmware CMD 35: Get firmware version */ | 720 | /* Get firmware version */ |
703 | cmd.args[0] = CMD_UPDFWVERS; | 721 | cmd.args[0] = CMD_FWVERSION; |
704 | cmd.len = 2; | 722 | cmd.len = 2; |
705 | for (i = 0; i < 4; i++) { | 723 | for (i = 0; i < 4; i++) { |
706 | cmd.args[1] = i; | 724 | cmd.args[1] = i; |
@@ -779,8 +797,8 @@ static int cx24117_read_signal_strength(struct dvb_frontend *fe, | |||
779 | u8 reg = (state->demod == 0) ? | 797 | u8 reg = (state->demod == 0) ? |
780 | CX24117_REG_SSTATUS0 : CX24117_REG_SSTATUS1; | 798 | CX24117_REG_SSTATUS0 : CX24117_REG_SSTATUS1; |
781 | 799 | ||
782 | /* Firmware CMD 1A */ | 800 | /* Read AGC accumulator register */ |
783 | cmd.args[0] = 0x1a; | 801 | cmd.args[0] = CMD_GET_AGCACC; |
784 | cmd.args[1] = (u8) state->demod; | 802 | cmd.args[1] = (u8) state->demod; |
785 | cmd.len = 2; | 803 | cmd.len = 2; |
786 | ret = cx24117_cmd_execute(fe, &cmd); | 804 | ret = cx24117_cmd_execute(fe, &cmd); |
@@ -899,22 +917,15 @@ static int cx24117_set_voltage(struct dvb_frontend *fe, | |||
899 | voltage == SEC_VOLTAGE_18 ? "SEC_VOLTAGE_18" : | 917 | voltage == SEC_VOLTAGE_18 ? "SEC_VOLTAGE_18" : |
900 | "SEC_VOLTAGE_OFF"); | 918 | "SEC_VOLTAGE_OFF"); |
901 | 919 | ||
902 | /* CMD 32 */ | 920 | /* Prepare a set GPIO logic level CMD */ |
903 | cmd.args[0] = 0x32; | 921 | cmd.args[0] = CMD_SET_GPIOOUT; |
904 | cmd.args[1] = reg; | 922 | cmd.args[2] = reg; /* mask */ |
905 | cmd.args[2] = reg; | ||
906 | cmd.len = 3; | 923 | cmd.len = 3; |
907 | ret = cx24117_cmd_execute(fe, &cmd); | ||
908 | if (ret) | ||
909 | return ret; | ||
910 | 924 | ||
911 | if ((voltage == SEC_VOLTAGE_13) || | 925 | if ((voltage == SEC_VOLTAGE_13) || |
912 | (voltage == SEC_VOLTAGE_18)) { | 926 | (voltage == SEC_VOLTAGE_18)) { |
913 | /* CMD 33 */ | 927 | /* power on LNB */ |
914 | cmd.args[0] = 0x33; | ||
915 | cmd.args[1] = reg; | 928 | cmd.args[1] = reg; |
916 | cmd.args[2] = reg; | ||
917 | cmd.len = 3; | ||
918 | ret = cx24117_cmd_execute(fe, &cmd); | 929 | ret = cx24117_cmd_execute(fe, &cmd); |
919 | if (ret != 0) | 930 | if (ret != 0) |
920 | return ret; | 931 | return ret; |
@@ -926,22 +937,22 @@ static int cx24117_set_voltage(struct dvb_frontend *fe, | |||
926 | /* Wait for voltage/min repeat delay */ | 937 | /* Wait for voltage/min repeat delay */ |
927 | msleep(100); | 938 | msleep(100); |
928 | 939 | ||
929 | /* CMD 22 - CMD_LNBDCLEVEL */ | 940 | /* Set 13V/18V select pin */ |
930 | cmd.args[0] = CMD_LNBDCLEVEL; | 941 | cmd.args[0] = CMD_LNBDCLEVEL; |
931 | cmd.args[1] = state->demod ? 0 : 1; | 942 | cmd.args[1] = state->demod ? 0 : 1; |
932 | cmd.args[2] = (voltage == SEC_VOLTAGE_18 ? 0x01 : 0x00); | 943 | cmd.args[2] = (voltage == SEC_VOLTAGE_18 ? 0x01 : 0x00); |
933 | cmd.len = 3; | 944 | cmd.len = 3; |
945 | ret = cx24117_cmd_execute(fe, &cmd); | ||
934 | 946 | ||
935 | /* Min delay time before DiSEqC send */ | 947 | /* Min delay time before DiSEqC send */ |
936 | msleep(20); | 948 | msleep(20); |
937 | } else { | 949 | } else { |
938 | cmd.args[0] = 0x33; | 950 | /* power off LNB */ |
939 | cmd.args[1] = 0x00; | 951 | cmd.args[1] = 0x00; |
940 | cmd.args[2] = reg; | 952 | ret = cx24117_cmd_execute(fe, &cmd); |
941 | cmd.len = 3; | ||
942 | } | 953 | } |
943 | 954 | ||
944 | return cx24117_cmd_execute(fe, &cmd); | 955 | return ret; |
945 | } | 956 | } |
946 | 957 | ||
947 | static int cx24117_set_tone(struct dvb_frontend *fe, | 958 | static int cx24117_set_tone(struct dvb_frontend *fe, |
@@ -968,8 +979,7 @@ static int cx24117_set_tone(struct dvb_frontend *fe, | |||
968 | msleep(20); | 979 | msleep(20); |
969 | 980 | ||
970 | /* Set the tone */ | 981 | /* Set the tone */ |
971 | /* CMD 23 - CMD_SET_TONE */ | 982 | cmd.args[0] = CMD_LNBPCBCONFIG; |
972 | cmd.args[0] = CMD_SET_TONE; | ||
973 | cmd.args[1] = (state->demod ? 0 : 1); | 983 | cmd.args[1] = (state->demod ? 0 : 1); |
974 | cmd.args[2] = 0x00; | 984 | cmd.args[2] = 0x00; |
975 | cmd.args[3] = 0x00; | 985 | cmd.args[3] = 0x00; |
@@ -1231,8 +1241,8 @@ static int cx24117_initfe(struct dvb_frontend *fe) | |||
1231 | 1241 | ||
1232 | mutex_lock(&state->priv->fe_lock); | 1242 | mutex_lock(&state->priv->fe_lock); |
1233 | 1243 | ||
1234 | /* Firmware CMD 36: Power config */ | 1244 | /* Set sleep mode off */ |
1235 | cmd.args[0] = CMD_TUNERSLEEP; | 1245 | cmd.args[0] = CMD_SET_SLEEPMODE; |
1236 | cmd.args[1] = (state->demod ? 1 : 0); | 1246 | cmd.args[1] = (state->demod ? 1 : 0); |
1237 | cmd.args[2] = 0; | 1247 | cmd.args[2] = 0; |
1238 | cmd.len = 3; | 1248 | cmd.len = 3; |
@@ -1244,8 +1254,8 @@ static int cx24117_initfe(struct dvb_frontend *fe) | |||
1244 | if (ret != 0) | 1254 | if (ret != 0) |
1245 | goto exit; | 1255 | goto exit; |
1246 | 1256 | ||
1247 | /* CMD 3C */ | 1257 | /* Set BER control */ |
1248 | cmd.args[0] = 0x3c; | 1258 | cmd.args[0] = CMD_BERCTRL; |
1249 | cmd.args[1] = (state->demod ? 1 : 0); | 1259 | cmd.args[1] = (state->demod ? 1 : 0); |
1250 | cmd.args[2] = 0x10; | 1260 | cmd.args[2] = 0x10; |
1251 | cmd.args[3] = 0x10; | 1261 | cmd.args[3] = 0x10; |
@@ -1254,12 +1264,22 @@ static int cx24117_initfe(struct dvb_frontend *fe) | |||
1254 | if (ret != 0) | 1264 | if (ret != 0) |
1255 | goto exit; | 1265 | goto exit; |
1256 | 1266 | ||
1257 | /* CMD 34 */ | 1267 | /* Set RS correction (enable/disable) */ |
1258 | cmd.args[0] = 0x34; | 1268 | cmd.args[0] = CMD_ENABLERSCORR; |
1259 | cmd.args[1] = (state->demod ? 1 : 0); | 1269 | cmd.args[1] = (state->demod ? 1 : 0); |
1260 | cmd.args[2] = CX24117_OCC; | 1270 | cmd.args[2] = CX24117_OCC; |
1261 | cmd.len = 3; | 1271 | cmd.len = 3; |
1262 | ret = cx24117_cmd_execute_nolock(fe, &cmd); | 1272 | ret = cx24117_cmd_execute_nolock(fe, &cmd); |
1273 | if (ret != 0) | ||
1274 | goto exit; | ||
1275 | |||
1276 | /* Set GPIO direction */ | ||
1277 | /* Set as output - controls LNB power on/off */ | ||
1278 | cmd.args[0] = CMD_SET_GPIODIR; | ||
1279 | cmd.args[1] = 0x30; | ||
1280 | cmd.args[2] = 0x30; | ||
1281 | cmd.len = 3; | ||
1282 | ret = cx24117_cmd_execute_nolock(fe, &cmd); | ||
1263 | 1283 | ||
1264 | exit: | 1284 | exit: |
1265 | mutex_unlock(&state->priv->fe_lock); | 1285 | mutex_unlock(&state->priv->fe_lock); |
@@ -1278,8 +1298,8 @@ static int cx24117_sleep(struct dvb_frontend *fe) | |||
1278 | dev_dbg(&state->priv->i2c->dev, "%s() demod%d\n", | 1298 | dev_dbg(&state->priv->i2c->dev, "%s() demod%d\n", |
1279 | __func__, state->demod); | 1299 | __func__, state->demod); |
1280 | 1300 | ||
1281 | /* Firmware CMD 36: Power config */ | 1301 | /* Set sleep mode on */ |
1282 | cmd.args[0] = CMD_TUNERSLEEP; | 1302 | cmd.args[0] = CMD_SET_SLEEPMODE; |
1283 | cmd.args[1] = (state->demod ? 1 : 0); | 1303 | cmd.args[1] = (state->demod ? 1 : 0); |
1284 | cmd.args[2] = 1; | 1304 | cmd.args[2] = 1; |
1285 | cmd.len = 3; | 1305 | cmd.len = 3; |
@@ -1558,7 +1578,8 @@ static int cx24117_get_frontend(struct dvb_frontend *fe) | |||
1558 | 1578 | ||
1559 | u8 buf[0x1f-4]; | 1579 | u8 buf[0x1f-4]; |
1560 | 1580 | ||
1561 | cmd.args[0] = 0x1c; | 1581 | /* Read current tune parameters */ |
1582 | cmd.args[0] = CMD_GETCTLACC; | ||
1562 | cmd.args[1] = (u8) state->demod; | 1583 | cmd.args[1] = (u8) state->demod; |
1563 | cmd.len = 2; | 1584 | cmd.len = 2; |
1564 | ret = cx24117_cmd_execute(fe, &cmd); | 1585 | ret = cx24117_cmd_execute(fe, &cmd); |
diff --git a/drivers/media/dvb-frontends/dib8000.c b/drivers/media/dvb-frontends/dib8000.c index 6dbbee453ee1..1632d78a5479 100644 --- a/drivers/media/dvb-frontends/dib8000.c +++ b/drivers/media/dvb-frontends/dib8000.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/slab.h> | 11 | #include <linux/slab.h> |
12 | #include <linux/i2c.h> | 12 | #include <linux/i2c.h> |
13 | #include <linux/mutex.h> | 13 | #include <linux/mutex.h> |
14 | #include <asm/div64.h> | ||
14 | 15 | ||
15 | #include "dvb_math.h" | 16 | #include "dvb_math.h" |
16 | 17 | ||
@@ -118,6 +119,12 @@ struct dib8000_state { | |||
118 | u8 longest_intlv_layer; | 119 | u8 longest_intlv_layer; |
119 | u16 output_mode; | 120 | u16 output_mode; |
120 | 121 | ||
122 | /* for DVBv5 stats */ | ||
123 | s64 init_ucb; | ||
124 | unsigned long per_jiffies_stats; | ||
125 | unsigned long ber_jiffies_stats; | ||
126 | unsigned long ber_jiffies_stats_layer[3]; | ||
127 | |||
121 | #ifdef DIB8000_AGC_FREEZE | 128 | #ifdef DIB8000_AGC_FREEZE |
122 | u16 agc1_max; | 129 | u16 agc1_max; |
123 | u16 agc1_min; | 130 | u16 agc1_min; |
@@ -157,15 +164,10 @@ static u16 dib8000_i2c_read16(struct i2c_device *i2c, u16 reg) | |||
157 | return ret; | 164 | return ret; |
158 | } | 165 | } |
159 | 166 | ||
160 | static u16 dib8000_read_word(struct dib8000_state *state, u16 reg) | 167 | static u16 __dib8000_read_word(struct dib8000_state *state, u16 reg) |
161 | { | 168 | { |
162 | u16 ret; | 169 | u16 ret; |
163 | 170 | ||
164 | if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { | ||
165 | dprintk("could not acquire lock"); | ||
166 | return 0; | ||
167 | } | ||
168 | |||
169 | state->i2c_write_buffer[0] = reg >> 8; | 171 | state->i2c_write_buffer[0] = reg >> 8; |
170 | state->i2c_write_buffer[1] = reg & 0xff; | 172 | state->i2c_write_buffer[1] = reg & 0xff; |
171 | 173 | ||
@@ -183,6 +185,21 @@ static u16 dib8000_read_word(struct dib8000_state *state, u16 reg) | |||
183 | dprintk("i2c read error on %d", reg); | 185 | dprintk("i2c read error on %d", reg); |
184 | 186 | ||
185 | ret = (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1]; | 187 | ret = (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1]; |
188 | |||
189 | return ret; | ||
190 | } | ||
191 | |||
192 | static u16 dib8000_read_word(struct dib8000_state *state, u16 reg) | ||
193 | { | ||
194 | u16 ret; | ||
195 | |||
196 | if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { | ||
197 | dprintk("could not acquire lock"); | ||
198 | return 0; | ||
199 | } | ||
200 | |||
201 | ret = __dib8000_read_word(state, reg); | ||
202 | |||
186 | mutex_unlock(&state->i2c_buffer_lock); | 203 | mutex_unlock(&state->i2c_buffer_lock); |
187 | 204 | ||
188 | return ret; | 205 | return ret; |
@@ -192,8 +209,15 @@ static u32 dib8000_read32(struct dib8000_state *state, u16 reg) | |||
192 | { | 209 | { |
193 | u16 rw[2]; | 210 | u16 rw[2]; |
194 | 211 | ||
195 | rw[0] = dib8000_read_word(state, reg + 0); | 212 | if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { |
196 | rw[1] = dib8000_read_word(state, reg + 1); | 213 | dprintk("could not acquire lock"); |
214 | return 0; | ||
215 | } | ||
216 | |||
217 | rw[0] = __dib8000_read_word(state, reg + 0); | ||
218 | rw[1] = __dib8000_read_word(state, reg + 1); | ||
219 | |||
220 | mutex_unlock(&state->i2c_buffer_lock); | ||
197 | 221 | ||
198 | return ((rw[0] << 16) | (rw[1])); | 222 | return ((rw[0] << 16) | (rw[1])); |
199 | } | 223 | } |
@@ -787,7 +811,7 @@ int dib8000_update_pll(struct dvb_frontend *fe, | |||
787 | dprintk("PLL: Update ratio (prediv: %d, ratio: %d)", state->cfg.pll->pll_prediv, ratio); | 811 | dprintk("PLL: Update ratio (prediv: %d, ratio: %d)", state->cfg.pll->pll_prediv, ratio); |
788 | dib8000_write_word(state, 901, (state->cfg.pll->pll_prediv << 8) | (ratio << 0)); /* only the PLL ratio is updated. */ | 812 | dib8000_write_word(state, 901, (state->cfg.pll->pll_prediv << 8) | (ratio << 0)); /* only the PLL ratio is updated. */ |
789 | } | 813 | } |
790 | } | 814 | } |
791 | 815 | ||
792 | return 0; | 816 | return 0; |
793 | } | 817 | } |
@@ -966,6 +990,45 @@ static u16 dib8000_identify(struct i2c_device *client) | |||
966 | return value; | 990 | return value; |
967 | } | 991 | } |
968 | 992 | ||
993 | static int dib8000_read_unc_blocks(struct dvb_frontend *fe, u32 *unc); | ||
994 | |||
995 | static void dib8000_reset_stats(struct dvb_frontend *fe) | ||
996 | { | ||
997 | struct dib8000_state *state = fe->demodulator_priv; | ||
998 | struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache; | ||
999 | u32 ucb; | ||
1000 | |||
1001 | memset(&c->strength, 0, sizeof(c->strength)); | ||
1002 | memset(&c->cnr, 0, sizeof(c->cnr)); | ||
1003 | memset(&c->post_bit_error, 0, sizeof(c->post_bit_error)); | ||
1004 | memset(&c->post_bit_count, 0, sizeof(c->post_bit_count)); | ||
1005 | memset(&c->block_error, 0, sizeof(c->block_error)); | ||
1006 | |||
1007 | c->strength.len = 1; | ||
1008 | c->cnr.len = 1; | ||
1009 | c->block_error.len = 1; | ||
1010 | c->block_count.len = 1; | ||
1011 | c->post_bit_error.len = 1; | ||
1012 | c->post_bit_count.len = 1; | ||
1013 | |||
1014 | c->strength.stat[0].scale = FE_SCALE_DECIBEL; | ||
1015 | c->strength.stat[0].uvalue = 0; | ||
1016 | |||
1017 | c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; | ||
1018 | c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; | ||
1019 | c->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; | ||
1020 | c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; | ||
1021 | c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; | ||
1022 | |||
1023 | dib8000_read_unc_blocks(fe, &ucb); | ||
1024 | |||
1025 | state->init_ucb = -ucb; | ||
1026 | state->ber_jiffies_stats = 0; | ||
1027 | state->per_jiffies_stats = 0; | ||
1028 | memset(&state->ber_jiffies_stats_layer, 0, | ||
1029 | sizeof(state->ber_jiffies_stats_layer)); | ||
1030 | } | ||
1031 | |||
969 | static int dib8000_reset(struct dvb_frontend *fe) | 1032 | static int dib8000_reset(struct dvb_frontend *fe) |
970 | { | 1033 | { |
971 | struct dib8000_state *state = fe->demodulator_priv; | 1034 | struct dib8000_state *state = fe->demodulator_priv; |
@@ -1071,6 +1134,8 @@ static int dib8000_reset(struct dvb_frontend *fe) | |||
1071 | 1134 | ||
1072 | dib8000_set_power_mode(state, DIB8000_POWER_INTERFACE_ONLY); | 1135 | dib8000_set_power_mode(state, DIB8000_POWER_INTERFACE_ONLY); |
1073 | 1136 | ||
1137 | dib8000_reset_stats(fe); | ||
1138 | |||
1074 | return 0; | 1139 | return 0; |
1075 | } | 1140 | } |
1076 | 1141 | ||
@@ -2445,7 +2510,8 @@ static int dib8000_autosearch_start(struct dvb_frontend *fe) | |||
2445 | if (state->revision == 0x8090) | 2510 | if (state->revision == 0x8090) |
2446 | internal = dib8000_read32(state, 23) / 1000; | 2511 | internal = dib8000_read32(state, 23) / 1000; |
2447 | 2512 | ||
2448 | if (state->autosearch_state == AS_SEARCHING_FFT) { | 2513 | if ((state->revision >= 0x8002) && |
2514 | (state->autosearch_state == AS_SEARCHING_FFT)) { | ||
2449 | dib8000_write_word(state, 37, 0x0065); /* P_ctrl_pha_off_max default values */ | 2515 | dib8000_write_word(state, 37, 0x0065); /* P_ctrl_pha_off_max default values */ |
2450 | dib8000_write_word(state, 116, 0x0000); /* P_ana_gain to 0 */ | 2516 | dib8000_write_word(state, 116, 0x0000); /* P_ana_gain to 0 */ |
2451 | 2517 | ||
@@ -2481,7 +2547,8 @@ static int dib8000_autosearch_start(struct dvb_frontend *fe) | |||
2481 | dib8000_write_word(state, 770, (dib8000_read_word(state, 770) & 0xdfff) | (1 << 13)); /* P_restart_ccg = 1 */ | 2547 | dib8000_write_word(state, 770, (dib8000_read_word(state, 770) & 0xdfff) | (1 << 13)); /* P_restart_ccg = 1 */ |
2482 | dib8000_write_word(state, 770, (dib8000_read_word(state, 770) & 0xdfff) | (0 << 13)); /* P_restart_ccg = 0 */ | 2548 | dib8000_write_word(state, 770, (dib8000_read_word(state, 770) & 0xdfff) | (0 << 13)); /* P_restart_ccg = 0 */ |
2483 | dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x7ff) | (0 << 15) | (1 << 13)); /* P_restart_search = 0; */ | 2549 | dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x7ff) | (0 << 15) | (1 << 13)); /* P_restart_search = 0; */ |
2484 | } else if (state->autosearch_state == AS_SEARCHING_GUARD) { | 2550 | } else if ((state->revision >= 0x8002) && |
2551 | (state->autosearch_state == AS_SEARCHING_GUARD)) { | ||
2485 | c->transmission_mode = TRANSMISSION_MODE_8K; | 2552 | c->transmission_mode = TRANSMISSION_MODE_8K; |
2486 | c->guard_interval = GUARD_INTERVAL_1_8; | 2553 | c->guard_interval = GUARD_INTERVAL_1_8; |
2487 | c->inversion = 0; | 2554 | c->inversion = 0; |
@@ -2583,7 +2650,8 @@ static int dib8000_autosearch_irq(struct dvb_frontend *fe) | |||
2583 | struct dib8000_state *state = fe->demodulator_priv; | 2650 | struct dib8000_state *state = fe->demodulator_priv; |
2584 | u16 irq_pending = dib8000_read_word(state, 1284); | 2651 | u16 irq_pending = dib8000_read_word(state, 1284); |
2585 | 2652 | ||
2586 | if (state->autosearch_state == AS_SEARCHING_FFT) { | 2653 | if ((state->revision >= 0x8002) && |
2654 | (state->autosearch_state == AS_SEARCHING_FFT)) { | ||
2587 | if (irq_pending & 0x1) { | 2655 | if (irq_pending & 0x1) { |
2588 | dprintk("dib8000_autosearch_irq: max correlation result available"); | 2656 | dprintk("dib8000_autosearch_irq: max correlation result available"); |
2589 | return 3; | 2657 | return 3; |
@@ -2853,6 +2921,91 @@ static int dib8090p_init_sdram(struct dib8000_state *state) | |||
2853 | return 0; | 2921 | return 0; |
2854 | } | 2922 | } |
2855 | 2923 | ||
2924 | /** | ||
2925 | * is_manual_mode - Check if TMCC should be used for parameters settings | ||
2926 | * @c: struct dvb_frontend_properties | ||
2927 | * | ||
2928 | * By default, TMCC table should be used for parameter settings on most | ||
2929 | * usercases. However, sometimes it is desirable to lock the demod to | ||
2930 | * use the manual parameters. | ||
2931 | * | ||
2932 | * On manual mode, the current dib8000_tune state machine is very restrict: | ||
2933 | * It requires that both per-layer and per-transponder parameters to be | ||
2934 | * properly specified, otherwise the device won't lock. | ||
2935 | * | ||
2936 | * Check if all those conditions are properly satisfied before allowing | ||
2937 | * the device to use the manual frequency lock mode. | ||
2938 | */ | ||
2939 | static int is_manual_mode(struct dtv_frontend_properties *c) | ||
2940 | { | ||
2941 | int i, n_segs = 0; | ||
2942 | |||
2943 | /* Use auto mode on DVB-T compat mode */ | ||
2944 | if (c->delivery_system != SYS_ISDBT) | ||
2945 | return 0; | ||
2946 | |||
2947 | /* | ||
2948 | * Transmission mode is only detected on auto mode, currently | ||
2949 | */ | ||
2950 | if (c->transmission_mode == TRANSMISSION_MODE_AUTO) { | ||
2951 | dprintk("transmission mode auto"); | ||
2952 | return 0; | ||
2953 | } | ||
2954 | |||
2955 | /* | ||
2956 | * Guard interval is only detected on auto mode, currently | ||
2957 | */ | ||
2958 | if (c->guard_interval == GUARD_INTERVAL_AUTO) { | ||
2959 | dprintk("guard interval auto"); | ||
2960 | return 0; | ||
2961 | } | ||
2962 | |||
2963 | /* | ||
2964 | * If no layer is enabled, assume auto mode, as at least one | ||
2965 | * layer should be enabled | ||
2966 | */ | ||
2967 | if (!c->isdbt_layer_enabled) { | ||
2968 | dprintk("no layer modulation specified"); | ||
2969 | return 0; | ||
2970 | } | ||
2971 | |||
2972 | /* | ||
2973 | * Check if the per-layer parameters aren't auto and | ||
2974 | * disable a layer if segment count is 0 or invalid. | ||
2975 | */ | ||
2976 | for (i = 0; i < 3; i++) { | ||
2977 | if (!(c->isdbt_layer_enabled & 1 << i)) | ||
2978 | continue; | ||
2979 | |||
2980 | if ((c->layer[i].segment_count > 13) || | ||
2981 | (c->layer[i].segment_count == 0)) { | ||
2982 | c->isdbt_layer_enabled &= ~(1 << i); | ||
2983 | continue; | ||
2984 | } | ||
2985 | |||
2986 | n_segs += c->layer[i].segment_count; | ||
2987 | |||
2988 | if ((c->layer[i].modulation == QAM_AUTO) || | ||
2989 | (c->layer[i].fec == FEC_AUTO)) { | ||
2990 | dprintk("layer %c has either modulation or FEC auto", | ||
2991 | 'A' + i); | ||
2992 | return 0; | ||
2993 | } | ||
2994 | } | ||
2995 | |||
2996 | /* | ||
2997 | * Userspace specified a wrong number of segments. | ||
2998 | * fallback to auto mode. | ||
2999 | */ | ||
3000 | if (n_segs == 0 || n_segs > 13) { | ||
3001 | dprintk("number of segments is invalid"); | ||
3002 | return 0; | ||
3003 | } | ||
3004 | |||
3005 | /* Everything looks ok for manual mode */ | ||
3006 | return 1; | ||
3007 | } | ||
3008 | |||
2856 | static int dib8000_tune(struct dvb_frontend *fe) | 3009 | static int dib8000_tune(struct dvb_frontend *fe) |
2857 | { | 3010 | { |
2858 | struct dib8000_state *state = fe->demodulator_priv; | 3011 | struct dib8000_state *state = fe->demodulator_priv; |
@@ -2878,40 +3031,19 @@ static int dib8000_tune(struct dvb_frontend *fe) | |||
2878 | 3031 | ||
2879 | switch (*tune_state) { | 3032 | switch (*tune_state) { |
2880 | case CT_DEMOD_START: /* 30 */ | 3033 | case CT_DEMOD_START: /* 30 */ |
3034 | dib8000_reset_stats(fe); | ||
3035 | |||
2881 | if (state->revision == 0x8090) | 3036 | if (state->revision == 0x8090) |
2882 | dib8090p_init_sdram(state); | 3037 | dib8090p_init_sdram(state); |
2883 | state->status = FE_STATUS_TUNE_PENDING; | 3038 | state->status = FE_STATUS_TUNE_PENDING; |
2884 | if ((c->delivery_system != SYS_ISDBT) || | 3039 | state->channel_parameters_set = is_manual_mode(c); |
2885 | (c->inversion == INVERSION_AUTO) || | 3040 | |
2886 | (c->transmission_mode == TRANSMISSION_MODE_AUTO) || | 3041 | dprintk("Tuning channel on %s search mode", |
2887 | (c->guard_interval == GUARD_INTERVAL_AUTO) || | 3042 | state->channel_parameters_set ? "manual" : "auto"); |
2888 | (((c->isdbt_layer_enabled & (1 << 0)) != 0) && | ||
2889 | (c->layer[0].segment_count != 0xff) && | ||
2890 | (c->layer[0].segment_count != 0) && | ||
2891 | ((c->layer[0].modulation == QAM_AUTO) || | ||
2892 | (c->layer[0].fec == FEC_AUTO))) || | ||
2893 | (((c->isdbt_layer_enabled & (1 << 1)) != 0) && | ||
2894 | (c->layer[1].segment_count != 0xff) && | ||
2895 | (c->layer[1].segment_count != 0) && | ||
2896 | ((c->layer[1].modulation == QAM_AUTO) || | ||
2897 | (c->layer[1].fec == FEC_AUTO))) || | ||
2898 | (((c->isdbt_layer_enabled & (1 << 2)) != 0) && | ||
2899 | (c->layer[2].segment_count != 0xff) && | ||
2900 | (c->layer[2].segment_count != 0) && | ||
2901 | ((c->layer[2].modulation == QAM_AUTO) || | ||
2902 | (c->layer[2].fec == FEC_AUTO))) || | ||
2903 | (((c->layer[0].segment_count == 0) || | ||
2904 | ((c->isdbt_layer_enabled & (1 << 0)) == 0)) && | ||
2905 | ((c->layer[1].segment_count == 0) || | ||
2906 | ((c->isdbt_layer_enabled & (2 << 0)) == 0)) && | ||
2907 | ((c->layer[2].segment_count == 0) || ((c->isdbt_layer_enabled & (3 << 0)) == 0)))) | ||
2908 | state->channel_parameters_set = 0; /* auto search */ | ||
2909 | else | ||
2910 | state->channel_parameters_set = 1; /* channel parameters are known */ | ||
2911 | 3043 | ||
2912 | dib8000_viterbi_state(state, 0); /* force chan dec in restart */ | 3044 | dib8000_viterbi_state(state, 0); /* force chan dec in restart */ |
2913 | 3045 | ||
2914 | /* Layer monit */ | 3046 | /* Layer monitor */ |
2915 | dib8000_write_word(state, 285, dib8000_read_word(state, 285) & 0x60); | 3047 | dib8000_write_word(state, 285, dib8000_read_word(state, 285) & 0x60); |
2916 | 3048 | ||
2917 | dib8000_set_frequency_offset(state); | 3049 | dib8000_set_frequency_offset(state); |
@@ -3256,15 +3388,27 @@ static int dib8000_sleep(struct dvb_frontend *fe) | |||
3256 | return dib8000_set_adc_state(state, DIBX000_SLOW_ADC_OFF) | dib8000_set_adc_state(state, DIBX000_ADC_OFF); | 3388 | return dib8000_set_adc_state(state, DIBX000_SLOW_ADC_OFF) | dib8000_set_adc_state(state, DIBX000_ADC_OFF); |
3257 | } | 3389 | } |
3258 | 3390 | ||
3391 | static int dib8000_read_status(struct dvb_frontend *fe, fe_status_t * stat); | ||
3392 | |||
3259 | static int dib8000_get_frontend(struct dvb_frontend *fe) | 3393 | static int dib8000_get_frontend(struct dvb_frontend *fe) |
3260 | { | 3394 | { |
3261 | struct dib8000_state *state = fe->demodulator_priv; | 3395 | struct dib8000_state *state = fe->demodulator_priv; |
3262 | u16 i, val = 0; | 3396 | u16 i, val = 0; |
3263 | fe_status_t stat; | 3397 | fe_status_t stat = 0; |
3264 | u8 index_frontend, sub_index_frontend; | 3398 | u8 index_frontend, sub_index_frontend; |
3265 | 3399 | ||
3266 | fe->dtv_property_cache.bandwidth_hz = 6000000; | 3400 | fe->dtv_property_cache.bandwidth_hz = 6000000; |
3267 | 3401 | ||
3402 | /* | ||
3403 | * If called to early, get_frontend makes dib8000_tune to either | ||
3404 | * not lock or not sync. This causes dvbv5-scan/dvbv5-zap to fail. | ||
3405 | * So, let's just return if frontend 0 has not locked. | ||
3406 | */ | ||
3407 | dib8000_read_status(fe, &stat); | ||
3408 | if (!(stat & FE_HAS_SYNC)) | ||
3409 | return 0; | ||
3410 | |||
3411 | dprintk("TMCC lock"); | ||
3268 | for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { | 3412 | for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { |
3269 | state->fe[index_frontend]->ops.read_status(state->fe[index_frontend], &stat); | 3413 | state->fe[index_frontend]->ops.read_status(state->fe[index_frontend], &stat); |
3270 | if (stat&FE_HAS_SYNC) { | 3414 | if (stat&FE_HAS_SYNC) { |
@@ -3335,9 +3479,13 @@ static int dib8000_get_frontend(struct dvb_frontend *fe) | |||
3335 | fe->dtv_property_cache.layer[i].segment_count = val & 0x0F; | 3479 | fe->dtv_property_cache.layer[i].segment_count = val & 0x0F; |
3336 | dprintk("dib8000_get_frontend : Layer %d segments = %d ", i, fe->dtv_property_cache.layer[i].segment_count); | 3480 | dprintk("dib8000_get_frontend : Layer %d segments = %d ", i, fe->dtv_property_cache.layer[i].segment_count); |
3337 | 3481 | ||
3338 | val = dib8000_read_word(state, 499 + i); | 3482 | val = dib8000_read_word(state, 499 + i) & 0x3; |
3339 | fe->dtv_property_cache.layer[i].interleaving = val & 0x3; | 3483 | /* Interleaving can be 0, 1, 2 or 4 */ |
3340 | dprintk("dib8000_get_frontend : Layer %d time_intlv = %d ", i, fe->dtv_property_cache.layer[i].interleaving); | 3484 | if (val == 3) |
3485 | val = 4; | ||
3486 | fe->dtv_property_cache.layer[i].interleaving = val; | ||
3487 | dprintk("dib8000_get_frontend : Layer %d time_intlv = %d ", | ||
3488 | i, fe->dtv_property_cache.layer[i].interleaving); | ||
3341 | 3489 | ||
3342 | val = dib8000_read_word(state, 481 + i); | 3490 | val = dib8000_read_word(state, 481 + i); |
3343 | switch (val & 0x7) { | 3491 | switch (val & 0x7) { |
@@ -3556,6 +3704,8 @@ static int dib8000_set_frontend(struct dvb_frontend *fe) | |||
3556 | return 0; | 3704 | return 0; |
3557 | } | 3705 | } |
3558 | 3706 | ||
3707 | static int dib8000_get_stats(struct dvb_frontend *fe, fe_status_t stat); | ||
3708 | |||
3559 | static int dib8000_read_status(struct dvb_frontend *fe, fe_status_t * stat) | 3709 | static int dib8000_read_status(struct dvb_frontend *fe, fe_status_t * stat) |
3560 | { | 3710 | { |
3561 | struct dib8000_state *state = fe->demodulator_priv; | 3711 | struct dib8000_state *state = fe->demodulator_priv; |
@@ -3593,6 +3743,7 @@ static int dib8000_read_status(struct dvb_frontend *fe, fe_status_t * stat) | |||
3593 | if (lock & 0x01) | 3743 | if (lock & 0x01) |
3594 | *stat |= FE_HAS_VITERBI; | 3744 | *stat |= FE_HAS_VITERBI; |
3595 | } | 3745 | } |
3746 | dib8000_get_stats(fe, *stat); | ||
3596 | 3747 | ||
3597 | return 0; | 3748 | return 0; |
3598 | } | 3749 | } |
@@ -3699,6 +3850,357 @@ static int dib8000_read_snr(struct dvb_frontend *fe, u16 * snr) | |||
3699 | return 0; | 3850 | return 0; |
3700 | } | 3851 | } |
3701 | 3852 | ||
3853 | struct per_layer_regs { | ||
3854 | u16 lock, ber, per; | ||
3855 | }; | ||
3856 | |||
3857 | static const struct per_layer_regs per_layer_regs[] = { | ||
3858 | { 554, 560, 562 }, | ||
3859 | { 555, 576, 578 }, | ||
3860 | { 556, 581, 583 }, | ||
3861 | }; | ||
3862 | |||
3863 | struct linear_segments { | ||
3864 | unsigned x; | ||
3865 | signed y; | ||
3866 | }; | ||
3867 | |||
3868 | /* | ||
3869 | * Table to estimate signal strength in dBm. | ||
3870 | * This table was empirically determinated by measuring the signal | ||
3871 | * strength generated by a DTA-2111 RF generator directly connected into | ||
3872 | * a dib8076 device (a PixelView PV-D231U stick), using a good quality | ||
3873 | * 3 meters RC6 cable and good RC6 connectors. | ||
3874 | * The real value can actually be different on other devices, depending | ||
3875 | * on several factors, like if LNA is enabled or not, if diversity is | ||
3876 | * enabled, type of connectors, etc. | ||
3877 | * Yet, it is better to use this measure in dB than a random non-linear | ||
3878 | * percentage value, especially for antenna adjustments. | ||
3879 | * On my tests, the precision of the measure using this table is about | ||
3880 | * 0.5 dB, with sounds reasonable enough. | ||
3881 | */ | ||
3882 | static struct linear_segments strength_to_db_table[] = { | ||
3883 | { 55953, 108500 }, /* -22.5 dBm */ | ||
3884 | { 55394, 108000 }, | ||
3885 | { 53834, 107000 }, | ||
3886 | { 52863, 106000 }, | ||
3887 | { 52239, 105000 }, | ||
3888 | { 52012, 104000 }, | ||
3889 | { 51803, 103000 }, | ||
3890 | { 51566, 102000 }, | ||
3891 | { 51356, 101000 }, | ||
3892 | { 51112, 100000 }, | ||
3893 | { 50869, 99000 }, | ||
3894 | { 50600, 98000 }, | ||
3895 | { 50363, 97000 }, | ||
3896 | { 50117, 96000 }, /* -35 dBm */ | ||
3897 | { 49889, 95000 }, | ||
3898 | { 49680, 94000 }, | ||
3899 | { 49493, 93000 }, | ||
3900 | { 49302, 92000 }, | ||
3901 | { 48929, 91000 }, | ||
3902 | { 48416, 90000 }, | ||
3903 | { 48035, 89000 }, | ||
3904 | { 47593, 88000 }, | ||
3905 | { 47282, 87000 }, | ||
3906 | { 46953, 86000 }, | ||
3907 | { 46698, 85000 }, | ||
3908 | { 45617, 84000 }, | ||
3909 | { 44773, 83000 }, | ||
3910 | { 43845, 82000 }, | ||
3911 | { 43020, 81000 }, | ||
3912 | { 42010, 80000 }, /* -51 dBm */ | ||
3913 | { 0, 0 }, | ||
3914 | }; | ||
3915 | |||
3916 | static u32 interpolate_value(u32 value, struct linear_segments *segments, | ||
3917 | unsigned len) | ||
3918 | { | ||
3919 | u64 tmp64; | ||
3920 | u32 dx; | ||
3921 | s32 dy; | ||
3922 | int i, ret; | ||
3923 | |||
3924 | if (value >= segments[0].x) | ||
3925 | return segments[0].y; | ||
3926 | if (value < segments[len-1].x) | ||
3927 | return segments[len-1].y; | ||
3928 | |||
3929 | for (i = 1; i < len - 1; i++) { | ||
3930 | /* If value is identical, no need to interpolate */ | ||
3931 | if (value == segments[i].x) | ||
3932 | return segments[i].y; | ||
3933 | if (value > segments[i].x) | ||
3934 | break; | ||
3935 | } | ||
3936 | |||
3937 | /* Linear interpolation between the two (x,y) points */ | ||
3938 | dy = segments[i - 1].y - segments[i].y; | ||
3939 | dx = segments[i - 1].x - segments[i].x; | ||
3940 | |||
3941 | tmp64 = value - segments[i].x; | ||
3942 | tmp64 *= dy; | ||
3943 | do_div(tmp64, dx); | ||
3944 | ret = segments[i].y + tmp64; | ||
3945 | |||
3946 | return ret; | ||
3947 | } | ||
3948 | |||
3949 | static u32 dib8000_get_time_us(struct dvb_frontend *fe, int layer) | ||
3950 | { | ||
3951 | struct dib8000_state *state = fe->demodulator_priv; | ||
3952 | struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache; | ||
3953 | int ini_layer, end_layer, i; | ||
3954 | u64 time_us, tmp64; | ||
3955 | u32 tmp, denom; | ||
3956 | int guard, rate_num, rate_denum = 1, bits_per_symbol, nsegs; | ||
3957 | int interleaving = 0, fft_div; | ||
3958 | |||
3959 | if (layer >= 0) { | ||
3960 | ini_layer = layer; | ||
3961 | end_layer = layer + 1; | ||
3962 | } else { | ||
3963 | ini_layer = 0; | ||
3964 | end_layer = 3; | ||
3965 | } | ||
3966 | |||
3967 | switch (c->guard_interval) { | ||
3968 | case GUARD_INTERVAL_1_4: | ||
3969 | guard = 4; | ||
3970 | break; | ||
3971 | case GUARD_INTERVAL_1_8: | ||
3972 | guard = 8; | ||
3973 | break; | ||
3974 | case GUARD_INTERVAL_1_16: | ||
3975 | guard = 16; | ||
3976 | break; | ||
3977 | default: | ||
3978 | case GUARD_INTERVAL_1_32: | ||
3979 | guard = 32; | ||
3980 | break; | ||
3981 | } | ||
3982 | |||
3983 | switch (c->transmission_mode) { | ||
3984 | case TRANSMISSION_MODE_2K: | ||
3985 | fft_div = 4; | ||
3986 | break; | ||
3987 | case TRANSMISSION_MODE_4K: | ||
3988 | fft_div = 2; | ||
3989 | break; | ||
3990 | default: | ||
3991 | case TRANSMISSION_MODE_8K: | ||
3992 | fft_div = 1; | ||
3993 | break; | ||
3994 | } | ||
3995 | |||
3996 | denom = 0; | ||
3997 | for (i = ini_layer; i < end_layer; i++) { | ||
3998 | nsegs = c->layer[i].segment_count; | ||
3999 | if (nsegs == 0 || nsegs > 13) | ||
4000 | continue; | ||
4001 | |||
4002 | switch (c->layer[i].modulation) { | ||
4003 | case DQPSK: | ||
4004 | case QPSK: | ||
4005 | bits_per_symbol = 2; | ||
4006 | break; | ||
4007 | case QAM_16: | ||
4008 | bits_per_symbol = 4; | ||
4009 | break; | ||
4010 | default: | ||
4011 | case QAM_64: | ||
4012 | bits_per_symbol = 6; | ||
4013 | break; | ||
4014 | } | ||
4015 | |||
4016 | switch (c->layer[i].fec) { | ||
4017 | case FEC_1_2: | ||
4018 | rate_num = 1; | ||
4019 | rate_denum = 2; | ||
4020 | break; | ||
4021 | case FEC_2_3: | ||
4022 | rate_num = 2; | ||
4023 | rate_denum = 3; | ||
4024 | break; | ||
4025 | case FEC_3_4: | ||
4026 | rate_num = 3; | ||
4027 | rate_denum = 4; | ||
4028 | break; | ||
4029 | case FEC_5_6: | ||
4030 | rate_num = 5; | ||
4031 | rate_denum = 6; | ||
4032 | break; | ||
4033 | default: | ||
4034 | case FEC_7_8: | ||
4035 | rate_num = 7; | ||
4036 | rate_denum = 8; | ||
4037 | break; | ||
4038 | } | ||
4039 | |||
4040 | interleaving = c->layer[i].interleaving; | ||
4041 | |||
4042 | denom += bits_per_symbol * rate_num * fft_div * nsegs * 384; | ||
4043 | } | ||
4044 | |||
4045 | /* If all goes wrong, wait for 1s for the next stats */ | ||
4046 | if (!denom) | ||
4047 | return 0; | ||
4048 | |||
4049 | /* Estimate the period for the total bit rate */ | ||
4050 | time_us = rate_denum * (1008 * 1562500L); | ||
4051 | tmp64 = time_us; | ||
4052 | do_div(tmp64, guard); | ||
4053 | time_us = time_us + tmp64; | ||
4054 | time_us += denom / 2; | ||
4055 | do_div(time_us, denom); | ||
4056 | |||
4057 | tmp = 1008 * 96 * interleaving; | ||
4058 | time_us += tmp + tmp / guard; | ||
4059 | |||
4060 | return time_us; | ||
4061 | } | ||
4062 | |||
4063 | static int dib8000_get_stats(struct dvb_frontend *fe, fe_status_t stat) | ||
4064 | { | ||
4065 | struct dib8000_state *state = fe->demodulator_priv; | ||
4066 | struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache; | ||
4067 | int i; | ||
4068 | int show_per_stats = 0; | ||
4069 | u32 time_us = 0, snr, val; | ||
4070 | u64 blocks; | ||
4071 | s32 db; | ||
4072 | u16 strength; | ||
4073 | |||
4074 | /* Get Signal strength */ | ||
4075 | dib8000_read_signal_strength(fe, &strength); | ||
4076 | val = strength; | ||
4077 | db = interpolate_value(val, | ||
4078 | strength_to_db_table, | ||
4079 | ARRAY_SIZE(strength_to_db_table)) - 131000; | ||
4080 | c->strength.stat[0].svalue = db; | ||
4081 | |||
4082 | /* UCB/BER/CNR measures require lock */ | ||
4083 | if (!(stat & FE_HAS_LOCK)) { | ||
4084 | c->cnr.len = 1; | ||
4085 | c->block_count.len = 1; | ||
4086 | c->block_error.len = 1; | ||
4087 | c->post_bit_error.len = 1; | ||
4088 | c->post_bit_count.len = 1; | ||
4089 | c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; | ||
4090 | c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; | ||
4091 | c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; | ||
4092 | c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; | ||
4093 | c->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; | ||
4094 | return 0; | ||
4095 | } | ||
4096 | |||
4097 | /* Check if time for stats was elapsed */ | ||
4098 | if (time_after(jiffies, state->per_jiffies_stats)) { | ||
4099 | state->per_jiffies_stats = jiffies + msecs_to_jiffies(1000); | ||
4100 | |||
4101 | /* Get SNR */ | ||
4102 | snr = dib8000_get_snr(fe); | ||
4103 | for (i = 1; i < MAX_NUMBER_OF_FRONTENDS; i++) { | ||
4104 | if (state->fe[i]) | ||
4105 | snr += dib8000_get_snr(state->fe[i]); | ||
4106 | } | ||
4107 | snr = snr >> 16; | ||
4108 | |||
4109 | if (snr) { | ||
4110 | snr = 10 * intlog10(snr); | ||
4111 | snr = (1000L * snr) >> 24; | ||
4112 | } else { | ||
4113 | snr = 0; | ||
4114 | } | ||
4115 | c->cnr.stat[0].svalue = snr; | ||
4116 | c->cnr.stat[0].scale = FE_SCALE_DECIBEL; | ||
4117 | |||
4118 | /* Get UCB measures */ | ||
4119 | dib8000_read_unc_blocks(fe, &val); | ||
4120 | if (val < state->init_ucb) | ||
4121 | state->init_ucb += 0x100000000LL; | ||
4122 | |||
4123 | c->block_error.stat[0].scale = FE_SCALE_COUNTER; | ||
4124 | c->block_error.stat[0].uvalue = val + state->init_ucb; | ||
4125 | |||
4126 | /* Estimate the number of packets based on bitrate */ | ||
4127 | if (!time_us) | ||
4128 | time_us = dib8000_get_time_us(fe, -1); | ||
4129 | |||
4130 | if (time_us) { | ||
4131 | blocks = 1250000ULL * 1000000ULL; | ||
4132 | do_div(blocks, time_us * 8 * 204); | ||
4133 | c->block_count.stat[0].scale = FE_SCALE_COUNTER; | ||
4134 | c->block_count.stat[0].uvalue += blocks; | ||
4135 | } | ||
4136 | |||
4137 | show_per_stats = 1; | ||
4138 | } | ||
4139 | |||
4140 | /* Get post-BER measures */ | ||
4141 | if (time_after(jiffies, state->ber_jiffies_stats)) { | ||
4142 | time_us = dib8000_get_time_us(fe, -1); | ||
4143 | state->ber_jiffies_stats = jiffies + msecs_to_jiffies((time_us + 500) / 1000); | ||
4144 | |||
4145 | dprintk("Next all layers stats available in %u us.", time_us); | ||
4146 | |||
4147 | dib8000_read_ber(fe, &val); | ||
4148 | c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER; | ||
4149 | c->post_bit_error.stat[0].uvalue += val; | ||
4150 | |||
4151 | c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER; | ||
4152 | c->post_bit_count.stat[0].uvalue += 100000000; | ||
4153 | } | ||
4154 | |||
4155 | if (state->revision < 0x8002) | ||
4156 | return 0; | ||
4157 | |||
4158 | c->block_error.len = 4; | ||
4159 | c->post_bit_error.len = 4; | ||
4160 | c->post_bit_count.len = 4; | ||
4161 | |||
4162 | for (i = 0; i < 3; i++) { | ||
4163 | unsigned nsegs = c->layer[i].segment_count; | ||
4164 | |||
4165 | if (nsegs == 0 || nsegs > 13) | ||
4166 | continue; | ||
4167 | |||
4168 | time_us = 0; | ||
4169 | |||
4170 | if (time_after(jiffies, state->ber_jiffies_stats_layer[i])) { | ||
4171 | time_us = dib8000_get_time_us(fe, i); | ||
4172 | |||
4173 | state->ber_jiffies_stats_layer[i] = jiffies + msecs_to_jiffies((time_us + 500) / 1000); | ||
4174 | dprintk("Next layer %c stats will be available in %u us\n", | ||
4175 | 'A' + i, time_us); | ||
4176 | |||
4177 | val = dib8000_read_word(state, per_layer_regs[i].ber); | ||
4178 | c->post_bit_error.stat[1 + i].scale = FE_SCALE_COUNTER; | ||
4179 | c->post_bit_error.stat[1 + i].uvalue += val; | ||
4180 | |||
4181 | c->post_bit_count.stat[1 + i].scale = FE_SCALE_COUNTER; | ||
4182 | c->post_bit_count.stat[1 + i].uvalue += 100000000; | ||
4183 | } | ||
4184 | |||
4185 | if (show_per_stats) { | ||
4186 | val = dib8000_read_word(state, per_layer_regs[i].per); | ||
4187 | |||
4188 | c->block_error.stat[1 + i].scale = FE_SCALE_COUNTER; | ||
4189 | c->block_error.stat[1 + i].uvalue += val; | ||
4190 | |||
4191 | if (!time_us) | ||
4192 | time_us = dib8000_get_time_us(fe, i); | ||
4193 | if (time_us) { | ||
4194 | blocks = 1250000ULL * 1000000ULL; | ||
4195 | do_div(blocks, time_us * 8 * 204); | ||
4196 | c->block_count.stat[0].scale = FE_SCALE_COUNTER; | ||
4197 | c->block_count.stat[0].uvalue += blocks; | ||
4198 | } | ||
4199 | } | ||
4200 | } | ||
4201 | return 0; | ||
4202 | } | ||
4203 | |||
3702 | int dib8000_set_slave_frontend(struct dvb_frontend *fe, struct dvb_frontend *fe_slave) | 4204 | int dib8000_set_slave_frontend(struct dvb_frontend *fe, struct dvb_frontend *fe_slave) |
3703 | { | 4205 | { |
3704 | struct dib8000_state *state = fe->demodulator_priv; | 4206 | struct dib8000_state *state = fe->demodulator_priv; |
diff --git a/drivers/media/dvb-frontends/drxk.h b/drivers/media/dvb-frontends/drxk.h index f22eb9f13ad5..f6cb34660327 100644 --- a/drivers/media/dvb-frontends/drxk.h +++ b/drivers/media/dvb-frontends/drxk.h | |||
@@ -29,7 +29,6 @@ | |||
29 | * A value of 0 (default) or lower indicates that | 29 | * A value of 0 (default) or lower indicates that |
30 | * the correct number of parameters will be | 30 | * the correct number of parameters will be |
31 | * automatically detected. | 31 | * automatically detected. |
32 | * @load_firmware_sync: Force the firmware load to be synchronous. | ||
33 | * | 32 | * |
34 | * On the *_gpio vars, bit 0 is UIO-1, bit 1 is UIO-2 and bit 2 is | 33 | * On the *_gpio vars, bit 0 is UIO-1, bit 1 is UIO-2 and bit 2 is |
35 | * UIO-3. | 34 | * UIO-3. |
@@ -41,7 +40,6 @@ struct drxk_config { | |||
41 | bool parallel_ts; | 40 | bool parallel_ts; |
42 | bool dynamic_clk; | 41 | bool dynamic_clk; |
43 | bool enable_merr_cfg; | 42 | bool enable_merr_cfg; |
44 | bool load_firmware_sync; | ||
45 | 43 | ||
46 | bool antenna_dvbt; | 44 | bool antenna_dvbt; |
47 | u16 antenna_gpio; | 45 | u16 antenna_gpio; |
diff --git a/drivers/media/dvb-frontends/drxk_hard.c b/drivers/media/dvb-frontends/drxk_hard.c index bf29a3f0e6f0..cce94a75b2e1 100644 --- a/drivers/media/dvb-frontends/drxk_hard.c +++ b/drivers/media/dvb-frontends/drxk_hard.c | |||
@@ -6830,25 +6830,13 @@ struct dvb_frontend *drxk_attach(const struct drxk_config *config, | |||
6830 | 6830 | ||
6831 | /* Load firmware and initialize DRX-K */ | 6831 | /* Load firmware and initialize DRX-K */ |
6832 | if (state->microcode_name) { | 6832 | if (state->microcode_name) { |
6833 | if (config->load_firmware_sync) { | 6833 | const struct firmware *fw = NULL; |
6834 | const struct firmware *fw = NULL; | ||
6835 | 6834 | ||
6836 | status = request_firmware(&fw, state->microcode_name, | 6835 | status = request_firmware(&fw, state->microcode_name, |
6837 | state->i2c->dev.parent); | 6836 | state->i2c->dev.parent); |
6838 | if (status < 0) | 6837 | if (status < 0) |
6839 | fw = NULL; | 6838 | fw = NULL; |
6840 | load_firmware_cb(fw, state); | 6839 | load_firmware_cb(fw, state); |
6841 | } else { | ||
6842 | status = request_firmware_nowait(THIS_MODULE, 1, | ||
6843 | state->microcode_name, | ||
6844 | state->i2c->dev.parent, | ||
6845 | GFP_KERNEL, | ||
6846 | state, load_firmware_cb); | ||
6847 | if (status < 0) { | ||
6848 | pr_err("failed to request a firmware\n"); | ||
6849 | return NULL; | ||
6850 | } | ||
6851 | } | ||
6852 | } else if (init_drxk(state) < 0) | 6840 | } else if (init_drxk(state) < 0) |
6853 | goto error; | 6841 | goto error; |
6854 | 6842 | ||
diff --git a/drivers/media/dvb-frontends/m88ds3103.c b/drivers/media/dvb-frontends/m88ds3103.c new file mode 100644 index 000000000000..b8a7897e7bd8 --- /dev/null +++ b/drivers/media/dvb-frontends/m88ds3103.c | |||
@@ -0,0 +1,1311 @@ | |||
1 | /* | ||
2 | * Montage M88DS3103 demodulator driver | ||
3 | * | ||
4 | * 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 | */ | ||
16 | |||
17 | #include "m88ds3103_priv.h" | ||
18 | |||
19 | static struct dvb_frontend_ops m88ds3103_ops; | ||
20 | |||
21 | /* write multiple registers */ | ||
22 | static int m88ds3103_wr_regs(struct m88ds3103_priv *priv, | ||
23 | u8 reg, const u8 *val, int len) | ||
24 | { | ||
25 | #define MAX_WR_LEN 32 | ||
26 | #define MAX_WR_XFER_LEN (MAX_WR_LEN + 1) | ||
27 | int ret; | ||
28 | u8 buf[MAX_WR_XFER_LEN]; | ||
29 | struct i2c_msg msg[1] = { | ||
30 | { | ||
31 | .addr = priv->cfg->i2c_addr, | ||
32 | .flags = 0, | ||
33 | .len = 1 + len, | ||
34 | .buf = buf, | ||
35 | } | ||
36 | }; | ||
37 | |||
38 | if (WARN_ON(len > MAX_WR_LEN)) | ||
39 | return -EINVAL; | ||
40 | |||
41 | buf[0] = reg; | ||
42 | memcpy(&buf[1], val, len); | ||
43 | |||
44 | mutex_lock(&priv->i2c_mutex); | ||
45 | ret = i2c_transfer(priv->i2c, msg, 1); | ||
46 | mutex_unlock(&priv->i2c_mutex); | ||
47 | if (ret == 1) { | ||
48 | ret = 0; | ||
49 | } else { | ||
50 | dev_warn(&priv->i2c->dev, | ||
51 | "%s: i2c wr failed=%d reg=%02x len=%d\n", | ||
52 | KBUILD_MODNAME, ret, reg, len); | ||
53 | ret = -EREMOTEIO; | ||
54 | } | ||
55 | |||
56 | return ret; | ||
57 | } | ||
58 | |||
59 | /* read multiple registers */ | ||
60 | static int m88ds3103_rd_regs(struct m88ds3103_priv *priv, | ||
61 | u8 reg, u8 *val, int len) | ||
62 | { | ||
63 | #define MAX_RD_LEN 3 | ||
64 | #define MAX_RD_XFER_LEN (MAX_RD_LEN) | ||
65 | int ret; | ||
66 | u8 buf[MAX_RD_XFER_LEN]; | ||
67 | struct i2c_msg msg[2] = { | ||
68 | { | ||
69 | .addr = priv->cfg->i2c_addr, | ||
70 | .flags = 0, | ||
71 | .len = 1, | ||
72 | .buf = ®, | ||
73 | }, { | ||
74 | .addr = priv->cfg->i2c_addr, | ||
75 | .flags = I2C_M_RD, | ||
76 | .len = len, | ||
77 | .buf = buf, | ||
78 | } | ||
79 | }; | ||
80 | |||
81 | if (WARN_ON(len > MAX_RD_LEN)) | ||
82 | return -EINVAL; | ||
83 | |||
84 | mutex_lock(&priv->i2c_mutex); | ||
85 | ret = i2c_transfer(priv->i2c, msg, 2); | ||
86 | mutex_unlock(&priv->i2c_mutex); | ||
87 | if (ret == 2) { | ||
88 | memcpy(val, buf, len); | ||
89 | ret = 0; | ||
90 | } else { | ||
91 | dev_warn(&priv->i2c->dev, | ||
92 | "%s: i2c rd failed=%d reg=%02x len=%d\n", | ||
93 | KBUILD_MODNAME, ret, reg, len); | ||
94 | ret = -EREMOTEIO; | ||
95 | } | ||
96 | |||
97 | return ret; | ||
98 | } | ||
99 | |||
100 | /* write single register */ | ||
101 | static int m88ds3103_wr_reg(struct m88ds3103_priv *priv, u8 reg, u8 val) | ||
102 | { | ||
103 | return m88ds3103_wr_regs(priv, reg, &val, 1); | ||
104 | } | ||
105 | |||
106 | /* read single register */ | ||
107 | static int m88ds3103_rd_reg(struct m88ds3103_priv *priv, u8 reg, u8 *val) | ||
108 | { | ||
109 | return m88ds3103_rd_regs(priv, reg, val, 1); | ||
110 | } | ||
111 | |||
112 | /* write single register with mask */ | ||
113 | static int m88ds3103_wr_reg_mask(struct m88ds3103_priv *priv, | ||
114 | u8 reg, u8 val, u8 mask) | ||
115 | { | ||
116 | int ret; | ||
117 | u8 u8tmp; | ||
118 | |||
119 | /* no need for read if whole reg is written */ | ||
120 | if (mask != 0xff) { | ||
121 | ret = m88ds3103_rd_regs(priv, reg, &u8tmp, 1); | ||
122 | if (ret) | ||
123 | return ret; | ||
124 | |||
125 | val &= mask; | ||
126 | u8tmp &= ~mask; | ||
127 | val |= u8tmp; | ||
128 | } | ||
129 | |||
130 | return m88ds3103_wr_regs(priv, reg, &val, 1); | ||
131 | } | ||
132 | |||
133 | /* read single register with mask */ | ||
134 | static int m88ds3103_rd_reg_mask(struct m88ds3103_priv *priv, | ||
135 | u8 reg, u8 *val, u8 mask) | ||
136 | { | ||
137 | int ret, i; | ||
138 | u8 u8tmp; | ||
139 | |||
140 | ret = m88ds3103_rd_regs(priv, reg, &u8tmp, 1); | ||
141 | if (ret) | ||
142 | return ret; | ||
143 | |||
144 | u8tmp &= mask; | ||
145 | |||
146 | /* find position of the first bit */ | ||
147 | for (i = 0; i < 8; i++) { | ||
148 | if ((mask >> i) & 0x01) | ||
149 | break; | ||
150 | } | ||
151 | *val = u8tmp >> i; | ||
152 | |||
153 | return 0; | ||
154 | } | ||
155 | |||
156 | /* write reg val table using reg addr auto increment */ | ||
157 | static int m88ds3103_wr_reg_val_tab(struct m88ds3103_priv *priv, | ||
158 | const struct m88ds3103_reg_val *tab, int tab_len) | ||
159 | { | ||
160 | int ret, i, j; | ||
161 | u8 buf[83]; | ||
162 | dev_dbg(&priv->i2c->dev, "%s: tab_len=%d\n", __func__, tab_len); | ||
163 | |||
164 | if (tab_len > 83) { | ||
165 | ret = -EINVAL; | ||
166 | goto err; | ||
167 | } | ||
168 | |||
169 | for (i = 0, j = 0; i < tab_len; i++, j++) { | ||
170 | buf[j] = tab[i].val; | ||
171 | |||
172 | if (i == tab_len - 1 || tab[i].reg != tab[i + 1].reg - 1 || | ||
173 | !((j + 1) % (priv->cfg->i2c_wr_max - 1))) { | ||
174 | ret = m88ds3103_wr_regs(priv, tab[i].reg - j, buf, j + 1); | ||
175 | if (ret) | ||
176 | goto err; | ||
177 | |||
178 | j = -1; | ||
179 | } | ||
180 | } | ||
181 | |||
182 | return 0; | ||
183 | err: | ||
184 | dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); | ||
185 | return ret; | ||
186 | } | ||
187 | |||
188 | static int m88ds3103_read_status(struct dvb_frontend *fe, fe_status_t *status) | ||
189 | { | ||
190 | struct m88ds3103_priv *priv = fe->demodulator_priv; | ||
191 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
192 | int ret; | ||
193 | u8 u8tmp; | ||
194 | |||
195 | *status = 0; | ||
196 | |||
197 | if (!priv->warm) { | ||
198 | ret = -EAGAIN; | ||
199 | goto err; | ||
200 | } | ||
201 | |||
202 | switch (c->delivery_system) { | ||
203 | case SYS_DVBS: | ||
204 | ret = m88ds3103_rd_reg_mask(priv, 0xd1, &u8tmp, 0x07); | ||
205 | if (ret) | ||
206 | goto err; | ||
207 | |||
208 | if (u8tmp == 0x07) | ||
209 | *status = FE_HAS_SIGNAL | FE_HAS_CARRIER | | ||
210 | FE_HAS_VITERBI | FE_HAS_SYNC | | ||
211 | FE_HAS_LOCK; | ||
212 | break; | ||
213 | case SYS_DVBS2: | ||
214 | ret = m88ds3103_rd_reg_mask(priv, 0x0d, &u8tmp, 0x8f); | ||
215 | if (ret) | ||
216 | goto err; | ||
217 | |||
218 | if (u8tmp == 0x8f) | ||
219 | *status = FE_HAS_SIGNAL | FE_HAS_CARRIER | | ||
220 | FE_HAS_VITERBI | FE_HAS_SYNC | | ||
221 | FE_HAS_LOCK; | ||
222 | break; | ||
223 | default: | ||
224 | dev_dbg(&priv->i2c->dev, "%s: invalid delivery_system\n", | ||
225 | __func__); | ||
226 | ret = -EINVAL; | ||
227 | goto err; | ||
228 | } | ||
229 | |||
230 | priv->fe_status = *status; | ||
231 | |||
232 | dev_dbg(&priv->i2c->dev, "%s: lock=%02x status=%02x\n", | ||
233 | __func__, u8tmp, *status); | ||
234 | |||
235 | return 0; | ||
236 | err: | ||
237 | dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); | ||
238 | return ret; | ||
239 | } | ||
240 | |||
241 | static int m88ds3103_set_frontend(struct dvb_frontend *fe) | ||
242 | { | ||
243 | struct m88ds3103_priv *priv = fe->demodulator_priv; | ||
244 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
245 | int ret, len; | ||
246 | const struct m88ds3103_reg_val *init; | ||
247 | u8 u8tmp, u8tmp1, u8tmp2; | ||
248 | u8 buf[2]; | ||
249 | u16 u16tmp, divide_ratio; | ||
250 | u32 tuner_frequency, target_mclk, ts_clk; | ||
251 | s32 s32tmp; | ||
252 | dev_dbg(&priv->i2c->dev, | ||
253 | "%s: delivery_system=%d modulation=%d frequency=%d symbol_rate=%d inversion=%d pilot=%d rolloff=%d\n", | ||
254 | __func__, c->delivery_system, | ||
255 | c->modulation, c->frequency, c->symbol_rate, | ||
256 | c->inversion, c->pilot, c->rolloff); | ||
257 | |||
258 | if (!priv->warm) { | ||
259 | ret = -EAGAIN; | ||
260 | goto err; | ||
261 | } | ||
262 | |||
263 | /* program tuner */ | ||
264 | if (fe->ops.tuner_ops.set_params) { | ||
265 | ret = fe->ops.tuner_ops.set_params(fe); | ||
266 | if (ret) | ||
267 | goto err; | ||
268 | } | ||
269 | |||
270 | if (fe->ops.tuner_ops.get_frequency) { | ||
271 | ret = fe->ops.tuner_ops.get_frequency(fe, &tuner_frequency); | ||
272 | if (ret) | ||
273 | goto err; | ||
274 | } | ||
275 | |||
276 | /* reset */ | ||
277 | ret = m88ds3103_wr_reg(priv, 0x07, 0x80); | ||
278 | if (ret) | ||
279 | goto err; | ||
280 | |||
281 | ret = m88ds3103_wr_reg(priv, 0x07, 0x00); | ||
282 | if (ret) | ||
283 | goto err; | ||
284 | |||
285 | ret = m88ds3103_wr_reg(priv, 0xb2, 0x01); | ||
286 | if (ret) | ||
287 | goto err; | ||
288 | |||
289 | ret = m88ds3103_wr_reg(priv, 0x00, 0x01); | ||
290 | if (ret) | ||
291 | goto err; | ||
292 | |||
293 | switch (c->delivery_system) { | ||
294 | case SYS_DVBS: | ||
295 | len = ARRAY_SIZE(m88ds3103_dvbs_init_reg_vals); | ||
296 | init = m88ds3103_dvbs_init_reg_vals; | ||
297 | target_mclk = 96000; | ||
298 | break; | ||
299 | case SYS_DVBS2: | ||
300 | len = ARRAY_SIZE(m88ds3103_dvbs2_init_reg_vals); | ||
301 | init = m88ds3103_dvbs2_init_reg_vals; | ||
302 | |||
303 | switch (priv->cfg->ts_mode) { | ||
304 | case M88DS3103_TS_SERIAL: | ||
305 | case M88DS3103_TS_SERIAL_D7: | ||
306 | if (c->symbol_rate < 18000000) | ||
307 | target_mclk = 96000; | ||
308 | else | ||
309 | target_mclk = 144000; | ||
310 | break; | ||
311 | case M88DS3103_TS_PARALLEL: | ||
312 | case M88DS3103_TS_PARALLEL_12: | ||
313 | case M88DS3103_TS_PARALLEL_16: | ||
314 | case M88DS3103_TS_PARALLEL_19_2: | ||
315 | case M88DS3103_TS_CI: | ||
316 | if (c->symbol_rate < 18000000) | ||
317 | target_mclk = 96000; | ||
318 | else if (c->symbol_rate < 28000000) | ||
319 | target_mclk = 144000; | ||
320 | else | ||
321 | target_mclk = 192000; | ||
322 | break; | ||
323 | default: | ||
324 | dev_dbg(&priv->i2c->dev, "%s: invalid ts_mode\n", | ||
325 | __func__); | ||
326 | ret = -EINVAL; | ||
327 | goto err; | ||
328 | } | ||
329 | break; | ||
330 | default: | ||
331 | dev_dbg(&priv->i2c->dev, "%s: invalid delivery_system\n", | ||
332 | __func__); | ||
333 | ret = -EINVAL; | ||
334 | goto err; | ||
335 | } | ||
336 | |||
337 | /* program init table */ | ||
338 | if (c->delivery_system != priv->delivery_system) { | ||
339 | ret = m88ds3103_wr_reg_val_tab(priv, init, len); | ||
340 | if (ret) | ||
341 | goto err; | ||
342 | } | ||
343 | |||
344 | u8tmp1 = 0; /* silence compiler warning */ | ||
345 | switch (priv->cfg->ts_mode) { | ||
346 | case M88DS3103_TS_SERIAL: | ||
347 | u8tmp1 = 0x00; | ||
348 | ts_clk = 0; | ||
349 | u8tmp = 0x46; | ||
350 | break; | ||
351 | case M88DS3103_TS_SERIAL_D7: | ||
352 | u8tmp1 = 0x20; | ||
353 | ts_clk = 0; | ||
354 | u8tmp = 0x46; | ||
355 | break; | ||
356 | case M88DS3103_TS_PARALLEL: | ||
357 | ts_clk = 24000; | ||
358 | u8tmp = 0x42; | ||
359 | break; | ||
360 | case M88DS3103_TS_PARALLEL_12: | ||
361 | ts_clk = 12000; | ||
362 | u8tmp = 0x42; | ||
363 | break; | ||
364 | case M88DS3103_TS_PARALLEL_16: | ||
365 | ts_clk = 16000; | ||
366 | u8tmp = 0x42; | ||
367 | break; | ||
368 | case M88DS3103_TS_PARALLEL_19_2: | ||
369 | ts_clk = 19200; | ||
370 | u8tmp = 0x42; | ||
371 | break; | ||
372 | case M88DS3103_TS_CI: | ||
373 | ts_clk = 6000; | ||
374 | u8tmp = 0x43; | ||
375 | break; | ||
376 | default: | ||
377 | dev_dbg(&priv->i2c->dev, "%s: invalid ts_mode\n", __func__); | ||
378 | ret = -EINVAL; | ||
379 | goto err; | ||
380 | } | ||
381 | |||
382 | /* TS mode */ | ||
383 | ret = m88ds3103_wr_reg(priv, 0xfd, u8tmp); | ||
384 | if (ret) | ||
385 | goto err; | ||
386 | |||
387 | switch (priv->cfg->ts_mode) { | ||
388 | case M88DS3103_TS_SERIAL: | ||
389 | case M88DS3103_TS_SERIAL_D7: | ||
390 | ret = m88ds3103_wr_reg_mask(priv, 0x29, u8tmp1, 0x20); | ||
391 | if (ret) | ||
392 | goto err; | ||
393 | } | ||
394 | |||
395 | if (ts_clk) { | ||
396 | divide_ratio = DIV_ROUND_UP(target_mclk, ts_clk); | ||
397 | u8tmp1 = divide_ratio / 2; | ||
398 | u8tmp2 = DIV_ROUND_UP(divide_ratio, 2); | ||
399 | } else { | ||
400 | divide_ratio = 0; | ||
401 | u8tmp1 = 0; | ||
402 | u8tmp2 = 0; | ||
403 | } | ||
404 | |||
405 | dev_dbg(&priv->i2c->dev, | ||
406 | "%s: target_mclk=%d ts_clk=%d divide_ratio=%d\n", | ||
407 | __func__, target_mclk, ts_clk, divide_ratio); | ||
408 | |||
409 | u8tmp1--; | ||
410 | u8tmp2--; | ||
411 | /* u8tmp1[5:2] => fe[3:0], u8tmp1[1:0] => ea[7:6] */ | ||
412 | u8tmp1 &= 0x3f; | ||
413 | /* u8tmp2[5:0] => ea[5:0] */ | ||
414 | u8tmp2 &= 0x3f; | ||
415 | |||
416 | ret = m88ds3103_rd_reg(priv, 0xfe, &u8tmp); | ||
417 | if (ret) | ||
418 | goto err; | ||
419 | |||
420 | u8tmp = ((u8tmp & 0xf0) << 0) | u8tmp1 >> 2; | ||
421 | ret = m88ds3103_wr_reg(priv, 0xfe, u8tmp); | ||
422 | if (ret) | ||
423 | goto err; | ||
424 | |||
425 | u8tmp = ((u8tmp1 & 0x03) << 6) | u8tmp2 >> 0; | ||
426 | ret = m88ds3103_wr_reg(priv, 0xea, u8tmp); | ||
427 | if (ret) | ||
428 | goto err; | ||
429 | |||
430 | switch (target_mclk) { | ||
431 | case 72000: | ||
432 | u8tmp1 = 0x00; /* 0b00 */ | ||
433 | u8tmp2 = 0x03; /* 0b11 */ | ||
434 | break; | ||
435 | case 96000: | ||
436 | u8tmp1 = 0x02; /* 0b10 */ | ||
437 | u8tmp2 = 0x01; /* 0b01 */ | ||
438 | break; | ||
439 | case 115200: | ||
440 | u8tmp1 = 0x01; /* 0b01 */ | ||
441 | u8tmp2 = 0x01; /* 0b01 */ | ||
442 | break; | ||
443 | case 144000: | ||
444 | u8tmp1 = 0x00; /* 0b00 */ | ||
445 | u8tmp2 = 0x01; /* 0b01 */ | ||
446 | break; | ||
447 | case 192000: | ||
448 | u8tmp1 = 0x03; /* 0b11 */ | ||
449 | u8tmp2 = 0x00; /* 0b00 */ | ||
450 | break; | ||
451 | default: | ||
452 | dev_dbg(&priv->i2c->dev, "%s: invalid target_mclk\n", __func__); | ||
453 | ret = -EINVAL; | ||
454 | goto err; | ||
455 | } | ||
456 | |||
457 | ret = m88ds3103_wr_reg_mask(priv, 0x22, u8tmp1 << 6, 0xc0); | ||
458 | if (ret) | ||
459 | goto err; | ||
460 | |||
461 | ret = m88ds3103_wr_reg_mask(priv, 0x24, u8tmp2 << 6, 0xc0); | ||
462 | if (ret) | ||
463 | goto err; | ||
464 | |||
465 | if (c->symbol_rate <= 3000000) | ||
466 | u8tmp = 0x20; | ||
467 | else if (c->symbol_rate <= 10000000) | ||
468 | u8tmp = 0x10; | ||
469 | else | ||
470 | u8tmp = 0x06; | ||
471 | |||
472 | ret = m88ds3103_wr_reg(priv, 0xc3, 0x08); | ||
473 | if (ret) | ||
474 | goto err; | ||
475 | |||
476 | ret = m88ds3103_wr_reg(priv, 0xc8, u8tmp); | ||
477 | if (ret) | ||
478 | goto err; | ||
479 | |||
480 | ret = m88ds3103_wr_reg(priv, 0xc4, 0x08); | ||
481 | if (ret) | ||
482 | goto err; | ||
483 | |||
484 | ret = m88ds3103_wr_reg(priv, 0xc7, 0x00); | ||
485 | if (ret) | ||
486 | goto err; | ||
487 | |||
488 | u16tmp = DIV_ROUND_CLOSEST((c->symbol_rate / 1000) << 15, M88DS3103_MCLK_KHZ / 2); | ||
489 | buf[0] = (u16tmp >> 0) & 0xff; | ||
490 | buf[1] = (u16tmp >> 8) & 0xff; | ||
491 | ret = m88ds3103_wr_regs(priv, 0x61, buf, 2); | ||
492 | if (ret) | ||
493 | goto err; | ||
494 | |||
495 | ret = m88ds3103_wr_reg_mask(priv, 0x4d, priv->cfg->spec_inv << 1, 0x02); | ||
496 | if (ret) | ||
497 | goto err; | ||
498 | |||
499 | ret = m88ds3103_wr_reg_mask(priv, 0x30, priv->cfg->agc_inv << 4, 0x10); | ||
500 | if (ret) | ||
501 | goto err; | ||
502 | |||
503 | ret = m88ds3103_wr_reg(priv, 0x33, priv->cfg->agc); | ||
504 | if (ret) | ||
505 | goto err; | ||
506 | |||
507 | dev_dbg(&priv->i2c->dev, "%s: carrier offset=%d\n", __func__, | ||
508 | (tuner_frequency - c->frequency)); | ||
509 | |||
510 | s32tmp = 0x10000 * (tuner_frequency - c->frequency); | ||
511 | s32tmp = DIV_ROUND_CLOSEST(s32tmp, M88DS3103_MCLK_KHZ); | ||
512 | if (s32tmp < 0) | ||
513 | s32tmp += 0x10000; | ||
514 | |||
515 | buf[0] = (s32tmp >> 0) & 0xff; | ||
516 | buf[1] = (s32tmp >> 8) & 0xff; | ||
517 | ret = m88ds3103_wr_regs(priv, 0x5e, buf, 2); | ||
518 | if (ret) | ||
519 | goto err; | ||
520 | |||
521 | ret = m88ds3103_wr_reg(priv, 0x00, 0x00); | ||
522 | if (ret) | ||
523 | goto err; | ||
524 | |||
525 | ret = m88ds3103_wr_reg(priv, 0xb2, 0x00); | ||
526 | if (ret) | ||
527 | goto err; | ||
528 | |||
529 | priv->delivery_system = c->delivery_system; | ||
530 | |||
531 | return 0; | ||
532 | err: | ||
533 | dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); | ||
534 | return ret; | ||
535 | } | ||
536 | |||
537 | static int m88ds3103_init(struct dvb_frontend *fe) | ||
538 | { | ||
539 | struct m88ds3103_priv *priv = fe->demodulator_priv; | ||
540 | int ret, len, remaining; | ||
541 | const struct firmware *fw = NULL; | ||
542 | u8 *fw_file = M88DS3103_FIRMWARE; | ||
543 | u8 u8tmp; | ||
544 | dev_dbg(&priv->i2c->dev, "%s:\n", __func__); | ||
545 | |||
546 | /* set cold state by default */ | ||
547 | priv->warm = false; | ||
548 | |||
549 | /* wake up device from sleep */ | ||
550 | ret = m88ds3103_wr_reg_mask(priv, 0x08, 0x01, 0x01); | ||
551 | if (ret) | ||
552 | goto err; | ||
553 | |||
554 | ret = m88ds3103_wr_reg_mask(priv, 0x04, 0x00, 0x01); | ||
555 | if (ret) | ||
556 | goto err; | ||
557 | |||
558 | ret = m88ds3103_wr_reg_mask(priv, 0x23, 0x00, 0x10); | ||
559 | if (ret) | ||
560 | goto err; | ||
561 | |||
562 | /* reset */ | ||
563 | ret = m88ds3103_wr_reg(priv, 0x07, 0x60); | ||
564 | if (ret) | ||
565 | goto err; | ||
566 | |||
567 | ret = m88ds3103_wr_reg(priv, 0x07, 0x00); | ||
568 | if (ret) | ||
569 | goto err; | ||
570 | |||
571 | /* firmware status */ | ||
572 | ret = m88ds3103_rd_reg(priv, 0xb9, &u8tmp); | ||
573 | if (ret) | ||
574 | goto err; | ||
575 | |||
576 | dev_dbg(&priv->i2c->dev, "%s: firmware=%02x\n", __func__, u8tmp); | ||
577 | |||
578 | if (u8tmp) | ||
579 | goto skip_fw_download; | ||
580 | |||
581 | /* cold state - try to download firmware */ | ||
582 | dev_info(&priv->i2c->dev, "%s: found a '%s' in cold state\n", | ||
583 | KBUILD_MODNAME, m88ds3103_ops.info.name); | ||
584 | |||
585 | /* request the firmware, this will block and timeout */ | ||
586 | ret = request_firmware(&fw, fw_file, priv->i2c->dev.parent); | ||
587 | if (ret) { | ||
588 | dev_err(&priv->i2c->dev, "%s: firmare file '%s' not found\n", | ||
589 | KBUILD_MODNAME, fw_file); | ||
590 | goto err; | ||
591 | } | ||
592 | |||
593 | dev_info(&priv->i2c->dev, "%s: downloading firmware from file '%s'\n", | ||
594 | KBUILD_MODNAME, fw_file); | ||
595 | |||
596 | ret = m88ds3103_wr_reg(priv, 0xb2, 0x01); | ||
597 | if (ret) | ||
598 | goto err; | ||
599 | |||
600 | for (remaining = fw->size; remaining > 0; | ||
601 | remaining -= (priv->cfg->i2c_wr_max - 1)) { | ||
602 | len = remaining; | ||
603 | if (len > (priv->cfg->i2c_wr_max - 1)) | ||
604 | len = (priv->cfg->i2c_wr_max - 1); | ||
605 | |||
606 | ret = m88ds3103_wr_regs(priv, 0xb0, | ||
607 | &fw->data[fw->size - remaining], len); | ||
608 | if (ret) { | ||
609 | dev_err(&priv->i2c->dev, | ||
610 | "%s: firmware download failed=%d\n", | ||
611 | KBUILD_MODNAME, ret); | ||
612 | goto err; | ||
613 | } | ||
614 | } | ||
615 | |||
616 | ret = m88ds3103_wr_reg(priv, 0xb2, 0x00); | ||
617 | if (ret) | ||
618 | goto err; | ||
619 | |||
620 | release_firmware(fw); | ||
621 | fw = NULL; | ||
622 | |||
623 | ret = m88ds3103_rd_reg(priv, 0xb9, &u8tmp); | ||
624 | if (ret) | ||
625 | goto err; | ||
626 | |||
627 | if (!u8tmp) { | ||
628 | dev_info(&priv->i2c->dev, "%s: firmware did not run\n", | ||
629 | KBUILD_MODNAME); | ||
630 | ret = -EFAULT; | ||
631 | goto err; | ||
632 | } | ||
633 | |||
634 | dev_info(&priv->i2c->dev, "%s: found a '%s' in warm state\n", | ||
635 | KBUILD_MODNAME, m88ds3103_ops.info.name); | ||
636 | dev_info(&priv->i2c->dev, "%s: firmware version %X.%X\n", | ||
637 | KBUILD_MODNAME, (u8tmp >> 4) & 0xf, (u8tmp >> 0 & 0xf)); | ||
638 | |||
639 | skip_fw_download: | ||
640 | /* warm state */ | ||
641 | priv->warm = true; | ||
642 | |||
643 | return 0; | ||
644 | err: | ||
645 | if (fw) | ||
646 | release_firmware(fw); | ||
647 | |||
648 | dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); | ||
649 | return ret; | ||
650 | } | ||
651 | |||
652 | static int m88ds3103_sleep(struct dvb_frontend *fe) | ||
653 | { | ||
654 | struct m88ds3103_priv *priv = fe->demodulator_priv; | ||
655 | int ret; | ||
656 | dev_dbg(&priv->i2c->dev, "%s:\n", __func__); | ||
657 | |||
658 | priv->delivery_system = SYS_UNDEFINED; | ||
659 | |||
660 | /* TS Hi-Z */ | ||
661 | ret = m88ds3103_wr_reg_mask(priv, 0x27, 0x00, 0x01); | ||
662 | if (ret) | ||
663 | goto err; | ||
664 | |||
665 | /* sleep */ | ||
666 | ret = m88ds3103_wr_reg_mask(priv, 0x08, 0x00, 0x01); | ||
667 | if (ret) | ||
668 | goto err; | ||
669 | |||
670 | ret = m88ds3103_wr_reg_mask(priv, 0x04, 0x01, 0x01); | ||
671 | if (ret) | ||
672 | goto err; | ||
673 | |||
674 | ret = m88ds3103_wr_reg_mask(priv, 0x23, 0x10, 0x10); | ||
675 | if (ret) | ||
676 | goto err; | ||
677 | |||
678 | return 0; | ||
679 | err: | ||
680 | dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); | ||
681 | return ret; | ||
682 | } | ||
683 | |||
684 | static int m88ds3103_get_frontend(struct dvb_frontend *fe) | ||
685 | { | ||
686 | struct m88ds3103_priv *priv = fe->demodulator_priv; | ||
687 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
688 | int ret; | ||
689 | u8 buf[3]; | ||
690 | dev_dbg(&priv->i2c->dev, "%s:\n", __func__); | ||
691 | |||
692 | if (!priv->warm || !(priv->fe_status & FE_HAS_LOCK)) { | ||
693 | ret = -EAGAIN; | ||
694 | goto err; | ||
695 | } | ||
696 | |||
697 | switch (c->delivery_system) { | ||
698 | case SYS_DVBS: | ||
699 | ret = m88ds3103_rd_reg(priv, 0xe0, &buf[0]); | ||
700 | if (ret) | ||
701 | goto err; | ||
702 | |||
703 | ret = m88ds3103_rd_reg(priv, 0xe6, &buf[1]); | ||
704 | if (ret) | ||
705 | goto err; | ||
706 | |||
707 | switch ((buf[0] >> 2) & 0x01) { | ||
708 | case 0: | ||
709 | c->inversion = INVERSION_OFF; | ||
710 | break; | ||
711 | case 1: | ||
712 | c->inversion = INVERSION_ON; | ||
713 | break; | ||
714 | default: | ||
715 | dev_dbg(&priv->i2c->dev, "%s: invalid inversion\n", | ||
716 | __func__); | ||
717 | } | ||
718 | |||
719 | switch ((buf[1] >> 5) & 0x07) { | ||
720 | case 0: | ||
721 | c->fec_inner = FEC_7_8; | ||
722 | break; | ||
723 | case 1: | ||
724 | c->fec_inner = FEC_5_6; | ||
725 | break; | ||
726 | case 2: | ||
727 | c->fec_inner = FEC_3_4; | ||
728 | break; | ||
729 | case 3: | ||
730 | c->fec_inner = FEC_2_3; | ||
731 | break; | ||
732 | case 4: | ||
733 | c->fec_inner = FEC_1_2; | ||
734 | break; | ||
735 | default: | ||
736 | dev_dbg(&priv->i2c->dev, "%s: invalid fec_inner\n", | ||
737 | __func__); | ||
738 | } | ||
739 | |||
740 | c->modulation = QPSK; | ||
741 | |||
742 | break; | ||
743 | case SYS_DVBS2: | ||
744 | ret = m88ds3103_rd_reg(priv, 0x7e, &buf[0]); | ||
745 | if (ret) | ||
746 | goto err; | ||
747 | |||
748 | ret = m88ds3103_rd_reg(priv, 0x89, &buf[1]); | ||
749 | if (ret) | ||
750 | goto err; | ||
751 | |||
752 | ret = m88ds3103_rd_reg(priv, 0xf2, &buf[2]); | ||
753 | if (ret) | ||
754 | goto err; | ||
755 | |||
756 | switch ((buf[0] >> 0) & 0x0f) { | ||
757 | case 2: | ||
758 | c->fec_inner = FEC_2_5; | ||
759 | break; | ||
760 | case 3: | ||
761 | c->fec_inner = FEC_1_2; | ||
762 | break; | ||
763 | case 4: | ||
764 | c->fec_inner = FEC_3_5; | ||
765 | break; | ||
766 | case 5: | ||
767 | c->fec_inner = FEC_2_3; | ||
768 | break; | ||
769 | case 6: | ||
770 | c->fec_inner = FEC_3_4; | ||
771 | break; | ||
772 | case 7: | ||
773 | c->fec_inner = FEC_4_5; | ||
774 | break; | ||
775 | case 8: | ||
776 | c->fec_inner = FEC_5_6; | ||
777 | break; | ||
778 | case 9: | ||
779 | c->fec_inner = FEC_8_9; | ||
780 | break; | ||
781 | case 10: | ||
782 | c->fec_inner = FEC_9_10; | ||
783 | break; | ||
784 | default: | ||
785 | dev_dbg(&priv->i2c->dev, "%s: invalid fec_inner\n", | ||
786 | __func__); | ||
787 | } | ||
788 | |||
789 | switch ((buf[0] >> 5) & 0x01) { | ||
790 | case 0: | ||
791 | c->pilot = PILOT_OFF; | ||
792 | break; | ||
793 | case 1: | ||
794 | c->pilot = PILOT_ON; | ||
795 | break; | ||
796 | default: | ||
797 | dev_dbg(&priv->i2c->dev, "%s: invalid pilot\n", | ||
798 | __func__); | ||
799 | } | ||
800 | |||
801 | switch ((buf[0] >> 6) & 0x07) { | ||
802 | case 0: | ||
803 | c->modulation = QPSK; | ||
804 | break; | ||
805 | case 1: | ||
806 | c->modulation = PSK_8; | ||
807 | break; | ||
808 | case 2: | ||
809 | c->modulation = APSK_16; | ||
810 | break; | ||
811 | case 3: | ||
812 | c->modulation = APSK_32; | ||
813 | break; | ||
814 | default: | ||
815 | dev_dbg(&priv->i2c->dev, "%s: invalid modulation\n", | ||
816 | __func__); | ||
817 | } | ||
818 | |||
819 | switch ((buf[1] >> 7) & 0x01) { | ||
820 | case 0: | ||
821 | c->inversion = INVERSION_OFF; | ||
822 | break; | ||
823 | case 1: | ||
824 | c->inversion = INVERSION_ON; | ||
825 | break; | ||
826 | default: | ||
827 | dev_dbg(&priv->i2c->dev, "%s: invalid inversion\n", | ||
828 | __func__); | ||
829 | } | ||
830 | |||
831 | switch ((buf[2] >> 0) & 0x03) { | ||
832 | case 0: | ||
833 | c->rolloff = ROLLOFF_35; | ||
834 | break; | ||
835 | case 1: | ||
836 | c->rolloff = ROLLOFF_25; | ||
837 | break; | ||
838 | case 2: | ||
839 | c->rolloff = ROLLOFF_20; | ||
840 | break; | ||
841 | default: | ||
842 | dev_dbg(&priv->i2c->dev, "%s: invalid rolloff\n", | ||
843 | __func__); | ||
844 | } | ||
845 | break; | ||
846 | default: | ||
847 | dev_dbg(&priv->i2c->dev, "%s: invalid delivery_system\n", | ||
848 | __func__); | ||
849 | ret = -EINVAL; | ||
850 | goto err; | ||
851 | } | ||
852 | |||
853 | ret = m88ds3103_rd_regs(priv, 0x6d, buf, 2); | ||
854 | if (ret) | ||
855 | goto err; | ||
856 | |||
857 | c->symbol_rate = 1ull * ((buf[1] << 8) | (buf[0] << 0)) * | ||
858 | M88DS3103_MCLK_KHZ * 1000 / 0x10000; | ||
859 | |||
860 | return 0; | ||
861 | err: | ||
862 | dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); | ||
863 | return ret; | ||
864 | } | ||
865 | |||
866 | static int m88ds3103_read_snr(struct dvb_frontend *fe, u16 *snr) | ||
867 | { | ||
868 | struct m88ds3103_priv *priv = fe->demodulator_priv; | ||
869 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
870 | int ret, i, tmp; | ||
871 | u8 buf[3]; | ||
872 | u16 noise, signal; | ||
873 | u32 noise_tot, signal_tot; | ||
874 | dev_dbg(&priv->i2c->dev, "%s:\n", __func__); | ||
875 | /* reports SNR in resolution of 0.1 dB */ | ||
876 | |||
877 | /* more iterations for more accurate estimation */ | ||
878 | #define M88DS3103_SNR_ITERATIONS 3 | ||
879 | |||
880 | switch (c->delivery_system) { | ||
881 | case SYS_DVBS: | ||
882 | tmp = 0; | ||
883 | |||
884 | for (i = 0; i < M88DS3103_SNR_ITERATIONS; i++) { | ||
885 | ret = m88ds3103_rd_reg(priv, 0xff, &buf[0]); | ||
886 | if (ret) | ||
887 | goto err; | ||
888 | |||
889 | tmp += buf[0]; | ||
890 | } | ||
891 | |||
892 | /* use of one register limits max value to 15 dB */ | ||
893 | /* SNR(X) dB = 10 * ln(X) / ln(10) dB */ | ||
894 | tmp = DIV_ROUND_CLOSEST(tmp, 8 * M88DS3103_SNR_ITERATIONS); | ||
895 | if (tmp) | ||
896 | *snr = 100ul * intlog2(tmp) / intlog2(10); | ||
897 | else | ||
898 | *snr = 0; | ||
899 | break; | ||
900 | case SYS_DVBS2: | ||
901 | noise_tot = 0; | ||
902 | signal_tot = 0; | ||
903 | |||
904 | for (i = 0; i < M88DS3103_SNR_ITERATIONS; i++) { | ||
905 | ret = m88ds3103_rd_regs(priv, 0x8c, buf, 3); | ||
906 | if (ret) | ||
907 | goto err; | ||
908 | |||
909 | noise = buf[1] << 6; /* [13:6] */ | ||
910 | noise |= buf[0] & 0x3f; /* [5:0] */ | ||
911 | noise >>= 2; | ||
912 | signal = buf[2] * buf[2]; | ||
913 | signal >>= 1; | ||
914 | |||
915 | noise_tot += noise; | ||
916 | signal_tot += signal; | ||
917 | } | ||
918 | |||
919 | noise = noise_tot / M88DS3103_SNR_ITERATIONS; | ||
920 | signal = signal_tot / M88DS3103_SNR_ITERATIONS; | ||
921 | |||
922 | /* SNR(X) dB = 10 * log10(X) dB */ | ||
923 | if (signal > noise) { | ||
924 | tmp = signal / noise; | ||
925 | *snr = 100ul * intlog10(tmp) / (1 << 24); | ||
926 | } else { | ||
927 | *snr = 0; | ||
928 | } | ||
929 | break; | ||
930 | default: | ||
931 | dev_dbg(&priv->i2c->dev, "%s: invalid delivery_system\n", | ||
932 | __func__); | ||
933 | ret = -EINVAL; | ||
934 | goto err; | ||
935 | } | ||
936 | |||
937 | return 0; | ||
938 | err: | ||
939 | dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); | ||
940 | return ret; | ||
941 | } | ||
942 | |||
943 | |||
944 | static int m88ds3103_set_tone(struct dvb_frontend *fe, | ||
945 | fe_sec_tone_mode_t fe_sec_tone_mode) | ||
946 | { | ||
947 | struct m88ds3103_priv *priv = fe->demodulator_priv; | ||
948 | int ret; | ||
949 | u8 u8tmp, tone, reg_a1_mask; | ||
950 | dev_dbg(&priv->i2c->dev, "%s: fe_sec_tone_mode=%d\n", __func__, | ||
951 | fe_sec_tone_mode); | ||
952 | |||
953 | if (!priv->warm) { | ||
954 | ret = -EAGAIN; | ||
955 | goto err; | ||
956 | } | ||
957 | |||
958 | switch (fe_sec_tone_mode) { | ||
959 | case SEC_TONE_ON: | ||
960 | tone = 0; | ||
961 | reg_a1_mask = 0x87; | ||
962 | break; | ||
963 | case SEC_TONE_OFF: | ||
964 | tone = 1; | ||
965 | reg_a1_mask = 0x00; | ||
966 | break; | ||
967 | default: | ||
968 | dev_dbg(&priv->i2c->dev, "%s: invalid fe_sec_tone_mode\n", | ||
969 | __func__); | ||
970 | ret = -EINVAL; | ||
971 | goto err; | ||
972 | } | ||
973 | |||
974 | u8tmp = tone << 7 | priv->cfg->envelope_mode << 5; | ||
975 | ret = m88ds3103_wr_reg_mask(priv, 0xa2, u8tmp, 0xe0); | ||
976 | if (ret) | ||
977 | goto err; | ||
978 | |||
979 | u8tmp = 1 << 2; | ||
980 | ret = m88ds3103_wr_reg_mask(priv, 0xa1, u8tmp, reg_a1_mask); | ||
981 | if (ret) | ||
982 | goto err; | ||
983 | |||
984 | return 0; | ||
985 | err: | ||
986 | dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); | ||
987 | return ret; | ||
988 | } | ||
989 | |||
990 | static int m88ds3103_diseqc_send_master_cmd(struct dvb_frontend *fe, | ||
991 | struct dvb_diseqc_master_cmd *diseqc_cmd) | ||
992 | { | ||
993 | struct m88ds3103_priv *priv = fe->demodulator_priv; | ||
994 | int ret, i; | ||
995 | u8 u8tmp; | ||
996 | dev_dbg(&priv->i2c->dev, "%s: msg=%*ph\n", __func__, | ||
997 | diseqc_cmd->msg_len, diseqc_cmd->msg); | ||
998 | |||
999 | if (!priv->warm) { | ||
1000 | ret = -EAGAIN; | ||
1001 | goto err; | ||
1002 | } | ||
1003 | |||
1004 | if (diseqc_cmd->msg_len < 3 || diseqc_cmd->msg_len > 6) { | ||
1005 | ret = -EINVAL; | ||
1006 | goto err; | ||
1007 | } | ||
1008 | |||
1009 | u8tmp = priv->cfg->envelope_mode << 5; | ||
1010 | ret = m88ds3103_wr_reg_mask(priv, 0xa2, u8tmp, 0xe0); | ||
1011 | if (ret) | ||
1012 | goto err; | ||
1013 | |||
1014 | ret = m88ds3103_wr_regs(priv, 0xa3, diseqc_cmd->msg, | ||
1015 | diseqc_cmd->msg_len); | ||
1016 | if (ret) | ||
1017 | goto err; | ||
1018 | |||
1019 | ret = m88ds3103_wr_reg(priv, 0xa1, | ||
1020 | (diseqc_cmd->msg_len - 1) << 3 | 0x07); | ||
1021 | if (ret) | ||
1022 | goto err; | ||
1023 | |||
1024 | /* DiSEqC message typical period is 54 ms */ | ||
1025 | usleep_range(40000, 60000); | ||
1026 | |||
1027 | /* wait DiSEqC TX ready */ | ||
1028 | for (i = 20, u8tmp = 1; i && u8tmp; i--) { | ||
1029 | usleep_range(5000, 10000); | ||
1030 | |||
1031 | ret = m88ds3103_rd_reg_mask(priv, 0xa1, &u8tmp, 0x40); | ||
1032 | if (ret) | ||
1033 | goto err; | ||
1034 | } | ||
1035 | |||
1036 | dev_dbg(&priv->i2c->dev, "%s: loop=%d\n", __func__, i); | ||
1037 | |||
1038 | if (i == 0) { | ||
1039 | dev_dbg(&priv->i2c->dev, "%s: diseqc tx timeout\n", __func__); | ||
1040 | |||
1041 | ret = m88ds3103_wr_reg_mask(priv, 0xa1, 0x40, 0xc0); | ||
1042 | if (ret) | ||
1043 | goto err; | ||
1044 | } | ||
1045 | |||
1046 | ret = m88ds3103_wr_reg_mask(priv, 0xa2, 0x80, 0xc0); | ||
1047 | if (ret) | ||
1048 | goto err; | ||
1049 | |||
1050 | if (i == 0) { | ||
1051 | ret = -ETIMEDOUT; | ||
1052 | goto err; | ||
1053 | } | ||
1054 | |||
1055 | return 0; | ||
1056 | err: | ||
1057 | dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); | ||
1058 | return ret; | ||
1059 | } | ||
1060 | |||
1061 | static int m88ds3103_diseqc_send_burst(struct dvb_frontend *fe, | ||
1062 | fe_sec_mini_cmd_t fe_sec_mini_cmd) | ||
1063 | { | ||
1064 | struct m88ds3103_priv *priv = fe->demodulator_priv; | ||
1065 | int ret, i; | ||
1066 | u8 u8tmp, burst; | ||
1067 | dev_dbg(&priv->i2c->dev, "%s: fe_sec_mini_cmd=%d\n", __func__, | ||
1068 | fe_sec_mini_cmd); | ||
1069 | |||
1070 | if (!priv->warm) { | ||
1071 | ret = -EAGAIN; | ||
1072 | goto err; | ||
1073 | } | ||
1074 | |||
1075 | u8tmp = priv->cfg->envelope_mode << 5; | ||
1076 | ret = m88ds3103_wr_reg_mask(priv, 0xa2, u8tmp, 0xe0); | ||
1077 | if (ret) | ||
1078 | goto err; | ||
1079 | |||
1080 | switch (fe_sec_mini_cmd) { | ||
1081 | case SEC_MINI_A: | ||
1082 | burst = 0x02; | ||
1083 | break; | ||
1084 | case SEC_MINI_B: | ||
1085 | burst = 0x01; | ||
1086 | break; | ||
1087 | default: | ||
1088 | dev_dbg(&priv->i2c->dev, "%s: invalid fe_sec_mini_cmd\n", | ||
1089 | __func__); | ||
1090 | ret = -EINVAL; | ||
1091 | goto err; | ||
1092 | } | ||
1093 | |||
1094 | ret = m88ds3103_wr_reg(priv, 0xa1, burst); | ||
1095 | if (ret) | ||
1096 | goto err; | ||
1097 | |||
1098 | /* DiSEqC ToneBurst period is 12.5 ms */ | ||
1099 | usleep_range(11000, 20000); | ||
1100 | |||
1101 | /* wait DiSEqC TX ready */ | ||
1102 | for (i = 5, u8tmp = 1; i && u8tmp; i--) { | ||
1103 | usleep_range(800, 2000); | ||
1104 | |||
1105 | ret = m88ds3103_rd_reg_mask(priv, 0xa1, &u8tmp, 0x40); | ||
1106 | if (ret) | ||
1107 | goto err; | ||
1108 | } | ||
1109 | |||
1110 | dev_dbg(&priv->i2c->dev, "%s: loop=%d\n", __func__, i); | ||
1111 | |||
1112 | ret = m88ds3103_wr_reg_mask(priv, 0xa2, 0x80, 0xc0); | ||
1113 | if (ret) | ||
1114 | goto err; | ||
1115 | |||
1116 | if (i == 0) { | ||
1117 | dev_dbg(&priv->i2c->dev, "%s: diseqc tx timeout\n", __func__); | ||
1118 | ret = -ETIMEDOUT; | ||
1119 | goto err; | ||
1120 | } | ||
1121 | |||
1122 | return 0; | ||
1123 | err: | ||
1124 | dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); | ||
1125 | return ret; | ||
1126 | } | ||
1127 | |||
1128 | static int m88ds3103_get_tune_settings(struct dvb_frontend *fe, | ||
1129 | struct dvb_frontend_tune_settings *s) | ||
1130 | { | ||
1131 | s->min_delay_ms = 3000; | ||
1132 | |||
1133 | return 0; | ||
1134 | } | ||
1135 | |||
1136 | static void m88ds3103_release(struct dvb_frontend *fe) | ||
1137 | { | ||
1138 | struct m88ds3103_priv *priv = fe->demodulator_priv; | ||
1139 | i2c_del_mux_adapter(priv->i2c_adapter); | ||
1140 | kfree(priv); | ||
1141 | } | ||
1142 | |||
1143 | static int m88ds3103_select(struct i2c_adapter *adap, void *mux_priv, u32 chan) | ||
1144 | { | ||
1145 | struct m88ds3103_priv *priv = mux_priv; | ||
1146 | int ret; | ||
1147 | struct i2c_msg gate_open_msg[1] = { | ||
1148 | { | ||
1149 | .addr = priv->cfg->i2c_addr, | ||
1150 | .flags = 0, | ||
1151 | .len = 2, | ||
1152 | .buf = "\x03\x11", | ||
1153 | } | ||
1154 | }; | ||
1155 | |||
1156 | mutex_lock(&priv->i2c_mutex); | ||
1157 | |||
1158 | /* open tuner I2C repeater for 1 xfer, closes automatically */ | ||
1159 | ret = __i2c_transfer(priv->i2c, gate_open_msg, 1); | ||
1160 | if (ret != 1) { | ||
1161 | dev_warn(&priv->i2c->dev, "%s: i2c wr failed=%d\n", | ||
1162 | KBUILD_MODNAME, ret); | ||
1163 | if (ret >= 0) | ||
1164 | ret = -EREMOTEIO; | ||
1165 | |||
1166 | return ret; | ||
1167 | } | ||
1168 | |||
1169 | return 0; | ||
1170 | } | ||
1171 | |||
1172 | static int m88ds3103_deselect(struct i2c_adapter *adap, void *mux_priv, | ||
1173 | u32 chan) | ||
1174 | { | ||
1175 | struct m88ds3103_priv *priv = mux_priv; | ||
1176 | |||
1177 | mutex_unlock(&priv->i2c_mutex); | ||
1178 | |||
1179 | return 0; | ||
1180 | } | ||
1181 | |||
1182 | struct dvb_frontend *m88ds3103_attach(const struct m88ds3103_config *cfg, | ||
1183 | struct i2c_adapter *i2c, struct i2c_adapter **tuner_i2c_adapter) | ||
1184 | { | ||
1185 | int ret; | ||
1186 | struct m88ds3103_priv *priv; | ||
1187 | u8 chip_id, u8tmp; | ||
1188 | |||
1189 | /* allocate memory for the internal priv */ | ||
1190 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | ||
1191 | if (!priv) { | ||
1192 | ret = -ENOMEM; | ||
1193 | dev_err(&i2c->dev, "%s: kzalloc() failed\n", KBUILD_MODNAME); | ||
1194 | goto err; | ||
1195 | } | ||
1196 | |||
1197 | priv->cfg = cfg; | ||
1198 | priv->i2c = i2c; | ||
1199 | mutex_init(&priv->i2c_mutex); | ||
1200 | |||
1201 | ret = m88ds3103_rd_reg(priv, 0x01, &chip_id); | ||
1202 | if (ret) | ||
1203 | goto err; | ||
1204 | |||
1205 | dev_dbg(&priv->i2c->dev, "%s: chip_id=%02x\n", __func__, chip_id); | ||
1206 | |||
1207 | switch (chip_id) { | ||
1208 | case 0xd0: | ||
1209 | break; | ||
1210 | default: | ||
1211 | goto err; | ||
1212 | } | ||
1213 | |||
1214 | switch (priv->cfg->clock_out) { | ||
1215 | case M88DS3103_CLOCK_OUT_DISABLED: | ||
1216 | u8tmp = 0x80; | ||
1217 | break; | ||
1218 | case M88DS3103_CLOCK_OUT_ENABLED: | ||
1219 | u8tmp = 0x00; | ||
1220 | break; | ||
1221 | case M88DS3103_CLOCK_OUT_ENABLED_DIV2: | ||
1222 | u8tmp = 0x10; | ||
1223 | break; | ||
1224 | default: | ||
1225 | goto err; | ||
1226 | } | ||
1227 | |||
1228 | ret = m88ds3103_wr_reg(priv, 0x29, u8tmp); | ||
1229 | if (ret) | ||
1230 | goto err; | ||
1231 | |||
1232 | /* sleep */ | ||
1233 | ret = m88ds3103_wr_reg_mask(priv, 0x08, 0x00, 0x01); | ||
1234 | if (ret) | ||
1235 | goto err; | ||
1236 | |||
1237 | ret = m88ds3103_wr_reg_mask(priv, 0x04, 0x01, 0x01); | ||
1238 | if (ret) | ||
1239 | goto err; | ||
1240 | |||
1241 | ret = m88ds3103_wr_reg_mask(priv, 0x23, 0x10, 0x10); | ||
1242 | if (ret) | ||
1243 | goto err; | ||
1244 | |||
1245 | /* create mux i2c adapter for tuner */ | ||
1246 | priv->i2c_adapter = i2c_add_mux_adapter(i2c, &i2c->dev, priv, 0, 0, 0, | ||
1247 | m88ds3103_select, m88ds3103_deselect); | ||
1248 | if (priv->i2c_adapter == NULL) | ||
1249 | goto err; | ||
1250 | |||
1251 | *tuner_i2c_adapter = priv->i2c_adapter; | ||
1252 | |||
1253 | /* create dvb_frontend */ | ||
1254 | memcpy(&priv->fe.ops, &m88ds3103_ops, sizeof(struct dvb_frontend_ops)); | ||
1255 | priv->fe.demodulator_priv = priv; | ||
1256 | |||
1257 | return &priv->fe; | ||
1258 | err: | ||
1259 | dev_dbg(&i2c->dev, "%s: failed=%d\n", __func__, ret); | ||
1260 | kfree(priv); | ||
1261 | return NULL; | ||
1262 | } | ||
1263 | EXPORT_SYMBOL(m88ds3103_attach); | ||
1264 | |||
1265 | static struct dvb_frontend_ops m88ds3103_ops = { | ||
1266 | .delsys = { SYS_DVBS, SYS_DVBS2 }, | ||
1267 | .info = { | ||
1268 | .name = "Montage M88DS3103", | ||
1269 | .frequency_min = 950000, | ||
1270 | .frequency_max = 2150000, | ||
1271 | .frequency_tolerance = 5000, | ||
1272 | .symbol_rate_min = 1000000, | ||
1273 | .symbol_rate_max = 45000000, | ||
1274 | .caps = FE_CAN_INVERSION_AUTO | | ||
1275 | FE_CAN_FEC_1_2 | | ||
1276 | FE_CAN_FEC_2_3 | | ||
1277 | FE_CAN_FEC_3_4 | | ||
1278 | FE_CAN_FEC_4_5 | | ||
1279 | FE_CAN_FEC_5_6 | | ||
1280 | FE_CAN_FEC_6_7 | | ||
1281 | FE_CAN_FEC_7_8 | | ||
1282 | FE_CAN_FEC_8_9 | | ||
1283 | FE_CAN_FEC_AUTO | | ||
1284 | FE_CAN_QPSK | | ||
1285 | FE_CAN_RECOVER | | ||
1286 | FE_CAN_2G_MODULATION | ||
1287 | }, | ||
1288 | |||
1289 | .release = m88ds3103_release, | ||
1290 | |||
1291 | .get_tune_settings = m88ds3103_get_tune_settings, | ||
1292 | |||
1293 | .init = m88ds3103_init, | ||
1294 | .sleep = m88ds3103_sleep, | ||
1295 | |||
1296 | .set_frontend = m88ds3103_set_frontend, | ||
1297 | .get_frontend = m88ds3103_get_frontend, | ||
1298 | |||
1299 | .read_status = m88ds3103_read_status, | ||
1300 | .read_snr = m88ds3103_read_snr, | ||
1301 | |||
1302 | .diseqc_send_master_cmd = m88ds3103_diseqc_send_master_cmd, | ||
1303 | .diseqc_send_burst = m88ds3103_diseqc_send_burst, | ||
1304 | |||
1305 | .set_tone = m88ds3103_set_tone, | ||
1306 | }; | ||
1307 | |||
1308 | MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); | ||
1309 | MODULE_DESCRIPTION("Montage M88DS3103 DVB-S/S2 demodulator driver"); | ||
1310 | MODULE_LICENSE("GPL"); | ||
1311 | MODULE_FIRMWARE(M88DS3103_FIRMWARE); | ||
diff --git a/drivers/media/dvb-frontends/m88ds3103.h b/drivers/media/dvb-frontends/m88ds3103.h new file mode 100644 index 000000000000..bbb7e3aa5675 --- /dev/null +++ b/drivers/media/dvb-frontends/m88ds3103.h | |||
@@ -0,0 +1,114 @@ | |||
1 | /* | ||
2 | * Montage M88DS3103 demodulator driver | ||
3 | * | ||
4 | * 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 | */ | ||
16 | |||
17 | #ifndef M88DS3103_H | ||
18 | #define M88DS3103_H | ||
19 | |||
20 | #include <linux/dvb/frontend.h> | ||
21 | |||
22 | struct m88ds3103_config { | ||
23 | /* | ||
24 | * I2C address | ||
25 | * Default: none, must set | ||
26 | * 0x68, ... | ||
27 | */ | ||
28 | u8 i2c_addr; | ||
29 | |||
30 | /* | ||
31 | * clock | ||
32 | * Default: none, must set | ||
33 | * 27000000 | ||
34 | */ | ||
35 | u32 clock; | ||
36 | |||
37 | /* | ||
38 | * max bytes I2C provider is asked to write at once | ||
39 | * Default: none, must set | ||
40 | * 33, 65, ... | ||
41 | */ | ||
42 | u16 i2c_wr_max; | ||
43 | |||
44 | /* | ||
45 | * TS output mode | ||
46 | * Default: M88DS3103_TS_SERIAL | ||
47 | */ | ||
48 | #define M88DS3103_TS_SERIAL 0 /* TS output pin D0, normal */ | ||
49 | #define M88DS3103_TS_SERIAL_D7 1 /* TS output pin D7 */ | ||
50 | #define M88DS3103_TS_PARALLEL 2 /* 24 MHz, normal */ | ||
51 | #define M88DS3103_TS_PARALLEL_12 3 /* 12 MHz */ | ||
52 | #define M88DS3103_TS_PARALLEL_16 4 /* 16 MHz */ | ||
53 | #define M88DS3103_TS_PARALLEL_19_2 5 /* 19.2 MHz */ | ||
54 | #define M88DS3103_TS_CI 6 /* 6 MHz */ | ||
55 | u8 ts_mode; | ||
56 | |||
57 | /* | ||
58 | * spectrum inversion | ||
59 | * Default: 0 | ||
60 | */ | ||
61 | u8 spec_inv:1; | ||
62 | |||
63 | /* | ||
64 | * AGC polarity | ||
65 | * Default: 0 | ||
66 | */ | ||
67 | u8 agc_inv:1; | ||
68 | |||
69 | /* | ||
70 | * clock output | ||
71 | * Default: M88DS3103_CLOCK_OUT_DISABLED | ||
72 | */ | ||
73 | #define M88DS3103_CLOCK_OUT_DISABLED 0 | ||
74 | #define M88DS3103_CLOCK_OUT_ENABLED 1 | ||
75 | #define M88DS3103_CLOCK_OUT_ENABLED_DIV2 2 | ||
76 | u8 clock_out; | ||
77 | |||
78 | /* | ||
79 | * DiSEqC envelope mode | ||
80 | * Default: 0 | ||
81 | */ | ||
82 | u8 envelope_mode:1; | ||
83 | |||
84 | /* | ||
85 | * AGC configuration | ||
86 | * Default: none, must set | ||
87 | */ | ||
88 | u8 agc; | ||
89 | }; | ||
90 | |||
91 | /* | ||
92 | * Driver implements own I2C-adapter for tuner I2C access. That's since chip | ||
93 | * has I2C-gate control which closes gate automatically after I2C transfer. | ||
94 | * Using own I2C adapter we can workaround that. | ||
95 | */ | ||
96 | |||
97 | #if defined(CONFIG_DVB_M88DS3103) || \ | ||
98 | (defined(CONFIG_DVB_M88DS3103_MODULE) && defined(MODULE)) | ||
99 | extern struct dvb_frontend *m88ds3103_attach( | ||
100 | const struct m88ds3103_config *config, | ||
101 | struct i2c_adapter *i2c, | ||
102 | struct i2c_adapter **tuner_i2c); | ||
103 | #else | ||
104 | static inline struct dvb_frontend *m88ds3103_attach( | ||
105 | const struct m88ds3103_config *config, | ||
106 | struct i2c_adapter *i2c, | ||
107 | struct i2c_adapter **tuner_i2c) | ||
108 | { | ||
109 | pr_warn("%s: driver disabled by Kconfig\n", __func__); | ||
110 | return NULL; | ||
111 | } | ||
112 | #endif | ||
113 | |||
114 | #endif | ||
diff --git a/drivers/media/dvb-frontends/m88ds3103_priv.h b/drivers/media/dvb-frontends/m88ds3103_priv.h new file mode 100644 index 000000000000..84c3c06df622 --- /dev/null +++ b/drivers/media/dvb-frontends/m88ds3103_priv.h | |||
@@ -0,0 +1,215 @@ | |||
1 | /* | ||
2 | * Montage M88DS3103 demodulator driver | ||
3 | * | ||
4 | * 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 | */ | ||
16 | |||
17 | #ifndef M88DS3103_PRIV_H | ||
18 | #define M88DS3103_PRIV_H | ||
19 | |||
20 | #include "dvb_frontend.h" | ||
21 | #include "m88ds3103.h" | ||
22 | #include "dvb_math.h" | ||
23 | #include <linux/firmware.h> | ||
24 | #include <linux/i2c-mux.h> | ||
25 | |||
26 | #define M88DS3103_FIRMWARE "dvb-demod-m88ds3103.fw" | ||
27 | #define M88DS3103_MCLK_KHZ 96000 | ||
28 | |||
29 | struct m88ds3103_priv { | ||
30 | struct i2c_adapter *i2c; | ||
31 | /* mutex needed due to own tuner I2C adapter */ | ||
32 | struct mutex i2c_mutex; | ||
33 | const struct m88ds3103_config *cfg; | ||
34 | struct dvb_frontend fe; | ||
35 | fe_delivery_system_t delivery_system; | ||
36 | fe_status_t fe_status; | ||
37 | bool warm; /* FW running */ | ||
38 | struct i2c_adapter *i2c_adapter; | ||
39 | }; | ||
40 | |||
41 | struct m88ds3103_reg_val { | ||
42 | u8 reg; | ||
43 | u8 val; | ||
44 | }; | ||
45 | |||
46 | static const struct m88ds3103_reg_val m88ds3103_dvbs_init_reg_vals[] = { | ||
47 | {0x23, 0x07}, | ||
48 | {0x08, 0x03}, | ||
49 | {0x0c, 0x02}, | ||
50 | {0x21, 0x54}, | ||
51 | {0x25, 0x8a}, | ||
52 | {0x27, 0x31}, | ||
53 | {0x30, 0x08}, | ||
54 | {0x31, 0x40}, | ||
55 | {0x32, 0x32}, | ||
56 | {0x35, 0xff}, | ||
57 | {0x3a, 0x00}, | ||
58 | {0x37, 0x10}, | ||
59 | {0x38, 0x10}, | ||
60 | {0x39, 0x02}, | ||
61 | {0x42, 0x60}, | ||
62 | {0x4a, 0x80}, | ||
63 | {0x4b, 0x04}, | ||
64 | {0x4d, 0x91}, | ||
65 | {0x5d, 0xc8}, | ||
66 | {0x50, 0x36}, | ||
67 | {0x51, 0x36}, | ||
68 | {0x52, 0x36}, | ||
69 | {0x53, 0x36}, | ||
70 | {0x56, 0x01}, | ||
71 | {0x63, 0x0f}, | ||
72 | {0x64, 0x30}, | ||
73 | {0x65, 0x40}, | ||
74 | {0x68, 0x26}, | ||
75 | {0x69, 0x4c}, | ||
76 | {0x70, 0x20}, | ||
77 | {0x71, 0x70}, | ||
78 | {0x72, 0x04}, | ||
79 | {0x73, 0x00}, | ||
80 | {0x70, 0x40}, | ||
81 | {0x71, 0x70}, | ||
82 | {0x72, 0x04}, | ||
83 | {0x73, 0x00}, | ||
84 | {0x70, 0x60}, | ||
85 | {0x71, 0x70}, | ||
86 | {0x72, 0x04}, | ||
87 | {0x73, 0x00}, | ||
88 | {0x70, 0x80}, | ||
89 | {0x71, 0x70}, | ||
90 | {0x72, 0x04}, | ||
91 | {0x73, 0x00}, | ||
92 | {0x70, 0xa0}, | ||
93 | {0x71, 0x70}, | ||
94 | {0x72, 0x04}, | ||
95 | {0x73, 0x00}, | ||
96 | {0x70, 0x1f}, | ||
97 | {0x76, 0x38}, | ||
98 | {0x77, 0xa6}, | ||
99 | {0x78, 0x0c}, | ||
100 | {0x79, 0x80}, | ||
101 | {0x7f, 0x14}, | ||
102 | {0x7c, 0x00}, | ||
103 | {0xae, 0x82}, | ||
104 | {0x80, 0x64}, | ||
105 | {0x81, 0x66}, | ||
106 | {0x82, 0x44}, | ||
107 | {0x85, 0x04}, | ||
108 | {0xcd, 0xf4}, | ||
109 | {0x90, 0x33}, | ||
110 | {0xa0, 0x44}, | ||
111 | {0xc0, 0x08}, | ||
112 | {0xc3, 0x10}, | ||
113 | {0xc4, 0x08}, | ||
114 | {0xc5, 0xf0}, | ||
115 | {0xc6, 0xff}, | ||
116 | {0xc7, 0x00}, | ||
117 | {0xc8, 0x1a}, | ||
118 | {0xc9, 0x80}, | ||
119 | {0xe0, 0xf8}, | ||
120 | {0xe6, 0x8b}, | ||
121 | {0xd0, 0x40}, | ||
122 | {0xf8, 0x20}, | ||
123 | {0xfa, 0x0f}, | ||
124 | {0x00, 0x00}, | ||
125 | {0xbd, 0x01}, | ||
126 | {0xb8, 0x00}, | ||
127 | }; | ||
128 | |||
129 | static const struct m88ds3103_reg_val m88ds3103_dvbs2_init_reg_vals[] = { | ||
130 | {0x23, 0x07}, | ||
131 | {0x08, 0x07}, | ||
132 | {0x0c, 0x02}, | ||
133 | {0x21, 0x54}, | ||
134 | {0x25, 0x8a}, | ||
135 | {0x27, 0x31}, | ||
136 | {0x30, 0x08}, | ||
137 | {0x32, 0x32}, | ||
138 | {0x35, 0xff}, | ||
139 | {0x3a, 0x00}, | ||
140 | {0x37, 0x10}, | ||
141 | {0x38, 0x10}, | ||
142 | {0x39, 0x02}, | ||
143 | {0x42, 0x60}, | ||
144 | {0x4a, 0x80}, | ||
145 | {0x4b, 0x04}, | ||
146 | {0x4d, 0x91}, | ||
147 | {0x5d, 0xc8}, | ||
148 | {0x50, 0x36}, | ||
149 | {0x51, 0x36}, | ||
150 | {0x52, 0x36}, | ||
151 | {0x53, 0x36}, | ||
152 | {0x56, 0x01}, | ||
153 | {0x63, 0x0f}, | ||
154 | {0x64, 0x10}, | ||
155 | {0x65, 0x20}, | ||
156 | {0x68, 0x46}, | ||
157 | {0x69, 0xcd}, | ||
158 | {0x70, 0x20}, | ||
159 | {0x71, 0x70}, | ||
160 | {0x72, 0x04}, | ||
161 | {0x73, 0x00}, | ||
162 | {0x70, 0x40}, | ||
163 | {0x71, 0x70}, | ||
164 | {0x72, 0x04}, | ||
165 | {0x73, 0x00}, | ||
166 | {0x70, 0x60}, | ||
167 | {0x71, 0x70}, | ||
168 | {0x72, 0x04}, | ||
169 | {0x73, 0x00}, | ||
170 | {0x70, 0x80}, | ||
171 | {0x71, 0x70}, | ||
172 | {0x72, 0x04}, | ||
173 | {0x73, 0x00}, | ||
174 | {0x70, 0xa0}, | ||
175 | {0x71, 0x70}, | ||
176 | {0x72, 0x04}, | ||
177 | {0x73, 0x00}, | ||
178 | {0x70, 0x1f}, | ||
179 | {0x76, 0x38}, | ||
180 | {0x77, 0xa6}, | ||
181 | {0x78, 0x0c}, | ||
182 | {0x79, 0x80}, | ||
183 | {0x7f, 0x14}, | ||
184 | {0x85, 0x08}, | ||
185 | {0xcd, 0xf4}, | ||
186 | {0x90, 0x33}, | ||
187 | {0x86, 0x00}, | ||
188 | {0x87, 0x0f}, | ||
189 | {0x89, 0x00}, | ||
190 | {0x8b, 0x44}, | ||
191 | {0x8c, 0x66}, | ||
192 | {0x9d, 0xc1}, | ||
193 | {0x8a, 0x10}, | ||
194 | {0xad, 0x40}, | ||
195 | {0xa0, 0x44}, | ||
196 | {0xc0, 0x08}, | ||
197 | {0xc1, 0x10}, | ||
198 | {0xc2, 0x08}, | ||
199 | {0xc3, 0x10}, | ||
200 | {0xc4, 0x08}, | ||
201 | {0xc5, 0xf0}, | ||
202 | {0xc6, 0xff}, | ||
203 | {0xc7, 0x00}, | ||
204 | {0xc8, 0x1a}, | ||
205 | {0xc9, 0x80}, | ||
206 | {0xca, 0x23}, | ||
207 | {0xcb, 0x24}, | ||
208 | {0xcc, 0xf4}, | ||
209 | {0xce, 0x74}, | ||
210 | {0x00, 0x00}, | ||
211 | {0xbd, 0x01}, | ||
212 | {0xb8, 0x00}, | ||
213 | }; | ||
214 | |||
215 | #endif | ||
diff --git a/drivers/media/dvb-frontends/m88rs2000.c b/drivers/media/dvb-frontends/m88rs2000.c index 4da5272075cb..b2351466b0da 100644 --- a/drivers/media/dvb-frontends/m88rs2000.c +++ b/drivers/media/dvb-frontends/m88rs2000.c | |||
@@ -110,28 +110,94 @@ static u8 m88rs2000_readreg(struct m88rs2000_state *state, u8 reg) | |||
110 | return b1[0]; | 110 | return b1[0]; |
111 | } | 111 | } |
112 | 112 | ||
113 | static u32 m88rs2000_get_mclk(struct dvb_frontend *fe) | ||
114 | { | ||
115 | struct m88rs2000_state *state = fe->demodulator_priv; | ||
116 | u32 mclk; | ||
117 | u8 reg; | ||
118 | /* Must not be 0x00 or 0xff */ | ||
119 | reg = m88rs2000_readreg(state, 0x86); | ||
120 | if (!reg || reg == 0xff) | ||
121 | return 0; | ||
122 | |||
123 | reg /= 2; | ||
124 | reg += 1; | ||
125 | |||
126 | mclk = (u32)(reg * RS2000_FE_CRYSTAL_KHZ + 28 / 2) / 28; | ||
127 | |||
128 | return mclk; | ||
129 | } | ||
130 | |||
131 | static int m88rs2000_set_carrieroffset(struct dvb_frontend *fe, s16 offset) | ||
132 | { | ||
133 | struct m88rs2000_state *state = fe->demodulator_priv; | ||
134 | u32 mclk; | ||
135 | s32 tmp; | ||
136 | u8 reg; | ||
137 | int ret; | ||
138 | |||
139 | mclk = m88rs2000_get_mclk(fe); | ||
140 | if (!mclk) | ||
141 | return -EINVAL; | ||
142 | |||
143 | tmp = (offset * 4096 + (s32)mclk / 2) / (s32)mclk; | ||
144 | if (tmp < 0) | ||
145 | tmp += 4096; | ||
146 | |||
147 | /* Carrier Offset */ | ||
148 | ret = m88rs2000_writereg(state, 0x9c, (u8)(tmp >> 4)); | ||
149 | |||
150 | reg = m88rs2000_readreg(state, 0x9d); | ||
151 | reg &= 0xf; | ||
152 | reg |= (u8)(tmp & 0xf) << 4; | ||
153 | |||
154 | ret |= m88rs2000_writereg(state, 0x9d, reg); | ||
155 | |||
156 | return ret; | ||
157 | } | ||
158 | |||
113 | static int m88rs2000_set_symbolrate(struct dvb_frontend *fe, u32 srate) | 159 | static int m88rs2000_set_symbolrate(struct dvb_frontend *fe, u32 srate) |
114 | { | 160 | { |
115 | struct m88rs2000_state *state = fe->demodulator_priv; | 161 | struct m88rs2000_state *state = fe->demodulator_priv; |
116 | int ret; | 162 | int ret; |
117 | u32 temp; | 163 | u64 temp; |
164 | u32 mclk; | ||
118 | u8 b[3]; | 165 | u8 b[3]; |
119 | 166 | ||
120 | if ((srate < 1000000) || (srate > 45000000)) | 167 | if ((srate < 1000000) || (srate > 45000000)) |
121 | return -EINVAL; | 168 | return -EINVAL; |
122 | 169 | ||
170 | mclk = m88rs2000_get_mclk(fe); | ||
171 | if (!mclk) | ||
172 | return -EINVAL; | ||
173 | |||
123 | temp = srate / 1000; | 174 | temp = srate / 1000; |
124 | temp *= 11831; | 175 | temp *= 1 << 24; |
125 | temp /= 68; | 176 | |
126 | temp -= 3; | 177 | do_div(temp, mclk); |
127 | 178 | ||
128 | b[0] = (u8) (temp >> 16) & 0xff; | 179 | b[0] = (u8) (temp >> 16) & 0xff; |
129 | b[1] = (u8) (temp >> 8) & 0xff; | 180 | b[1] = (u8) (temp >> 8) & 0xff; |
130 | b[2] = (u8) temp & 0xff; | 181 | b[2] = (u8) temp & 0xff; |
182 | |||
131 | ret = m88rs2000_writereg(state, 0x93, b[2]); | 183 | ret = m88rs2000_writereg(state, 0x93, b[2]); |
132 | ret |= m88rs2000_writereg(state, 0x94, b[1]); | 184 | ret |= m88rs2000_writereg(state, 0x94, b[1]); |
133 | ret |= m88rs2000_writereg(state, 0x95, b[0]); | 185 | ret |= m88rs2000_writereg(state, 0x95, b[0]); |
134 | 186 | ||
187 | if (srate > 10000000) | ||
188 | ret |= m88rs2000_writereg(state, 0xa0, 0x20); | ||
189 | else | ||
190 | ret |= m88rs2000_writereg(state, 0xa0, 0x60); | ||
191 | |||
192 | ret |= m88rs2000_writereg(state, 0xa1, 0xe0); | ||
193 | |||
194 | if (srate > 12000000) | ||
195 | ret |= m88rs2000_writereg(state, 0xa3, 0x20); | ||
196 | else if (srate > 2800000) | ||
197 | ret |= m88rs2000_writereg(state, 0xa3, 0x98); | ||
198 | else | ||
199 | ret |= m88rs2000_writereg(state, 0xa3, 0x90); | ||
200 | |||
135 | deb_info("m88rs2000: m88rs2000_set_symbolrate\n"); | 201 | deb_info("m88rs2000: m88rs2000_set_symbolrate\n"); |
136 | return ret; | 202 | return ret; |
137 | } | 203 | } |
@@ -261,8 +327,6 @@ struct inittab m88rs2000_shutdown[] = { | |||
261 | 327 | ||
262 | struct inittab fe_reset[] = { | 328 | struct inittab fe_reset[] = { |
263 | {DEMOD_WRITE, 0x00, 0x01}, | 329 | {DEMOD_WRITE, 0x00, 0x01}, |
264 | {DEMOD_WRITE, 0xf1, 0xbf}, | ||
265 | {DEMOD_WRITE, 0x00, 0x01}, | ||
266 | {DEMOD_WRITE, 0x20, 0x81}, | 330 | {DEMOD_WRITE, 0x20, 0x81}, |
267 | {DEMOD_WRITE, 0x21, 0x80}, | 331 | {DEMOD_WRITE, 0x21, 0x80}, |
268 | {DEMOD_WRITE, 0x10, 0x33}, | 332 | {DEMOD_WRITE, 0x10, 0x33}, |
@@ -305,9 +369,6 @@ struct inittab fe_trigger[] = { | |||
305 | {DEMOD_WRITE, 0x9b, 0x64}, | 369 | {DEMOD_WRITE, 0x9b, 0x64}, |
306 | {DEMOD_WRITE, 0x9e, 0x00}, | 370 | {DEMOD_WRITE, 0x9e, 0x00}, |
307 | {DEMOD_WRITE, 0x9f, 0xf8}, | 371 | {DEMOD_WRITE, 0x9f, 0xf8}, |
308 | {DEMOD_WRITE, 0xa0, 0x20}, | ||
309 | {DEMOD_WRITE, 0xa1, 0xe0}, | ||
310 | {DEMOD_WRITE, 0xa3, 0x38}, | ||
311 | {DEMOD_WRITE, 0x98, 0xff}, | 372 | {DEMOD_WRITE, 0x98, 0xff}, |
312 | {DEMOD_WRITE, 0xc0, 0x0f}, | 373 | {DEMOD_WRITE, 0xc0, 0x0f}, |
313 | {DEMOD_WRITE, 0x89, 0x01}, | 374 | {DEMOD_WRITE, 0x89, 0x01}, |
@@ -408,7 +469,7 @@ static int m88rs2000_read_status(struct dvb_frontend *fe, fe_status_t *status) | |||
408 | 469 | ||
409 | *status = 0; | 470 | *status = 0; |
410 | 471 | ||
411 | if ((reg & 0x7) == 0x7) { | 472 | if ((reg & 0xee) == 0xee) { |
412 | *status = FE_HAS_CARRIER | FE_HAS_SIGNAL | FE_HAS_VITERBI | 473 | *status = FE_HAS_CARRIER | FE_HAS_SIGNAL | FE_HAS_VITERBI |
413 | | FE_HAS_SYNC | FE_HAS_LOCK; | 474 | | FE_HAS_SYNC | FE_HAS_LOCK; |
414 | if (state->config->set_ts_params) | 475 | if (state->config->set_ts_params) |
@@ -480,33 +541,38 @@ static int m88rs2000_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) | |||
480 | static int m88rs2000_set_fec(struct m88rs2000_state *state, | 541 | static int m88rs2000_set_fec(struct m88rs2000_state *state, |
481 | fe_code_rate_t fec) | 542 | fe_code_rate_t fec) |
482 | { | 543 | { |
483 | u16 fec_set; | 544 | u8 fec_set, reg; |
545 | int ret; | ||
546 | |||
484 | switch (fec) { | 547 | switch (fec) { |
485 | /* This is not confirmed kept for reference */ | 548 | case FEC_1_2: |
486 | /* case FEC_1_2: | 549 | fec_set = 0x8; |
487 | fec_set = 0x88; | ||
488 | break; | 550 | break; |
489 | case FEC_2_3: | 551 | case FEC_2_3: |
490 | fec_set = 0x68; | 552 | fec_set = 0x10; |
491 | break; | 553 | break; |
492 | case FEC_3_4: | 554 | case FEC_3_4: |
493 | fec_set = 0x48; | 555 | fec_set = 0x20; |
494 | break; | 556 | break; |
495 | case FEC_5_6: | 557 | case FEC_5_6: |
496 | fec_set = 0x28; | 558 | fec_set = 0x40; |
497 | break; | 559 | break; |
498 | case FEC_7_8: | 560 | case FEC_7_8: |
499 | fec_set = 0x18; | 561 | fec_set = 0x80; |
500 | break; */ | 562 | break; |
501 | case FEC_AUTO: | 563 | case FEC_AUTO: |
502 | default: | 564 | default: |
503 | fec_set = 0x08; | 565 | fec_set = 0x0; |
504 | } | 566 | } |
505 | m88rs2000_writereg(state, 0x76, fec_set); | ||
506 | 567 | ||
507 | return 0; | 568 | reg = m88rs2000_readreg(state, 0x70); |
508 | } | 569 | reg &= 0x7; |
570 | ret = m88rs2000_writereg(state, 0x70, reg | fec_set); | ||
509 | 571 | ||
572 | ret |= m88rs2000_writereg(state, 0x76, 0x8); | ||
573 | |||
574 | return ret; | ||
575 | } | ||
510 | 576 | ||
511 | static fe_code_rate_t m88rs2000_get_fec(struct m88rs2000_state *state) | 577 | static fe_code_rate_t m88rs2000_get_fec(struct m88rs2000_state *state) |
512 | { | 578 | { |
@@ -515,18 +581,20 @@ static fe_code_rate_t m88rs2000_get_fec(struct m88rs2000_state *state) | |||
515 | reg = m88rs2000_readreg(state, 0x76); | 581 | reg = m88rs2000_readreg(state, 0x76); |
516 | m88rs2000_writereg(state, 0x9a, 0xb0); | 582 | m88rs2000_writereg(state, 0x9a, 0xb0); |
517 | 583 | ||
584 | reg &= 0xf0; | ||
585 | reg >>= 5; | ||
586 | |||
518 | switch (reg) { | 587 | switch (reg) { |
519 | case 0x88: | 588 | case 0x4: |
520 | return FEC_1_2; | 589 | return FEC_1_2; |
521 | case 0x68: | 590 | case 0x3: |
522 | return FEC_2_3; | 591 | return FEC_2_3; |
523 | case 0x48: | 592 | case 0x2: |
524 | return FEC_3_4; | 593 | return FEC_3_4; |
525 | case 0x28: | 594 | case 0x1: |
526 | return FEC_5_6; | 595 | return FEC_5_6; |
527 | case 0x18: | 596 | case 0x0: |
528 | return FEC_7_8; | 597 | return FEC_7_8; |
529 | case 0x08: | ||
530 | default: | 598 | default: |
531 | break; | 599 | break; |
532 | } | 600 | } |
@@ -540,9 +608,8 @@ static int m88rs2000_set_frontend(struct dvb_frontend *fe) | |||
540 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | 608 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; |
541 | fe_status_t status; | 609 | fe_status_t status; |
542 | int i, ret = 0; | 610 | int i, ret = 0; |
543 | s32 tmp; | ||
544 | u32 tuner_freq; | 611 | u32 tuner_freq; |
545 | u16 offset = 0; | 612 | s16 offset = 0; |
546 | u8 reg; | 613 | u8 reg; |
547 | 614 | ||
548 | state->no_lock_count = 0; | 615 | state->no_lock_count = 0; |
@@ -567,38 +634,31 @@ static int m88rs2000_set_frontend(struct dvb_frontend *fe) | |||
567 | if (ret < 0) | 634 | if (ret < 0) |
568 | return -ENODEV; | 635 | return -ENODEV; |
569 | 636 | ||
570 | offset = tuner_freq - c->frequency; | 637 | offset = (s16)((s32)tuner_freq - c->frequency); |
571 | |||
572 | /* calculate offset assuming 96000kHz*/ | ||
573 | tmp = offset; | ||
574 | tmp *= 65536; | ||
575 | |||
576 | tmp = (2 * tmp + 96000) / (2 * 96000); | ||
577 | if (tmp < 0) | ||
578 | tmp += 65536; | ||
579 | 638 | ||
580 | offset = tmp & 0xffff; | 639 | /* default mclk value 96.4285 * 2 * 1000 = 192857 */ |
640 | if (((c->frequency % 192857) >= (192857 - 3000)) || | ||
641 | (c->frequency % 192857) <= 3000) | ||
642 | ret = m88rs2000_writereg(state, 0x86, 0xc2); | ||
643 | else | ||
644 | ret = m88rs2000_writereg(state, 0x86, 0xc6); | ||
581 | 645 | ||
582 | ret = m88rs2000_writereg(state, 0x9a, 0x30); | 646 | ret |= m88rs2000_set_carrieroffset(fe, offset); |
583 | /* Unknown usually 0xc6 sometimes 0xc1 */ | 647 | if (ret < 0) |
584 | reg = m88rs2000_readreg(state, 0x86); | 648 | return -ENODEV; |
585 | ret |= m88rs2000_writereg(state, 0x86, reg); | ||
586 | /* Offset lower nibble always 0 */ | ||
587 | ret |= m88rs2000_writereg(state, 0x9c, (offset >> 8)); | ||
588 | ret |= m88rs2000_writereg(state, 0x9d, offset & 0xf0); | ||
589 | 649 | ||
650 | /* Reset demod by symbol rate */ | ||
651 | if (c->symbol_rate > 27500000) | ||
652 | ret = m88rs2000_writereg(state, 0xf1, 0xa4); | ||
653 | else | ||
654 | ret = m88rs2000_writereg(state, 0xf1, 0xbf); | ||
590 | 655 | ||
591 | /* Reset Demod */ | 656 | ret |= m88rs2000_tab_set(state, fe_reset); |
592 | ret = m88rs2000_tab_set(state, fe_reset); | ||
593 | if (ret < 0) | 657 | if (ret < 0) |
594 | return -ENODEV; | 658 | return -ENODEV; |
595 | 659 | ||
596 | /* Unknown */ | ||
597 | reg = m88rs2000_readreg(state, 0x70); | ||
598 | ret = m88rs2000_writereg(state, 0x70, reg); | ||
599 | |||
600 | /* Set FEC */ | 660 | /* Set FEC */ |
601 | ret |= m88rs2000_set_fec(state, c->fec_inner); | 661 | ret = m88rs2000_set_fec(state, c->fec_inner); |
602 | ret |= m88rs2000_writereg(state, 0x85, 0x1); | 662 | ret |= m88rs2000_writereg(state, 0x85, 0x1); |
603 | ret |= m88rs2000_writereg(state, 0x8a, 0xbf); | 663 | ret |= m88rs2000_writereg(state, 0x8a, 0xbf); |
604 | ret |= m88rs2000_writereg(state, 0x8d, 0x1e); | 664 | ret |= m88rs2000_writereg(state, 0x8d, 0x1e); |
@@ -620,7 +680,7 @@ static int m88rs2000_set_frontend(struct dvb_frontend *fe) | |||
620 | 680 | ||
621 | for (i = 0; i < 25; i++) { | 681 | for (i = 0; i < 25; i++) { |
622 | reg = m88rs2000_readreg(state, 0x8c); | 682 | reg = m88rs2000_readreg(state, 0x8c); |
623 | if ((reg & 0x7) == 0x7) { | 683 | if ((reg & 0xee) == 0xee) { |
624 | status = FE_HAS_LOCK; | 684 | status = FE_HAS_LOCK; |
625 | break; | 685 | break; |
626 | } | 686 | } |
diff --git a/drivers/media/dvb-frontends/m88rs2000.h b/drivers/media/dvb-frontends/m88rs2000.h index 14ce31e76ae6..0a50ea90736b 100644 --- a/drivers/media/dvb-frontends/m88rs2000.h +++ b/drivers/media/dvb-frontends/m88rs2000.h | |||
@@ -53,6 +53,8 @@ static inline struct dvb_frontend *m88rs2000_attach( | |||
53 | } | 53 | } |
54 | #endif /* CONFIG_DVB_M88RS2000 */ | 54 | #endif /* CONFIG_DVB_M88RS2000 */ |
55 | 55 | ||
56 | #define RS2000_FE_CRYSTAL_KHZ 27000 | ||
57 | |||
56 | enum { | 58 | enum { |
57 | DEMOD_WRITE = 0x1, | 59 | DEMOD_WRITE = 0x1, |
58 | WRITE_DELAY = 0x10, | 60 | WRITE_DELAY = 0x10, |
diff --git a/drivers/media/dvb-frontends/nxt200x.c b/drivers/media/dvb-frontends/nxt200x.c index fbca9856313a..4bf057544607 100644 --- a/drivers/media/dvb-frontends/nxt200x.c +++ b/drivers/media/dvb-frontends/nxt200x.c | |||
@@ -40,7 +40,7 @@ | |||
40 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | 40 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
41 | 41 | ||
42 | /* Max transfer size done by I2C transfer functions */ | 42 | /* Max transfer size done by I2C transfer functions */ |
43 | #define MAX_XFER_SIZE 64 | 43 | #define MAX_XFER_SIZE 256 |
44 | 44 | ||
45 | #define NXT2002_DEFAULT_FIRMWARE "dvb-fe-nxt2002.fw" | 45 | #define NXT2002_DEFAULT_FIRMWARE "dvb-fe-nxt2002.fw" |
46 | #define NXT2004_DEFAULT_FIRMWARE "dvb-fe-nxt2004.fw" | 46 | #define NXT2004_DEFAULT_FIRMWARE "dvb-fe-nxt2004.fw" |