summaryrefslogtreecommitdiff
path: root/drivers/media/dvb/frontends
diff options
context:
space:
mode:
authorHans-Frieder Vogt <hfvogt@gmx.net>2012-04-07 17:34:34 +0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-05-14 20:19:31 +0400
commit47eafa5427c2da51f676e4c0b48bc851df8779f8 (patch)
treea8475fb21a9c6eb1a4051bd2a6477768833a566f /drivers/media/dvb/frontends
parent3234bd2f193936da6180a7dc6699a75191bc44d1 (diff)
downloadlinux-47eafa5427c2da51f676e4c0b48bc851df8779f8.tar.xz
[media] af9033: implement ber and ucb functions
af9033: implement read_ber and read_ucblocks functions. Version 2 of patch that reflects my findings on the behaviour of abort_cnt, err_cnt and bit_cnt: - bit_cnt is always 0x2710 (10000) - abort_cnt is between 0 and 0x2710 - err_cnt is between 0 and 640000 (= 0x2710 * 8 * 8) in the current implementation BER is calculated as the number of bit errors per processed bits, ignoring those bits that are already discarded and counted in abort_cnt, i.e. UCBLOCKS. Signed-off-by: Hans-Frieder Vogt <hfvogt@gmx.net> Signed-off-by: Antti Palosaari <crope@iki.fi> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/dvb/frontends')
-rw-r--r--drivers/media/dvb/frontends/af9033.c65
1 files changed, 63 insertions, 2 deletions
diff --git a/drivers/media/dvb/frontends/af9033.c b/drivers/media/dvb/frontends/af9033.c
index 2cb1f8d6955e..a38998286260 100644
--- a/drivers/media/dvb/frontends/af9033.c
+++ b/drivers/media/dvb/frontends/af9033.c
@@ -29,6 +29,10 @@ struct af9033_state {
u32 bandwidth_hz;
bool ts_mode_parallel;
bool ts_mode_serial;
+
+ u32 ber;
+ u32 ucb;
+ unsigned long last_stat_check;
};
/* write multiple registers */
@@ -772,16 +776,73 @@ err:
return ret;
}
+static int af9033_update_ch_stat(struct af9033_state *state)
+{
+ int ret = 0;
+ u32 err_cnt, bit_cnt;
+ u16 abort_cnt;
+ u8 buf[7];
+
+ /* only update data every half second */
+ if (time_after(jiffies, state->last_stat_check + msecs_to_jiffies(500))) {
+ ret = af9033_rd_regs(state, 0x800032, buf, sizeof(buf));
+ if (ret < 0)
+ goto err;
+ /* in 8 byte packets? */
+ abort_cnt = (buf[1] << 8) + buf[0];
+ /* in bits */
+ err_cnt = (buf[4] << 16) + (buf[3] << 8) + buf[2];
+ /* in 8 byte packets? always(?) 0x2710 = 10000 */
+ bit_cnt = (buf[6] << 8) + buf[5];
+
+ if (bit_cnt < abort_cnt) {
+ abort_cnt = 1000;
+ state->ber = 0xffffffff;
+ } else {
+ /* 8 byte packets, that have not been rejected already */
+ bit_cnt -= (u32)abort_cnt;
+ if (bit_cnt == 0) {
+ state->ber = 0xffffffff;
+ } else {
+ err_cnt -= (u32)abort_cnt * 8 * 8;
+ bit_cnt *= 8 * 8;
+ state->ber = err_cnt * (0xffffffff / bit_cnt);
+ }
+ }
+ state->ucb += abort_cnt;
+ state->last_stat_check = jiffies;
+ }
+
+ return 0;
+err:
+ pr_debug("%s: failed=%d\n", __func__, ret);
+ return ret;
+}
+
static int af9033_read_ber(struct dvb_frontend *fe, u32 *ber)
{
- *ber = 0;
+ struct af9033_state *state = fe->demodulator_priv;
+ int ret;
+
+ ret = af9033_update_ch_stat(state);
+ if (ret < 0)
+ return ret;
+
+ *ber = state->ber;
return 0;
}
static int af9033_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
{
- *ucblocks = 0;
+ struct af9033_state *state = fe->demodulator_priv;
+ int ret;
+
+ ret = af9033_update_ch_stat(state);
+ if (ret < 0)
+ return ret;
+
+ *ucblocks = state->ucb;
return 0;
}