Commit 06bae122 authored by Antti Palosaari's avatar Antti Palosaari Committed by Mauro Carvalho Chehab

[media] dvb_frontend: implement suspend / resume

Move initial suspend / resume support from dvb_usb_v2 to dvb_frontend
as it is dvb general feature that could be used all dvb devices.
Signed-off-by: default avatarAntti Palosaari <crope@iki.fi>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 0898b954
...@@ -307,15 +307,6 @@ void dvb_frontend_reinitialise(struct dvb_frontend *fe) ...@@ -307,15 +307,6 @@ void dvb_frontend_reinitialise(struct dvb_frontend *fe)
} }
EXPORT_SYMBOL(dvb_frontend_reinitialise); EXPORT_SYMBOL(dvb_frontend_reinitialise);
void dvb_frontend_retune(struct dvb_frontend *fe)
{
struct dvb_frontend_private *fepriv = fe->frontend_priv;
fepriv->state = FESTATE_RETUNE;
dvb_frontend_wakeup(fe);
}
EXPORT_SYMBOL(dvb_frontend_retune);
static void dvb_frontend_swzigzag_update_delay(struct dvb_frontend_private *fepriv, int locked) static void dvb_frontend_swzigzag_update_delay(struct dvb_frontend_private *fepriv, int locked)
{ {
int q2; int q2;
...@@ -2448,6 +2439,44 @@ static const struct file_operations dvb_frontend_fops = { ...@@ -2448,6 +2439,44 @@ static const struct file_operations dvb_frontend_fops = {
.llseek = noop_llseek, .llseek = noop_llseek,
}; };
int dvb_frontend_suspend(struct dvb_frontend *fe)
{
int ret = 0;
dev_dbg(fe->dvb->device, "%s: adap=%d fe=%d\n", __func__, fe->dvb->num,
fe->id);
if (fe->ops.tuner_ops.sleep)
ret = fe->ops.tuner_ops.sleep(fe);
if (fe->ops.sleep)
ret = fe->ops.sleep(fe);
return ret;
}
EXPORT_SYMBOL(dvb_frontend_suspend);
int dvb_frontend_resume(struct dvb_frontend *fe)
{
struct dvb_frontend_private *fepriv = fe->frontend_priv;
int ret = 0;
dev_dbg(fe->dvb->device, "%s: adap=%d fe=%d\n", __func__, fe->dvb->num,
fe->id);
if (fe->ops.init)
ret = fe->ops.init(fe);
if (fe->ops.tuner_ops.init)
ret = fe->ops.tuner_ops.init(fe);
fepriv->state = FESTATE_RETUNE;
dvb_frontend_wakeup(fe);
return ret;
}
EXPORT_SYMBOL(dvb_frontend_resume);
int dvb_register_frontend(struct dvb_adapter* dvb, int dvb_register_frontend(struct dvb_adapter* dvb,
struct dvb_frontend* fe) struct dvb_frontend* fe)
{ {
......
...@@ -418,7 +418,8 @@ extern int dvb_unregister_frontend(struct dvb_frontend *fe); ...@@ -418,7 +418,8 @@ extern int dvb_unregister_frontend(struct dvb_frontend *fe);
extern void dvb_frontend_detach(struct dvb_frontend *fe); extern void dvb_frontend_detach(struct dvb_frontend *fe);
extern void dvb_frontend_reinitialise(struct dvb_frontend *fe); extern void dvb_frontend_reinitialise(struct dvb_frontend *fe);
extern void dvb_frontend_retune(struct dvb_frontend *fe); extern int dvb_frontend_suspend(struct dvb_frontend *fe);
extern int dvb_frontend_resume(struct dvb_frontend *fe);
extern void dvb_frontend_sleep_until(struct timeval *waketime, u32 add_usec); extern void dvb_frontend_sleep_until(struct timeval *waketime, u32 add_usec);
extern s32 timeval_usec_diff(struct timeval lasttime, struct timeval curtime); extern s32 timeval_usec_diff(struct timeval lasttime, struct timeval curtime);
......
...@@ -295,6 +295,7 @@ struct usb_data_stream { ...@@ -295,6 +295,7 @@ struct usb_data_stream {
* @stream: adapter the usb data stream * @stream: adapter the usb data stream
* @id: index of this adapter (starting with 0) * @id: index of this adapter (starting with 0)
* @ts_type: transport stream, input stream, type * @ts_type: transport stream, input stream, type
* @suspend_resume_active: set when there is ongoing suspend / resume
* @pid_filtering: is hardware pid_filtering used or not * @pid_filtering: is hardware pid_filtering used or not
* @feed_count: current feed count * @feed_count: current feed count
* @max_feed_count: maimum feed count device can handle * @max_feed_count: maimum feed count device can handle
...@@ -312,6 +313,7 @@ struct dvb_usb_adapter { ...@@ -312,6 +313,7 @@ struct dvb_usb_adapter {
struct usb_data_stream stream; struct usb_data_stream stream;
u8 id; u8 id;
u8 ts_type; u8 ts_type;
bool suspend_resume_active;
bool pid_filtering; bool pid_filtering;
u8 feed_count; u8 feed_count;
u8 max_feed_count; u8 max_feed_count;
...@@ -381,6 +383,7 @@ extern int dvb_usbv2_probe(struct usb_interface *, ...@@ -381,6 +383,7 @@ extern int dvb_usbv2_probe(struct usb_interface *,
extern void dvb_usbv2_disconnect(struct usb_interface *); extern void dvb_usbv2_disconnect(struct usb_interface *);
extern int dvb_usbv2_suspend(struct usb_interface *, pm_message_t); extern int dvb_usbv2_suspend(struct usb_interface *, pm_message_t);
extern int dvb_usbv2_resume(struct usb_interface *); extern int dvb_usbv2_resume(struct usb_interface *);
#define dvb_usbv2_reset_resume dvb_usbv2_resume
/* the generic read/write method for device control */ /* the generic read/write method for device control */
extern int dvb_usbv2_generic_rw(struct dvb_usb_device *, u8 *, u16, u8 *, u16); extern int dvb_usbv2_generic_rw(struct dvb_usb_device *, u8 *, u16, u8 *, u16);
......
...@@ -489,6 +489,11 @@ static int dvb_usb_fe_init(struct dvb_frontend *fe) ...@@ -489,6 +489,11 @@ static int dvb_usb_fe_init(struct dvb_frontend *fe)
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);
if (!adap->suspend_resume_active) {
adap->active_fe = fe->id;
mutex_lock(&adap->sync_mutex);
}
ret = dvb_usbv2_device_power_ctrl(d, 1); ret = dvb_usbv2_device_power_ctrl(d, 1);
if (ret < 0) if (ret < 0)
goto err; goto err;
...@@ -504,23 +509,11 @@ static int dvb_usb_fe_init(struct dvb_frontend *fe) ...@@ -504,23 +509,11 @@ static int dvb_usb_fe_init(struct dvb_frontend *fe)
if (ret < 0) if (ret < 0)
goto err; goto err;
} }
return 0;
err: err:
dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); if (!adap->suspend_resume_active)
return ret; mutex_unlock(&adap->sync_mutex);
}
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); dev_dbg(&d->udev->dev, "%s: ret=%d\n", __func__, ret);
return ret; return ret;
} }
...@@ -532,6 +525,9 @@ static int dvb_usb_fe_sleep(struct dvb_frontend *fe) ...@@ -532,6 +525,9 @@ static int dvb_usb_fe_sleep(struct dvb_frontend *fe)
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);
if (!adap->suspend_resume_active)
mutex_lock(&adap->sync_mutex);
if (adap->fe_sleep[fe->id]) { if (adap->fe_sleep[fe->id]) {
ret = adap->fe_sleep[fe->id](fe); ret = adap->fe_sleep[fe->id](fe);
if (ret < 0) if (ret < 0)
...@@ -547,23 +543,13 @@ static int dvb_usb_fe_sleep(struct dvb_frontend *fe) ...@@ -547,23 +543,13 @@ static int dvb_usb_fe_sleep(struct dvb_frontend *fe)
ret = dvb_usbv2_device_power_ctrl(d, 0); ret = dvb_usbv2_device_power_ctrl(d, 0);
if (ret < 0) if (ret < 0)
goto err; goto err;
return 0;
err: err:
dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); if (!adap->suspend_resume_active) {
return ret; adap->active_fe = -1;
} mutex_unlock(&adap->sync_mutex);
}
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); dev_dbg(&d->udev->dev, "%s: ret=%d\n", __func__, ret);
return ret; return ret;
} }
...@@ -594,9 +580,9 @@ int dvb_usbv2_adapter_frontend_init(struct dvb_usb_adapter *adap) ...@@ -594,9 +580,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_lock; adap->fe[i]->ops.init = dvb_usb_fe_init;
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_lock; adap->fe[i]->ops.sleep = dvb_usb_fe_sleep;
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) {
...@@ -978,6 +964,7 @@ int dvb_usbv2_suspend(struct usb_interface *intf, pm_message_t msg) ...@@ -978,6 +964,7 @@ int dvb_usbv2_suspend(struct usb_interface *intf, pm_message_t msg)
active_fe = d->adapter[i].active_fe; active_fe = d->adapter[i].active_fe;
if (d->adapter[i].dvb_adap.priv && active_fe != -1) { if (d->adapter[i].dvb_adap.priv && active_fe != -1) {
fe = d->adapter[i].fe[active_fe]; fe = d->adapter[i].fe[active_fe];
d->adapter[i].suspend_resume_active = true;
if (d->props->streaming_ctrl) if (d->props->streaming_ctrl)
d->props->streaming_ctrl(fe, 0); d->props->streaming_ctrl(fe, 0);
...@@ -985,10 +972,7 @@ int dvb_usbv2_suspend(struct usb_interface *intf, pm_message_t msg) ...@@ -985,10 +972,7 @@ int dvb_usbv2_suspend(struct usb_interface *intf, pm_message_t msg)
/* stop usb streaming */ /* stop usb streaming */
usb_urb_killv2(&d->adapter[i].stream); usb_urb_killv2(&d->adapter[i].stream);
if (fe->ops.tuner_ops.sleep) dvb_frontend_suspend(fe);
fe->ops.tuner_ops.sleep(fe);
dvb_usb_fe_sleep(fe);
} }
} }
...@@ -1008,19 +992,15 @@ int dvb_usbv2_resume(struct usb_interface *intf) ...@@ -1008,19 +992,15 @@ int dvb_usbv2_resume(struct usb_interface *intf)
if (d->adapter[i].dvb_adap.priv && active_fe != -1) { if (d->adapter[i].dvb_adap.priv && active_fe != -1) {
fe = d->adapter[i].fe[active_fe]; fe = d->adapter[i].fe[active_fe];
dvb_usb_fe_init(fe); dvb_frontend_resume(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 */ /* resume usb streaming */
usb_urb_submitv2(&d->adapter[i].stream, NULL); usb_urb_submitv2(&d->adapter[i].stream, NULL);
if (d->props->streaming_ctrl) if (d->props->streaming_ctrl)
d->props->streaming_ctrl(fe, 1); d->props->streaming_ctrl(fe, 1);
d->adapter[i].suspend_resume_active = false;
} }
} }
......
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