Commit 77557abe authored by Manu Abraham's avatar Manu Abraham Committed by Mauro Carvalho Chehab

V4L/DVB (13717): [MB86A16] Statistics Updates

* Demodulator status check made reliable
* Code simplification for Viterbi Sync check, makes
  acquisition more reliable

* Implement a BER monitor
* Implement a Signal strength monitor
* Implement a "simple" UCB monitor, no real UCB monitor
Signed-off-by: default avatarManu Abraham <manu@linuxtv.org>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 41703684
...@@ -36,7 +36,6 @@ struct mb86a16_state { ...@@ -36,7 +36,6 @@ struct mb86a16_state {
struct i2c_adapter *i2c_adap; struct i2c_adapter *i2c_adap;
const struct mb86a16_config *config; const struct mb86a16_config *config;
struct dvb_frontend frontend; struct dvb_frontend frontend;
u8 signal;
// tuning parameters // tuning parameters
int frequency; int frequency;
...@@ -593,17 +592,39 @@ static int dagcm_val_get(struct mb86a16_state *state) ...@@ -593,17 +592,39 @@ static int dagcm_val_get(struct mb86a16_state *state)
static int mb86a16_read_status(struct dvb_frontend *fe, fe_status_t *status) static int mb86a16_read_status(struct dvb_frontend *fe, fe_status_t *status)
{ {
u8 stat, stat2;
struct mb86a16_state *state = fe->demodulator_priv; struct mb86a16_state *state = fe->demodulator_priv;
*status = 0; *status = 0;
if (state->signal & 0x02)
*status |= FE_HAS_VITERBI; if (mb86a16_read(state, MB86A16_SIG1, &stat) != 2)
if (state->signal & 0x01) goto err;
if (mb86a16_read(state, MB86A16_SIG2, &stat2) != 2)
goto err;
if ((stat > 25) && (stat2 > 25))
*status |= FE_HAS_SIGNAL;
if ((stat > 45) && (stat2 > 45))
*status |= FE_HAS_CARRIER;
if (mb86a16_read(state, MB86A16_STATUS, &stat) != 2)
goto err;
if (stat & 0x01)
*status |= FE_HAS_SYNC; *status |= FE_HAS_SYNC;
if (state->signal & 0x03) if (stat & 0x01)
*status |= FE_HAS_VITERBI;
if (mb86a16_read(state, MB86A16_FRAMESYNC, &stat) != 2)
goto err;
if ((stat & 0x0f) && (*status & FE_HAS_VITERBI))
*status |= FE_HAS_LOCK; *status |= FE_HAS_LOCK;
return 0; return 0;
err:
dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
return -EREMOTEIO;
} }
static int sync_chk(struct mb86a16_state *state, static int sync_chk(struct mb86a16_state *state,
...@@ -1439,10 +1460,6 @@ static int mb86a16_set_fe(struct mb86a16_state *state) ...@@ -1439,10 +1460,6 @@ static int mb86a16_set_fe(struct mb86a16_state *state)
msleep_interruptible(wait_t); msleep_interruptible(wait_t);
sync = sync_chk(state, &VIRM); sync = sync_chk(state, &VIRM);
dprintk(verbose, MB86A16_INFO, 1, "-------- Viterbi=[%d] SYNC=[%d] ---------", VIRM, sync); dprintk(verbose, MB86A16_INFO, 1, "-------- Viterbi=[%d] SYNC=[%d] ---------", VIRM, sync);
if (mb86a16_read(state, 0x0d, &state->signal) != 2) {
dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
return -EREMOTEIO;
}
if (VIRM) { if (VIRM) {
if (VIRM == 4) { // 5/6 if (VIRM == 4) { // 5/6
if (SIG1 > 110) if (SIG1 > 110)
...@@ -1459,22 +1476,14 @@ static int mb86a16_set_fe(struct mb86a16_state *state) ...@@ -1459,22 +1476,14 @@ static int mb86a16_set_fe(struct mb86a16_state *state)
iq_vt_set(state, 1); iq_vt_set(state, 1);
FEC_srst(state); FEC_srst(state);
} }
if (SIG1 > 110)
wait_t = ( 786432 + state->srate / 2) / state->srate;
else
wait_t = (1572864 + state->srate / 2) / state->srate;
msleep_interruptible(wait_t);
SEQ_set(state, 1);
} else { // 1/2, 2/3, 3/4, 7/8
if (SIG1 > 110)
wait_t = ( 786432 + state->srate / 2) / state->srate;
else
wait_t = (1572864 + state->srate / 2) / state->srate;
msleep_interruptible(wait_t);
SEQ_set(state, 1);
} }
// 1/2, 2/3, 3/4, 7/8
if (SIG1 > 110)
wait_t = ( 786432 + state->srate / 2) / state->srate;
else
wait_t = (1572864 + state->srate / 2) / state->srate;
msleep_interruptible(wait_t);
SEQ_set(state, 1);
} else { } else {
dprintk(verbose, MB86A16_INFO, 1, "NO -- SYNC"); dprintk(verbose, MB86A16_INFO, 1, "NO -- SYNC");
SEQ_set(state, 1); SEQ_set(state, 1);
...@@ -1648,12 +1657,85 @@ static int mb86a16_sleep(struct dvb_frontend *fe) ...@@ -1648,12 +1657,85 @@ static int mb86a16_sleep(struct dvb_frontend *fe)
static int mb86a16_read_ber(struct dvb_frontend *fe, u32 *ber) static int mb86a16_read_ber(struct dvb_frontend *fe, u32 *ber)
{ {
u8 ber_mon, ber_tab, ber_lsb, ber_mid, ber_msb, ber_tim, ber_rst;
u32 timer;
struct mb86a16_state *state = fe->demodulator_priv;
*ber = 0;
if (mb86a16_read(state, MB86A16_BERMON, &ber_mon) != 2)
goto err;
if (mb86a16_read(state, MB86A16_BERTAB, &ber_tab) != 2)
goto err;
if (mb86a16_read(state, MB86A16_BERLSB, &ber_lsb) != 2)
goto err;
if (mb86a16_read(state, MB86A16_BERMID, &ber_mid) != 2)
goto err;
if (mb86a16_read(state, MB86A16_BERMSB, &ber_msb) != 2)
goto err;
/* BER monitor invalid when BER_EN = 0 */
if (ber_mon & 0x04) {
/* coarse, fast calculation */
*ber = ber_tab & 0x1f;
dprintk(verbose, MB86A16_DEBUG, 1, "BER coarse=[0x%02x]", *ber);
if (ber_mon & 0x01) {
/*
* BER_SEL = 1, The monitored BER is the estimated
* value with a Reed-Solomon decoder error amount at
* the deinterleaver output.
* monitored BER is expressed as a 20 bit output in total
*/
ber_rst = ber_mon >> 3;
*ber = (((ber_msb << 8) | ber_mid) << 8) | ber_lsb;
if (ber_rst == 0)
timer = 12500000;
if (ber_rst == 1)
timer = 25000000;
if (ber_rst == 2)
timer = 50000000;
if (ber_rst == 3)
timer = 100000000;
*ber /= timer;
dprintk(verbose, MB86A16_DEBUG, 1, "BER fine=[0x%02x]", *ber);
} else {
/*
* BER_SEL = 0, The monitored BER is the estimated
* value with a Viterbi decoder error amount at the
* QPSK demodulator output.
* monitored BER is expressed as a 24 bit output in total
*/
ber_tim = ber_mon >> 1;
*ber = (((ber_msb << 8) | ber_mid) << 8) | ber_lsb;
if (ber_tim == 0)
timer = 16;
if (ber_tim == 1)
timer = 24;
*ber /= 2 ^ timer;
dprintk(verbose, MB86A16_DEBUG, 1, "BER fine=[0x%02x]", *ber);
}
}
return 0; return 0;
err:
dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
return -EREMOTEIO;
} }
static int mb86a16_read_signal_strength(struct dvb_frontend *fe, u16 *strength) static int mb86a16_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
{ {
u8 agcm = 0;
struct mb86a16_state *state = fe->demodulator_priv;
*strength = 0; *strength = 0;
if (mb86a16_read(state, MB86A16_AGCM, &agcm) != 2) {
dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
return -EREMOTEIO;
}
*strength = ((0xff - agcm) * 100) / 256;
dprintk(verbose, MB86A16_DEBUG, 1, "Signal strength=[%d %%]", (u8) *strength);
*strength = (0xffff - 0xff) + agcm;
return 0; return 0;
} }
...@@ -1708,12 +1790,22 @@ static int mb86a16_read_snr(struct dvb_frontend *fe, u16 *snr) ...@@ -1708,12 +1790,22 @@ static int mb86a16_read_snr(struct dvb_frontend *fe, u16 *snr)
} }
q_level = (*snr * 100) / (high_tide - low_tide); q_level = (*snr * 100) / (high_tide - low_tide);
dprintk(verbose, MB86A16_ERROR, 1, "SNR (Quality) = [%d dB], Level=%d %%", *snr, q_level); dprintk(verbose, MB86A16_ERROR, 1, "SNR (Quality) = [%d dB], Level=%d %%", *snr, q_level);
*snr = (0xffff - 0xff) + *snr;
return 0; return 0;
} }
static int mb86a16_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) static int mb86a16_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
{ {
u8 dist;
struct mb86a16_state *state = fe->demodulator_priv;
if (mb86a16_read(state, MB86A16_DISTMON, &dist) != 2) {
dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
return -EREMOTEIO;
}
*ucblocks = dist;
return 0; return 0;
} }
...@@ -1723,7 +1815,7 @@ static struct dvb_frontend_ops mb86a16_ops = { ...@@ -1723,7 +1815,7 @@ static struct dvb_frontend_ops mb86a16_ops = {
.type = FE_QPSK, .type = FE_QPSK,
.frequency_min = 950000, .frequency_min = 950000,
.frequency_max = 2150000, .frequency_max = 2150000,
.frequency_stepsize = 125, .frequency_stepsize = 3000,
.frequency_tolerance = 0, .frequency_tolerance = 0,
.symbol_rate_min = 1000000, .symbol_rate_min = 1000000,
.symbol_rate_max = 45000000, .symbol_rate_max = 45000000,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment