diff options
Diffstat (limited to 'drivers/media/dvb/frontends/dib7000p.c')
-rw-r--r-- | drivers/media/dvb/frontends/dib7000p.c | 35 |
1 files changed, 33 insertions, 2 deletions
diff --git a/drivers/media/dvb/frontends/dib7000p.c b/drivers/media/dvb/frontends/dib7000p.c index 8217e5b38f47..55ef6eeb0769 100644 --- a/drivers/media/dvb/frontends/dib7000p.c +++ b/drivers/media/dvb/frontends/dib7000p.c @@ -10,6 +10,7 @@ #include <linux/kernel.h> #include <linux/i2c.h> +#include "dvb_math.h" #include "dvb_frontend.h" #include "dib7000p.h" @@ -883,7 +884,7 @@ static void dib7000p_spur_protect(struct dib7000p_state *state, u32 rf_khz, u32 255, 255, 255, 255, 255, 255}; u32 xtal = state->cfg.bw->xtal_hz / 1000; - int f_rel = ( (rf_khz + xtal/2) / xtal) * xtal - rf_khz; + int f_rel = DIV_ROUND_CLOSEST(rf_khz, xtal) * xtal - rf_khz; int k; int coef_re[8],coef_im[8]; int bw_khz = bw; @@ -1217,7 +1218,37 @@ static int dib7000p_read_signal_strength(struct dvb_frontend *fe, u16 *strength) static int dib7000p_read_snr(struct dvb_frontend* fe, u16 *snr) { - *snr = 0x0000; + struct dib7000p_state *state = fe->demodulator_priv; + u16 val; + s32 signal_mant, signal_exp, noise_mant, noise_exp; + u32 result = 0; + + val = dib7000p_read_word(state, 479); + noise_mant = (val >> 4) & 0xff; + noise_exp = ((val & 0xf) << 2); + val = dib7000p_read_word(state, 480); + noise_exp += ((val >> 14) & 0x3); + if ((noise_exp & 0x20) != 0) + noise_exp -= 0x40; + + signal_mant = (val >> 6) & 0xFF; + signal_exp = (val & 0x3F); + if ((signal_exp & 0x20) != 0) + signal_exp -= 0x40; + + if (signal_mant != 0) + result = intlog10(2) * 10 * signal_exp + 10 * + intlog10(signal_mant); + else + result = intlog10(2) * 10 * signal_exp - 100; + + if (noise_mant != 0) + result -= intlog10(2) * 10 * noise_exp + 10 * + intlog10(noise_mant); + else + result -= intlog10(2) * 10 * noise_exp - 100; + + *snr = result / ((1 << 24) / 10); return 0; } |