aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
authorRusty Scott <rustys@ieee.org>2006-12-04 16:04:16 -0500
committerMauro Carvalho Chehab <mchehab@infradead.org>2006-12-10 06:22:53 -0500
commit1444e5f591b8c68d7a326f5b0ad6c63a984d56dd (patch)
tree3f30789f0142578a54f074736242da4299b360b5 /drivers/media
parentb2fb7f55a1837e39a9f74e2fd7be990ccba90eb4 (diff)
V4L/DVB (4940): Or51211: Changed SNR and signal strength calculations
Removes embedded log functions and makes use of the DVB math functions to provide SNR in dB. The changes are modeled after recent changes made to the LGDT330x frontends in lgdt330x.c Signed-off-by: Rusty Scott <rustys@ieee.org> Signed-off-by: Trent Piepho <xyzzy@speakeasy.org> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/dvb/frontends/or51211.c124
1 files changed, 50 insertions, 74 deletions
diff --git a/drivers/media/dvb/frontends/or51211.c b/drivers/media/dvb/frontends/or51211.c
index 2bf124b53689..048d7cfe12d3 100644
--- a/drivers/media/dvb/frontends/or51211.c
+++ b/drivers/media/dvb/frontends/or51211.c
@@ -39,6 +39,7 @@
39#include <linux/slab.h> 39#include <linux/slab.h>
40#include <asm/byteorder.h> 40#include <asm/byteorder.h>
41 41
42#include "dvb_math.h"
42#include "dvb_frontend.h" 43#include "dvb_frontend.h"
43#include "or51211.h" 44#include "or51211.h"
44 45
@@ -63,6 +64,7 @@ struct or51211_state {
63 64
64 /* Demodulator private data */ 65 /* Demodulator private data */
65 u8 initialized:1; 66 u8 initialized:1;
67 u32 snr; /* Result of last SNR claculation */
66 68
67 /* Tuner private data */ 69 /* Tuner private data */
68 u32 current_frequency; 70 u32 current_frequency;
@@ -292,107 +294,81 @@ static int or51211_read_status(struct dvb_frontend* fe, fe_status_t* status)
292 return 0; 294 return 0;
293} 295}
294 296
295/* log10-1 table at .5 increments from 1 to 100.5 */ 297/* Calculate SNR estimation (scaled by 2^24)
296static unsigned int i100x20log10[] = {
297 0, 352, 602, 795, 954, 1088, 1204, 1306, 1397, 1480,
298 1556, 1625, 1690, 1750, 1806, 1858, 1908, 1955, 2000, 2042,
299 2082, 2121, 2158, 2193, 2227, 2260, 2292, 2322, 2352, 2380,
300 2408, 2434, 2460, 2486, 2510, 2534, 2557, 2580, 2602, 2623,
301 2644, 2664, 2684, 2704, 2723, 2742, 2760, 2778, 2795, 2813,
302 2829, 2846, 2862, 2878, 2894, 2909, 2924, 2939, 2954, 2968,
303 2982, 2996, 3010, 3023, 3037, 3050, 3062, 3075, 3088, 3100,
304 3112, 3124, 3136, 3148, 3159, 3170, 3182, 3193, 3204, 3214,
305 3225, 3236, 3246, 3256, 3266, 3276, 3286, 3296, 3306, 3316,
306 3325, 3334, 3344, 3353, 3362, 3371, 3380, 3389, 3397, 3406,
307 3415, 3423, 3432, 3440, 3448, 3456, 3464, 3472, 3480, 3488,
308 3496, 3504, 3511, 3519, 3526, 3534, 3541, 3549, 3556, 3563,
309 3570, 3577, 3584, 3591, 3598, 3605, 3612, 3619, 3625, 3632,
310 3639, 3645, 3652, 3658, 3665, 3671, 3677, 3683, 3690, 3696,
311 3702, 3708, 3714, 3720, 3726, 3732, 3738, 3744, 3750, 3755,
312 3761, 3767, 3772, 3778, 3784, 3789, 3795, 3800, 3806, 3811,
313 3816, 3822, 3827, 3832, 3838, 3843, 3848, 3853, 3858, 3863,
314 3868, 3874, 3879, 3884, 3888, 3893, 3898, 3903, 3908, 3913,
315 3918, 3922, 3927, 3932, 3936, 3941, 3946, 3950, 3955, 3960,
316 3964, 3969, 3973, 3978, 3982, 3986, 3991, 3995, 4000, 4004,
317};
318
319static unsigned int denom[] = {1,1,100,1000,10000,100000,1000000,10000000,100000000};
320 298
321static unsigned int i20Log10(unsigned short val) 299 8-VSB SNR equation from Oren datasheets
322{
323 unsigned int rntval = 100;
324 unsigned int tmp = val;
325 unsigned int exp = 1;
326 300
327 while(tmp > 100) {tmp /= 100; exp++;} 301 For 8-VSB:
302 SNR[dB] = 10 * log10(219037.9454 / MSE^2 )
328 303
329 val = (2 * val)/denom[exp]; 304 We re-write the snr equation as:
330 if (exp > 1) rntval = 2000*exp; 305 SNR * 2^24 = 10*(c - 2*intlog10(MSE))
306 Where for 8-VSB, c = log10(219037.9454) * 2^24 */
331 307
332 rntval += i100x20log10[val]; 308static u32 calculate_snr(u32 mse, u32 c)
333 return rntval; 309{
310 if (mse == 0) /* No signal */
311 return 0;
312
313 mse = 2*intlog10(mse);
314 if (mse > c) {
315 /* Negative SNR, which is possible, but realisticly the
316 demod will lose lock before the signal gets this bad. The
317 API only allows for unsigned values, so just return 0 */
318 return 0;
319 }
320 return 10*(c - mse);
334} 321}
335 322
336static int or51211_read_signal_strength(struct dvb_frontend* fe, u16* strength) 323static int or51211_read_snr(struct dvb_frontend* fe, u16* snr)
337{ 324{
338 struct or51211_state* state = fe->demodulator_priv; 325 struct or51211_state* state = fe->demodulator_priv;
339 u8 rec_buf[2]; 326 u8 rec_buf[2];
340 u8 snd_buf[4]; 327 u8 snd_buf[3];
341 u8 snr_equ;
342 u32 signal_strength;
343 328
344 /* SNR after Equalizer */ 329 /* SNR after Equalizer */
345 snd_buf[0] = 0x04; 330 snd_buf[0] = 0x04;
346 snd_buf[1] = 0x00; 331 snd_buf[1] = 0x00;
347 snd_buf[2] = 0x04; 332 snd_buf[2] = 0x04;
348 snd_buf[3] = 0x00;
349 333
350 if (i2c_writebytes(state,state->config->demod_address,snd_buf,3)) { 334 if (i2c_writebytes(state,state->config->demod_address,snd_buf,3)) {
351 printk(KERN_WARNING "or51211: read_status write error\n"); 335 printk(KERN_WARNING "%s: error writing snr reg\n",
336 __FUNCTION__);
352 return -1; 337 return -1;
353 } 338 }
354 msleep(3);
355 if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) { 339 if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) {
356 printk(KERN_WARNING "or51211: read_status read error\n"); 340 printk(KERN_WARNING "%s: read_status read error\n",
341 __FUNCTION__);
357 return -1; 342 return -1;
358 } 343 }
359 snr_equ = rec_buf[0] & 0xff;
360 344
361 /* The value reported back from the frontend will be FFFF=100% 0000=0% */ 345 state->snr = calculate_snr(rec_buf[0], 89599047);
362 signal_strength = (((5334 - i20Log10(snr_equ))/3+5)*65535)/1000; 346 *snr = (state->snr) >> 16;
363 if (signal_strength > 0xffff) 347
364 *strength = 0xffff; 348 dprintk("%s: noise = 0x%02x, snr = %d.%02d dB\n", __FUNCTION__, rec_buf[0],
365 else 349 state->snr >> 24, (((state->snr>>8) & 0xffff) * 100) >> 16);
366 *strength = signal_strength;
367 dprintk("read_signal_strength %i\n",*strength);
368 350
369 return 0; 351 return 0;
370} 352}
371 353
372static int or51211_read_snr(struct dvb_frontend* fe, u16* snr) 354static int or51211_read_signal_strength(struct dvb_frontend* fe, u16* strength)
373{ 355{
374 struct or51211_state* state = fe->demodulator_priv; 356 /* Calculate Strength from SNR up to 35dB */
375 u8 rec_buf[2]; 357 /* Even though the SNR can go higher than 35dB, there is some comfort */
376 u8 snd_buf[4]; 358 /* factor in having a range of strong signals that can show at 100% */
377 359 struct or51211_state* state = (struct or51211_state*)fe->demodulator_priv;
378 /* SNR after Equalizer */ 360 u16 snr;
379 snd_buf[0] = 0x04; 361 int ret;
380 snd_buf[1] = 0x00; 362
381 snd_buf[2] = 0x04; 363 ret = fe->ops.read_snr(fe, &snr);
382 snd_buf[3] = 0x00; 364 if (ret != 0)
383 365 return ret;
384 if (i2c_writebytes(state,state->config->demod_address,snd_buf,3)) { 366 /* Rather than use the 8.8 value snr, use state->snr which is 8.24 */
385 printk(KERN_WARNING "or51211: read_status write error\n"); 367 /* scale the range 0 - 35*2^24 into 0 - 65535 */
386 return -1; 368 if (state->snr >= 8960 * 0x10000)
387 } 369 *strength = 0xffff;
388 msleep(3); 370 else
389 if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) { 371 *strength = state->snr / 8960;
390 printk(KERN_WARNING "or51211: read_status read error\n");
391 return -1;
392 }
393 *snr = rec_buf[0] & 0xff;
394
395 dprintk("read_snr %i\n",*snr);
396 372
397 return 0; 373 return 0;
398} 374}