diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2013-03-20 05:15:45 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2013-03-21 09:26:50 -0400 |
commit | 8f3741e02831d1181be9ca0ea711dd0c8d7f8a7b (patch) | |
tree | d7b262cec4ea88ce491fb9f937b62ae335825835 | |
parent | 2b0e1f3afda10dfc33a6bdae07caa24b906d1114 (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.c | 179 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/drxk_hard.h | 2 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/drxk_map.h | 3 |
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 | ||
6388 | static int drxk_read_status(struct dvb_frontend *fe, fe_status_t *status) | 6393 | static 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, ®16); | ||
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 , ®16); | ||
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, ®16); | ||
6463 | if (status < 0) | ||
6464 | goto error; | ||
6465 | post_bit_err_count = reg16; | ||
6466 | |||
6467 | status = read16(state, FEC_RS_MEASUREMENT_PRESCALE__A, ®16); | ||
6468 | if (status < 0) | ||
6469 | goto error; | ||
6470 | post_bit_error_scale = reg16; | ||
6471 | |||
6472 | status = read16(state, FEC_RS_MEASUREMENT_PERIOD__A, ®16); | ||
6473 | if (status < 0) | ||
6474 | goto error; | ||
6475 | pkt_count = reg16; | ||
6476 | |||
6477 | status = read16(state, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A, ®16); | ||
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, ®16); | ||
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 | |||
6519 | error: | ||
6520 | return status; | ||
6521 | } | ||
6522 | |||
6523 | |||
6524 | static 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 = { | |||
6522 | struct dvb_frontend *drxk_attach(const struct drxk_config *config, | 6655 | struct 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 |