diff options
author | Antti Palosaari <crope@iki.fi> | 2014-09-02 02:55:21 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@osg.samsung.com> | 2014-09-21 18:44:43 -0400 |
commit | 83f1161911c5f32dc4cfa817a73ae028d32c43b7 (patch) | |
tree | db5b828ed5bfc629b6cdf7b5d7ce57b58e560bc9 /drivers/media/dvb-frontends/af9033.c | |
parent | 249c697e5e2c8e1347d79be0a9c93a985f2ad12e (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.c | 48 |
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 { | |||
28 | struct i2c_client *client; | 28 | struct i2c_client *client; |
29 | struct dvb_frontend fe; | 29 | struct dvb_frontend fe; |
30 | struct af9033_config cfg; | 30 | struct af9033_config cfg; |
31 | bool is_af9035; | ||
32 | bool is_it9135; | ||
31 | 33 | ||
32 | u32 bandwidth_hz; | 34 | u32 bandwidth_hz; |
33 | bool ts_mode_parallel; | 35 | bool ts_mode_parallel; |
34 | bool ts_mode_serial; | 36 | bool ts_mode_serial; |
35 | 37 | ||
38 | fe_status_t fe_status; | ||
36 | u32 ber; | 39 | u32 ber; |
37 | u32 ucb; | 40 | u32 ucb; |
41 | struct delayed_work stat_work; | ||
38 | unsigned long last_stat_check; | 42 | unsigned long last_stat_check; |
39 | }; | 43 | }; |
40 | 44 | ||
@@ -442,6 +446,8 @@ static int af9033_init(struct dvb_frontend *fe) | |||
442 | } | 446 | } |
443 | 447 | ||
444 | dev->bandwidth_hz = 0; /* force to program all parameters */ | 448 | dev->bandwidth_hz = 0; /* force to program all parameters */ |
449 | /* start statistics polling */ | ||
450 | schedule_delayed_work(&dev->stat_work, msecs_to_jiffies(2000)); | ||
445 | 451 | ||
446 | return 0; | 452 | return 0; |
447 | 453 | ||
@@ -457,6 +463,9 @@ static int af9033_sleep(struct dvb_frontend *fe) | |||
457 | int ret, i; | 463 | int ret, i; |
458 | u8 tmp; | 464 | u8 tmp; |
459 | 465 | ||
466 | /* stop statistics polling */ | ||
467 | cancel_delayed_work_sync(&dev->stat_work); | ||
468 | |||
460 | ret = af9033_wr_reg(dev, 0x80004c, 1); | 469 | ret = af9033_wr_reg(dev, 0x80004c, 1); |
461 | if (ret < 0) | 470 | if (ret < 0) |
462 | goto err; | 471 | goto err; |
@@ -810,6 +819,8 @@ static int af9033_read_status(struct dvb_frontend *fe, fe_status_t *status) | |||
810 | FE_HAS_LOCK; | 819 | FE_HAS_LOCK; |
811 | } | 820 | } |
812 | 821 | ||
822 | dev->fe_status = *status; | ||
823 | |||
813 | return 0; | 824 | return 0; |
814 | 825 | ||
815 | err: | 826 | err: |
@@ -1039,6 +1050,40 @@ err: | |||
1039 | return ret; | 1050 | return ret; |
1040 | } | 1051 | } |
1041 | 1052 | ||
1053 | static void af9033_stat_work(struct work_struct *work) | ||
1054 | { | ||
1055 | struct af9033_dev *dev = container_of(work, struct af9033_dev, stat_work.work); | ||
1056 | struct dtv_frontend_properties *c = &dev->fe.dtv_property_cache; | ||
1057 | int ret, tmp; | ||
1058 | u8 u8tmp; | ||
1059 | |||
1060 | dev_dbg(&dev->client->dev, "\n"); | ||
1061 | |||
1062 | if (dev->fe_status & FE_HAS_SIGNAL) { | ||
1063 | if (dev->is_af9035) { | ||
1064 | ret = af9033_rd_reg(dev, 0x80004a, &u8tmp); | ||
1065 | tmp = -u8tmp * 1000; | ||
1066 | } else { | ||
1067 | ret = af9033_rd_reg(dev, 0x8000f7, &u8tmp); | ||
1068 | tmp = (u8tmp - 100) * 1000; | ||
1069 | } | ||
1070 | if (ret) | ||
1071 | goto err; | ||
1072 | |||
1073 | c->strength.len = 1; | ||
1074 | c->strength.stat[0].scale = FE_SCALE_DECIBEL; | ||
1075 | c->strength.stat[0].svalue = tmp; | ||
1076 | } else { | ||
1077 | c->strength.len = 1; | ||
1078 | c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE; | ||
1079 | } | ||
1080 | |||
1081 | schedule_delayed_work(&dev->stat_work, msecs_to_jiffies(2000)); | ||
1082 | return; | ||
1083 | err: | ||
1084 | dev_dbg(&dev->client->dev, "failed=%d\n", ret); | ||
1085 | } | ||
1086 | |||
1042 | static struct dvb_frontend_ops af9033_ops = { | 1087 | static struct dvb_frontend_ops af9033_ops = { |
1043 | .delsys = { SYS_DVBT }, | 1088 | .delsys = { SYS_DVBT }, |
1044 | .info = { | 1089 | .info = { |
@@ -1099,6 +1144,7 @@ static int af9033_probe(struct i2c_client *client, | |||
1099 | 1144 | ||
1100 | /* setup the state */ | 1145 | /* setup the state */ |
1101 | dev->client = client; | 1146 | dev->client = client; |
1147 | INIT_DELAYED_WORK(&dev->stat_work, af9033_stat_work); | ||
1102 | memcpy(&dev->cfg, cfg, sizeof(struct af9033_config)); | 1148 | memcpy(&dev->cfg, cfg, sizeof(struct af9033_config)); |
1103 | 1149 | ||
1104 | if (dev->cfg.clock != 12000000) { | 1150 | if (dev->cfg.clock != 12000000) { |
@@ -1117,9 +1163,11 @@ static int af9033_probe(struct i2c_client *client, | |||
1117 | case AF9033_TUNER_IT9135_60: | 1163 | case AF9033_TUNER_IT9135_60: |
1118 | case AF9033_TUNER_IT9135_61: | 1164 | case AF9033_TUNER_IT9135_61: |
1119 | case AF9033_TUNER_IT9135_62: | 1165 | case AF9033_TUNER_IT9135_62: |
1166 | dev->is_it9135 = true; | ||
1120 | reg = 0x004bfc; | 1167 | reg = 0x004bfc; |
1121 | break; | 1168 | break; |
1122 | default: | 1169 | default: |
1170 | dev->is_af9035 = true; | ||
1123 | reg = 0x0083e9; | 1171 | reg = 0x0083e9; |
1124 | break; | 1172 | break; |
1125 | } | 1173 | } |