diff options
author | Antti Palosaari <crope@iki.fi> | 2013-07-09 01:44:56 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <m.chehab@samsung.com> | 2013-08-20 12:33:46 -0400 |
commit | b15208573d926e2fdf46a753ae167235d73e1bf6 (patch) | |
tree | 6e415e514b1c989f24385283edafe825ac186d2c /drivers/staging | |
parent | 34599b9b5305eb70644d54fe22e6df4aa5fef65c (diff) |
[media] msi3101: fix sampling rate calculation
These calculations seem to give 100% correct results. Calculation
formulas could be still a little bit wrong as I have no knowledge
what kind of dividers, multipliers and VCO limits there really is.
Signed-off-by: Antti Palosaari <crope@iki.fi>
Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
Diffstat (limited to 'drivers/staging')
-rw-r--r-- | drivers/staging/media/msi3101/sdr-msi3101.c | 58 |
1 files changed, 31 insertions, 27 deletions
diff --git a/drivers/staging/media/msi3101/sdr-msi3101.c b/drivers/staging/media/msi3101/sdr-msi3101.c index 87896eebc2a8..4de4f505f0ac 100644 --- a/drivers/staging/media/msi3101/sdr-msi3101.c +++ b/drivers/staging/media/msi3101/sdr-msi3101.c | |||
@@ -960,16 +960,14 @@ static int msi3101_tuner_write(struct msi3101_state *s, u32 data) | |||
960 | }; | 960 | }; |
961 | 961 | ||
962 | #define F_REF 24000000 | 962 | #define F_REF 24000000 |
963 | #define DIV_R_IN 2 | ||
963 | static int msi3101_set_usb_adc(struct msi3101_state *s) | 964 | static int msi3101_set_usb_adc(struct msi3101_state *s) |
964 | { | 965 | { |
965 | int ret, div_n, div_m, div_r_out, f_sr; | 966 | int ret, div_n, div_m, div_r_out, f_sr, f_vco; |
966 | u32 reg4, reg3; | 967 | u32 reg4, reg3; |
967 | /* | 968 | /* |
968 | * FIXME: Synthesizer config is just a educated guess... | 969 | * Synthesizer config is just a educated guess... |
969 | * It seems to give reasonable values when N is 5-12 and output | ||
970 | * divider R is 2, which means sampling rates 5-12 Msps in practise. | ||
971 | * | 970 | * |
972 | * reg 3 ADC synthesizer config | ||
973 | * [7:0] 0x03, register address | 971 | * [7:0] 0x03, register address |
974 | * [8] 1, always | 972 | * [8] 1, always |
975 | * [9] ? | 973 | * [9] ? |
@@ -984,42 +982,48 @@ static int msi3101_set_usb_adc(struct msi3101_state *s) | |||
984 | * output divider | 982 | * output divider |
985 | * val div | 983 | * val div |
986 | * 0 - (invalid) | 984 | * 0 - (invalid) |
987 | * 1 2 | 985 | * 1 4 |
988 | * 2 3 | 986 | * 2 6 |
989 | * 3 4 | 987 | * 3 8 |
990 | * 4 5 | 988 | * 4 10 |
991 | * 5 6 | 989 | * 5 12 |
992 | * 6 7 | 990 | * 6 14 |
993 | * 7 8 | 991 | * 7 16 |
992 | * | ||
993 | * VCO 202000000 - 720000000++ | ||
994 | */ | 994 | */ |
995 | 995 | ||
996 | f_sr = s->ctrl_sampling_rate->val64; | 996 | f_sr = s->ctrl_sampling_rate->val64; |
997 | reg3 = 0x01c00303; | 997 | reg3 = 0x01c00303; |
998 | 998 | ||
999 | for (div_n = 12; div_n > 5; div_n--) { | 999 | for (div_r_out = 4; div_r_out < 16; div_r_out += 2) { |
1000 | if (f_sr >= div_n * 1000000) | 1000 | f_vco = f_sr * div_r_out * 12; |
1001 | dev_dbg(&s->udev->dev, "%s: div_r_out=%d f_vco=%d\n", | ||
1002 | __func__, div_r_out, f_vco); | ||
1003 | if (f_vco >= 202000000) | ||
1001 | break; | 1004 | break; |
1002 | } | 1005 | } |
1003 | 1006 | ||
1004 | reg3 |= div_n << 16; | 1007 | div_n = f_vco / (F_REF * DIV_R_IN); |
1005 | 1008 | div_m = f_vco % (F_REF * DIV_R_IN); | |
1006 | for (div_r_out = 2; div_r_out < 8; div_r_out++) { | ||
1007 | if (f_sr >= div_n * F_REF / div_r_out / 12) | ||
1008 | break; | ||
1009 | } | ||
1010 | 1009 | ||
1011 | reg3 |= (div_r_out - 1) << 10; | 1010 | reg3 |= div_n << 16; |
1012 | div_m = f_sr % (div_n * F_REF / div_r_out / 12); | 1011 | reg3 |= (div_r_out / 2 - 1) << 10; |
1012 | reg4 = 0x0ffffful * div_m / F_REF; | ||
1013 | 1013 | ||
1014 | if (div_m >= 500000) { | 1014 | if (reg4 >= 0x0ffffful) { |
1015 | dev_dbg(&s->udev->dev, | ||
1016 | "%s: extending fractional part value %08x\n", | ||
1017 | __func__, reg4); | ||
1018 | reg4 -= 0x0ffffful; | ||
1015 | reg3 |= 1 << 15; | 1019 | reg3 |= 1 << 15; |
1016 | div_m -= 500000; | ||
1017 | } | 1020 | } |
1018 | 1021 | ||
1019 | reg4 = ((div_m * 0x0ffffful / 500000) << 8) | 0x04; | 1022 | reg4 = (reg4 << 8) | 0x04; |
1020 | 1023 | ||
1021 | dev_dbg(&s->udev->dev, "%s: sr=%d n=%d m=%d r_out=%d reg4=%08x\n", | 1024 | dev_dbg(&s->udev->dev, |
1022 | __func__, f_sr, div_n, div_m, div_r_out, reg4); | 1025 | "%s: f_sr=%d f_vco=%d div_n=%d div_m=%d div_r_out=%d reg4=%08x\n", |
1026 | __func__, f_sr, f_vco, div_n, div_m, div_r_out, reg4); | ||
1023 | 1027 | ||
1024 | ret = msi3101_ctrl_msg(s, CMD_WREG, 0x00608008); | 1028 | ret = msi3101_ctrl_msg(s, CMD_WREG, 0x00608008); |
1025 | if (ret) | 1029 | if (ret) |