@@ -641,9 +641,17 @@ static int au8522_set_frontend(struct dvb_frontend *fe)
state->current_frequency = c->frequency;
+ /* Reset DVBv5 stats */
+ c->strength.stat[0].scale = FE_SCALE_RELATIVE;
+ c->strength.stat[0].uvalue = 0;
+ c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+ c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+
return 0;
}
+static void au8522_get_stats(struct dvb_frontend *fe, enum fe_status status);
+
static int au8522_read_status(struct dvb_frontend *fe, enum fe_status *status)
{
struct au8522_state *state = fe->demodulator_priv;
@@ -699,6 +707,8 @@ static int au8522_read_status(struct dvb_frontend *fe, enum fe_status *status)
dprintk("%s() status 0x%08x\n", __func__, *status);
+ au8522_get_stats(fe, *status);
+
return 0;
}
@@ -764,70 +774,108 @@ static int au8522_read_snr(struct dvb_frontend *fe, u16 *snr)
return ret;
}
-static int au8522_read_signal_strength(struct dvb_frontend *fe,
- u16 *signal_strength)
+static void au8522_get_stats(struct dvb_frontend *fe, enum fe_status status)
{
- u16 snr;
- u32 tmp;
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+ struct au8522_state *state = fe->demodulator_priv;
int ret;
- /* If the tuner has RF strength, use it */
+ /* Get S/N ratio */
+ if (status & FE_HAS_LOCK) {
+ ret = au8522_read_snr(fe, &state->snr);
+ if (ret < 0) {
+ state->snr = 0;
+ c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+ } else {
+ c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
+ c->cnr.stat[0].svalue = state->snr * 100;
+ }
+ } else {
+ state->snr = 0;
+ c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+ }
+
+ /* Get (or estimate) RF strength */
if (fe->ops.tuner_ops.get_rf_strength) {
+ /* If the tuner has RF strength, use it */
+
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1);
- ret = fe->ops.tuner_ops.get_rf_strength(fe, signal_strength);
+ ret = fe->ops.tuner_ops.get_rf_strength(fe, &state->strength);
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
- return ret;
- }
-
- /*
- * If it doen't, estimate from SNR
- * (borrowed from lgdt330x.c)
- *
- * Calculate strength from SNR up to 35dB
- * Even though the SNR can go higher than 35dB,
- * there is some comfort factor in having a range of
- * strong signals that can show at 100%
- */
- ret = au8522_read_snr(fe, &snr);
-
- *signal_strength = 0;
-
- if (0 == ret) {
- /* The following calculation method was chosen
+ if (ret < 0)
+ state->strength = 0;
+ } else {
+ u32 tmp;
+ /*
+ * If it doen't, estimate from SNR
+ * (borrowed from lgdt330x.c)
+ *
+ * Calculate strength from SNR up to 35dB
+ * Even though the SNR can go higher than 35dB,
+ * there is some comfort factor in having a range of
+ * strong signals that can show at 100%
+ *
+ * The following calculation method was chosen
* purely for the sake of code re-use from the
- * other demod drivers that use this method */
+ * other demod drivers that use this method
+ */
/* Convert from SNR in dB * 10 to 8.24 fixed-point */
- tmp = (snr * ((1 << 24) / 10));
+ tmp = (state->snr * ((1 << 24) / 10));
/* Convert from 8.24 fixed-point to
- * scale the range 0 - 35*2^24 into 0 - 65535*/
+ * scale the range 0 - 35*2^24 into 0 - 65535*/
if (tmp >= 8960 * 0x10000)
- *signal_strength = 0xffff;
+ state->strength = 0xffff;
else
- *signal_strength = tmp / 8960;
+ state->strength = tmp / 8960;
}
+ c->strength.stat[0].scale = FE_SCALE_RELATIVE;
+ c->strength.stat[0].uvalue = state->strength;
- return ret;
-}
-
-static int au8522_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
-{
- struct au8522_state *state = fe->demodulator_priv;
+ /* Read UCB blocks */
+ if (!(status & FE_HAS_LOCK)) {
+ c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+ return;
+ }
if (state->current_modulation == VSB_8)
- *ucblocks = au8522_readreg(state, 0x4087);
+ state->ucblocks = au8522_readreg(state, 0x4087);
else
- *ucblocks = au8522_readreg(state, 0x4543);
+ state->ucblocks = au8522_readreg(state, 0x4543);
+
+ c->block_error.stat[0].scale = FE_SCALE_COUNTER;
+ c->block_error.stat[0].uvalue = state->ucblocks;
+}
+static int au8522_read_signal_strength(struct dvb_frontend *fe,
+ u16 *signal_strength)
+{
+ struct au8522_state *state = fe->demodulator_priv;
+
+ *signal_strength = state->strength;
+
+ return 0;
+}
+
+static int au8522_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+ struct au8522_state *state = fe->demodulator_priv;
+
+ *ucblocks = state->ucblocks;
return 0;
}
static int au8522_read_ber(struct dvb_frontend *fe, u32 *ber)
{
- return au8522_read_ucblocks(fe, ber);
+ struct au8522_state *state = fe->demodulator_priv;
+
+ /* FIXME: This is so wrong! */
+ *ber = state->ucblocks;
+
+ return 0;
}
static int au8522_get_frontend(struct dvb_frontend *fe,
@@ -908,6 +956,22 @@ error:
}
EXPORT_SYMBOL(au8522_attach);
+static int au8522_dvb_init(struct dvb_frontend *fe)
+{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+
+ /* Initialize DVBv5 statistics */
+ c->strength.stat[0].scale = FE_SCALE_RELATIVE;
+ c->strength.stat[0].uvalue = 0;
+ c->strength.len = 1;
+ c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+ c->cnr.len = 1;
+ c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+ c->block_error.len = 1;
+
+ return au8522_init(fe);
+}
+
static struct dvb_frontend_ops au8522_ops = {
.delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
.info = {
@@ -918,7 +982,7 @@ static struct dvb_frontend_ops au8522_ops = {
.caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
},
- .init = au8522_init,
+ .init = au8522_dvb_init,
.sleep = au8522_sleep,
.i2c_gate_ctrl = au8522_i2c_gate_ctrl,
.set_frontend = au8522_set_frontend,
@@ -70,6 +70,11 @@ struct au8522_state {
u32 rev;
struct v4l2_ctrl_handler hdl;
+ /* Statistics */
+ u16 strength;
+ u16 snr;
+ u32 ucblocks;
+
#ifdef CONFIG_MEDIA_CONTROLLER
struct media_pad pads[DEMOD_NUM_PADS];
#endif
It is possible to provide both SNR and signal strength in dB. Let's convert it to use the DVBv5 API and start showing the SNR in dB. Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com> --- drivers/media/dvb-frontends/au8522_dig.c | 142 ++++++++++++++++++++++-------- drivers/media/dvb-frontends/au8522_priv.h | 5 ++ 2 files changed, 108 insertions(+), 39 deletions(-)