Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[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>

+172 -12
+167 -12
drivers/media/dvb-frontends/drxk_hard.c
··· 2655 2655 c = Log10Times100(SqrErrIQ); 2656 2656 2657 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 2659 *pSignalToNoise = iMER; 2665 2660 ··· 6375 6380 fe->ops.tuner_ops.get_if_frequency(fe, &IF); 6376 6381 Start(state, 0, IF); 6377 6382 6383 + /* After set_frontend, stats aren't avaliable */ 6384 + p->strength.stat[0].scale = FE_SCALE_RELATIVE; 6385 + p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 6386 + p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 6387 + p->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 6388 + p->pre_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 6389 + p->pre_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 6390 + p->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 6391 + p->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 6392 + 6378 6393 /* printk(KERN_DEBUG "drxk: %s IF=%d done\n", __func__, IF); */ 6379 6394 6380 6395 return 0; 6381 6396 } 6382 6397 6383 - static int drxk_read_status(struct dvb_frontend *fe, fe_status_t *status) 6398 + static int drxk_get_stats(struct dvb_frontend *fe) 6384 6399 { 6400 + struct dtv_frontend_properties *c = &fe->dtv_property_cache; 6385 6401 struct drxk_state *state = fe->demodulator_priv; 6402 + int status; 6386 6403 u32 stat; 6387 - 6388 - dprintk(1, "\n"); 6404 + u16 reg16; 6405 + u32 post_bit_count; 6406 + u32 post_bit_err_count; 6407 + u32 post_bit_error_scale; 6408 + u32 pre_bit_err_count; 6409 + u32 pre_bit_count; 6410 + u32 pkt_count; 6411 + u32 pkt_error_count; 6412 + s32 cnr, gain; 6389 6413 6390 6414 if (state->m_DrxkState == DRXK_NO_DEV) 6391 6415 return -ENODEV; 6392 6416 if (state->m_DrxkState == DRXK_UNINITIALIZED) 6393 6417 return -EAGAIN; 6394 6418 6395 - *status = 0; 6419 + /* get status */ 6420 + state->fe_status = 0; 6396 6421 GetLockStatus(state, &stat, 0); 6397 6422 if (stat == MPEG_LOCK) 6398 - *status |= 0x1f; 6423 + state->fe_status |= 0x1f; 6399 6424 if (stat == FEC_LOCK) 6400 - *status |= 0x0f; 6425 + state->fe_status |= 0x0f; 6401 6426 if (stat == DEMOD_LOCK) 6402 - *status |= 0x07; 6427 + state->fe_status |= 0x07; 6428 + 6429 + if (stat >= DEMOD_LOCK) { 6430 + GetSignalToNoise(state, &cnr); 6431 + c->cnr.stat[0].svalue = cnr * 100; 6432 + c->cnr.stat[0].scale = FE_SCALE_DECIBEL; 6433 + } else { 6434 + c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 6435 + } 6436 + 6437 + if (stat < FEC_LOCK) { 6438 + c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 6439 + c->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 6440 + c->pre_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 6441 + c->pre_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 6442 + c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 6443 + c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 6444 + return 0; 6445 + } 6446 + 6447 + /* Get post BER */ 6448 + 6449 + /* BER measurement is valid if at least FEC lock is achieved */ 6450 + 6451 + /* OFDM_EC_VD_REQ_SMB_CNT__A and/or OFDM_EC_VD_REQ_BIT_CNT can be written 6452 + to set nr of symbols or bits over which 6453 + to measure EC_VD_REG_ERR_BIT_CNT__A . See CtrlSetCfg(). */ 6454 + 6455 + /* Read registers for post/preViterbi BER calculation */ 6456 + status = read16(state, OFDM_EC_VD_ERR_BIT_CNT__A, &reg16); 6457 + if (status < 0) 6458 + goto error; 6459 + pre_bit_err_count = reg16; 6460 + 6461 + status = read16(state, OFDM_EC_VD_IN_BIT_CNT__A , &reg16); 6462 + if (status < 0) 6463 + goto error; 6464 + pre_bit_count = reg16; 6465 + 6466 + /* Number of bit-errors */ 6467 + status = read16(state, FEC_RS_NR_BIT_ERRORS__A, &reg16); 6468 + if (status < 0) 6469 + goto error; 6470 + post_bit_err_count = reg16; 6471 + 6472 + status = read16(state, FEC_RS_MEASUREMENT_PRESCALE__A, &reg16); 6473 + if (status < 0) 6474 + goto error; 6475 + post_bit_error_scale = reg16; 6476 + 6477 + status = read16(state, FEC_RS_MEASUREMENT_PERIOD__A, &reg16); 6478 + if (status < 0) 6479 + goto error; 6480 + pkt_count = reg16; 6481 + 6482 + status = read16(state, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A, &reg16); 6483 + if (status < 0) 6484 + goto error; 6485 + pkt_error_count = reg16; 6486 + write16(state, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A, 0); 6487 + 6488 + post_bit_err_count *= post_bit_error_scale; 6489 + 6490 + post_bit_count = pkt_count * 204 * 8; 6491 + 6492 + /* Store the results */ 6493 + c->block_error.stat[0].scale = FE_SCALE_COUNTER; 6494 + c->block_error.stat[0].uvalue += pkt_error_count; 6495 + c->block_count.stat[0].scale = FE_SCALE_COUNTER; 6496 + c->block_count.stat[0].uvalue += pkt_count; 6497 + 6498 + c->pre_bit_error.stat[0].scale = FE_SCALE_COUNTER; 6499 + c->pre_bit_error.stat[0].uvalue += pre_bit_err_count; 6500 + c->pre_bit_count.stat[0].scale = FE_SCALE_COUNTER; 6501 + c->pre_bit_count.stat[0].uvalue += pre_bit_count; 6502 + 6503 + c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER; 6504 + c->post_bit_error.stat[0].uvalue += post_bit_err_count; 6505 + c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER; 6506 + c->post_bit_count.stat[0].uvalue += post_bit_count; 6507 + 6508 + /* 6509 + * Read AGC gain 6510 + * 6511 + * IFgain = (IQM_AF_AGC_IF__A * 26.75) (nA) 6512 + */ 6513 + status = read16(state, IQM_AF_AGC_IF__A, &reg16); 6514 + if (status < 0) { 6515 + printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); 6516 + return status; 6517 + } 6518 + gain = 2675 * (reg16 - DRXK_AGC_DAC_OFFSET) / 100; 6519 + 6520 + /* FIXME: it makes sense to fix the scale here to dBm */ 6521 + c->strength.stat[0].scale = FE_SCALE_RELATIVE; 6522 + c->strength.stat[0].uvalue = gain; 6523 + 6524 + error: 6525 + return status; 6526 + } 6527 + 6528 + 6529 + static int drxk_read_status(struct dvb_frontend *fe, fe_status_t *status) 6530 + { 6531 + struct drxk_state *state = fe->demodulator_priv; 6532 + int rc; 6533 + 6534 + dprintk(1, "\n"); 6535 + 6536 + rc = drxk_get_stats(fe); 6537 + if (rc < 0) 6538 + return rc; 6539 + 6540 + *status = state->fe_status; 6541 + 6403 6542 return 0; 6404 6543 } 6405 6544 ··· 6568 6439 return -EAGAIN; 6569 6440 6570 6441 GetSignalToNoise(state, &snr2); 6442 + 6443 + /* No negative SNR, clip to zero */ 6444 + if (snr2 < 0) 6445 + snr2 = 0; 6571 6446 *snr = snr2 & 0xffff; 6572 6447 return 0; 6573 6448 } ··· 6655 6522 struct dvb_frontend *drxk_attach(const struct drxk_config *config, 6656 6523 struct i2c_adapter *i2c) 6657 6524 { 6525 + struct dtv_frontend_properties *p; 6658 6526 struct drxk_state *state = NULL; 6659 6527 u8 adr = config->adr; 6660 6528 int status; ··· 6735 6601 } 6736 6602 } else if (init_drxk(state) < 0) 6737 6603 goto error; 6604 + 6605 + 6606 + /* Initialize stats */ 6607 + p = &state->frontend.dtv_property_cache; 6608 + p->strength.len = 1; 6609 + p->cnr.len = 1; 6610 + p->block_error.len = 1; 6611 + p->block_count.len = 1; 6612 + p->pre_bit_error.len = 1; 6613 + p->pre_bit_count.len = 1; 6614 + p->post_bit_error.len = 1; 6615 + p->post_bit_count.len = 1; 6616 + 6617 + p->strength.stat[0].scale = FE_SCALE_RELATIVE; 6618 + p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 6619 + p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 6620 + p->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 6621 + p->pre_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 6622 + p->pre_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 6623 + p->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 6624 + p->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 6738 6625 6739 6626 printk(KERN_INFO "drxk: frontend initialized.\n"); 6740 6627 return &state->frontend;
+2
drivers/media/dvb-frontends/drxk_hard.h
··· 345 345 bool antenna_dvbt; 346 346 u16 antenna_gpio; 347 347 348 + fe_status_t fe_status; 349 + 348 350 /* Firmware */ 349 351 const char *microcode_name; 350 352 struct completion fw_wait_load;
+3
drivers/media/dvb-frontends/drxk_map.h
··· 10 10 #define FEC_RS_COMM_EXEC_STOP 0x0 11 11 #define FEC_RS_MEASUREMENT_PERIOD__A 0x1C30012 12 12 #define FEC_RS_MEASUREMENT_PRESCALE__A 0x1C30013 13 + #define FEC_RS_NR_BIT_ERRORS__A 0x1C30014 13 14 #define FEC_OC_MODE__A 0x1C40011 14 15 #define FEC_OC_MODE_PARITY__M 0x1 15 16 #define FEC_OC_DTO_MODE__A 0x1C40014 ··· 130 129 #define OFDM_EC_SB_PRIOR__A 0x3410013 131 130 #define OFDM_EC_SB_PRIOR_HI 0x0 132 131 #define OFDM_EC_SB_PRIOR_LO 0x1 132 + #define OFDM_EC_VD_ERR_BIT_CNT__A 0x3420017 133 + #define OFDM_EC_VD_IN_BIT_CNT__A 0x3420018 133 134 #define OFDM_EQ_TOP_TD_TPS_CONST__A 0x3010054 134 135 #define OFDM_EQ_TOP_TD_TPS_CONST__M 0x3 135 136 #define OFDM_EQ_TOP_TD_TPS_CONST_64QAM 0x2