diff options
author | Mauro Carvalho Chehab <m.chehab@samsung.com> | 2014-05-21 12:57:30 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <m.chehab@samsung.com> | 2014-05-25 16:50:16 -0400 |
commit | f7a27ff1fb77e114d1059a5eb2ed1cffdc508ce8 (patch) | |
tree | 07e3ab839ced4dbee349f50869050c9aa3bd4634 | |
parent | 5015c27b60de2b41ddcf8f1b88da2a3025b87cd4 (diff) |
[media] xc5000: delay tuner sleep to 5 seconds
Some drivers, like au0828 are very sensitive to tuner sleep and may
break if the sleep happens too fast. Also, by keeping the tuner alive
for a while could speedup tuning process during channel scan. So,
change the logic to delay the actual sleep to 5 seconds after its
command.
Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
-rw-r--r-- | drivers/media/tuners/xc5000.c | 43 |
1 files changed, 34 insertions, 9 deletions
diff --git a/drivers/media/tuners/xc5000.c b/drivers/media/tuners/xc5000.c index 8df92619883f..2b3d514be672 100644 --- a/drivers/media/tuners/xc5000.c +++ b/drivers/media/tuners/xc5000.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/moduleparam.h> | 25 | #include <linux/moduleparam.h> |
26 | #include <linux/videodev2.h> | 26 | #include <linux/videodev2.h> |
27 | #include <linux/delay.h> | 27 | #include <linux/delay.h> |
28 | #include <linux/workqueue.h> | ||
28 | #include <linux/dvb/frontend.h> | 29 | #include <linux/dvb/frontend.h> |
29 | #include <linux/i2c.h> | 30 | #include <linux/i2c.h> |
30 | 31 | ||
@@ -65,12 +66,18 @@ struct xc5000_priv { | |||
65 | u16 pll_register_no; | 66 | u16 pll_register_no; |
66 | u8 init_status_supported; | 67 | u8 init_status_supported; |
67 | u8 fw_checksum_supported; | 68 | u8 fw_checksum_supported; |
69 | |||
70 | struct dvb_frontend *fe; | ||
71 | struct delayed_work timer_sleep; | ||
68 | }; | 72 | }; |
69 | 73 | ||
70 | /* Misc Defines */ | 74 | /* Misc Defines */ |
71 | #define MAX_TV_STANDARD 24 | 75 | #define MAX_TV_STANDARD 24 |
72 | #define XC_MAX_I2C_WRITE_LENGTH 64 | 76 | #define XC_MAX_I2C_WRITE_LENGTH 64 |
73 | 77 | ||
78 | /* Time to suspend after the .sleep callback is called */ | ||
79 | #define XC5000_SLEEP_TIME 5000 /* ms */ | ||
80 | |||
74 | /* Signal Types */ | 81 | /* Signal Types */ |
75 | #define XC_RF_MODE_AIR 0 | 82 | #define XC_RF_MODE_AIR 0 |
76 | #define XC_RF_MODE_CABLE 1 | 83 | #define XC_RF_MODE_CABLE 1 |
@@ -1096,6 +1103,8 @@ static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe, int force) | |||
1096 | u16 pll_lock_status; | 1103 | u16 pll_lock_status; |
1097 | u16 fw_ck; | 1104 | u16 fw_ck; |
1098 | 1105 | ||
1106 | cancel_delayed_work(&priv->timer_sleep); | ||
1107 | |||
1099 | if (force || xc5000_is_firmware_loaded(fe) != 0) { | 1108 | if (force || xc5000_is_firmware_loaded(fe) != 0) { |
1100 | 1109 | ||
1101 | fw_retry: | 1110 | fw_retry: |
@@ -1164,27 +1173,39 @@ fw_retry: | |||
1164 | return ret; | 1173 | return ret; |
1165 | } | 1174 | } |
1166 | 1175 | ||
1167 | static int xc5000_sleep(struct dvb_frontend *fe) | 1176 | static void xc5000_do_timer_sleep(struct work_struct *timer_sleep) |
1168 | { | 1177 | { |
1178 | struct xc5000_priv *priv =container_of(timer_sleep, struct xc5000_priv, | ||
1179 | timer_sleep.work); | ||
1180 | struct dvb_frontend *fe = priv->fe; | ||
1169 | int ret; | 1181 | int ret; |
1170 | 1182 | ||
1171 | dprintk(1, "%s()\n", __func__); | 1183 | dprintk(1, "%s()\n", __func__); |
1172 | 1184 | ||
1173 | /* Avoid firmware reload on slow devices */ | ||
1174 | if (no_poweroff) | ||
1175 | return 0; | ||
1176 | |||
1177 | /* According to Xceive technical support, the "powerdown" register | 1185 | /* According to Xceive technical support, the "powerdown" register |
1178 | was removed in newer versions of the firmware. The "supported" | 1186 | was removed in newer versions of the firmware. The "supported" |
1179 | way to sleep the tuner is to pull the reset pin low for 10ms */ | 1187 | way to sleep the tuner is to pull the reset pin low for 10ms */ |
1180 | ret = xc5000_tuner_reset(fe); | 1188 | ret = xc5000_tuner_reset(fe); |
1181 | if (ret != 0) { | 1189 | if (ret != 0) |
1182 | printk(KERN_ERR | 1190 | printk(KERN_ERR |
1183 | "xc5000: %s() unable to shutdown tuner\n", | 1191 | "xc5000: %s() unable to shutdown tuner\n", |
1184 | __func__); | 1192 | __func__); |
1185 | return -EREMOTEIO; | 1193 | } |
1186 | } else | 1194 | |
1195 | static int xc5000_sleep(struct dvb_frontend *fe) | ||
1196 | { | ||
1197 | struct xc5000_priv *priv = fe->tuner_priv; | ||
1198 | |||
1199 | dprintk(1, "%s()\n", __func__); | ||
1200 | |||
1201 | /* Avoid firmware reload on slow devices */ | ||
1202 | if (no_poweroff) | ||
1187 | return 0; | 1203 | return 0; |
1204 | |||
1205 | schedule_delayed_work(&priv->timer_sleep, | ||
1206 | msecs_to_jiffies(XC5000_SLEEP_TIME)); | ||
1207 | |||
1208 | return 0; | ||
1188 | } | 1209 | } |
1189 | 1210 | ||
1190 | static int xc5000_init(struct dvb_frontend *fe) | 1211 | static int xc5000_init(struct dvb_frontend *fe) |
@@ -1211,8 +1232,10 @@ static int xc5000_release(struct dvb_frontend *fe) | |||
1211 | 1232 | ||
1212 | mutex_lock(&xc5000_list_mutex); | 1233 | mutex_lock(&xc5000_list_mutex); |
1213 | 1234 | ||
1214 | if (priv) | 1235 | if (priv) { |
1236 | cancel_delayed_work(&priv->timer_sleep); | ||
1215 | hybrid_tuner_release_state(priv); | 1237 | hybrid_tuner_release_state(priv); |
1238 | } | ||
1216 | 1239 | ||
1217 | mutex_unlock(&xc5000_list_mutex); | 1240 | mutex_unlock(&xc5000_list_mutex); |
1218 | 1241 | ||
@@ -1284,6 +1307,8 @@ struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe, | |||
1284 | /* new tuner instance */ | 1307 | /* new tuner instance */ |
1285 | priv->bandwidth = 6000000; | 1308 | priv->bandwidth = 6000000; |
1286 | fe->tuner_priv = priv; | 1309 | fe->tuner_priv = priv; |
1310 | priv->fe = fe; | ||
1311 | INIT_DELAYED_WORK(&priv->timer_sleep, xc5000_do_timer_sleep); | ||
1287 | break; | 1312 | break; |
1288 | default: | 1313 | default: |
1289 | /* existing tuner instance */ | 1314 | /* existing tuner instance */ |