Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6ef06e78 authored by Mauro Carvalho Chehab's avatar Mauro Carvalho Chehab
Browse files

[media] dib8000: add DVBv5 stats



The advantage of DVBv5 stats is that it allows adding proper
scales to all measures. use it for this frontend.

This patch adds a basic set of stats, basically cloning what's already
provided by DVBv3 API. Latter patches will improve it.

Signed-off-by: default avatarMauro Carvalho Chehab <m.chehab@samsung.com>
Acked-by: default avatarPatrick Boettcher <pboettcher@kernellabs.com>
parent 51fea113
Loading
Loading
Loading
Loading
+141 −1
Original line number Original line Diff line number Diff line
@@ -124,6 +124,8 @@ struct dib8000_state {
	u16 agc2_max;
	u16 agc2_max;
	u16 agc2_min;
	u16 agc2_min;
#endif
#endif

	unsigned long get_stats_time;
};
};


enum dib8000_power_mode {
enum dib8000_power_mode {
@@ -983,6 +985,32 @@ static u16 dib8000_identify(struct i2c_device *client)
	return value;
	return value;
}
}


static void dib8000_reset_stats(struct dvb_frontend *fe)
{
	struct dib8000_state *state = fe->demodulator_priv;
	struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache;

	memset(&c->strength, 0, sizeof(c->strength));
	memset(&c->cnr, 0, sizeof(c->cnr));
	memset(&c->post_bit_error, 0, sizeof(c->post_bit_error));
	memset(&c->post_bit_count, 0, sizeof(c->post_bit_count));
	memset(&c->block_error, 0, sizeof(c->block_error));

	c->strength.len = 1;
	c->cnr.len = 1;
	c->block_error.len = 1;
	c->post_bit_error.len = 1;
	c->post_bit_count.len = 1;

	c->strength.stat[0].scale = FE_SCALE_RELATIVE;
	c->strength.stat[0].uvalue = 0;

	c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
	c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
	c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
	c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
}

static int dib8000_reset(struct dvb_frontend *fe)
static int dib8000_reset(struct dvb_frontend *fe)
{
{
	struct dib8000_state *state = fe->demodulator_priv;
	struct dib8000_state *state = fe->demodulator_priv;
@@ -1088,6 +1116,8 @@ static int dib8000_reset(struct dvb_frontend *fe)


	dib8000_set_power_mode(state, DIB8000_POWER_INTERFACE_ONLY);
	dib8000_set_power_mode(state, DIB8000_POWER_INTERFACE_ONLY);


	dib8000_reset_stats(fe);

	return 0;
	return 0;
}
}


@@ -2983,6 +3013,8 @@ static int dib8000_tune(struct dvb_frontend *fe)


	switch (*tune_state) {
	switch (*tune_state) {
	case CT_DEMOD_START: /* 30 */
	case CT_DEMOD_START: /* 30 */
			dib8000_reset_stats(fe);

			if (state->revision == 0x8090)
			if (state->revision == 0x8090)
				dib8090p_init_sdram(state);
				dib8090p_init_sdram(state);
			state->status = FE_STATUS_TUNE_PENDING;
			state->status = FE_STATUS_TUNE_PENDING;
@@ -3654,6 +3686,8 @@ static int dib8000_set_frontend(struct dvb_frontend *fe)
	return 0;
	return 0;
}
}


static int dib8000_get_stats(struct dvb_frontend *fe, fe_status_t stat);

static int dib8000_read_status(struct dvb_frontend *fe, fe_status_t * stat)
static int dib8000_read_status(struct dvb_frontend *fe, fe_status_t * stat)
{
{
	struct dib8000_state *state = fe->demodulator_priv;
	struct dib8000_state *state = fe->demodulator_priv;
@@ -3691,6 +3725,7 @@ static int dib8000_read_status(struct dvb_frontend *fe, fe_status_t * stat)
		if (lock & 0x01)
		if (lock & 0x01)
			*stat |= FE_HAS_VITERBI;
			*stat |= FE_HAS_VITERBI;
	}
	}
	dib8000_get_stats(fe, *stat);


	return 0;
	return 0;
}
}
@@ -3797,6 +3832,111 @@ static int dib8000_read_snr(struct dvb_frontend *fe, u16 * snr)
	return 0;
	return 0;
}
}


