@ -39,6 +39,7 @@
# include <linux/slab.h>
# include <asm/byteorder.h>
# include "dvb_math.h"
# include "dvb_frontend.h"
# include "or51211.h"
@ -63,6 +64,7 @@ struct or51211_state {
/* Demodulator private data */
u8 initialized : 1 ;
u32 snr ; /* Result of last SNR claculation */
/* Tuner private data */
u32 current_frequency ;
@ -292,107 +294,81 @@ static int or51211_read_status(struct dvb_frontend* fe, fe_status_t* status)
return 0 ;
}
/* log10-1 table at .5 increments from 1 to 100.5 */
static unsigned int i100x20log10 [ ] = {
0 , 352 , 602 , 795 , 954 , 1088 , 1204 , 1306 , 1397 , 1480 ,
1556 , 1625 , 1690 , 1750 , 1806 , 1858 , 1908 , 1955 , 2000 , 2042 ,
2082 , 2121 , 2158 , 2193 , 2227 , 2260 , 2292 , 2322 , 2352 , 2380 ,
2408 , 2434 , 2460 , 2486 , 2510 , 2534 , 2557 , 2580 , 2602 , 2623 ,
2644 , 2664 , 2684 , 2704 , 2723 , 2742 , 2760 , 2778 , 2795 , 2813 ,
2829 , 2846 , 2862 , 2878 , 2894 , 2909 , 2924 , 2939 , 2954 , 2968 ,
2982 , 2996 , 3010 , 3023 , 3037 , 3050 , 3062 , 3075 , 3088 , 3100 ,
3112 , 3124 , 3136 , 3148 , 3159 , 3170 , 3182 , 3193 , 3204 , 3214 ,
3225 , 3236 , 3246 , 3256 , 3266 , 3276 , 3286 , 3296 , 3306 , 3316 ,
3325 , 3334 , 3344 , 3353 , 3362 , 3371 , 3380 , 3389 , 3397 , 3406 ,
3415 , 3423 , 3432 , 3440 , 3448 , 3456 , 3464 , 3472 , 3480 , 3488 ,
3496 , 3504 , 3511 , 3519 , 3526 , 3534 , 3541 , 3549 , 3556 , 3563 ,
3570 , 3577 , 3584 , 3591 , 3598 , 3605 , 3612 , 3619 , 3625 , 3632 ,
3639 , 3645 , 3652 , 3658 , 3665 , 3671 , 3677 , 3683 , 3690 , 3696 ,
3702 , 3708 , 3714 , 3720 , 3726 , 3732 , 3738 , 3744 , 3750 , 3755 ,
3761 , 3767 , 3772 , 3778 , 3784 , 3789 , 3795 , 3800 , 3806 , 3811 ,
3816 , 3822 , 3827 , 3832 , 3838 , 3843 , 3848 , 3853 , 3858 , 3863 ,
3868 , 3874 , 3879 , 3884 , 3888 , 3893 , 3898 , 3903 , 3908 , 3913 ,
3918 , 3922 , 3927 , 3932 , 3936 , 3941 , 3946 , 3950 , 3955 , 3960 ,
3964 , 3969 , 3973 , 3978 , 3982 , 3986 , 3991 , 3995 , 4000 , 4004 ,
} ;
static unsigned int denom [ ] = { 1 , 1 , 100 , 1000 , 10000 , 100000 , 1000000 , 10000000 , 100000000 } ;
/* Calculate SNR estimation (scaled by 2^24)
static unsigned int i20Log10 ( unsigned short val )
{
unsigned int rntval = 100 ;
unsigned int tmp = val ;
unsigned int exp = 1 ;
8 - VSB SNR equation from Oren datasheets
while ( tmp > 100 ) { tmp / = 100 ; exp + + ; }
For 8 - VSB :
SNR [ dB ] = 10 * log10 ( 219037.9454 / MSE ^ 2 )
val = ( 2 * val ) / denom [ exp ] ;
if ( exp > 1 ) rntval = 2000 * exp ;
We re - write the snr equation as :
SNR * 2 ^ 24 = 10 * ( c - 2 * intlog10 ( MSE ) )
Where for 8 - VSB , c = log10 ( 219037.9454 ) * 2 ^ 24 */
rntval + = i100x20log10 [ val ] ;
return rntval ;
static u32 calculate_snr ( u32 mse , u32 c )
{
if ( mse = = 0 ) /* No signal */
return 0 ;
mse = 2 * intlog10 ( mse ) ;
if ( mse > c ) {
/* Negative SNR, which is possible, but realisticly the
demod will lose lock before the signal gets this bad . The
API only allows for unsigned values , so just return 0 */
return 0 ;
}
return 10 * ( c - mse ) ;
}
static int or51211_read_signal_strength ( struct dvb_frontend * fe , u16 * strength )
static int or51211_read_snr ( struct dvb_frontend * fe , u16 * snr )
{
struct or51211_state * state = fe - > demodulator_priv ;
u8 rec_buf [ 2 ] ;
u8 snd_buf [ 4 ] ;
u8 snr_equ ;
u32 signal_strength ;
u8 snd_buf [ 3 ] ;
/* SNR after Equalizer */
snd_buf [ 0 ] = 0x04 ;
snd_buf [ 1 ] = 0x00 ;
snd_buf [ 2 ] = 0x04 ;
snd_buf [ 3 ] = 0x00 ;
if ( i2c_writebytes ( state , state - > config - > demod_address , snd_buf , 3 ) ) {
printk ( KERN_WARNING " or51211: read_status write error \n " ) ;
printk ( KERN_WARNING " %s: error writing snr reg \n " ,
__FUNCTION__ ) ;
return - 1 ;
}
msleep ( 3 ) ;
if ( i2c_readbytes ( state , state - > config - > demod_address , rec_buf , 2 ) ) {
printk ( KERN_WARNING " or51211: read_status read error \n " ) ;
printk ( KERN_WARNING " %s: read_status read error \n " ,
__FUNCTION__ ) ;
return - 1 ;
}
snr_equ = rec_buf [ 0 ] & 0xff ;
/* The value reported back from the frontend will be FFFF=100% 0000=0% */
signal_strength = ( ( ( 5334 - i20Log10 ( snr_equ ) ) / 3 + 5 ) * 65535 ) / 1000 ;
if ( signal_strength > 0xffff )
* strength = 0xffff ;
else
* strength = signal_strength ;
dprintk ( " read_signal_strength %i \n " , * strength ) ;
state - > snr = calculate_snr ( rec_buf [ 0 ] , 89599047 ) ;
* snr = ( state - > snr ) > > 16 ;
dprintk ( " %s: noise = 0x%02x, snr = %d.%02d dB \n " , __FUNCTION__ , rec_buf [ 0 ] ,
state - > snr > > 24 , ( ( ( state - > snr > > 8 ) & 0xffff ) * 100 ) > > 16 ) ;
return 0 ;
}
static int or51211_read_snr ( struct dvb_frontend * fe , u16 * snr )
static int or51211_read_sig nal_st rength ( struct dvb_frontend * fe , u16 * strength )
{
struct or51211_state * state = fe - > demodulator_priv ;
u8 rec_buf [ 2 ] ;
u8 snd_buf [ 4 ] ;
/* SNR after Equalizer */
snd_buf [ 0 ] = 0x04 ;
snd_buf [ 1 ] = 0x00 ;
snd_buf [ 2 ] = 0x04 ;
snd_buf [ 3 ] = 0x00 ;
if ( i2c_writebytes ( state , state - > config - > demod_address , snd_buf , 3 ) ) {
printk ( KERN_WARNING " or51211: read_status write error \n " ) ;
return - 1 ;
}
msleep ( 3 ) ;
if ( i2c_readbytes ( state , state - > config - > demod_address , rec_buf , 2 ) ) {
printk ( KERN_WARNING " or51211: read_status read error \n " ) ;
return - 1 ;
}
* snr = rec_buf [ 0 ] & 0xff ;
dprintk ( " read_snr %i \n " , * snr ) ;
/* Calculate Strength from SNR up to 35dB */
/* Even though the SNR can go higher than 35dB, there is some comfort */
/* factor in having a range of strong signals that can show at 100% */
struct or51211_state * state = ( struct or51211_state * ) fe - > demodulator_priv ;
u16 snr ;
int ret ;
ret = fe - > ops . read_snr ( fe , & snr ) ;
if ( ret ! = 0 )
return ret ;
/* Rather than use the 8.8 value snr, use state->snr which is 8.24 */
/* scale the range 0 - 35*2^24 into 0 - 65535 */
if ( state - > snr > = 8960 * 0x10000 )
* strength = 0xffff ;
else
* strength = state - > snr / 8960 ;
return 0 ;
}