diff options
-rw-r--r-- | drivers/media/dvb-frontends/cxd2820r_priv.h | 2 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/cxd2820r_t.c | 88 |
2 files changed, 90 insertions, 0 deletions
diff --git a/drivers/media/dvb-frontends/cxd2820r_priv.h b/drivers/media/dvb-frontends/cxd2820r_priv.h index acfae17991e3..a97570b7fa1d 100644 --- a/drivers/media/dvb-frontends/cxd2820r_priv.h +++ b/drivers/media/dvb-frontends/cxd2820r_priv.h | |||
@@ -27,6 +27,7 @@ | |||
27 | #include "dvb_math.h" | 27 | #include "dvb_math.h" |
28 | #include "cxd2820r.h" | 28 | #include "cxd2820r.h" |
29 | #include <linux/gpio.h> | 29 | #include <linux/gpio.h> |
30 | #include <linux/math64.h> | ||
30 | 31 | ||
31 | struct reg_val_mask { | 32 | struct reg_val_mask { |
32 | u32 reg; | 33 | u32 reg; |
@@ -40,6 +41,7 @@ struct cxd2820r_priv { | |||
40 | struct i2c_adapter *i2c; | 41 | struct i2c_adapter *i2c; |
41 | struct dvb_frontend fe; | 42 | struct dvb_frontend fe; |
42 | struct cxd2820r_config cfg; | 43 | struct cxd2820r_config cfg; |
44 | u64 post_bit_error; | ||
43 | 45 | ||
44 | bool ber_running; | 46 | bool ber_running; |
45 | 47 | ||
diff --git a/drivers/media/dvb-frontends/cxd2820r_t.c b/drivers/media/dvb-frontends/cxd2820r_t.c index 67cc33bc3c35..d402ab68368b 100644 --- a/drivers/media/dvb-frontends/cxd2820r_t.c +++ b/drivers/media/dvb-frontends/cxd2820r_t.c | |||
@@ -351,7 +351,9 @@ int cxd2820r_read_ucblocks_t(struct dvb_frontend *fe, u32 *ucblocks) | |||
351 | int cxd2820r_read_status_t(struct dvb_frontend *fe, enum fe_status *status) | 351 | int cxd2820r_read_status_t(struct dvb_frontend *fe, enum fe_status *status) |
352 | { | 352 | { |
353 | struct cxd2820r_priv *priv = fe->demodulator_priv; | 353 | struct cxd2820r_priv *priv = fe->demodulator_priv; |
354 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
354 | int ret; | 355 | int ret; |
356 | unsigned int utmp; | ||
355 | u8 buf[4]; | 357 | u8 buf[4]; |
356 | *status = 0; | 358 | *status = 0; |
357 | 359 | ||
@@ -388,6 +390,92 @@ int cxd2820r_read_status_t(struct dvb_frontend *fe, enum fe_status *status) | |||
388 | 390 | ||
389 | dev_dbg(&priv->i2c->dev, "%s: lock=%*ph\n", __func__, 4, buf); | 391 | dev_dbg(&priv->i2c->dev, "%s: lock=%*ph\n", __func__, 4, buf); |
390 | 392 | ||
393 | /* Signal strength */ | ||
394 | if (*status & FE_HAS_SIGNAL) { | ||
395 | unsigned int strength; | ||
396 | |||
397 | ret = cxd2820r_rd_regs(priv, 0x00026, buf, 2); | ||
398 | if (ret) | ||
399 | goto error; | ||
400 | |||
401 | utmp = buf[0] << 8 | buf[1] << 0; | ||
402 | utmp = ~utmp & 0x0fff; | ||
403 | /* Scale value to 0x0000-0xffff */ | ||
404 | strength = utmp << 4 | utmp >> 8; | ||
405 | |||
406 | c->strength.len = 1; | ||
407 | c->strength.stat[0].scale = FE_SCALE_RELATIVE; | ||
408 | c->strength.stat[0].uvalue = strength; | ||
409 | } else { | ||
410 | c->strength.len = 1; | ||
411 | c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE; | ||
412 | } | ||
413 | |||
414 | /* CNR */ | ||
415 | if (*status & FE_HAS_VITERBI) { | ||
416 | unsigned int cnr; | ||
417 | |||
418 | ret = cxd2820r_rd_regs(priv, 0x0002c, buf, 2); | ||
419 | if (ret) | ||
420 | goto error; | ||
421 | |||
422 | utmp = buf[0] << 8 | buf[1] << 0; | ||
423 | if (utmp) | ||
424 | cnr = div_u64((u64)(intlog10(utmp) | ||
425 | - intlog10(32000 - utmp) + 55532585) | ||
426 | * 10000, (1 << 24)); | ||
427 | else | ||
428 | cnr = 0; | ||
429 | |||
430 | c->cnr.len = 1; | ||
431 | c->cnr.stat[0].scale = FE_SCALE_DECIBEL; | ||
432 | c->cnr.stat[0].svalue = cnr; | ||
433 | } else { | ||
434 | c->cnr.len = 1; | ||
435 | c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; | ||
436 | } | ||
437 | |||
438 | /* BER */ | ||
439 | if (*status & FE_HAS_SYNC) { | ||
440 | unsigned int post_bit_error; | ||
441 | bool start_ber; | ||
442 | |||
443 | if (priv->ber_running) { | ||
444 | ret = cxd2820r_rd_regs(priv, 0x00076, buf, 3); | ||
445 | if (ret) | ||
446 | goto error; | ||
447 | |||
448 | if ((buf[2] >> 7) & 0x01) { | ||
449 | post_bit_error = buf[2] << 16 | buf[1] << 8 | | ||
450 | buf[0] << 0; | ||
451 | post_bit_error &= 0x0fffff; | ||
452 | start_ber = true; | ||
453 | } else { | ||
454 | post_bit_error = 0; | ||
455 | start_ber = false; | ||
456 | } | ||
457 | } else { | ||
458 | post_bit_error = 0; | ||
459 | start_ber = true; | ||
460 | } | ||
461 | |||
462 | if (start_ber) { | ||
463 | ret = cxd2820r_wr_reg(priv, 0x00079, 0x01); | ||
464 | if (ret) | ||
465 | goto error; | ||
466 | priv->ber_running = true; | ||
467 | } | ||
468 | |||
469 | priv->post_bit_error += post_bit_error; | ||
470 | |||
471 | c->post_bit_error.len = 1; | ||
472 | c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER; | ||
473 | c->post_bit_error.stat[0].uvalue = priv->post_bit_error; | ||
474 | } else { | ||
475 | c->post_bit_error.len = 1; | ||
476 | c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; | ||
477 | } | ||
478 | |||
391 | return ret; | 479 | return ret; |
392 | error: | 480 | error: |
393 | dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); | 481 | dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); |