aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
authorAntti Palosaari <crope@iki.fi>2012-08-14 21:21:06 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-08-15 18:18:43 -0400
commit06bae1227aadf51d047f7a75834ed446e56ebae2 (patch)
tree0f8900b4515c07fbadab099c45fbe8342cab3fd2 /drivers/media
parent0898b95409489abd7219f5f7ca675c84656fb94f (diff)
[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>
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/dvb-core/dvb_frontend.c47
-rw-r--r--drivers/media/dvb-core/dvb_frontend.h3
-rw-r--r--drivers/media/usb/dvb-usb-v2/dvb_usb.h3
-rw-r--r--drivers/media/usb/dvb-usb-v2/dvb_usb_core.c66
4 files changed, 66 insertions, 53 deletions
diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c
index 5fb19eae5a82..aa4d4d85dc20 100644
--- a/drivers/media/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb-core/dvb_frontend.c
@@ -307,15 +307,6 @@ void dvb_frontend_reinitialise(struct dvb_frontend *fe)
307} 307}
308EXPORT_SYMBOL(dvb_frontend_reinitialise); 308EXPORT_SYMBOL(dvb_frontend_reinitialise);
309 309
310void dvb_frontend_retune(struct dvb_frontend *fe)
311{
312 struct dvb_frontend_private *fepriv = fe->frontend_priv;
313
314 fepriv->state = FESTATE_RETUNE;
315 dvb_frontend_wakeup(fe);
316}
317EXPORT_SYMBOL(dvb_frontend_retune);
318
319static void dvb_frontend_swzigzag_update_delay(struct dvb_frontend_private *fepriv, int locked) 310static void dvb_frontend_swzigzag_update_delay(struct dvb_frontend_private *fepriv, int locked)
320{ 311{
321 int q2; 312 int q2;
@@ -2448,6 +2439,44 @@ static const struct file_operations dvb_frontend_fops = {
2448 .llseek = noop_llseek, 2439 .llseek = noop_llseek,
2449}; 2440};
2450 2441
2442int dvb_frontend_suspend(struct dvb_frontend *fe)
2443{
2444 int ret = 0;
2445
2446 dev_dbg(fe->dvb->device, "%s: adap=%d fe=%d\n", __func__, fe->dvb->num,
2447 fe->id);
2448
2449 if (fe->ops.tuner_ops.sleep)
2450 ret = fe->ops.tuner_ops.sleep(fe);
2451
2452 if (fe->ops.sleep)
2453 ret = fe->ops.sleep(fe);
2454
2455 return ret;
2456}
2457EXPORT_SYMBOL(dvb_frontend_suspend);
2458
2459int dvb_frontend_resume(struct dvb_frontend *fe)
2460{
2461 struct dvb_frontend_private *fepriv = fe->frontend_priv;
2462 int ret = 0;
2463
2464 dev_dbg(fe->dvb->device, "%s: adap=%d fe=%d\n", __func__, fe->dvb->num,
2465 fe->id);
2466
2467 if (fe->ops.init)
2468 ret = fe->ops.init(fe);
2469
2470 if (fe->ops.tuner_ops.init)
2471 ret = fe->ops.tuner_ops.init(fe);
2472
2473 fepriv->state = FESTATE_RETUNE;
2474 dvb_frontend_wakeup(fe);
2475
2476 return ret;
2477}
2478EXPORT_SYMBOL(dvb_frontend_resume);
2479
2451int dvb_register_frontend(struct dvb_adapter* dvb, 2480int dvb_register_frontend(struct dvb_adapter* dvb,
2452 struct dvb_frontend* fe) 2481 struct dvb_frontend* fe)
2453{ 2482{
diff --git a/drivers/media/dvb-core/dvb_frontend.h b/drivers/media/dvb-core/dvb_frontend.h
index 58f6b4c16b40..db309db79bd6 100644
--- a/drivers/media/dvb-core/dvb_frontend.h
+++ b/drivers/media/dvb-core/dvb_frontend.h
@@ -418,7 +418,8 @@ extern int dvb_unregister_frontend(struct dvb_frontend *fe);
418extern void dvb_frontend_detach(struct dvb_frontend *fe); 418extern void dvb_frontend_detach(struct dvb_frontend *fe);
419 419
420extern void dvb_frontend_reinitialise(struct dvb_frontend *fe); 420extern void dvb_frontend_reinitialise(struct dvb_frontend *fe);
421extern void dvb_frontend_retune(struct dvb_frontend *fe); 421extern int dvb_frontend_suspend(struct dvb_frontend *fe);
422extern int dvb_frontend_resume(struct dvb_frontend *fe);
422 423
423extern void dvb_frontend_sleep_until(struct timeval *waketime, u32 add_usec); 424extern void dvb_frontend_sleep_until(struct timeval *waketime, u32 add_usec);
424extern s32 timeval_usec_diff(struct timeval lasttime, struct timeval curtime); 425extern s32 timeval_usec_diff(struct timeval lasttime, struct timeval curtime);
diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb.h b/drivers/media/usb/dvb-usb-v2/dvb_usb.h
index 79b3b8b6750d..63fc275c6497 100644
--- a/drivers/media/usb/dvb-usb-v2/dvb_usb.h
+++ b/drivers/media/usb/dvb-usb-v2/dvb_usb.h
@@ -295,6 +295,7 @@ struct usb_data_stream {
295 * @stream: adapter the usb data stream 295 * @stream: adapter the usb data stream
296 * @id: index of this adapter (starting with 0) 296 * @id: index of this adapter (starting with 0)
297 * @ts_type: transport stream, input stream, type 297 * @ts_type: transport stream, input stream, type
298 * @suspend_resume_active: set when there is ongoing suspend / resume
298 * @pid_filtering: is hardware pid_filtering used or not 299 * @pid_filtering: is hardware pid_filtering used or not
299 * @feed_count: current feed count 300 * @feed_count: current feed count
300 * @max_feed_count: maimum feed count device can handle 301 * @max_feed_count: maimum feed count device can handle
@@ -312,6 +313,7 @@ struct dvb_usb_adapter {
312 struct usb_data_stream stream; 313 struct usb_data_stream stream;
313 u8 id; 314 u8 id;
314 u8 ts_type; 315 u8 ts_type;
316 bool suspend_resume_active;
315 bool pid_filtering; 317 bool pid_filtering;
316 u8 feed_count; 318 u8 feed_count;
317 u8 max_feed_count; 319 u8 max_feed_count;
@@ -381,6 +383,7 @@ extern int dvb_usbv2_probe(struct usb_interface *,
381extern void dvb_usbv2_disconnect(struct usb_interface *); 383extern void dvb_usbv2_disconnect(struct usb_interface *);
382extern int dvb_usbv2_suspend(struct usb_interface *, pm_message_t); 384extern int dvb_usbv2_suspend(struct usb_interface *, pm_message_t);
383extern int dvb_usbv2_resume(struct usb_interface *); 385extern int dvb_usbv2_resume(struct usb_interface *);
386#define dvb_usbv2_reset_resume dvb_usbv2_resume
384 387
385/* the generic read/write method for device control */ 388/* the generic read/write method for device control */
386extern int dvb_usbv2_generic_rw(struct dvb_usb_device *, u8 *, u16, u8 *, u16); 389extern int dvb_usbv2_generic_rw(struct dvb_usb_device *, u8 *, u16, u8 *, u16);
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 7ce8ffef8aca..a0e70e91834a 100644
--- a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c
+++ b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c
@@ -489,6 +489,11 @@ static int dvb_usb_fe_init(struct dvb_frontend *fe)
489 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,
490 fe->id); 490 fe->id);
491 491
492 if (!adap->suspend_resume_active) {
493 adap->active_fe = fe->id;
494 mutex_lock(&adap->sync_mutex);
495 }
496
492 ret = dvb_usbv2_device_power_ctrl(d, 1); 497 ret = dvb_usbv2_device_power_ctrl(d, 1);
493 if (ret < 0) 498 if (ret < 0)
494 goto err; 499 goto err;
@@ -504,23 +509,11 @@ static int dvb_usb_fe_init(struct dvb_frontend *fe)
504 if (ret < 0) 509 if (ret < 0)
505 goto err; 510 goto err;
506 } 511 }
507
508 return 0;
509err: 512err:
510 dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); 513 if (!adap->suspend_resume_active)
511 return ret; 514 mutex_unlock(&adap->sync_mutex);
512}
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 515
523 mutex_unlock(&adap->sync_mutex); 516 dev_dbg(&d->udev->dev, "%s: ret=%d\n", __func__, ret);
524 return ret; 517 return ret;
525} 518}
526 519
@@ -532,6 +525,9 @@ static int dvb_usb_fe_sleep(struct dvb_frontend *fe)
532 dev_dbg(&d->udev->dev, "%s: adap=%d fe=%d\n", __func__, adap->id, 525 dev_dbg(&d->udev->dev, "%s: adap=%d fe=%d\n", __func__, adap->id,
533 fe->id); 526 fe->id);
534 527
528 if (!adap->suspend_resume_active)
529 mutex_lock(&adap->sync_mutex);
530
535 if (adap->fe_sleep[fe->id]) { 531 if (adap->fe_sleep[fe->id]) {
536 ret = adap->fe_sleep[fe->id](fe); 532 ret = adap->fe_sleep[fe->id](fe);
537 if (ret < 0) 533 if (ret < 0)
@@ -547,23 +543,13 @@ static int dvb_usb_fe_sleep(struct dvb_frontend *fe)
547 ret = dvb_usbv2_device_power_ctrl(d, 0); 543 ret = dvb_usbv2_device_power_ctrl(d, 0);
548 if (ret < 0) 544 if (ret < 0)
549 goto err; 545 goto err;
550
551 return 0;
552err: 546err:
553 dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); 547 if (!adap->suspend_resume_active) {
554 return ret; 548 adap->active_fe = -1;
555} 549 mutex_unlock(&adap->sync_mutex);
556 550 }
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 551
566 mutex_unlock(&adap->sync_mutex); 552 dev_dbg(&d->udev->dev, "%s: ret=%d\n", __func__, ret);
567 return ret; 553 return ret;
568} 554}
569 555
@@ -594,9 +580,9 @@ int dvb_usbv2_adapter_frontend_init(struct dvb_usb_adapter *adap)
594 adap->fe[i]->id = i; 580 adap->fe[i]->id = i;
595 /* re-assign sleep and wakeup functions */ 581 /* re-assign sleep and wakeup functions */
596 adap->fe_init[i] = adap->fe[i]->ops.init; 582 adap->fe_init[i] = adap->fe[i]->ops.init;
597 adap->fe[i]->ops.init = dvb_usb_fe_init_lock; 583 adap->fe[i]->ops.init = dvb_usb_fe_init;
598 adap->fe_sleep[i] = adap->fe[i]->ops.sleep; 584 adap->fe_sleep[i] = adap->fe[i]->ops.sleep;
599 adap->fe[i]->ops.sleep = dvb_usb_fe_sleep_lock; 585 adap->fe[i]->ops.sleep = dvb_usb_fe_sleep;
600 586
601 ret = dvb_register_frontend(&adap->dvb_adap, adap->fe[i]); 587 ret = dvb_register_frontend(&adap->dvb_adap, adap->fe[i]);
602 if (ret < 0) { 588 if (ret < 0) {
@@ -978,6 +964,7 @@ int dvb_usbv2_suspend(struct usb_interface *intf, pm_message_t msg)
978 active_fe = d->adapter[i].active_fe; 964 active_fe = d->adapter[i].active_fe;
979 if (d->adapter[i].dvb_adap.priv && active_fe != -1) { 965 if (d->adapter[i].dvb_adap.priv && active_fe != -1) {
980 fe = d->adapter[i].fe[active_fe]; 966 fe = d->adapter[i].fe[active_fe];
967 d->adapter[i].suspend_resume_active = true;
981 968
982 if (d->props->streaming_ctrl) 969 if (d->props->streaming_ctrl)
983 d->props->streaming_ctrl(fe, 0); 970 d->props->streaming_ctrl(fe, 0);
@@ -985,10 +972,7 @@ int dvb_usbv2_suspend(struct usb_interface *intf, pm_message_t msg)
985 /* stop usb streaming */ 972 /* stop usb streaming */
986 usb_urb_killv2(&d->adapter[i].stream); 973 usb_urb_killv2(&d->adapter[i].stream);
987 974
988 if (fe->ops.tuner_ops.sleep) 975 dvb_frontend_suspend(fe);
989 fe->ops.tuner_ops.sleep(fe);
990
991 dvb_usb_fe_sleep(fe);
992 } 976 }
993 } 977 }
994 978
@@ -1008,19 +992,15 @@ int dvb_usbv2_resume(struct usb_interface *intf)
1008 if (d->adapter[i].dvb_adap.priv && active_fe != -1) { 992 if (d->adapter[i].dvb_adap.priv && active_fe != -1) {
1009 fe = d->adapter[i].fe[active_fe]; 993 fe = d->adapter[i].fe[active_fe];
1010 994
1011 dvb_usb_fe_init(fe); 995 dvb_frontend_resume(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 996
1019 /* resume usb streaming */ 997 /* resume usb streaming */
1020 usb_urb_submitv2(&d->adapter[i].stream, NULL); 998 usb_urb_submitv2(&d->adapter[i].stream, NULL);
1021 999
1022 if (d->props->streaming_ctrl) 1000 if (d->props->streaming_ctrl)
1023 d->props->streaming_ctrl(fe, 1); 1001 d->props->streaming_ctrl(fe, 1);
1002
1003 d->adapter[i].suspend_resume_active = false;
1024 } 1004 }
1025 } 1005 }
1026 1006