Commit 42ff76bd authored by Mauro Carvalho Chehab's avatar Mauro Carvalho Chehab

[media] dib8000: make a better estimation for dBm

Use multiple linear segments to better interpolate the dBm
for the signal strength.

The table that converts from linear strength to dB was
empirically determinated with the help of a signal generator
(DTA-2111).

The entries from -35dBm to -22.5dBm were taken using just
the signal generator and the board.

For the entries from -36dBm to -51dBm, a 16 dB tap was used,
in order to extend its range.

Signals below to -51dBm are just linearly interpolated.
Signed-off-by: default avatarMauro Carvalho Chehab <m.chehab@samsung.com>
Acked-by: default avatarPatrick Boettcher <pboettcher@kernellabs.com>
parent b4600d70
...@@ -3843,35 +3843,108 @@ static const struct per_layer_regs per_layer_regs[] = { ...@@ -3843,35 +3843,108 @@ static const struct per_layer_regs per_layer_regs[] = {
{ 556, 581, 583 }, { 556, 581, 583 },
}; };
struct linear_segments {
unsigned x;
signed y;
};
/*
* Table to estimate signal strength in dBm.
* This table was empirically determinated by measuring the signal
* strength generated by a DTA-2111 RF generator directly connected into
* a dib8076 device (a PixelView PV-D231U stick), using a good quality
* 3 meters RC6 cable and good RC6 connectors.
* The real value can actually be different on other devices, depending
* on several factors, like if LNA is enabled or not, if diversity is
* enabled, type of connectors, etc.
* Yet, it is better to use this measure in dB than a random non-linear
* percentage value, especially for antenna adjustments.
* On my tests, the precision of the measure using this table is about
* 0.5 dB, with sounds reasonable enough.
*/
static struct linear_segments strength_to_db_table[] = {
{ 55953, 108500 }, /* -22.5 dBm */
{ 55394, 108000 },
{ 53834, 107000 },
{ 52863, 106000 },
{ 52239, 105000 },
{ 52012, 104000 },
{ 51803, 103000 },
{ 51566, 102000 },
{ 51356, 101000 },
{ 51112, 100000 },
{ 50869, 99000 },
{ 50600, 98000 },
{ 50363, 97000 },
{ 50117, 96000 }, /* -35 dBm */
{ 49889, 95000 },
{ 49680, 94000 },
{ 49493, 93000 },
{ 49302, 92000 },
{ 48929, 91000 },
{ 48416, 90000 },
{ 48035, 89000 },
{ 47593, 88000 },
{ 47282, 87000 },
{ 46953, 86000 },
{ 46698, 85000 },
{ 45617, 84000 },
{ 44773, 83000 },
{ 43845, 82000 },
{ 43020, 81000 },
{ 42010, 80000 }, /* -51 dBm */
{ 0, 0 },
};
static u32 interpolate_value(u32 value, struct linear_segments *segments,
unsigned len)
{
u64 tmp64;
u32 dx;
s32 dy;
int i, ret;
if (value >= segments[0].x)
return segments[0].y;
if (value < segments[len-1].x)
return segments[len-1].y;
for (i = 1; i < len - 1; i++) {
/* If value is identical, no need to interpolate */
if (value == segments[i].x)
return segments[i].y;
if (value > segments[i].x)
break;
}
/* Linear interpolation between the two (x,y) points */
dy = segments[i - 1].y - segments[i].y;
dx = segments[i - 1].x - segments[i].x;
tmp64 = value - segments[i].x;
tmp64 *= dy;
do_div(tmp64, dx);
ret = segments[i].y + tmp64;
return ret;
}
static int dib8000_get_stats(struct dvb_frontend *fe, fe_status_t stat) static int dib8000_get_stats(struct dvb_frontend *fe, fe_status_t stat)
{ {
struct dib8000_state *state = fe->demodulator_priv; struct dib8000_state *state = fe->demodulator_priv;
struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache; struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache;
int i, lock; int i, lock;
u64 tmp;
u32 snr, val; u32 snr, val;
s32 db;
u16 strength; u16 strength;
/* Get Signal strength */ /* Get Signal strength */
dib8000_read_signal_strength(fe, &strength); dib8000_read_signal_strength(fe, &strength);
val = strength;
/* db = interpolate_value(val,
* Estimate it in dBm strength_to_db_table,
* This calculus was empirically determinated by measuring the signal ARRAY_SIZE(strength_to_db_table)) - 131000;
* strength generated by a DTA-2111 RF generator directly connected into c->strength.stat[0].svalue = db;
* a dib8076 device. The real value can actually be different on other
* devices, depending if LNA is enabled or not, if diversity is enabled,
* etc.
*/
if (strength == 65535) {
c->strength.stat[0].svalue = -22000;
} else {
tmp = strength * 25000L;
do_div(tmp, 11646);
c->strength.stat[0].svalue = tmp - 142569;
if (c->strength.stat[0].svalue > -22000)
c->strength.stat[0].svalue = -22000;
}
/* Check if 1 second was elapsed */ /* Check if 1 second was elapsed */
if (!time_after(jiffies, state->get_stats_time)) if (!time_after(jiffies, state->get_stats_time))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment