Skip to content

Commit

Permalink
[media] drxk: Add pre/post BER and PER/UCB stats
Browse files Browse the repository at this point in the history
The original az6007 driver has the code to calculate such
stats. Add it to the driver, reporting them via DVBv5
stats API.

Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
  • Loading branch information
Mauro Carvalho Chehab committed Mar 21, 2013
1 parent 2b0e1f3 commit 8f3741e
Show file tree
Hide file tree
Showing 3 changed files with 172 additions and 12 deletions.
179 changes: 167 additions & 12 deletions drivers/media/dvb-frontends/drxk_hard.c
Original file line number Diff line number Diff line change
Expand Up @@ -2655,11 +2655,6 @@ static int GetDVBTSignalToNoise(struct drxk_state *state,
c = Log10Times100(SqrErrIQ);

iMER = a + b;
/* No negative MER, clip to zero */
if (iMER > c)
iMER -= c;
else
iMER = 0;
}
*pSignalToNoise = iMER;

Expand Down Expand Up @@ -6380,31 +6375,165 @@ static int drxk_set_parameters(struct dvb_frontend *fe)
fe->ops.tuner_ops.get_if_frequency(fe, &IF);
Start(state, 0, IF);

/* After set_frontend, stats aren't avaliable */
p->strength.stat[0].scale = FE_SCALE_RELATIVE;
p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
p->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
p->pre_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
p->pre_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
p->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
p->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;

/* printk(KERN_DEBUG "drxk: %s IF=%d done\n", __func__, IF); */

return 0;
}

static int drxk_read_status(struct dvb_frontend *fe, fe_status_t *status)
static int drxk_get_stats(struct dvb_frontend *fe)
{
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct drxk_state *state = fe->demodulator_priv;
int status;
u32 stat;

dprintk(1, "\n");
u16 reg16;
u32 post_bit_count;
u32 post_bit_err_count;
u32 post_bit_error_scale;
u32 pre_bit_err_count;
u32 pre_bit_count;
u32 pkt_count;
u32 pkt_error_count;
s32 cnr, gain;

if (state->m_DrxkState == DRXK_NO_DEV)
return -ENODEV;
if (state->m_DrxkState == DRXK_UNINITIALIZED)
return -EAGAIN;

*status = 0;
/* get status */
state->fe_status = 0;
GetLockStatus(state, &stat, 0);
if (stat == MPEG_LOCK)
*status |= 0x1f;
state->fe_status |= 0x1f;
if (stat == FEC_LOCK)
*status |= 0x0f;
state->fe_status |= 0x0f;
if (stat == DEMOD_LOCK)
*status |= 0x07;
state->fe_status |= 0x07;

if (stat >= DEMOD_LOCK) {
GetSignalToNoise(state, &cnr);
c->cnr.stat[0].svalue = cnr * 100;
c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
} else {
c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
}

if (stat < FEC_LOCK) {
c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
c->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
c->pre_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
c->pre_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
return 0;
}

/* Get post BER */

/* BER measurement is valid if at least FEC lock is achieved */

/* OFDM_EC_VD_REQ_SMB_CNT__A and/or OFDM_EC_VD_REQ_BIT_CNT can be written
to set nr of symbols or bits over which
to measure EC_VD_REG_ERR_BIT_CNT__A . See CtrlSetCfg(). */

/* Read registers for post/preViterbi BER calculation */
status = read16(state, OFDM_EC_VD_ERR_BIT_CNT__A, &reg16);
if (status < 0)
goto error;
pre_bit_err_count = reg16;

status = read16(state, OFDM_EC_VD_IN_BIT_CNT__A , &reg16);
if (status < 0)
goto error;
pre_bit_count = reg16;

/* Number of bit-errors */
status = read16(state, FEC_RS_NR_BIT_ERRORS__A, &reg16);
if (status < 0)
goto error;
post_bit_err_count = reg16;

status = read16(state, FEC_RS_MEASUREMENT_PRESCALE__A, &reg16);
if (status < 0)
goto error;
post_bit_error_scale = reg16;

status = read16(state, FEC_RS_MEASUREMENT_PERIOD__A, &reg16);
if (status < 0)
goto error;
pkt_count = reg16;

status = read16(state, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A, &reg16);
if (status < 0)
goto error;
pkt_error_count = reg16;
write16(state, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A, 0);

post_bit_err_count *= post_bit_error_scale;

post_bit_count = pkt_count * 204 * 8;

/* Store the results */
c->block_error.stat[0].scale = FE_SCALE_COUNTER;
c->block_error.stat[0].uvalue += pkt_error_count;
c->block_count.stat[0].scale = FE_SCALE_COUNTER;
c->block_count.stat[0].uvalue += pkt_count;

c->pre_bit_error.stat[0].scale = FE_SCALE_COUNTER;
c->pre_bit_error.stat[0].uvalue += pre_bit_err_count;
c->pre_bit_count.stat[0].scale = FE_SCALE_COUNTER;
c->pre_bit_count.stat[0].uvalue += pre_bit_count;

c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
c->post_bit_error.stat[0].uvalue += post_bit_err_count;
c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;
c->post_bit_count.stat[0].uvalue += post_bit_count;

/*
* Read AGC gain
*
* IFgain = (IQM_AF_AGC_IF__A * 26.75) (nA)
*/
status = read16(state, IQM_AF_AGC_IF__A, &reg16);
if (status < 0) {
printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
return status;
}
gain = 2675 * (reg16 - DRXK_AGC_DAC_OFFSET) / 100;

/* FIXME: it makes sense to fix the scale here to dBm */
c->strength.stat[0].scale = FE_SCALE_RELATIVE;
c->strength.stat[0].uvalue = gain;

error:
return status;
}


