aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
authorAntti Palosaari <crope@iki.fi>2012-08-14 21:21:05 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-08-15 18:17:02 -0400
commit0898b95409489abd7219f5f7ca675c84656fb94f (patch)
tree59d9b3909dde1641ca7dd71e8032b27064dc094e /drivers/media
parent6304a60eb891137cfc20047263073a5d087e2f69 (diff)
[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: Antti Palosaari <crope@iki.fi> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/usb/dvb-usb-v2/dvb_usb_core.c83
1 files changed, 63 insertions, 20 deletions
diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c
index a72f9c7de68..7ce8ffef8ac 100644
--- a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c
+++ b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c
@@ -486,7 +486,6 @@ static int dvb_usb_fe_init(struct dvb_frontend *fe)
486 int ret; 486 int ret;
487 struct dvb_usb_adapter *adap = fe->dvb->priv; 487 struct dvb_usb_adapter *adap = fe->dvb->priv;
488 struct dvb_usb_device *d = adap_to_d(adap); 488 struct dvb_usb_device *d = adap_to_d(adap);
489 mutex_lock(&adap->sync_mutex);
490 dev_dbg(&d->udev->dev, "%s: adap=%d fe=%d\n", __func__, adap->id, 489 dev_dbg(&d->udev->dev, "%s: adap=%d fe=%d\n", __func__, adap->id,
491 fe->id); 490 fe->id);
492 491
@@ -506,22 +505,30 @@ static int dvb_usb_fe_init(struct dvb_frontend *fe)
506 goto err; 505 goto err;
507 } 506 }
508 507
509 adap->active_fe = fe->id;
510 mutex_unlock(&adap->sync_mutex);
511
512 return 0; 508 return 0;
513err: 509err:
514 mutex_unlock(&adap->sync_mutex);
515 dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); 510 dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
516 return ret; 511 return ret;
517} 512}
518 513
514static int dvb_usb_fe_init_lock(struct dvb_frontend *fe)
515{
516 int ret;
517 struct dvb_usb_adapter *adap = fe->dvb->priv;
518 mutex_lock(&adap->sync_mutex);
519
520 ret = dvb_usb_fe_init(fe);
521 adap->active_fe = fe->id;
522
523 mutex_unlock(&adap->sync_mutex);
524 return ret;
525}
526
519static int dvb_usb_fe_sleep(struct dvb_frontend *fe) 527static int dvb_usb_fe_sleep(struct dvb_frontend *fe)
520{ 528{
521 int ret; 529 int ret;
522 struct dvb_usb_adapter *adap = fe->dvb->priv; 530 struct dvb_usb_adapter *adap = fe->dvb->priv;
523 struct dvb_usb_device *d = adap_to_d(adap); 531 struct dvb_usb_device *d = adap_to_d(adap);
524 mutex_lock(&adap->sync_mutex);
525 dev_dbg(&d->udev->dev, "%s: adap=%d fe=%d\n", __func__, adap->id, 532 dev_dbg(&d->udev->dev, "%s: adap=%d fe=%d\n", __func__, adap->id,
526 fe->id); 533 fe->id);
527 534
@@ -541,16 +548,25 @@ static int dvb_usb_fe_sleep(struct dvb_frontend *fe)
541 if (ret < 0) 548 if (ret < 0)
542 goto err; 549 goto err;
543 550
544 adap->active_fe = -1;
545 mutex_unlock(&adap->sync_mutex);
546
547 return 0; 551 return 0;
548err: 552err:
549 mutex_unlock(&adap->sync_mutex);
550 dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); 553 dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
551 return ret; 554 return ret;
552} 555}
553 556
557static int dvb_usb_fe_sleep_lock(struct dvb_frontend *fe)
558{
559 int ret;
560 struct dvb_usb_adapter *adap = fe->dvb->priv;
561 mutex_lock(&adap->sync_mutex);
562
563 ret = dvb_usb_fe_sleep(fe);
564 adap->active_fe = -1;
565
566 mutex_unlock(&adap->sync_mutex);
567 return ret;
568}
569
554int dvb_usbv2_adapter_frontend_init(struct dvb_usb_adapter *adap) 570int dvb_usbv2_adapter_frontend_init(struct dvb_usb_adapter *adap)
555{ 571{
556 int ret, i, count_registered = 0; 572 int ret, i, count_registered = 0;
@@ -578,9 +594,9 @@ int dvb_usbv2_adapter_frontend_init(struct dvb_usb_adapter *adap)
578 adap->fe[i]->id = i; 594 adap->fe[i]->id = i;
579 /* re-assign sleep and wakeup functions */ 595 /* re-assign sleep and wakeup functions */
580 adap->fe_init[i] = adap->fe[i]->ops.init; 596 adap->fe_init[i] = adap->fe[i]->ops.init;
581 adap->fe[i]->ops.init = dvb_usb_fe_init; 597 adap->fe[i]->ops.init = dvb_usb_fe_init_lock;
582 adap->fe_sleep[i] = adap->fe[i]->ops.sleep; 598 adap->fe_sleep[i] = adap->fe[i]->ops.sleep;
583 adap->fe[i]->ops.sleep = dvb_usb_fe_sleep; 599 adap->fe[i]->ops.sleep = dvb_usb_fe_sleep_lock;
584 600
585 ret = dvb_register_frontend(&adap->dvb_adap, adap->fe[i]); 601 ret = dvb_register_frontend(&adap->dvb_adap, adap->fe[i]);
586 if (ret < 0) { 602 if (ret < 0) {
@@ -950,18 +966,30 @@ EXPORT_SYMBOL(dvb_usbv2_disconnect);
950int dvb_usbv2_suspend(struct usb_interface *intf, pm_message_t msg) 966int dvb_usbv2_suspend(struct usb_interface *intf, pm_message_t msg)
951{ 967{
952 struct dvb_usb_device *d = usb_get_intfdata(intf); 968 struct dvb_usb_device *d = usb_get_intfdata(intf);
953 int i; 969 int i, active_fe;
970 struct dvb_frontend *fe;
954 dev_dbg(&d->udev->dev, "%s:\n", __func__); 971 dev_dbg(&d->udev->dev, "%s:\n", __func__);
955 972
956 /* stop remote controller poll */ 973 /* stop remote controller poll */
957 if (d->rc.query && !d->rc.bulk_mode) 974 if (d->rc.query && !d->rc.bulk_mode)
958 cancel_delayed_work_sync(&d->rc_query_work); 975 cancel_delayed_work_sync(&d->rc_query_work);
959 976
960 /* stop streaming */
961 for (i = MAX_NO_OF_ADAPTER_PER_DEVICE - 1; i >= 0; i--) { 977 for (i = MAX_NO_OF_ADAPTER_PER_DEVICE - 1; i >= 0; i--) {
962 if (d->adapter[i].dvb_adap.priv && 978 active_fe = d->adapter[i].active_fe;
963 d->adapter[i].active_fe != -1) 979 if (d->adapter[i].dvb_adap.priv && active_fe != -1) {
980 fe = d->adapter[i].fe[active_fe];
981
982 if (d->props->streaming_ctrl)
983 d->props->streaming_ctrl(fe, 0);
984
985 /* stop usb streaming */
964 usb_urb_killv2(&d->adapter[i].stream); 986 usb_urb_killv2(&d->adapter[i].stream);
987
988 if (fe->ops.tuner_ops.sleep)
989 fe->ops.tuner_ops.sleep(fe);
990
991 dvb_usb_fe_sleep(fe);
992 }
965 } 993 }
966 994
967 return 0; 995 return 0;
@@ -971,14 +999,29 @@ EXPORT_SYMBOL(dvb_usbv2_suspend);
971int dvb_usbv2_resume(struct usb_interface *intf) 999int dvb_usbv2_resume(struct usb_interface *intf)
972{ 1000{
973 struct dvb_usb_device *d = usb_get_intfdata(intf); 1001 struct dvb_usb_device *d = usb_get_intfdata(intf);
974 int i; 1002 int i, active_fe;
1003 struct dvb_frontend *fe;
975 dev_dbg(&d->udev->dev, "%s:\n", __func__); 1004 dev_dbg(&d->udev->dev, "%s:\n", __func__);
976 1005
977 /* start streaming */
978 for (i = 0; i < MAX_NO_OF_ADAPTER_PER_DEVICE; i++) { 1006 for (i = 0; i < MAX_NO_OF_ADAPTER_PER_DEVICE; i++) {
979 if (d->adapter[i].dvb_adap.priv && 1007 active_fe = d->adapter[i].active_fe;
980 d->adapter[i].active_fe != -1) 1008 if (d->adapter[i].dvb_adap.priv && active_fe != -1) {
1009 fe = d->adapter[i].fe[active_fe];
1010
1011 dvb_usb_fe_init(fe);
1012
1013 if (fe->ops.tuner_ops.init)
1014 fe->ops.tuner_ops.init(fe);
1015
1016 /* acquire dvb-core perform retune */
1017 dvb_frontend_retune(fe);
1018
1019 /* resume usb streaming */
981 usb_urb_submitv2(&d->adapter[i].stream, NULL); 1020 usb_urb_submitv2(&d->adapter[i].stream, NULL);
1021
1022 if (d->props->streaming_ctrl)
1023 d->props->streaming_ctrl(fe, 1);
1024 }
982 } 1025 }
983 1026
984 /* start remote controller poll */ 1027 /* start remote controller poll */