From 83f1161911c5f32dc4cfa817a73ae028d32c43b7 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Tue, 2 Sep 2014 03:55:21 -0300 Subject: [PATCH] [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 Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/af9033.c | 48 ++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) 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; } -- 2.34.1