media: dvb-frontends/stv0367: improve QAM fe_status

While cab_state->state gives a quite accurate indication of the demod
signal status, it might be incorrect if cab_algo() wasn't able to
determine the exact status, with cab_algo() being the only place where
this status was updated from, and it is only called upon tuning to new
parameters passed to set_frontend(). Thus, the status will be wrong
until the demod is retuned. With the cab_signal_type parsing in
read_status(), this results in unusual fe_states like FE_HAS_SIGNAL |
FE_HAS_CARRIER | FE_HAS_LOCK, which, while userspace applications check
for FE_HAS_LOCK and work fine, leads to missing CNR or UCB stats.

Fix this by re-reading CAB_FSM_STATUS and updating cab_state->state() in
read_status(). While at it, refactor the fsm/qamfeclock and the
fsm->signaltype parsing into separate functions to make things cleaner
and deduplicate code. Also, assume full QAM FEC lock equals full
FE_STATUS.

Signed-off-by: Daniel Scheller <d.scheller@gmx.net>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
This commit is contained in:
Daniel Scheller 2017-07-14 17:23:36 -04:00 committed by Mauro Carvalho Chehab
parent 552636be7a
commit d105d08344
1 changed files with 87 additions and 65 deletions

View File

@ -2149,6 +2149,71 @@ static u32 stv0367cab_GetSymbolRate(struct stv0367_state *state, u32 mclk_hz)
return regsym;
}
static u32 stv0367cab_fsm_status(struct stv0367_state *state)
{
return stv0367_readbits(state, F367CAB_FSM_STATUS);
}
static u32 stv0367cab_qamfec_lock(struct stv0367_state *state)
{
return stv0367_readbits(state,
(state->cab_state->qamfec_status_reg ?
state->cab_state->qamfec_status_reg :
F367CAB_QAMFEC_LOCK));
}
static
enum stv0367_cab_signal_type stv0367cab_fsm_signaltype(u32 qam_fsm_status)
{
enum stv0367_cab_signal_type signaltype = FE_CAB_NOAGC;
switch (qam_fsm_status) {
case 1:
signaltype = FE_CAB_NOAGC;
break;
case 2:
signaltype = FE_CAB_NOTIMING;
break;
case 3:
signaltype = FE_CAB_TIMINGOK;
break;
case 4:
signaltype = FE_CAB_NOCARRIER;
break;
case 5:
signaltype = FE_CAB_CARRIEROK;
break;
case 7:
signaltype = FE_CAB_NOBLIND;
break;
case 8:
signaltype = FE_CAB_BLINDOK;
break;
case 10:
signaltype = FE_CAB_NODEMOD;
break;
case 11:
signaltype = FE_CAB_DEMODOK;
break;
case 12:
signaltype = FE_CAB_DEMODOK;
break;
case 13:
signaltype = FE_CAB_NODEMOD;
break;
case 14:
signaltype = FE_CAB_NOBLIND;
break;
case 15:
signaltype = FE_CAB_NOSIGNAL;
break;
default:
break;
}
return signaltype;
}
static int stv0367cab_read_status(struct dvb_frontend *fe,
enum fe_status *status)
{
@ -2158,22 +2223,26 @@ static int stv0367cab_read_status(struct dvb_frontend *fe,
*status = 0;
if (state->cab_state->state > FE_CAB_NOSIGNAL)
*status |= FE_HAS_SIGNAL;
/* update cab_state->state from QAM_FSM_STATUS */
state->cab_state->state = stv0367cab_fsm_signaltype(
stv0367cab_fsm_status(state));
if (state->cab_state->state > FE_CAB_NOCARRIER)
*status |= FE_HAS_CARRIER;
if (state->cab_state->state >= FE_CAB_DEMODOK)
*status |= FE_HAS_VITERBI;
if (state->cab_state->state >= FE_CAB_DATAOK)
*status |= FE_HAS_SYNC;
if (stv0367_readbits(state, (state->cab_state->qamfec_status_reg ?
state->cab_state->qamfec_status_reg : F367CAB_QAMFEC_LOCK))) {
*status |= FE_HAS_LOCK;
if (stv0367cab_qamfec_lock(state)) {
*status = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI
| FE_HAS_SYNC | FE_HAS_LOCK;
dprintk("%s: stv0367 has locked\n", __func__);
} else {
if (state->cab_state->state > FE_CAB_NOSIGNAL)
*status |= FE_HAS_SIGNAL;
if (state->cab_state->state > FE_CAB_NOCARRIER)
*status |= FE_HAS_CARRIER;
if (state->cab_state->state >= FE_CAB_DEMODOK)
*status |= FE_HAS_VITERBI;
if (state->cab_state->state >= FE_CAB_DATAOK)
*status |= FE_HAS_SYNC;
}
return 0;
@ -2374,7 +2443,7 @@ enum stv0367_cab_signal_type stv0367cab_algo(struct stv0367_state *state,
LockTime = 0;
stv0367_writereg(state, R367CAB_CTRL_1, 0x00);
do {
QAM_Lock = stv0367_readbits(state, F367CAB_FSM_STATUS);
QAM_Lock = stv0367cab_fsm_status(state);
if ((LockTime >= (DemodTimeOut - EQLTimeOut)) &&
(QAM_Lock == 0x04))
/*
@ -2435,10 +2504,7 @@ enum stv0367_cab_signal_type stv0367cab_algo(struct stv0367_state *state,
do {
usleep_range(5000, 7000);
LockTime += 5;
QAMFEC_Lock = stv0367_readbits(state,
(state->cab_state->qamfec_status_reg ?
state->cab_state->qamfec_status_reg :
F367CAB_QAMFEC_LOCK));
QAMFEC_Lock = stv0367cab_qamfec_lock(state);
} while (!QAMFEC_Lock && (LockTime < FECTimeOut));
} else
QAMFEC_Lock = 0;
@ -2474,52 +2540,8 @@ enum stv0367_cab_signal_type stv0367cab_algo(struct stv0367_state *state,
cab_state->locked = 1;
/* stv0367_setbits(state, F367CAB_AGC_ACCUMRSTSEL,7);*/
} else {
switch (QAM_Lock) {
case 1:
signalType = FE_CAB_NOAGC;
break;
case 2:
signalType = FE_CAB_NOTIMING;
break;
case 3:
signalType = FE_CAB_TIMINGOK;
break;
case 4:
signalType = FE_CAB_NOCARRIER;
break;
case 5:
signalType = FE_CAB_CARRIEROK;
break;
case 7:
signalType = FE_CAB_NOBLIND;
break;
case 8:
signalType = FE_CAB_BLINDOK;
break;
case 10:
signalType = FE_CAB_NODEMOD;
break;
case 11:
signalType = FE_CAB_DEMODOK;
break;
case 12:
signalType = FE_CAB_DEMODOK;
break;
case 13:
signalType = FE_CAB_NODEMOD;
break;
case 14:
signalType = FE_CAB_NOBLIND;
break;
case 15:
signalType = FE_CAB_NOSIGNAL;
break;
default:
break;
}
}
} else
signalType = stv0367cab_fsm_signaltype(QAM_Lock);
/* Set the AGC control values to tracking values */
stv0367_writebits(state, F367CAB_AGC_ACCUMRSTSEL, TrackAGCAccum);