static int drxk_read_status(struct dvb_frontend *fe, fe_status_t *status)
{
struct drxk_state *state = fe->demodulator_priv;
int rc;

dprintk(1, "\n");

rc = drxk_get_stats(fe);
if (rc < 0)
return rc;

*status = state->fe_status;

return 0;
}

Expand Down Expand Up @@ -6439,6 +6568,10 @@ static int drxk_read_snr(struct dvb_frontend *fe, u16 *snr)
return -EAGAIN;

GetSignalToNoise(state, &snr2);

/* No negative SNR, clip to zero */
if (snr2 < 0)
snr2 = 0;
*snr = snr2 & 0xffff;
return 0;
}
Expand Down Expand Up @@ -6522,6 +6655,7 @@ static struct dvb_frontend_ops drxk_ops = {
struct dvb_frontend *drxk_attach(const struct drxk_config *config,
struct i2c_adapter *i2c)
{
struct dtv_frontend_properties *p;
struct drxk_state *state = NULL;
u8 adr = config->adr;
int status;
Expand Down Expand Up @@ -6602,6 +6736,27 @@ struct dvb_frontend *drxk_attach(const struct drxk_config *config,
} else if (init_drxk(state) < 0)
goto error;


/* Initialize stats */
p = &state->frontend.dtv_property_cache;
p->strength.len = 1;
p->cnr.len = 1;
p->block_error.len = 1;
p->block_count.len = 1;
p->pre_bit_error.len = 1;
p->pre_bit_count.len = 1;
p->post_bit_error.len = 1;
p->post_bit_count.len = 1;

p->strength.stat[0].scale = FE_SCALE_RELATIVE;
p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
p->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
p->pre_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
p->pre_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
p->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
p->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;

printk(KERN_INFO "drxk: frontend initialized.\n");
return &state->frontend;

Expand Down
2 changes: 2 additions & 0 deletions drivers/media/dvb-frontends/drxk_hard.h
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,8 @@ struct drxk_state {
bool antenna_dvbt;
u16 antenna_gpio;

fe_status_t fe_status;

/* Firmware */
const char *microcode_name;
struct completion fw_wait_load;
Expand Down
3 changes: 3 additions & 0 deletions drivers/media/dvb-frontends/drxk_map.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#define FEC_RS_COMM_EXEC_STOP 0x0
#define FEC_RS_MEASUREMENT_PERIOD__A 0x1C30012
#define FEC_RS_MEASUREMENT_PRESCALE__A 0x1C30013
#define FEC_RS_NR_BIT_ERRORS__A 0x1C30014
#define FEC_OC_MODE__A 0x1C40011
#define FEC_OC_MODE_PARITY__M 0x1
#define FEC_OC_DTO_MODE__A 0x1C40014
Expand Down Expand Up @@ -129,6 +130,8 @@
#define OFDM_EC_SB_PRIOR__A 0x3410013
#define OFDM_EC_SB_PRIOR_HI 0x0
#define OFDM_EC_SB_PRIOR_LO 0x1
#define OFDM_EC_VD_ERR_BIT_CNT__A 0x3420017
#define OFDM_EC_VD_IN_BIT_CNT__A 0x3420018
#define OFDM_EQ_TOP_TD_TPS_CONST__A 0x3010054
#define OFDM_EQ_TOP_TD_TPS_CONST__M 0x3
#define OFDM_EQ_TOP_TD_TPS_CONST_64QAM 0x2
Expand Down

0 comments on commit 8f3741e

Please sign in to comment.