summaryrefslogtreecommitdiff
path: root/drivers/media/dvb-frontends/af9033.c
diff options
context:
space:
mode:
authorAntti Palosaari <crope@iki.fi>2014-09-02 03:55:21 -0300
committerMauro Carvalho Chehab <mchehab@osg.samsung.com>2014-09-21 19:44:43 -0300
commit83f1161911c5f32dc4cfa817a73ae028d32c43b7 (patch)
treedb5b828ed5bfc629b6cdf7b5d7ce57b58e560bc9 /drivers/media/dvb-frontends/af9033.c
parent249c697e5e2c8e1347d79be0a9c93a985f2ad12e (diff)
[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>
Diffstat (limited to 'drivers/media/dvb-frontends/af9033.c')
-rw-r--r--drivers/media/dvb-frontends/af9033.c48
1 files changed, 48 insertions, 0 deletions
diff --git a/drivers/media/dvb-frontends/af9033.c b/drivers/media/dvb-frontends/af9033.c
index 1bd5a9af7db5..b9a0b009aeda 100644
--- a/drivers/media/dvb-frontends/af9033.c
+++ b/drivers/media/dvb-frontends/af9033.c
@@ -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 @@ err:
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;
}