aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAntti Palosaari <crope@iki.fi>2013-08-02 20:49:49 -0400
committerMauro Carvalho Chehab <m.chehab@samsung.com>2013-08-20 15:04:50 -0400
commit23df427e3333882beea2e65d27fd2a581e37fae4 (patch)
treed9dde0746899c8dd9db50ccf451694eca5544a9d
parent22ca680e02aceb88d939b1eb1bbe3e94b71bf555 (diff)
[media] msi3101: improve tuner synth calc step size
Allow stepless synthesizer configuration. With that change we lose precision a little bit, as it is now between +-500Hz from the target. It could be better but on that case calculation algorithm goes more complex and atm there is more important things to do. Two approach to improve which comes to my mind are: 1) select and use biggest suitable step 2) use greatest common divisor algo to find divisor for thresh & frac when possible to avoid rounding errors, which is root of cause of current +-500Hz inaccuracy. Signed-off-by: Antti Palosaari <crope@iki.fi> Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
-rw-r--r--drivers/staging/media/msi3101/sdr-msi3101.c44
1 files changed, 27 insertions, 17 deletions
diff --git a/drivers/staging/media/msi3101/sdr-msi3101.c b/drivers/staging/media/msi3101/sdr-msi3101.c
index 04bbbdf0acd3..4ff6030bc950 100644
--- a/drivers/staging/media/msi3101/sdr-msi3101.c
+++ b/drivers/staging/media/msi3101/sdr-msi3101.c
@@ -1079,9 +1079,10 @@ err:
1079 1079
1080static int msi3101_set_tuner(struct msi3101_state *s) 1080static int msi3101_set_tuner(struct msi3101_state *s)
1081{ 1081{
1082 int i, ret, len; 1082 int ret, i, len;
1083 u32 reg, synthstep, thresh, n, frac; 1083 unsigned int n, m, thresh, frac, vco_step, tmp;
1084 u64 fsynth; 1084 u32 reg;
1085 u64 f_vco;
1085 u8 mode, lo_div; 1086 u8 mode, lo_div;
1086 const struct msi3101_gain *gain_lut; 1087 const struct msi3101_gain *gain_lut;
1087 static const struct { 1088 static const struct {
@@ -1176,21 +1177,30 @@ static int msi3101_set_tuner(struct msi3101_state *s)
1176 if (i == ARRAY_SIZE(bandwidth_lut)) 1177 if (i == ARRAY_SIZE(bandwidth_lut))
1177 goto err; 1178 goto err;
1178 1179
1179 #define FSTEP 10000 1180#define F_OUT_STEP 1
1180 #define FREF1 24000000 1181#define R_REF 4
1181 fsynth = (rf_freq + 0) * lo_div; 1182#define F_IF 0
1182 synthstep = FSTEP * lo_div; 1183 f_vco = (rf_freq + F_IF) * lo_div;
1183 thresh = (FREF1 * 4) / synthstep; 1184 n = f_vco / (F_REF * R_REF);
1184 n = fsynth / (FREF1 * 4); 1185 m = f_vco % (F_REF * R_REF);
1185 frac = thresh * (fsynth % (FREF1 * 4)) / (FREF1 * 4);
1186 1186
1187 if (thresh > 4095 || n > 63 || frac > 4095) { 1187 vco_step = F_OUT_STEP * lo_div;
1188 dev_dbg(&s->udev->dev, 1188 thresh = (F_REF * R_REF) / vco_step;
1189 "%s: synth setup failed rf=%d thresh=%d n=%d frac=%d\n", 1189 frac = 1ul * thresh * m / (F_REF * R_REF);
1190 __func__, rf_freq, thresh, n, frac); 1190
1191 ret = -EINVAL; 1191 /* Divide to reg max. After that RF resolution will be +-500Hz. */
1192 goto err; 1192 tmp = DIV_ROUND_UP(thresh, 4095);
1193 } 1193 thresh = DIV_ROUND_CLOSEST(thresh, tmp);
1194 frac = DIV_ROUND_CLOSEST(frac, tmp);
1195
1196 /* calc real RF set */
1197 tmp = 1ul * F_REF * R_REF * n;
1198 tmp += 1ul * F_REF * R_REF * frac / thresh;
1199 tmp /= lo_div;
1200
1201 dev_dbg(&s->udev->dev,
1202 "%s: rf=%u:%u n=%d thresh=%d frac=%d\n",
1203 __func__, rf_freq, tmp, n, thresh, frac);
1194 1204
1195 ret = msi3101_tuner_write(s, 0x00000e); 1205 ret = msi3101_tuner_write(s, 0x00000e);
1196 ret = msi3101_tuner_write(s, 0x000003); 1206 ret = msi3101_tuner_write(s, 0x000003);