Skip to content

Commit f7a27ff

Browse files
committed
[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>
1 parent 5015c27 commit f7a27ff

File tree

1 file changed

+34
-9
lines changed

1 file changed

+34
-9
lines changed

drivers/media/tuners/xc5000.c

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <linux/moduleparam.h>
2626
#include <linux/videodev2.h>
2727
#include <linux/delay.h>
28+
#include <linux/workqueue.h>
2829
#include <linux/dvb/frontend.h>
2930
#include <linux/i2c.h>
3031

@@ -65,12 +66,18 @@ struct xc5000_priv {
6566
u16 pll_register_no;
6667
u8 init_status_supported;
6768
u8 fw_checksum_supported;
69+
70+
struct dvb_frontend *fe;
71+
struct delayed_work timer_sleep;
6872
};
6973

7074
/* Misc Defines */
7175
#define MAX_TV_STANDARD 24
7276
#define XC_MAX_I2C_WRITE_LENGTH 64
7377

78+
/* Time to suspend after the .sleep callback is called */
79+
#define XC5000_SLEEP_TIME 5000 /* ms */
80+
7481
/* Signal Types */
7582
#define XC_RF_MODE_AIR 0
7683
#define XC_RF_MODE_CABLE 1
@@ -1096,6 +1103,8 @@ static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe, int force)
10961103
u16 pll_lock_status;
10971104
u16 fw_ck;
10981105

1106+
cancel_delayed_work(&priv->timer_sleep);
1107+
10991108
if (force || xc5000_is_firmware_loaded(fe) != 0) {
11001109

11011110
fw_retry:
@@ -1164,27 +1173,39 @@ static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe, int force)
11641173
return ret;
11651174
}
11661175

1167-
static int xc5000_sleep(struct dvb_frontend *fe)
1176+
static void xc5000_do_timer_sleep(struct work_struct *timer_sleep)
11681177
{
1178+
struct xc5000_priv *priv =container_of(timer_sleep, struct xc5000_priv,
1179+
timer_sleep.work);
1180+
struct dvb_frontend *fe = priv->fe;
11691181
int ret;
11701182

11711183
dprintk(1, "%s()\n", __func__);
11721184

1173-
/* Avoid firmware reload on slow devices */
1174-
if (no_poweroff)
1175-
return 0;
1176-
11771185
/* According to Xceive technical support, the "powerdown" register
11781186
was removed in newer versions of the firmware. The "supported"
11791187
way to sleep the tuner is to pull the reset pin low for 10ms */
11801188
ret = xc5000_tuner_reset(fe);
1181-
if (ret != 0) {
1189+
if (ret != 0)
11821190
printk(KERN_ERR
11831191
"xc5000: %s() unable to shutdown tuner\n",
11841192
__func__);
1185-
return -EREMOTEIO;
1186-
} else
1193+
}
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)
11871203
return 0;
1204+
1205+
schedule_delayed_work(&priv->timer_sleep,
1206+
msecs_to_jiffies(XC5000_SLEEP_TIME));
1207+
1208+
return 0;
11881209
}
11891210

11901211
static int xc5000_init(struct dvb_frontend *fe)
@@ -1211,8 +1232,10 @@ static int xc5000_release(struct dvb_frontend *fe)
12111232

12121233
mutex_lock(&xc5000_list_mutex);
12131234

1214-
if (priv)
1235+
if (priv) {
1236+
cancel_delayed_work(&priv->timer_sleep);
12151237
hybrid_tuner_release_state(priv);
1238+
}
12161239

12171240
mutex_unlock(&xc5000_list_mutex);
12181241

@@ -1284,6 +1307,8 @@ struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe,
12841307
/* new tuner instance */
12851308
priv->bandwidth = 6000000;
12861309
fe->tuner_priv = priv;
1310+
priv->fe = fe;
1311+
INIT_DELAYED_WORK(&priv->timer_sleep, xc5000_do_timer_sleep);
12871312
break;
12881313
default:
12891314
/* existing tuner instance */

0 commit comments

Comments
 (0)