[media] af9033: implement DVBv5 statistics for signal strength

Let the demod firmware estimate RF signal strength and return it
to the app as a dBm. To handle that, use thread which reads signal
strengths from firmware in 2 sec intervals when device is active.

Signed-off-by: Antti Palosaari <crope@iki.fi>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
This commit is contained in:
Antti Palosaari 2014-09-02 03:55:21 -03:00 committed by Mauro Carvalho Chehab
parent 249c697e5e
commit 83f1161911
1 changed files with 48 additions and 0 deletions

View File

@ -28,13 +28,17 @@ struct af9033_dev {
struct i2c_client *client;
struct dvb_frontend fe;
struct af9033_config cfg;
bool is_af9035;
bool is_it9135;
u32 bandwidth_hz;
bool ts_mode_parallel;
bool ts_mode_serial;
fe_status_t fe_status;
u32 ber;
u32 ucb;
struct delayed_work stat_work;
unsigned long last_stat_check;
};
@ -442,6 +446,8 @@ static int af9033_init(struct dvb_frontend *fe)
}
dev->bandwidth_hz = 0; /* force to program all parameters */
/* start statistics polling */
schedule_delayed_work(&dev->stat_work, msecs_to_jiffies(2000));
return 0;
@ -457,6 +463,9 @@ static int af9033_sleep(struct dvb_frontend *fe)
int ret, i;
u8 tmp;
/* stop statistics polling */
cancel_delayed_work_sync(&dev->stat_work);
ret = af9033_wr_reg(dev, 0x80004c, 1);
if (ret < 0)
goto err;
@ -810,6 +819,8 @@ static int af9033_read_status(struct dvb_frontend *fe, fe_status_t *status)
FE_HAS_LOCK;
}
dev->fe_status = *status;
return 0;
err:
@ -1039,6 +1050,40 @@ static int af9033_pid_filter(struct dvb_frontend *fe, int index, u16 pid,
return ret;
}
static void af9033_stat_work(struct work_struct *work)
{
struct af9033_dev *dev = container_of(work, struct af9033_dev, stat_work.work);
struct dtv_frontend_properties *c = &dev->fe.dtv_property_cache;
int ret, tmp;
u8 u8tmp;
dev_dbg(&dev->client->dev, "\n");
if (dev->fe_status & FE_HAS_SIGNAL) {
if (dev->is_af9035) {
ret = af9033_rd_reg(dev, 0x80004a, &u8tmp);
tmp = -u8tmp * 1000;
} else {
ret = af9033_rd_reg(dev, 0x8000f7, &u8tmp);
tmp = (u8tmp - 100) * 1000;
}
if (ret)
goto err;
c->strength.len = 1;
c->strength.stat[0].scale = FE_SCALE_DECIBEL;
c->strength.stat[0].svalue = tmp;
} else {
c->strength.len = 1;
c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
}
schedule_delayed_work(&dev->stat_work, msecs_to_jiffies(2000));
return;
err:
dev_dbg(&dev->client->dev, "failed=%d\n", ret);
}
static struct dvb_frontend_ops af9033_ops = {
.delsys = { SYS_DVBT },
.info = {
@ -1099,6 +1144,7 @@ static int af9033_probe(struct i2c_client *client,
/* setup the state */
dev->client = client;
INIT_DELAYED_WORK(&dev->stat_work, af9033_stat_work);
memcpy(&dev->cfg, cfg, sizeof(struct af9033_config));
if (dev->cfg.clock != 12000000) {
@ -1117,9 +1163,11 @@ static int af9033_probe(struct i2c_client *client,
case AF9033_TUNER_IT9135_60:
case AF9033_TUNER_IT9135_61:
case AF9033_TUNER_IT9135_62:
dev->is_it9135 = true;
reg = 0x004bfc;
break;
default:
dev->is_af9035 = true;
reg = 0x0083e9;
break;
}