Skip to content

Commit

Permalink
[media] dvb-frontends/stv0910: merge upstream changes from 0.9.23 update
Browse files Browse the repository at this point in the history
Merge in stv0910 changes from upstream dddvb-0.9.23 package. Changes (mostly
DVBv5 stats readout) have been checkpatch cleaned. Also, our usual Log10x100
inclusion has been replaced by the intlog10x100 define, utilising dvb_math.h.
  • Loading branch information
herrnst committed Apr 13, 2016
1 parent 0efcfa8 commit 4e6dde5
Showing 1 changed file with 171 additions and 33 deletions.
204 changes: 171 additions & 33 deletions drivers/media/dvb-frontends/stv0910.c
Expand Up @@ -23,6 +23,8 @@
* Or, point your browser to http://www.gnu.org/copyleft/gpl.html
*/

#define intlog10x100(x) ((u32) (((u64) intlog10(x) * 100) >> 24))

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
Expand All @@ -33,6 +35,7 @@
#include <linux/version.h>
#include <asm/div64.h>

#include "dvb_math.h"
#include "dvb_frontend.h"
#include "stv0910.h"
#include "stv0910_regs.h"
Expand All @@ -46,7 +49,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 +136,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 +196,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 +253,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 +552,49 @@ 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 +613,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 @@ -1039,6 +1058,73 @@ static int set_parameters(struct dvb_frontend *fe)
return stat;
}

static int get_frontend(struct dvb_frontend *fe,
struct dtv_frontend_properties *p)
{
struct stv *state = fe->demodulator_priv;
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_NONE, FEC_NONE, 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;
}


static int read_snr(struct dvb_frontend *fe, u16 *snr);
static int read_signal_strength(struct dvb_frontend *fe, u16 *strength);
static int read_ber(struct dvb_frontend *fe, u32 *ber);

static int read_status(struct dvb_frontend *fe, enum fe_status *status)
{
Expand All @@ -1047,6 +1133,14 @@ static int read_status(struct dvb_frontend *fe, enum fe_status *status)
u8 DStatus = 0;
enum ReceiveMode CurReceiveMode = Mode_None;
u32 FECLock = 0;
u16 val;
u32 ber;

read_signal_strength(fe, &val);

read_snr(fe, &val);

read_ber(fe, &ber);

read_reg(state, RSTV0910_P2_DMDSTATE + state->regoff, &DmdState);

Expand All @@ -1065,7 +1159,7 @@ static int read_status(struct dvb_frontend *fe, enum fe_status *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 @@ -1259,40 +1353,83 @@ 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;
}

static int read_ber(struct dvb_frontend *fe, u32 *ber)
{
struct stv *state = fe->demodulator_priv;
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
u32 n, d;

GetBitErrorRate(state, &n, &d);
if (d)
*ber = n / d;
else
*ber = 0;

p->pre_bit_error.len = 1;
p->pre_bit_error.stat[0].scale = FE_SCALE_COUNTER;
p->pre_bit_error.stat[0].uvalue = n;
p->pre_bit_count.len = 1;
p->pre_bit_count.stat[0].scale = FE_SCALE_COUNTER;
p->pre_bit_count.stat[0].uvalue = d;
return 0;
}

static int read_signal_strength(struct dvb_frontend *fe, u16 *strength)
{
struct stv *state = fe->demodulator_priv;
u8 Agc1, Agc0;
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
u8 Reg[2];
s32 bbgain;
s32 Power = 0;
int i;

read_regs(state, RSTV0910_P2_AGCIQIN1 + state->regoff, Reg, 2);

*strength = (((u32) Reg[0]) << 8) | Reg[1];

for (i = 0; i < 5; i += 1) {
read_regs(state, RSTV0910_P2_POWERI + state->regoff, Reg, 2);
Power += (u32) Reg[0] * (u32) Reg[0]
+ (u32) Reg[1] * (u32) Reg[1];
usleep_range(3000, 4000);
}
Power /= 5;

bbgain = (465 - intlog10x100(Power)) * 10;

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

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

read_reg(state, RSTV0910_P2_AGCIQIN1 + state->regoff, &Agc1);
read_reg(state, RSTV0910_P2_AGCIQIN0 + state->regoff, &Agc0);
p->strength.len = 1;
p->strength.stat[0].scale = FE_SCALE_DECIBEL;
p->strength.stat[0].uvalue = 10 * (s64) (s16) *strength - 108750;

*strength = ((255 - Agc1) * 3300) / 256;
return 0;
}

Expand Down Expand Up @@ -1324,6 +1461,7 @@ static struct dvb_frontend_ops stv0910_ops = {
.release = release,
.i2c_gate_ctrl = gate_ctrl,
.get_frontend_algo = get_algo,
.get_frontend = get_frontend,
.tune = tune,
.read_status = read_status,
.set_tone = set_tone,
Expand Down Expand Up @@ -1362,7 +1500,7 @@ struct dvb_frontend *stv0910_attach(struct i2c_adapter *i2c,
state->tscfgh = 0x20 | (cfg->parallel ? 0 : 0x40);
state->tsgeneral = (cfg->parallel == 2) ? 0x02 : 0x00;
state->i2crpt = 0x0A | ((cfg->rptlvl & 0x07) << 4);
state->tsspeed = 0x40;
state->tsspeed = 0x28;
state->nr = nr;
state->regoff = state->nr ? 0 : 0x200;
state->SearchRange = 16000000;
Expand Down

0 comments on commit 4e6dde5

Please sign in to comment.