struct per_layer_regs {
	u16 lock, ber, per;
};

static const struct per_layer_regs per_layer_regs[] = {
	{ 554, 560, 562 },
	{ 555, 576, 578 },
	{ 556, 581, 583 },
};

static int dib8000_get_stats(struct dvb_frontend *fe, fe_status_t stat)
{
	struct dib8000_state *state = fe->demodulator_priv;
	struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache;
	int i, lock;
	u32 snr, val;
	u16 strength;

	/* Get Signal strength */
	dib8000_read_signal_strength(fe, &strength);
	c->strength.stat[0].uvalue = strength;

	/* Check if 1 second was elapsed */
	if (!time_after(jiffies, state->get_stats_time))
		return 0;
	state->get_stats_time = jiffies + msecs_to_jiffies(1000);

	/* Get SNR */
	snr = dib8000_get_snr(fe);
	for (i = 1; i < MAX_NUMBER_OF_FRONTENDS; i++) {
		if (state->fe[i])
			snr += dib8000_get_snr(state->fe[i]);
	}
	snr = snr >> 16;

	if (snr) {
		snr = 10 * intlog10(snr);
		snr = (1000L * snr) >> 24;
	} else {
		snr = 0;
	}
	c->cnr.stat[0].svalue = snr;
	c->cnr.stat[0].scale = FE_SCALE_DECIBEL;

	/* UCB/BER measures require lock */
	if (!(stat & FE_HAS_LOCK)) {
		c->block_error.len = 1;
		c->post_bit_error.len = 1;
		c->post_bit_count.len = 1;
		c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
		c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
		c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
		return 0;
	}

	/* Get UCB and post-BER measures */

	/* FIXME: need to check if 1.25e6 bits already passed */
	dib8000_read_ber(fe, &val);
	c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
	c->post_bit_error.stat[0].uvalue += val;

	c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;
	c->post_bit_count.stat[0].uvalue += 100000000;

	/*
	 * FIXME: this is refreshed on every second, but a time
	 * drift between dib8000 and PC clock may cause troubles
	 */
	dib8000_read_unc_blocks(fe, &val);

	c->block_error.stat[0].scale = FE_SCALE_COUNTER;
	c->block_error.stat[0].uvalue += val;

	if (state->revision < 0x8002)
		return 0;

	c->block_error.len = 4;
	c->post_bit_error.len = 4;
	c->post_bit_count.len = 4;

	for (i = 0; i < 3; i++) {
		lock = dib8000_read_word(state, per_layer_regs[i].lock);
		if (lock & 0x01) {
			/* FIXME: need to check if 1.25e6 bits already passed */
			val = dib8000_read_word(state, per_layer_regs[i].ber);
			c->post_bit_error.stat[1 + i].scale = FE_SCALE_COUNTER;
			c->post_bit_error.stat[1 + i].uvalue += val;

			c->post_bit_count.stat[1 + i].scale = FE_SCALE_COUNTER;
			c->post_bit_count.stat[1 + i].uvalue += 100000000;

			/*
			 * FIXME: this is refreshed on every second, but a time
			 * drift between dib8000 and PC clock may cause troubles
			 */
			val = dib8000_read_word(state, per_layer_regs[i].per);

			c->block_error.stat[1 + i].scale = FE_SCALE_COUNTER;
			c->block_error.stat[1 + i].uvalue += val;
		}
	}
	return 0;
}

int dib8000_set_slave_frontend(struct dvb_frontend *fe, struct dvb_frontend *fe_slave)
int dib8000_set_slave_frontend(struct dvb_frontend *fe, struct dvb_frontend *fe_slave)
{
{
	struct dib8000_state *state = fe->demodulator_priv;
	struct dib8000_state *state = fe->demodulator_priv;