Commit b1520857 authored by Antti Palosaari's avatar Antti Palosaari Committed by Mauro Carvalho Chehab

[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: default avatarAntti Palosaari <crope@iki.fi>
Signed-off-by: default avatarMauro Carvalho Chehab <m.chehab@samsung.com>
parent 34599b9b
...@@ -960,16 +960,14 @@ static int msi3101_tuner_write(struct msi3101_state *s, u32 data) ...@@ -960,16 +960,14 @@ static int msi3101_tuner_write(struct msi3101_state *s, u32 data)
}; };
#define F_REF 24000000 #define F_REF 24000000
#define DIV_R_IN 2
static int msi3101_set_usb_adc(struct msi3101_state *s) static int msi3101_set_usb_adc(struct msi3101_state *s)
{ {
int ret, div_n, div_m, div_r_out, f_sr; int ret, div_n, div_m, div_r_out, f_sr, f_vco;
u32 reg4, reg3; u32 reg4, reg3;
/* /*
* FIXME: Synthesizer config is just a educated guess... * Synthesizer config is just a educated guess...
* It seems to give reasonable values when N is 5-12 and output
* divider R is 2, which means sampling rates 5-12 Msps in practise.
* *
* reg 3 ADC synthesizer config
* [7:0] 0x03, register address * [7:0] 0x03, register address
* [8] 1, always * [8] 1, always
* [9] ? * [9] ?
...@@ -984,42 +982,48 @@ static int msi3101_set_usb_adc(struct msi3101_state *s) ...@@ -984,42 +982,48 @@ static int msi3101_set_usb_adc(struct msi3101_state *s)
* output divider * output divider
* val div * val div
* 0 - (invalid) * 0 - (invalid)
* 1 2 * 1 4
* 2 3 * 2 6
* 3 4 * 3 8
* 4 5 * 4 10
* 5 6 * 5 12
* 6 7 * 6 14
* 7 8 * 7 16
*
* VCO 202000000 - 720000000++
*/ */
f_sr = s->ctrl_sampling_rate->val64; f_sr = s->ctrl_sampling_rate->val64;
reg3 = 0x01c00303; reg3 = 0x01c00303;
for (div_n = 12; div_n > 5; div_n--) { for (div_r_out = 4; div_r_out < 16; div_r_out += 2) {
if (f_sr >= div_n * 1000000) f_vco = f_sr * div_r_out * 12;
dev_dbg(&s->udev->dev, "%s: div_r_out=%d f_vco=%d\n",
__func__, div_r_out, f_vco);
if (f_vco >= 202000000)
break; break;
} }
reg3 |= div_n << 16; div_n = f_vco / (F_REF * DIV_R_IN);
div_m = f_vco % (F_REF * DIV_R_IN);
for (div_r_out = 2; div_r_out < 8; div_r_out++) {
if (f_sr >= div_n * F_REF / div_r_out / 12)
break;
}
reg3 |= (div_r_out - 1) << 10; reg3 |= div_n << 16;
div_m = f_sr % (div_n * F_REF / div_r_out / 12); reg3 |= (div_r_out / 2 - 1) << 10;
reg4 = 0x0ffffful * div_m / F_REF;
if (div_m >= 500000) { if (reg4 >= 0x0ffffful) {
dev_dbg(&s->udev->dev,
"%s: extending fractional part value %08x\n",
__func__, reg4);
reg4 -= 0x0ffffful;
reg3 |= 1 << 15; reg3 |= 1 << 15;
div_m -= 500000;
} }
reg4 = ((div_m * 0x0ffffful / 500000) << 8) | 0x04; reg4 = (reg4 << 8) | 0x04;
dev_dbg(&s->udev->dev, "%s: sr=%d n=%d m=%d r_out=%d reg4=%08x\n", dev_dbg(&s->udev->dev,
__func__, f_sr, div_n, div_m, div_r_out, reg4); "%s: f_sr=%d f_vco=%d div_n=%d div_m=%d div_r_out=%d reg4=%08x\n",
__func__, f_sr, f_vco, div_n, div_m, div_r_out, reg4);
ret = msi3101_ctrl_msg(s, CMD_WREG, 0x00608008); ret = msi3101_ctrl_msg(s, CMD_WREG, 0x00608008);
if (ret) if (ret)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment