diff options
author | Antti Palosaari <crope@iki.fi> | 2012-08-14 21:21:06 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-08-15 18:18:43 -0400 |
commit | 06bae1227aadf51d047f7a75834ed446e56ebae2 (patch) | |
tree | 0f8900b4515c07fbadab099c45fbe8342cab3fd2 /drivers/media | |
parent | 0898b95409489abd7219f5f7ca675c84656fb94f (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.c | 47 | ||||
-rw-r--r-- | drivers/media/dvb-core/dvb_frontend.h | 3 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/dvb_usb.h | 3 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/dvb_usb_core.c | 66 |
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 | } |
308 | EXPORT_SYMBOL(dvb_frontend_reinitialise); | 308 | EXPORT_SYMBOL(dvb_frontend_reinitialise); |
309 | 309 | ||
310 | void 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 | } | ||
317 | EXPORT_SYMBOL(dvb_frontend_retune); | ||
318 | |||
319 | static void dvb_frontend_swzigzag_update_delay(struct dvb_frontend_private *fepriv, int locked) | 310 | static 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 | ||
2442 | int 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 | } | ||
2457 | EXPORT_SYMBOL(dvb_frontend_suspend); | ||
2458 | |||
2459 | int 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 | } | ||
2478 | EXPORT_SYMBOL(dvb_frontend_resume); | ||
2479 | |||
2451 | int dvb_register_frontend(struct dvb_adapter* dvb, | 2480 | int 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); | |||
418 | extern void dvb_frontend_detach(struct dvb_frontend *fe); | 418 | extern void dvb_frontend_detach(struct dvb_frontend *fe); |
419 | 419 | ||
420 | extern void dvb_frontend_reinitialise(struct dvb_frontend *fe); | 420 | extern void dvb_frontend_reinitialise(struct dvb_frontend *fe); |
421 | extern void dvb_frontend_retune(struct dvb_frontend *fe); | 421 | extern int dvb_frontend_suspend(struct dvb_frontend *fe); |
422 | extern int dvb_frontend_resume(struct dvb_frontend *fe); | ||
422 | 423 | ||
423 | extern void dvb_frontend_sleep_until(struct timeval *waketime, u32 add_usec); | 424 | extern void dvb_frontend_sleep_until(struct timeval *waketime, u32 add_usec); |
424 | extern s32 timeval_usec_diff(struct timeval lasttime, struct timeval curtime); | 425 | extern 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 *, | |||
381 | extern void dvb_usbv2_disconnect(struct usb_interface *); | 383 | extern void dvb_usbv2_disconnect(struct usb_interface *); |
382 | extern int dvb_usbv2_suspend(struct usb_interface *, pm_message_t); | 384 | extern int dvb_usbv2_suspend(struct usb_interface *, pm_message_t); |
383 | extern int dvb_usbv2_resume(struct usb_interface *); | 385 | extern 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 */ |
386 | extern int dvb_usbv2_generic_rw(struct dvb_usb_device *, u8 *, u16, u8 *, u16); | 389 | extern 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; | ||
509 | err: | 512 | err: |
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 | |||
514 | static 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; | ||
552 | err: | 546 | err: |
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 | } | |
557 | static 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 | ||