diff options
author | Antti Palosaari <crope@iki.fi> | 2016-12-08 22:19:19 -0200 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@s-opensource.com> | 2017-01-31 10:26:23 -0200 |
commit | 8393c00369f1fe68182295b7adca80a73646fdd3 (patch) | |
tree | 125e679a58bc9fd2c09680cbef1e31686f4493ad /drivers/media/dvb-frontends/si2168.c | |
parent | e5360224ebce416586eae3b3967ee8dbd87ad17d (diff) |
[media] si2168: implement ber statistics
Implement DVBv5 BER.
Signed-off-by: Antti Palosaari <crope@iki.fi>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
Diffstat (limited to 'drivers/media/dvb-frontends/si2168.c')
-rw-r--r-- | drivers/media/dvb-frontends/si2168.c | 46 |
1 files changed, 44 insertions, 2 deletions
diff --git a/drivers/media/dvb-frontends/si2168.c b/drivers/media/dvb-frontends/si2168.c index 20b4a659e2e4..5fbb6c12b766 100644 --- a/drivers/media/dvb-frontends/si2168.c +++ b/drivers/media/dvb-frontends/si2168.c @@ -85,7 +85,8 @@ static int si2168_read_status(struct dvb_frontend *fe, enum fe_status *status) struct i2c_client *client = fe->demodulator_priv; struct si2168_dev *dev = i2c_get_clientdata(client); struct dtv_frontend_properties *c = &fe->dtv_property_cache; - int ret; + int ret, i; + unsigned int utmp, utmp1, utmp2; struct si2168_cmd cmd; *status = 0; @@ -144,6 +145,39 @@ static int si2168_read_status(struct dvb_frontend *fe, enum fe_status *status) dev_dbg(&client->dev, "status=%02x args=%*ph\n", *status, cmd.rlen, cmd.args); + /* BER */ + if (*status & FE_HAS_VITERBI) { + memcpy(cmd.args, "\x82\x00", 2); + cmd.wlen = 2; + cmd.rlen = 3; + ret = si2168_cmd_execute(client, &cmd); + if (ret) + goto err; + + /* + * Firmware returns [0, 255] mantissa and [0, 8] exponent. + * Convert to DVB API: mantissa * 10^(8 - exponent) / 10^8 + */ + utmp = clamp(8 - cmd.args[1], 0, 8); + for (i = 0, utmp1 = 1; i < utmp; i++) + utmp1 = utmp1 * 10; + + utmp1 = cmd.args[2] * utmp1; + utmp2 = 100000000; /* 10^8 */ + + dev_dbg(&client->dev, + "post_bit_error=%u post_bit_count=%u ber=%u*10^-%u\n", + utmp1, utmp2, cmd.args[2], cmd.args[1]); + + c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER; + c->post_bit_error.stat[0].uvalue += utmp1; + c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER; + c->post_bit_count.stat[0].uvalue += utmp2; + } else { + c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + } + return 0; err: dev_dbg(&client->dev, "failed=%d\n", ret); @@ -355,6 +389,7 @@ static int si2168_init(struct dvb_frontend *fe) { struct i2c_client *client = fe->demodulator_priv; struct si2168_dev *dev = i2c_get_clientdata(client); + struct dtv_frontend_properties *c = &fe->dtv_property_cache; int ret, len, remaining; const struct firmware *fw; struct si2168_cmd cmd; @@ -493,10 +528,17 @@ static int si2168_init(struct dvb_frontend *fe) dev->warm = true; warm: + /* Init stats here to indicate which stats are supported */ + c->cnr.len = 1; + c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + c->post_bit_error.len = 1; + c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + c->post_bit_count.len = 1; + c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + dev->active = true; return 0; - err_release_firmware: release_firmware(fw); err: |