media: dvb-frontends/stv0367: improve QAM fe_status
authorDaniel Scheller <d.scheller@gmx.net>
Fri, 14 Jul 2017 21:23:36 +0000 (17:23 -0400)
committerMauro Carvalho Chehab <mchehab@s-opensource.com>
Thu, 20 Jul 2017 19:16:48 +0000 (15:16 -0400)
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>
drivers/media/dvb-frontends/stv0367.c

index 59c1aad256c2f6e71dc2ff11f101bed9be8bdbda..bc6eb0ab733e23f785d21b5d236ce792912019ea 100644 (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 (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_DEMODOK)
-               *status |= FE_HAS_VITERBI;
+               if (state->cab_state->state > FE_CAB_NOCARRIER)
+                       *status |= FE_HAS_CARRIER;
 
-       if (state->cab_state->state >= FE_CAB_DATAOK)
-               *status |= FE_HAS_SYNC;
+               if (state->cab_state->state >= FE_CAB_DEMODOK)
+                       *status |= FE_HAS_VITERBI;
 
-       if (stv0367_readbits(state, (state->cab_state->qamfec_status_reg ?
-               state->cab_state->qamfec_status_reg : F367CAB_QAMFEC_LOCK))) {
-               *status |= FE_HAS_LOCK;
-               dprintk("%s: stv0367 has locked\n", __func__);
+               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);