Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
fix stv0910 strength and snr values
  • Loading branch information
rjkm authored and mvoelkel committed Apr 11, 2016
1 parent 906efaf commit c18503f
Show file tree
Hide file tree
Showing 2 changed files with 112 additions and 37 deletions.
147 changes: 110 additions & 37 deletions frontends/stv0910.c
Expand Up @@ -46,7 +46,6 @@ LIST_HEAD(stvlist);

enum ReceiveMode { Mode_None, Mode_DVBS, Mode_DVBS2, Mode_Auto };


enum DVBS2_FECType { DVBS2_64K, DVBS2_16K };

enum DVBS2_ModCod {
Expand Down Expand Up @@ -134,9 +133,9 @@ struct SInitTable {
u8 Data;
};

struct SLookupSNTable {
s16 SignalToNoise;
u16 RefValue;
struct SLookup {
s16 Value;
u16 RegValue;
};

static inline int i2c_write(struct i2c_adapter *adap, u8 adr,
Expand Down Expand Up @@ -194,7 +193,7 @@ static int read_regs(struct stv *state, u16 reg, u8 *val, int len)
reg, val, len);
}

struct SLookupSNTable S1_SN_Lookup[] = {
struct SLookup S1_SN_Lookup[] = {
{ 0, 9242 }, /*C/N= 0dB*/
{ 05, 9105 }, /*C/N=0.5dB*/
{ 10, 8950 }, /*C/N=1.0dB*/
Expand Down Expand Up @@ -251,7 +250,7 @@ struct SLookupSNTable S1_SN_Lookup[] = {
{ 510, 425 } /*C/N=51.0dB*/
};

struct SLookupSNTable S2_SN_Lookup[] = {
struct SLookup S2_SN_Lookup[] = {
{ -30, 13950 }, /*C/N=-2.5dB*/
{ -25, 13580 }, /*C/N=-2.5dB*/
{ -20, 13150 }, /*C/N=-2.0dB*/
Expand Down Expand Up @@ -550,14 +549,48 @@ static int TrackingOptimization(struct stv *state)
return 0;
}

static int GetSignalToNoise(struct stv *state, s32 *SignalToNoise)
static s32 TableLookup(struct SLookup *Table,
int TableSize, u16 RegValue)
{
s32 Value;
int imin = 0;
int imax = TableSize - 1;
int i;
s32 RegDiff;

// Assumes Table[0].RegValue > Table[imax].RegValue
if( RegValue >= Table[0].RegValue )
Value = Table[0].Value;
else if( RegValue <= Table[imax].RegValue )
Value = Table[imax].Value;
else
{
while(imax-imin > 1)
{
i = (imax + imin) / 2;
if( (Table[imin].RegValue >= RegValue) && (RegValue >= Table[i].RegValue) )
imax = i;
else
imin = i;
}

RegDiff = Table[imax].RegValue - Table[imin].RegValue;
Value = Table[imin].Value;
if( RegDiff != 0 )
Value += ((s32)(RegValue - Table[imin].RegValue) *
(s32)(Table[imax].Value - Table[imin].Value))/(RegDiff);
}

return Value;
}

static int GetSignalToNoise(struct stv *state, s32 *SignalToNoise)
{
u8 Data0;
u8 Data1;
u16 Data;
int nLookup;
struct SLookupSNTable *Lookup;
struct SLookup *Lookup;

*SignalToNoise = 0;

Expand All @@ -576,25 +609,7 @@ static int GetSignalToNoise(struct stv *state, s32 *SignalToNoise)
Lookup = S1_SN_Lookup;
}
Data = (((u16)Data1) << 8) | (u16) Data0;
if (Data > Lookup[0].RefValue) {
*SignalToNoise = Lookup[0].SignalToNoise;
} else if (Data <= Lookup[nLookup-1].RefValue) {
*SignalToNoise = Lookup[nLookup-1].SignalToNoise;
} else {
for (i = 0; i < nLookup - 1; i += 1) {
if (Data <= Lookup[i].RefValue &&
Data > Lookup[i+1].RefValue) {
*SignalToNoise =
(s32)(Lookup[i].SignalToNoise) +
((s32)(Data - Lookup[i].RefValue) *
(s32)(Lookup[i+1].SignalToNoise -
Lookup[i].SignalToNoise)) /
((s32)(Lookup[i+1].RefValue) -
(s32)(Lookup[i].RefValue));
break;
}
}
}
*SignalToNoise = TableLookup(Lookup, nLookup, Data);
return 0;
}

Expand Down Expand Up @@ -1043,8 +1058,62 @@ static int get_frontend(struct dvb_frontend *fe)
{
struct stv *state = fe->demodulator_priv;
struct dtv_frontend_properties *p = &fe->dtv_property_cache;

u8 tmp;

if (state->ReceiveMode == Mode_DVBS2) {
u32 mc;
enum fe_modulation modcod2mod[0x20] = {
QPSK, QPSK, QPSK, QPSK,
QPSK, QPSK, QPSK, QPSK,
QPSK, QPSK, QPSK, QPSK,
PSK_8, PSK_8, PSK_8, PSK_8,
PSK_8, PSK_8, APSK_16, APSK_16,
APSK_16, APSK_16, APSK_16, APSK_16,
APSK_32, APSK_32, APSK_32, APSK_32,
APSK_32,
};
enum fe_code_rate modcod2fec[0x20] = {
FEC_NONE, FEC_1_4, FEC_1_3, FEC_2_5,
FEC_1_2, FEC_3_5, FEC_2_3, FEC_3_4,
FEC_4_5, FEC_5_6, FEC_8_9, FEC_9_10,
FEC_3_5, FEC_2_3, FEC_3_4, FEC_5_6,
FEC_8_9, FEC_9_10, FEC_2_3, FEC_3_4,
FEC_4_5, FEC_5_6, FEC_8_9, FEC_9_10,
FEC_3_4, FEC_4_5, FEC_5_6, FEC_8_9,
FEC_9_10
};
read_reg(state, RSTV0910_P2_DMDMODCOD + state->regoff, &tmp);
mc = ((tmp & 0x7c) >> 2);
p->pilot = (tmp & 0x01) ? PILOT_ON : PILOT_OFF;
p->modulation = modcod2mod[mc];
p->fec_inner = modcod2fec[mc];
} else if (state->ReceiveMode == Mode_DVBS) {
read_reg(state, RSTV0910_P2_VITCURPUN + state->regoff, &tmp);
switch( tmp & 0x1F ) {
case 0x0d:
p->fec_inner = FEC_1_2;
break;
case 0x12:
p->fec_inner = FEC_2_3;
break;
case 0x15:
p->fec_inner = FEC_3_4;
break;
case 0x18:
p->fec_inner = FEC_5_6;
break;
case 0x1a:
p->fec_inner = FEC_7_8;
break;
default:
p->fec_inner = FEC_NONE;
break;
}
p->rolloff = ROLLOFF_35;
} else {

}

return 0;
}

Expand All @@ -1067,9 +1136,6 @@ static int read_status(struct dvb_frontend *fe, fe_status_t *status)
read_signal_strength(fe, &val);

read_snr(fe, &val);
p->cnr.len = 1;
p->cnr.stat[0].scale = FE_SCALE_DECIBEL;
p->cnr.stat[0].uvalue = (s64) (s16) val;

read_ber(fe, &ber);

Expand All @@ -1090,7 +1156,7 @@ static int read_status(struct dvb_frontend *fe, fe_status_t *status)
if (state->ReceiveMode == Mode_None) {
state->ReceiveMode = CurReceiveMode;
state->DemodLockTime = jiffies;
state->FirstTimeLock = 0;
state->FirstTimeLock = 1;

write_reg(state, RSTV0910_P2_TSCFGH + state->regoff,
state->tscfgh);
Expand Down Expand Up @@ -1284,15 +1350,21 @@ static int sleep(struct dvb_frontend *fe)
return 0;
}


static int read_snr(struct dvb_frontend *fe, u16 *snr)
{
struct stv *state = fe->demodulator_priv;
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
s32 SNR;

*snr = 0;
if (GetSignalToNoise(state, &SNR))
return -EIO;
*snr = SNR;
p->cnr.len = 1;
p->cnr.stat[0].scale = FE_SCALE_DECIBEL;
p->cnr.stat[0].uvalue = 100 * (s64) SNR;

return 0;
}

Expand Down Expand Up @@ -1369,7 +1441,7 @@ static int read_signal_strength(struct dvb_frontend *fe, u16 *strength)
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
u8 Agc1, Agc0;
u8 Reg[2];
u32 pBBGain;
s32 bbgain;
s32 Power = 0;
int i;

Expand All @@ -1385,15 +1457,16 @@ static int read_signal_strength(struct dvb_frontend *fe, u16 *strength)
}
Power /= 5;

pBBGain = (465 - Log10x100(Power)) * 10;
bbgain = (465 - Log10x100(Power)) * 10;

if (fe->ops.tuner_ops.get_rf_strength)
fe->ops.tuner_ops.get_rf_strength(fe, strength);
else
*strength = 0;

if (pBBGain < *strength)
*strength -= pBBGain;

printk("pwr = %d bb = %d str = %u\n", Power, bbgain, *strength);
if (bbgain < (s32) *strength)
*strength -= bbgain;
else
*strength = 0;

Expand Down
2 changes: 2 additions & 0 deletions include/linux/dvb/frontend.h
Expand Up @@ -165,6 +165,8 @@ typedef enum fe_code_rate {
FEC_3_5,
FEC_9_10,
FEC_2_5,
FEC_1_4,
FEC_1_3,
} fe_code_rate_t;


Expand Down

5 comments on commit c18503f

@belliash
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about 090x?

@emilsvennesson
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CXD2843 doesn't work either.

@belliash
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are other drivers available that work with DD Cine and Duoflex S2, that already provides signal parameters like SNR and BER. Could you also consider fixing this for stv090x module? Actually I found this official drivers working best, but they miss such information.

@Pasha49
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about cxd2099?

@belliash
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any news?

Please sign in to comment.