[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: Antti Palosaari <crope@iki.fi> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
parent
0898b95409
commit
06bae1227a
@ -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 = {
|
|||||||
.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);
|
|||||||
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 {
|
|||||||
* @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 {
|
|||||||
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 *,
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
dev_dbg(&d->udev->dev, "%s: ret=%d\n", __func__, ret);
|
||||||
{
|
|
||||||
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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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)
|
|||||||
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)
|
dev_dbg(&d->udev->dev, "%s: ret=%d\n", __func__, ret);
|
||||||
{
|
|
||||||
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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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)
|
|||||||
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)
|
|||||||
/* 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)
|
|||||||
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user