aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@redhat.com>2013-03-20 05:15:45 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2013-03-21 09:26:50 -0400
commit8f3741e02831d1181be9ca0ea711dd0c8d7f8a7b (patch)
treed7b262cec4ea88ce491fb9f937b62ae335825835
parent2b0e1f3afda10dfc33a6bdae07caa24b906d1114 (diff)
[media] drxk: Add pre/post BER and PER/UCB stats
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>
-rw-r--r--drivers/media/dvb-frontends/drxk_hard.c179
-rw-r--r--drivers/media/dvb-frontends/drxk_hard.h2
-rw-r--r--drivers/media/dvb-frontends/drxk_map.h3
3 files changed, 172 insertions, 12 deletions
diff --git a/drivers/media/dvb-frontends/drxk_hard.c b/drivers/media/dvb-frontends/drxk_hard.c
index 0e40832a9a59..8c4de7cc4500 100644
--- a/drivers/media/dvb-frontends/drxk_hard.c
+++ b/drivers/media/dvb-frontends/drxk_hard.c
@@ -2655,11 +2655,6 @@ static int GetDVBTSignalToNoise(struct drxk_state *state,
2655 c = Log10Times100(SqrErrIQ); 2655 c = Log10Times100(SqrErrIQ);
2656 2656
2657 iMER = a + b; 2657 iMER = a + b;
2658 /* No negative MER, clip to zero */
2659 if (iMER > c)
2660 iMER -= c;
2661 else
2662 iMER = 0;
2663 } 2658 }
2664 *pSignalToNoise = iMER; 2659 *pSignalToNoise = iMER;
2665 2660
@@ -6380,31 +6375,165 @@ static int drxk_set_parameters(struct dvb_frontend *fe)
6380 fe->ops.tuner_ops.get_if_frequency(fe, &IF); 6375 fe->ops.tuner_ops.get_if_frequency(fe, &IF);
6381 Start(state, 0, IF); 6376 Start(state, 0, IF);
6382 6377
6378 /* After set_frontend, stats aren't avaliable */
6379 p->strength.stat[0].scale = FE_SCALE_RELATIVE;
6380 p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
6381 p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
6382 p->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
6383 p->pre_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
6384 p->pre_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
6385 p->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
6386 p->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
6387
6383 /* printk(KERN_DEBUG "drxk: %s IF=%d done\n", __func__, IF); */ 6388 /* printk(KERN_DEBUG "drxk: %s IF=%d done\n", __func__, IF); */
6384 6389
6385 return 0; 6390 return 0;
6386} 6391}
6387 6392
6388static int drxk_read_status(struct dvb_frontend *fe, fe_status_t *status) 6393static int drxk_get_stats(struct dvb_frontend *fe)
6389{ 6394{
6395 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
6390 struct drxk_state *state = fe->demodulator_priv; 6396 struct drxk_state *state = fe->demodulator_priv;
6397 int status;
6391 u32 stat; 6398 u32 stat;
6392 6399 u16 reg16;
6393 dprintk(1, "\n"); 6400 u32 post_bit_count;
6401 u32 post_bit_err_count;
6402 u32 post_bit_error_scale;
6403 u32 pre_bit_err_count;
6404 u32 pre_bit_count;
6405 u32 pkt_count;
6406 u32 pkt_error_count;
6407 s32 cnr, gain;
6394 6408
6395 if (state->m_DrxkState == DRXK_NO_DEV) 6409 if (state->m_DrxkState == DRXK_NO_DEV)
6396 return -ENODEV; 6410 return -ENODEV;
6397 if (state->m_DrxkState == DRXK_UNINITIALIZED) 6411 if (state->m_DrxkState == DRXK_UNINITIALIZED)
6398 return -EAGAIN; 6412 return -EAGAIN;
6399 6413
6400 *status = 0; 6414 /* get status */
6415 state->fe_status = 0;
6401 GetLockStatus(state, &stat, 0); 6416 GetLockStatus(state, &stat, 0);
6402 if (stat == MPEG_LOCK) 6417 if (stat == MPEG_LOCK)
6403 *status |= 0x1f; 6418 state->fe_status |= 0x1f;
6404 if (stat == FEC_LOCK) 6419 if (stat == FEC_LOCK)
6405 *status |= 0x0f; 6420 state->fe_status |= 0x0f;
6406 if (stat == DEMOD_LOCK) 6421 if (stat == DEMOD_LOCK)
6407 *status |= 0x07; 6422 state->fe_status |= 0x07;
6423
6424 if (stat >= DEMOD_LOCK) {
6425 GetSignalToNoise(state, &cnr);
6426 c->cnr.stat[0].svalue = cnr * 100;
6427 c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
6428 } else {
6429 c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
6430 }
6431
6432 if (stat < FEC_LOCK) {
6433 c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
6434 c->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
6435 c->pre_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
6436 c->pre_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
6437 c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
6438 c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
6439 return 0;
6440 }
6441
6442 /* Get post BER */
6443
6444 /* BER measurement is valid if at least FEC lock is achieved */
6445
6446 /* OFDM_EC_VD_REQ_SMB_CNT__A and/or OFDM_EC_VD_REQ_BIT_CNT can be written
6447 to set nr of symbols or bits over which
6448 to measure EC_VD_REG_ERR_BIT_CNT__A . See CtrlSetCfg(). */
6449
6450 /* Read registers for post/preViterbi BER calculation */
6451 status = read16(state, OFDM_EC_VD_ERR_BIT_CNT__A, &reg16);
6452 if (status < 0)
6453 goto error;
6454 pre_bit_err_count = reg16;
6455
6456 status = read16(state, OFDM_EC_VD_IN_BIT_CNT__A , &reg16);
6457 if (status < 0)
6458 goto error;
6459 pre_bit_count = reg16;
6460
6461 /* Number of bit-errors */
6462 status = read16(state, FEC_RS_NR_BIT_ERRORS__A, &reg16);
6463 if (status < 0)
6464 goto error;
6465 post_bit_err_count = reg16;
6466
6467 status = read16(state, FEC_RS_MEASUREMENT_PRESCALE__A, &reg16);
6468 if (status < 0)
6469 goto error;
6470 post_bit_error_scale = reg16;
6471
6472 status = read16(state, FEC_RS_MEASUREMENT_PERIOD__A, &reg16);
6473 if (status < 0)
6474 goto error;
6475 pkt_count = reg16;
6476
6477 status = read16(state, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A, &reg16);
6478 if (status < 0)
6479 goto error;
6480 pkt_error_count = reg16;
6481 write16(state, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A, 0);
6482
6483 post_bit_err_count *= post_bit_error_scale;
6484
6485 post_bit_count = pkt_count * 204 * 8;
6486
6487 /* Store the results */
6488 c->block_error.stat[0].scale = FE_SCALE_COUNTER;
6489 c->block_error.stat[0].uvalue += pkt_error_count;
6490 c->block_count.stat[0].scale = FE_SCALE_COUNTER;
6491 c->block_count.stat[0].uvalue += pkt_count;
6492
6493 c->pre_bit_error.stat[0].scale = FE_SCALE_COUNTER;
6494 c->pre_bit_error.stat[0].uvalue += pre_bit_err_count;
6495 c->pre_bit_count.stat[0].scale = FE_SCALE_COUNTER;
6496 c->pre_bit_count.stat[0].uvalue += pre_bit_count;
6497
6498 c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
6499 c->post_bit_error.stat[0].uvalue += post_bit_err_count;
6500 c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;
6501 c->post_bit_count.stat[0].uvalue += post_bit_count;
6502
6503 /*
6504 * Read AGC gain
6505 *
6506 * IFgain = (IQM_AF_AGC_IF__A * 26.75) (nA)
6507 */
6508 status = read16(state, IQM_AF_AGC_IF__A, &reg16);
6509 if (status < 0) {
6510 printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
6511 return status;
6512 }
6513 gain = 2675 * (reg16 - DRXK_AGC_DAC_OFFSET) / 100;
6514
6515 /* FIXME: it makes sense to fix the scale here to dBm */
6516 c->strength.stat[0].scale = FE_SCALE_RELATIVE;
6517 c->strength.stat[0].uvalue = gain;
6518
6519error:
6520 return status;
6521}
6522
6523
6524static int drxk_read_status(struct dvb_frontend *fe, fe_status_t *status)
6525{
6526 struct drxk_state *state = fe->demodulator_priv;
6527 int rc;
6528
6529 dprintk(1, "\n");
6530
6531 rc = drxk_get_stats(fe);
6532 if (rc < 0)
6533 return rc;
6534
6535 *status = state->fe_status;
6536
6408 return 0; 6537 return 0;
6409} 6538}
6410 6539
@@ -6439,6 +6568,10 @@ static int drxk_read_snr(struct dvb_frontend *fe, u16 *snr)
6439 return -EAGAIN; 6568 return -EAGAIN;
6440 6569
6441 GetSignalToNoise(state, &snr2); 6570 GetSignalToNoise(state, &snr2);
6571
6572 /* No negative SNR, clip to zero */
6573 if (snr2 < 0)
6574 snr2 = 0;
6442 *snr = snr2 & 0xffff; 6575 *snr = snr2 & 0xffff;
6443 return 0; 6576 return 0;
6444} 6577}
@@ -6522,6 +6655,7 @@ static struct dvb_frontend_ops drxk_ops = {
6522struct dvb_frontend *drxk_attach(const struct drxk_config *config, 6655struct dvb_frontend *drxk_attach(const struct drxk_config *config,
6523 struct i2c_adapter *i2c) 6656 struct i2c_adapter *i2c)
6524{ 6657{
6658 struct dtv_frontend_properties *p;
6525 struct drxk_state *state = NULL; 6659 struct drxk_state *state = NULL;
6526 u8 adr = config->adr; 6660 u8 adr = config->adr;
6527 int status; 6661 int status;
@@ -6602,6 +6736,27 @@ struct dvb_frontend *drxk_attach(const struct drxk_config *config,
6602 } else if (init_drxk(state) < 0) 6736 } else if (init_drxk(state) < 0)
6603 goto error; 6737 goto error;
6604 6738
6739
6740 /* Initialize stats */
6741 p = &state->frontend.dtv_property_cache;
6742 p->strength.len = 1;
6743 p->cnr.len = 1;
6744 p->block_error.len = 1;
6745 p->block_count.len = 1;
6746 p->pre_bit_error.len = 1;
6747 p->pre_bit_count.len = 1;
6748 p->post_bit_error.len = 1;
6749 p->post_bit_count.len = 1;
6750
6751 p->strength.stat[0].scale = FE_SCALE_RELATIVE;
6752 p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
6753 p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
6754 p->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
6755 p->pre_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
6756 p->pre_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
6757 p->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
6758 p->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
6759
6605 printk(KERN_INFO "drxk: frontend initialized.\n"); 6760 printk(KERN_INFO "drxk: frontend initialized.\n");
6606 return &state->frontend; 6761 return &state->frontend;
6607 6762
diff --git a/drivers/media/dvb-frontends/drxk_hard.h b/drivers/media/dvb-frontends/drxk_hard.h
index d18a896a9835..b8424f15f9a6 100644
--- a/drivers/media/dvb-frontends/drxk_hard.h
+++ b/drivers/media/dvb-frontends/drxk_hard.h
@@ -345,6 +345,8 @@ struct drxk_state {
345 bool antenna_dvbt; 345 bool antenna_dvbt;
346 u16 antenna_gpio; 346 u16 antenna_gpio;
347 347
348 fe_status_t fe_status;
349
348 /* Firmware */ 350 /* Firmware */
349 const char *microcode_name; 351 const char *microcode_name;
350 struct completion fw_wait_load; 352 struct completion fw_wait_load;
diff --git a/drivers/media/dvb-frontends/drxk_map.h b/drivers/media/dvb-frontends/drxk_map.h
index 23e16c12f234..761613f9fd5a 100644
--- a/drivers/media/dvb-frontends/drxk_map.h
+++ b/drivers/media/dvb-frontends/drxk_map.h
@@ -10,6 +10,7 @@
10#define FEC_RS_COMM_EXEC_STOP 0x0 10#define FEC_RS_COMM_EXEC_STOP 0x0
11#define FEC_RS_MEASUREMENT_PERIOD__A 0x1C30012 11#define FEC_RS_MEASUREMENT_PERIOD__A 0x1C30012
12#define FEC_RS_MEASUREMENT_PRESCALE__A 0x1C30013 12#define FEC_RS_MEASUREMENT_PRESCALE__A 0x1C30013
13#define FEC_RS_NR_BIT_ERRORS__A 0x1C30014
13#define FEC_OC_MODE__A 0x1C40011 14#define FEC_OC_MODE__A 0x1C40011
14#define FEC_OC_MODE_PARITY__M 0x1 15#define FEC_OC_MODE_PARITY__M 0x1
15#define FEC_OC_DTO_MODE__A 0x1C40014 16#define FEC_OC_DTO_MODE__A 0x1C40014
@@ -129,6 +130,8 @@
129#define OFDM_EC_SB_PRIOR__A 0x3410013 130#define OFDM_EC_SB_PRIOR__A 0x3410013
130#define OFDM_EC_SB_PRIOR_HI 0x0 131#define OFDM_EC_SB_PRIOR_HI 0x0
131#define OFDM_EC_SB_PRIOR_LO 0x1 132#define OFDM_EC_SB_PRIOR_LO 0x1
133#define OFDM_EC_VD_ERR_BIT_CNT__A 0x3420017
134#define OFDM_EC_VD_IN_BIT_CNT__A 0x3420018
132#define OFDM_EQ_TOP_TD_TPS_CONST__A 0x3010054 135#define OFDM_EQ_TOP_TD_TPS_CONST__A 0x3010054
133#define OFDM_EQ_TOP_TD_TPS_CONST__M 0x3 136#define OFDM_EQ_TOP_TD_TPS_CONST__M 0x3
134#define OFDM_EQ_TOP_TD_TPS_CONST_64QAM 0x2 137#define OFDM_EQ_TOP_TD_TPS_CONST_64QAM 0x2