Commit 0898b954 authored by Antti Palosaari's avatar Antti Palosaari Committed by Mauro Carvalho Chehab

[media] dvb_usb_v2: implement power-management for suspend

Put device full sleep on suspend, wake-up it on resume and acquire
retune in order to return same television channel.
Signed-off-by: default avatarAntti Palosaari <crope@iki.fi>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 6304a60e
...@@ -486,7 +486,6 @@ static int dvb_usb_fe_init(struct dvb_frontend *fe) ...@@ -486,7 +486,6 @@ static int dvb_usb_fe_init(struct dvb_frontend *fe)
int ret; int ret;
struct dvb_usb_adapter *adap = fe->dvb->priv; struct dvb_usb_adapter *adap = fe->dvb->priv;
struct dvb_usb_device *d = adap_to_d(adap); struct dvb_usb_device *d = adap_to_d(adap);
mutex_lock(&adap->sync_mutex);
dev_dbg(&d->udev->dev, "%s: adap=%d fe=%d\n", __func__, adap->id, dev_dbg(&d->udev->dev, "%s: adap=%d fe=%d\n", __func__, adap->id,
fe->id); fe->id);
...@@ -506,22 +505,30 @@ static int dvb_usb_fe_init(struct dvb_frontend *fe) ...@@ -506,22 +505,30 @@ static int dvb_usb_fe_init(struct dvb_frontend *fe)
goto err; goto err;
} }
adap->active_fe = fe->id;
mutex_unlock(&adap->sync_mutex);
return 0; return 0;
err: err:
mutex_unlock(&adap->sync_mutex);
dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
return ret; return ret;
} }
static int dvb_usb_fe_init_lock(struct dvb_frontend *fe)
{
int ret;
struct dvb_usb_adapter *adap = fe->dvb->priv;
mutex_lock(&adap->sync_mutex);
ret = dvb_usb_fe_init(fe);
adap->active_fe = fe->id;
mutex_unlock(&adap->sync_mutex);
return ret;
}
static int dvb_usb_fe_sleep(struct dvb_frontend *fe) static int dvb_usb_fe_sleep(struct dvb_frontend *fe)
{ {
int ret; int ret;
struct dvb_usb_adapter *adap = fe->dvb->priv; struct dvb_usb_adapter *adap = fe->dvb->priv;
struct dvb_usb_device *d = adap_to_d(adap); struct dvb_usb_device *d = adap_to_d(adap);
mutex_lock(&adap->sync_mutex);
dev_dbg(&d->udev->dev, "%s: adap=%d fe=%d\n", __func__, adap->id, dev_dbg(&d->udev->dev, "%s: adap=%d fe=%d\n", __func__, adap->id,
fe->id); fe->id);
...@@ -541,16 +548,25 @@ static int dvb_usb_fe_sleep(struct dvb_frontend *fe) ...@@ -541,16 +548,25 @@ static int dvb_usb_fe_sleep(struct dvb_frontend *fe)
if (ret < 0) if (ret < 0)
goto err; goto err;
adap->active_fe = -1;
mutex_unlock(&adap->sync_mutex);
return 0; return 0;
err: err:
mutex_unlock(&adap->sync_mutex);
dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
return ret; return ret;
} }
static int dvb_usb_fe_sleep_lock(struct dvb_frontend *fe)
{
int ret;
struct dvb_usb_adapter *adap = fe->dvb->priv;
mutex_lock(&adap->sync_mutex);
ret = dvb_usb_fe_sleep(fe);
adap->active_fe = -1;
mutex_unlock(&adap->sync_mutex);
return ret;
}
int dvb_usbv2_adapter_frontend_init(struct dvb_usb_adapter *adap) int dvb_usbv2_adapter_frontend_init(struct dvb_usb_adapter *adap)
{ {
int ret, i, count_registered = 0; int ret, i, count_registered = 0;
...@@ -578,9 +594,9 @@ int dvb_usbv2_adapter_frontend_init(struct dvb_usb_adapter *adap) ...@@ -578,9 +594,9 @@ int dvb_usbv2_adapter_frontend_init(struct dvb_usb_adapter *adap)
adap->fe[i]->id = i; adap->fe[i]->id = i;
/* re-assign sleep and wakeup functions */ /* re-assign sleep and wakeup functions */
adap->fe_init[i] = adap->fe[i]->ops.init; adap->fe_init[i] = adap->fe[i]->ops.init;
adap->fe[i]->ops.init = dvb_usb_fe_init; adap->fe[i]->ops.init = dvb_usb_fe_init_lock;
adap->fe_sleep[i] = adap->fe[i]->ops.sleep; adap->fe_sleep[i] = adap->fe[i]->ops.sleep;
adap->fe[i]->ops.sleep = dvb_usb_fe_sleep; adap->fe[i]->ops.sleep = dvb_usb_fe_sleep_lock;
ret = dvb_register_frontend(&adap->dvb_adap, adap->fe[i]); ret = dvb_register_frontend(&adap->dvb_adap, adap->fe[i]);
if (ret < 0) { if (ret < 0) {
...@@ -950,18 +966,30 @@ EXPORT_SYMBOL(dvb_usbv2_disconnect); ...@@ -950,18 +966,30 @@ EXPORT_SYMBOL(dvb_usbv2_disconnect);
int dvb_usbv2_suspend(struct usb_interface *intf, pm_message_t msg) int dvb_usbv2_suspend(struct usb_interface *intf, pm_message_t msg)
{ {
struct dvb_usb_device *d = usb_get_intfdata(intf); struct dvb_usb_device *d = usb_get_intfdata(intf);
int i; int i, active_fe;
struct dvb_frontend *fe;
dev_dbg(&d->udev->dev, "%s:\n", __func__); dev_dbg(&d->udev->dev, "%s:\n", __func__);
/* stop remote controller poll */ /* stop remote controller poll */
if (d->rc.query && !d->rc.bulk_mode) if (d->rc.query && !d->rc.bulk_mode)
cancel_delayed_work_sync(&d->rc_query_work); cancel_delayed_work_sync(&d->rc_query_work);
/* stop streaming */
for (i = MAX_NO_OF_ADAPTER_PER_DEVICE - 1; i >= 0; i--) { for (i = MAX_NO_OF_ADAPTER_PER_DEVICE - 1; i >= 0; i--) {
if (d->adapter[i].dvb_adap.priv && active_fe = d->adapter[i].active_fe;
d->adapter[i].active_fe != -1) if (d->adapter[i].dvb_adap.priv && active_fe != -1) {
fe = d->adapter[i].fe[active_fe];
if (d->props->streaming_ctrl)
d->props->streaming_ctrl(fe, 0);
/* stop usb streaming */
usb_urb_killv2(&d->adapter[i].stream); usb_urb_killv2(&d->adapter[i].stream);
if (fe->ops.tuner_ops.sleep)
fe->ops.tuner_ops.sleep(fe);
dvb_usb_fe_sleep(fe);
}
} }
return 0; return 0;
...@@ -971,14 +999,29 @@ EXPORT_SYMBOL(dvb_usbv2_suspend); ...@@ -971,14 +999,29 @@ EXPORT_SYMBOL(dvb_usbv2_suspend);
int dvb_usbv2_resume(struct usb_interface *intf) int dvb_usbv2_resume(struct usb_interface *intf)
{ {
struct dvb_usb_device *d = usb_get_intfdata(intf); struct dvb_usb_device *d = usb_get_intfdata(intf);
int i; int i, active_fe;
struct dvb_frontend *fe;
dev_dbg(&d->udev->dev, "%s:\n", __func__); dev_dbg(&d->udev->dev, "%s:\n", __func__);
/* start streaming */
for (i = 0; i < MAX_NO_OF_ADAPTER_PER_DEVICE; i++) { for (i = 0; i < MAX_NO_OF_ADAPTER_PER_DEVICE; i++) {
if (d->adapter[i].dvb_adap.priv && active_fe = d->adapter[i].active_fe;
d->adapter[i].active_fe != -1) if (d->adapter[i].dvb_adap.priv && active_fe != -1) {
fe = d->adapter[i].fe[active_fe];
dvb_usb_fe_init(fe);
if (fe->ops.tuner_ops.init)
fe->ops.tuner_ops.init(fe);
/* acquire dvb-core perform retune */
dvb_frontend_retune(fe);
/* resume usb streaming */
usb_urb_submitv2(&d->adapter[i].stream, NULL); usb_urb_submitv2(&d->adapter[i].stream, NULL);
if (d->props->streaming_ctrl)
d->props->streaming_ctrl(fe, 1);
}
} }
/* start remote controller poll */ /* start remote controller poll */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment