aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/dvb
diff options
context:
space:
mode:
authorRusty Scott <rustys@ieee.org>2006-12-04 16:04:15 -0500
committerMauro Carvalho Chehab <mchehab@infradead.org>2006-12-10 06:22:53 -0500
commitb2fb7f55a1837e39a9f74e2fd7be990ccba90eb4 (patch)
tree1529361a3f105a364c24b2ac54b54064b9351649 /drivers/media/dvb
parent1c5ee876d697a9d1b70117e4277eaa445d14a728 (diff)
V4L/DVB (4939): Or51132: Changed SNR and signal strength reporting
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/dvb')
-rw-r--r--drivers/media/dvb/frontends/or51132.c176
1 files changed, 91 insertions, 85 deletions
diff --git a/drivers/media/dvb/frontends/or51132.c b/drivers/media/dvb/frontends/or51132.c
index d20ab30c1e83..5a3a6e53cda2 100644
--- a/drivers/media/dvb/frontends/or51132.c
+++ b/drivers/media/dvb/frontends/or51132.c
@@ -40,6 +40,7 @@
40#include <linux/slab.h> 40#include <linux/slab.h>
41#include <asm/byteorder.h> 41#include <asm/byteorder.h>
42 42
43#include "dvb_math.h"
43#include "dvb_frontend.h" 44#include "dvb_frontend.h"
44#include "dvb-pll.h" 45#include "dvb-pll.h"
45#include "or51132.h" 46#include "or51132.h"
@@ -62,6 +63,7 @@ struct or51132_state
62 63
63 /* Demodulator private data */ 64 /* Demodulator private data */
64 fe_modulation_t current_modulation; 65 fe_modulation_t current_modulation;
66 u32 snr; /* Result of last SNR calculation */
65 67
66 /* Tuner private data */ 68 /* Tuner private data */
67 u32 current_frequency; 69 u32 current_frequency;
@@ -465,124 +467,128 @@ static int or51132_read_status(struct dvb_frontend* fe, fe_status_t* status)
465 return 0; 467 return 0;
466} 468}
467 469
468/* log10-1 table at .5 increments from 1 to 100.5 */ 470/* Calculate SNR estimation (scaled by 2^24)
469static unsigned int i100x20log10[] = {
470 0, 352, 602, 795, 954, 1088, 1204, 1306, 1397, 1480,
471 1556, 1625, 1690, 1750, 1806, 1858, 1908, 1955, 2000, 2042,
472 2082, 2121, 2158, 2193, 2227, 2260, 2292, 2322, 2352, 2380,
473 2408, 2434, 2460, 2486, 2510, 2534, 2557, 2580, 2602, 2623,
474 2644, 2664, 2684, 2704, 2723, 2742, 2760, 2778, 2795, 2813,
475 2829, 2846, 2862, 2878, 2894, 2909, 2924, 2939, 2954, 2968,
476 2982, 2996, 3010, 3023, 3037, 3050, 3062, 3075, 3088, 3100,
477 3112, 3124, 3136, 3148, 3159, 3170, 3182, 3193, 3204, 3214,
478 3225, 3236, 3246, 3256, 3266, 3276, 3286, 3296, 3306, 3316,
479 3325, 3334, 3344, 3353, 3362, 3371, 3380, 3389, 3397, 3406,
480 3415, 3423, 3432, 3440, 3448, 3456, 3464, 3472, 3480, 3488,
481 3496, 3504, 3511, 3519, 3526, 3534, 3541, 3549, 3556, 3563,
482 3570, 3577, 3584, 3591, 3598, 3605, 3612, 3619, 3625, 3632,
483 3639, 3645, 3652, 3658, 3665, 3671, 3677, 3683, 3690, 3696,
484 3702, 3708, 3714, 3720, 3726, 3732, 3738, 3744, 3750, 3755,
485 3761, 3767, 3772, 3778, 3784, 3789, 3795, 3800, 3806, 3811,
486 3816, 3822, 3827, 3832, 3838, 3843, 3848, 3853, 3858, 3863,
487 3868, 3874, 3879, 3884, 3888, 3893, 3898, 3903, 3908, 3913,
488 3918, 3922, 3927, 3932, 3936, 3941, 3946, 3950, 3955, 3960,
489 3964, 3969, 3973, 3978, 3982, 3986, 3991, 3995, 4000, 4004,
490};
491 471
492static unsigned int denom[] = {1,1,100,1000,10000,100000,1000000,10000000,100000000}; 472 8-VSB SNR and QAM equations from Oren datasheets
493 473
494static unsigned int i20Log10(unsigned short val) 474 For 8-VSB:
495{ 475 SNR[dB] = 10 * log10(897152044.8282 / MSE^2 ) - K
496 unsigned int rntval = 100; 476
497 unsigned int tmp = val; 477 Where K = 0 if NTSC rejection filter is OFF; and
498 unsigned int exp = 1; 478 K = 3 if NTSC rejection filter is ON
479
480 For QAM64:
481 SNR[dB] = 10 * log10(897152044.8282 / MSE^2 )
499 482
500 while(tmp > 100) {tmp /= 100; exp++;} 483 For QAM256:
484 SNR[dB] = 10 * log10(907832426.314266 / MSE^2 )
501 485
502 val = (2 * val)/denom[exp]; 486 We re-write the snr equation as:
503 if (exp > 1) rntval = 2000*exp; 487 SNR * 2^24 = 10*(c - 2*intlog10(MSE))
488 Where for QAM256, c = log10(907832426.314266) * 2^24
489 and for 8-VSB and QAM64, c = log10(897152044.8282) * 2^24 */
504 490
505 rntval += i100x20log10[val]; 491static u32 calculate_snr(u32 mse, u32 c)
506 return rntval; 492{
493 if (mse == 0) /* No signal */
494 return 0;
495
496 mse = 2*intlog10(mse);
497 if (mse > c) {
498 /* Negative SNR, which is possible, but realisticly the
499 demod will lose lock before the signal gets this bad. The
500 API only allows for unsigned values, so just return 0 */
501 return 0;
502 }
503 return 10*(c - mse);
507} 504}
508 505
509static int or51132_read_signal_strength(struct dvb_frontend* fe, u16* strength) 506static int or51132_read_snr(struct dvb_frontend* fe, u16* snr)
510{ 507{
511 struct or51132_state* state = fe->demodulator_priv; 508 struct or51132_state* state = fe->demodulator_priv;
512 unsigned char rec_buf[2]; 509 u8 rec_buf[2];
513 unsigned char snd_buf[2]; 510 u8 snd_buf[2];
514 u8 rcvr_stat; 511 u32 noise;
515 u16 snr_equ; 512 u32 c;
516 u32 signal_strength; 513 u32 usK;
517 int usK;
518 514
515 /* Register is same for VSB or QAM firmware */
519 snd_buf[0]=0x04; 516 snd_buf[0]=0x04;
520 snd_buf[1]=0x02; /* SNR after Equalizer */ 517 snd_buf[1]=0x02; /* SNR after Equalizer */
521 msleep(30); /* 30ms */ 518 msleep(30); /* 30ms */
522 if (i2c_writebytes(state,state->config->demod_address,snd_buf,2)) { 519 if (i2c_writebytes(state,state->config->demod_address,snd_buf,2)) {
523 printk(KERN_WARNING "or51132: read_status write error\n"); 520 printk(KERN_WARNING "or51132: snr write error\n");
524 return -1; 521 return -EREMOTEIO;
525 } 522 }
526 msleep(30); /* 30ms */ 523 msleep(30); /* 30ms */
527 if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) { 524 if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) {
528 printk(KERN_WARNING "or51132: read_status read error\n"); 525 printk(KERN_WARNING "or51132: snr read error\n");
529 return -1; 526 return -EREMOTEIO;
530 } 527 }
531 snr_equ = rec_buf[0] | (rec_buf[1] << 8); 528 noise = rec_buf[0] | (rec_buf[1] << 8);
532 dprintk("read_signal_strength snr_equ %x %x (%i)\n",rec_buf[0],rec_buf[1],snr_equ); 529 dprintk("read_snr noise %x %x (%i)\n",rec_buf[0],rec_buf[1],noise);
533 530
534 /* Receiver Status */ 531 /* Read status, contains modulation type for QAM_AUTO and
532 NTSC filter for VSB */
535 snd_buf[0]=0x04; 533 snd_buf[0]=0x04;
536 snd_buf[1]=0x00; 534 snd_buf[1]=0x00; /* Status register */
537 msleep(30); /* 30ms */ 535 msleep(30); /* 30ms */
538 if (i2c_writebytes(state,state->config->demod_address,snd_buf,2)) { 536 if (i2c_writebytes(state,state->config->demod_address,snd_buf,2)) {
539 printk(KERN_WARNING "or51132: read_signal_strength read_status write error\n"); 537 printk(KERN_WARNING "or51132: status write error\n");
540 return -1; 538 return -EREMOTEIO;
541 } 539 }
542 msleep(30); /* 30ms */ 540 msleep(30); /* 30ms */
543 if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) { 541 if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) {
544 printk(KERN_WARNING "or51132: read_signal_strength read_status read error\n"); 542 printk(KERN_WARNING "or51132: status read error\n");
545 return -1; 543 return -EREMOTEIO;
546 } 544 }
547 dprintk("read_signal_strength read_status %x %x\n",rec_buf[0],rec_buf[1]);
548 rcvr_stat = rec_buf[1];
549 usK = (rcvr_stat & 0x10) ? 3 : 0;
550 545
551 /* The value reported back from the frontend will be FFFF=100% 0000=0% */ 546 usK = 0;
552 signal_strength = (((8952 - i20Log10(snr_equ) - usK*100)/3+5)*65535)/1000; 547 switch (rec_buf[0]) {
553 if (signal_strength > 0xffff) 548 case 0x06:
554 *strength = 0xffff; 549 usK = (rec_buf[1] & 0x10) ? 0x03000000 : 0;
555 else 550 /* Fall through to QAM64 case */
556 *strength = signal_strength; 551 case 0x43:
557 dprintk("read_signal_strength %i\n",*strength); 552 c = 150204167;
553 break;
554 case 0x45:
555 c = 150290396;
556 break;
557 default:
558 printk(KERN_ERR "or51132: unknown status 0x%02x\n", rec_buf[0]);
559 return -EREMOTEIO;
560 }
561 dprintk("%s: modulation %02x, NTSC rej O%s\n", __FUNCTION__,
562 rec_buf[0], rec_buf[1]&0x10?"n":"ff");
563
564 /* Calculate SNR using noise, c, and NTSC rejection correction */
565 state->snr = calculate_snr(noise, c) - usK;
566 *snr = (state->snr) >> 16;
567
568 dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __FUNCTION__, noise,
569 state->snr >> 24, (((state->snr>>8) & 0xffff) * 100) >> 16);
558 570
559 return 0; 571 return 0;
560} 572}
561 573
562static int or51132_read_snr(struct dvb_frontend* fe, u16* snr) 574static int or51132_read_signal_strength(struct dvb_frontend* fe, u16* strength)
563{ 575{
564 struct or51132_state* state = fe->demodulator_priv; 576 /* Calculate Strength from SNR up to 35dB */
565 unsigned char rec_buf[2]; 577 /* Even though the SNR can go higher than 35dB, there is some comfort */
566 unsigned char snd_buf[2]; 578 /* factor in having a range of strong signals that can show at 100% */
567 u16 snr_equ; 579 struct or51132_state* state = (struct or51132_state*) fe->demodulator_priv;
568 580 u16 snr;
569 snd_buf[0]=0x04; 581 int ret;
570 snd_buf[1]=0x02; /* SNR after Equalizer */
571 msleep(30); /* 30ms */
572 if (i2c_writebytes(state,state->config->demod_address,snd_buf,2)) {
573 printk(KERN_WARNING "or51132: read_snr write error\n");
574 return -1;
575 }
576 msleep(30); /* 30ms */
577 if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) {
578 printk(KERN_WARNING "or51132: read_snr dvr read error\n");
579 return -1;
580 }
581 snr_equ = rec_buf[0] | (rec_buf[1] << 8);
582 dprintk("read_snr snr_equ %x %x (%i)\n",rec_buf[0],rec_buf[1],snr_equ);
583 582
584 *snr = 0xFFFF - snr_equ; 583 ret = fe->ops.read_snr(fe, &snr);
585 dprintk("read_snr %i\n",*snr); 584 if (ret != 0)
585 return ret;
586 /* Rather than use the 8.8 value snr, use state->snr which is 8.24 */
587 /* scale the range 0 - 35*2^24 into 0 - 65535 */
588 if (state->snr >= 8960 * 0x10000)
589 *strength = 0xffff;
590 else
591 *strength = state->snr / 8960;
586 592
587 return 0; 593 return 0;
588} 594}