media: em28xx - power management support em28xx
Subsystems (2)
cover media: em28xx - power management support em28xx
Add power management support to em28xx usb driver. This driver works in conjunction with extensions for each of the functions on the USB device for video/audio/dvb/remote functionality that is present on media USB devices it supports. During suspend and resume each of these extensions will have to do their part in suspending the components they control.
Adding suspend and resume hooks to the existing struct em28xx_ops will enable the extensions the ability to implement suspend and resume hooks to be called from em28xx driver. The overall approach is as follows:
-- add suspend and resume hooks to em28xx_ops
-- add suspend and resume routines to em28xx-core to invoke suspend
and resume hooks for all registered extensions.
-- change em28xx dvb, audio, input, and video extensions to implement
em28xx_ops: suspend and resume hooks. These hooks do what is necessary to suspend and resume the devices they control.
Shuah Khan (6):
media: em28xx - add suspend/resume to em28xx_ops
media: em28xx-audio - implement em28xx_ops: suspend/resume hooks
media: em28xx-dvb - implement em28xx_ops: suspend/resume hooks
media: em28xx-input - implement em28xx_ops: suspend/resume hooks
media: em28xx-video - implement em28xx_ops: suspend/resume hooks
media: em28xx - implement em28xx_usb_driver suspend, resume,
reset_resume hooks
drivers/media/usb/em28xx/em28xx-audio.c | 30 +++++++++++++++++ drivers/media/usb/em28xx/em28xx-cards.c | 26 +++++++++++++++ drivers/media/usb/em28xx/em28xx-core.c | 28 ++++++++++++++++ drivers/media/usb/em28xx/em28xx-dvb.c | 57 +++++++++++++++++++++++++++++++++ drivers/media/usb/em28xx/em28xx-input.c | 35 ++++++++++++++++++++ drivers/media/usb/em28xx/em28xx-video.c | 28 ++++++++++++++++ drivers/media/usb/em28xx/em28xx.h | 4 +++ 7 files changed, 208 insertions(+)
Signature · 1 line
1.8.3.2
RFC PATCH 1/6 media: em28xx - add suspend/resume to em28xx_ops
em28xx usb driver will have to suspend and resume its extensions. Adding suspend and resume to em28xx_ops gives extensions the ability to install suspend and resume that can be invoked from em28xx_usb driver suspend() and resume() interfaces.
Approach:
Add power management support to em28xx usb driver. This driver works in conjunction with extensions for each of the functions on the USB device for video/audio/dvb/remote functionality that is present on media USB devices it supports. During suspend and resume each of these extensions will have to do their part in suspending the components they control.
Adding suspend and resume hooks to the existing struct em28xx_ops will enable the extensions the ability to implement suspend and resume hooks to be called from em28xx driver. The overall approach is as follows:
-- add suspend and resume hooks to em28xx_ops
-- add suspend and resume routines to em28xx-core to invoke suspend
and resume hooks for all registered extensions.
-- change em28xx dvb, audio, input, and video extensions to implement
em28xx_ops: suspend and resume hooks. These hooks do what is necessary to suspend and resume the devices they control.
--- drivers/media/usb/em28xx/em28xx-core.c | 28 ++++++++++++++++++++++++++++ drivers/media/usb/em28xx/em28xx.h | 4 ++++ 2 files changed, 32 insertions(+)
drivers/media/usb/em28xx/em28xx-core.c +28 -0
@@ -1106,3 +1106,31 @@ void em28xx_close_extension(struct em28xx *dev)list_del (&dev->devlist);mutex_unlock (&em28xx_devlist_mutex); } + +int em28xx_suspend_extension (struct em28xx *dev) +{ +const struct em28xx_ops *ops =NULL ; + +em28xx_info ("Suspending extensions" ); +mutex_lock (&em28xx_devlist_mutex); +list_for_each_entry (ops, &em28xx_extension_devlist, next) { +if (ops->suspend) + ops->suspend (dev); + } +mutex_unlock (&em28xx_devlist_mutex); +return 0 ; +} + +int em28xx_resume_extension (struct em28xx *dev) +{ +const struct em28xx_ops *ops =NULL ; + +em28xx_info ("Resuming extensions" ); +mutex_lock (&em28xx_devlist_mutex); +list_for_each_entry (ops, &em28xx_extension_devlist, next) { +if (ops->resume) + ops->resume (dev); + } +mutex_unlock (&em28xx_devlist_mutex); +return 0 ; +}
drivers/media/usb/em28xx/em28xx.h +4 -0
@@ -713,6 +713,8 @@ struct em28xx_ops {int id;int (*init)(struct em28xx *);int (*fini)(struct em28xx *); +int (*suspend)(struct em28xx *); +int (*resume)(struct em28xx *); };/* Provided by em28xx-i2c.c */
@@ -758,6 +760,8 @@ int em28xx_register_extension(struct em28xx_ops *dev);void em28xx_unregister_extension (struct em28xx_ops *dev);void em28xx_init_extension (struct em28xx *dev);void em28xx_close_extension (struct em28xx *dev); +int em28xx_suspend_extension (struct em28xx *dev); +int em28xx_resume_extension (struct em28xx *dev);/* Provided by em28xx-cards.c */ extern struct em28xx_board em28xx_boards[];
Signature · 1 line
1.8.3.2
RFC PATCH 2/6 media: em28xx-audio - implement em28xx_ops: suspend/resume hooks
In reply to Shuah KhanImplement em28xx_ops: suspend/resume hooks. em28xx usb driver will invoke em28xx_ops: suspend and resume hooks for all its extensions from its suspend() and resume() interfaces.
--- drivers/media/usb/em28xx/em28xx-audio.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+)
drivers/media/usb/em28xx/em28xx-audio.c +30 -0
@@ -989,11 +989,41 @@ static int em28xx_audio_fini(struct em28xx *dev)return 0 ; } +static int em28xx_audio_suspend (struct em28xx *dev) +{ +if (dev ==NULL ) +return 0 ; + +if (!dev->has_alsa_audio) +return 0 ; + +em28xx_info ("Suspending audio extension" ); +em28xx_deinit_isoc_audio (dev); +atomic_set (&dev->stream_started,0 ); +return 0 ; +} + +static int em28xx_audio_resume (struct em28xx *dev) +{ +if (dev ==NULL ) +return 0 ; + +if (!dev->has_alsa_audio) +return 0 ; + +em28xx_info ("Resuming audio extension" ); +/* Nothing to do other than schedule_work() ?? */ +schedule_work (&dev->wq_trigger); +return 0 ; +} +static struct em28xx_ops audio_ops = { .id =EM28XX_AUDIO , .name ="Em28xx Audio Extension" , .init = em28xx_audio_init, .fini = em28xx_audio_fini, + .suspend = em28xx_audio_suspend, + .resume = em28xx_audio_resume, };static int __init em28xx_alsa_register (void )
Signature · 1 line
1.8.3.2
RFC PATCH 3/6 media: em28xx-dvb - implement em28xx_ops: suspend/resume hooks
In reply to Shuah KhanImplement em28xx_ops: suspend/resume hooks. em28xx usb driver will invoke em28xx_ops: suspend and resume hooks for all its extensions from its suspend() and resume() interfaces.
--- drivers/media/usb/em28xx/em28xx-dvb.c | 57 +++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+)
drivers/media/usb/em28xx/em28xx-dvb.c +57 -0
@@ -1492,11 +1492,68 @@ static int em28xx_dvb_fini(struct em28xx *dev)return 0 ; } +static int em28xx_dvb_suspend (struct em28xx *dev) +{ +int ret =0 ; + +if (dev->is_audio_only) +return 0 ; + +if (!dev->board.has_dvb) +return 0 ; + +em28xx_info ("Suspending DVB extension" ); +if (dev->dvb) { +struct em28xx_dvb *dvb = dev->dvb; + +if (dvb->fe[0 ]) { + ret =dvb_frontend_suspend (dvb->fe[0 ]); +em28xx_info ("fe0 suspend %d" , ret); + } +if (dvb->fe[1 ]) { +dvb_frontend_suspend (dvb->fe[1 ]); +em28xx_info ("fe1 suspend %d" , ret); + } + } + +return 0 ; +} + +static int em28xx_dvb_resume (struct em28xx *dev) +{ +int ret =0 ; + +if (dev->is_audio_only) +return 0 ; + +if (!dev->board.has_dvb) +return 0 ; + +em28xx_info ("Resuming DVB extension" ); +if (dev->dvb) { +struct em28xx_dvb *dvb = dev->dvb; + +if (dvb->fe[0 ]) { + ret =dvb_frontend_resume (dvb->fe[0 ]); +em28xx_info ("fe0 resume %d" , ret); + } + +if (dvb->fe[1 ]) { + ret =dvb_frontend_resume (dvb->fe[1 ]); +em28xx_info ("fe1 resume %d" , ret); + } + } + +return 0 ; +} +static struct em28xx_ops dvb_ops = { .id =EM28XX_DVB , .name ="Em28xx dvb Extension" , .init = em28xx_dvb_init, .fini = em28xx_dvb_fini, + .suspend = em28xx_dvb_suspend, + .resume = em28xx_dvb_resume, };static int __init em28xx_dvb_register (void )
Signature · 1 line
1.8.3.2
RFC PATCH 4/6 media: em28xx-input - implement em28xx_ops: suspend/resume hooks
In reply to Shuah KhanImplement em28xx_ops: suspend/resume hooks. em28xx usb driver will invoke em28xx_ops: suspend and resume hooks for all its extensions from its suspend() and resume() interfaces.
--- drivers/media/usb/em28xx/em28xx-input.c | 35 +++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+)
drivers/media/usb/em28xx/em28xx-input.c +35 -0
@@ -827,11 +827,46 @@ static int em28xx_ir_fini(struct em28xx *dev)return 0 ; } +static int em28xx_ir_suspend (struct em28xx *dev) +{ +struct em28xx_IR *ir = dev->ir; + +if (dev->is_audio_only) +return 0 ; + +em28xx_info ("Suspending input extension" ); +cancel_delayed_work_sync (&ir->work); +cancel_delayed_work_sync (&dev->buttons_query_work); +/* is canceling delayed work sufficient or does the rc event +kthread needs stopping? kthread is stopped in +ir_raw_event_unregister() */ +return 0 ; +} + +static int em28xx_ir_resume (struct em28xx *dev) +{ +struct em28xx_IR *ir = dev->ir; + +if (dev->is_audio_only) +return 0 ; + +em28xx_info ("Resuming input extension" ); +/* if suspend calls ir_raw_event_unregister(), the should call +ir_raw_event_register() */ +schedule_delayed_work_sync (&ir->work); +if (dev->num_button_polling_addresses) +schedule_delayed_work (&dev->buttons_query_work, +msecs_to_jiffies (dev->button_polling_interval)); +return 0 ; +} +static struct em28xx_ops rc_ops = { .id =EM28XX_RC , .name ="Em28xx Input Extension" , .init = em28xx_ir_init, .fini = em28xx_ir_fini, + .suspend = em28xx_ir_suspend, + .resume = em28xx_ir_resume, };static int __init em28xx_rc_register (void )
Signature · 1 line
1.8.3.2
Re: [RFC] [PATCH 4/6] media: em28xx-input - implement em28xx_ops: suspend/resume hooks
Em Fri, 21 Feb 2014 17:50:16 -0700
Shuah Khan <[email protected]> escreveu:
Quoted 34 lines
Implement
em28xx_ops: suspend/resume hooks. em28xx usb driver will invokeem28xx_ops: suspend and resume hooks for all its extensions from itssuspend()andresume()interfaces.Signed-off-by Shuah Khan <[email protected]>--- drivers/media/usb/em28xx/em28xx-input.c | 35 +++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+)drivers/media/usb/em28xx/em28xx-input.c +17
-0@@ -827,11 +827,46 @@ static int em28xx_ir_fini(struct em28xx *dev)return 0 ; } +static int em28xx_ir_suspend (struct em28xx *dev) +{ +struct em28xx_IR *ir = dev->ir; + +if (dev->is_audio_only) +return 0 ; + +em28xx_info ("Suspending input extension" ); +cancel_delayed_work_sync (&ir->work); +cancel_delayed_work_sync (&dev->buttons_query_work); +/* is canceling delayed work sufficient or does the rc event +kthread needs stopping? kthread is stopped in +ir_raw_event_unregister() */ +return 0 ; +} + +static int em28xx_ir_resume (struct em28xx *dev)
drivers/media/usb/em28xx/em28xx-input.c static int em28xx_ir_fini(struct em28xx *dev) · line 856
Quoted 10 lines
drivers/media/usb/em28xx/em28xx-input.c +10
-0+{ +struct em28xx_IR *ir = dev->ir; + +if (dev->is_audio_only) +return 0 ; + +em28xx_info ("Resuming input extension" ); +/* if suspend calls ir_raw_event_unregister(), the should call +ir_raw_event_register() */ +schedule_delayed_work_sync (&ir->work);
This causes a compilation breakage:
drivers/media/usb/em28xx/em28xx-input.c: In function ‘em28xx_ir_resume’:drivers/media/usb/em28xx/em28xx-input.c:856:2: error: implicit declaration of function ‘schedule_delayed_work_sync’ [-Werror=implicit-function-declaration]
schedule_delayed_work_sync(&ir->work);
Quoted 16 lines
drivers/media/usb/em28xx/em28xx-input.c +8
-0+if (dev->num_button_polling_addresses) +schedule_delayed_work (&dev->buttons_query_work, +msecs_to_jiffies (dev->button_polling_interval)); +return 0 ; +} +static struct em28xx_ops rc_ops = { .id =EM28XX_RC , .name ="Em28xx Input Extension" , .init = em28xx_ir_init, .fini = em28xx_ir_fini, + .suspend = em28xx_ir_suspend, + .resume = em28xx_ir_resume, };static int __init em28xx_rc_register (void )
Signature · 2 lines
Cheers, Mauro
Re: [RFC] [PATCH 4/6] media: em28xx-input - implement em28xx_ops: suspend/resume hooks
Em Sat, 01 Mar 2014 10:48:35 -0300
Mauro Carvalho Chehab <[email protected]> escreveu:
Quoted 50 lines
Em Fri, 21 Feb 2014 17:50:16 -0700
Shuah Khan <[email protected]> escreveu:Quoted 34 lines
Implement
em28xx_ops: suspend/resume hooks. em28xx usb driver will invokeem28xx_ops: suspend and resume hooks for all its extensions from itssuspend()andresume()interfaces.Signed-off-by Shuah Khan <[email protected]>--- drivers/media/usb/em28xx/em28xx-input.c | 35 +++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+)drivers/media/usb/em28xx/em28xx-input.c +17
-0@@ -827,11 +827,46 @@ static int em28xx_ir_fini(struct em28xx *dev)return 0 ; } +static int em28xx_ir_suspend (struct em28xx *dev) +{ +struct em28xx_IR *ir = dev->ir; + +if (dev->is_audio_only) +return 0 ; + +em28xx_info ("Suspending input extension" ); +cancel_delayed_work_sync (&ir->work); +cancel_delayed_work_sync (&dev->buttons_query_work); +/* is canceling delayed work sufficient or does the rc event +kthread needs stopping? kthread is stopped in +ir_raw_event_unregister() */ +return 0 ; +} + +static int em28xx_ir_resume (struct em28xx *dev)drivers/media/usb/em28xx/em28xx-input.c static int em28xx_ir_fini(struct em28xx *dev) · line 856
Quoted 10 lines
drivers/media/usb/em28xx/em28xx-input.c +10
-0+{ +struct em28xx_IR *ir = dev->ir; + +if (dev->is_audio_only) +return 0 ; + +em28xx_info ("Resuming input extension" ); +/* if suspend calls ir_raw_event_unregister(), the should call +ir_raw_event_register() */ +schedule_delayed_work_sync (&ir->work);This causes a compilation breakage:
Quoted 4 lines
drivers/media/usb/em28xx/em28xx-input.c: In function ‘em28xx_ir_resume’:drivers/media/usb/em28xx/em28xx-input.c:856:2: error: implicit declaration of function ‘schedule_delayed_work_sync’ [-Werror=implicit-function-declaration]
schedule_delayed_work_sync(&ir->work);
Ok, I reworked it fixing the above compilation bug, and added a test to be sure that IR is enabled before using ir->work.
Patch enclosed.
This series look OK on my eyes with this change, and it worked fine here with PCTV 80e, so I'll be merging it. In any case, this won't cause any regressions, as suspending before those patches on those devices make the machine to hang.
Regards,
Mauro
From: Shuah Khan <[email protected]>
Date: Fri, 21 Feb 2014 21:50:16 -0300
Subject: [PATCH] [media] em28xx-input: implement em28xx_ops: suspend/resume
hooks
Implement em28xx_ops: suspend/resume hooks. em28xx usb driver will invoke em28xx_ops: suspend and resume hooks for all its extensions from its suspend() and resume() interfaces.
[[email protected]: Fix a breakage caused by calling a non-existing
function call: schedule_delayed_work_sync(), and test if IR was defined at suspend/resume]
drivers/media/usb/em28xx/em28xx-input.c +37 -0
@@ -827,11 +827,48 @@ static int em28xx_ir_fini(struct em28xx *dev)return 0 ; } +static int em28xx_ir_suspend (struct em28xx *dev) +{ +struct em28xx_IR *ir = dev->ir; + +if (dev->is_audio_only) +return 0 ; + +em28xx_info ("Suspending input extension" ); +if (ir) +cancel_delayed_work_sync (&ir->work); +cancel_delayed_work_sync (&dev->buttons_query_work); +/* is canceling delayed work sufficient or does the rc event +kthread needs stopping? kthread is stopped in +ir_raw_event_unregister() */ +return 0 ; +} + +static int em28xx_ir_resume (struct em28xx *dev) +{ +struct em28xx_IR *ir = dev->ir; + +if (dev->is_audio_only) +return 0 ; + +em28xx_info ("Resuming input extension" ); +/* if suspend calls ir_raw_event_unregister(), the should call +ir_raw_event_register() */ +if (ir) +schedule_delayed_work (&ir->work,msecs_to_jiffies (ir->polling)); +if (dev->num_button_polling_addresses) +schedule_delayed_work (&dev->buttons_query_work, +msecs_to_jiffies (dev->button_polling_interval)); +return 0 ; +} +static struct em28xx_ops rc_ops = { .id =EM28XX_RC , .name ="Em28xx Input Extension" , .init = em28xx_ir_init, .fini = em28xx_ir_fini, + .suspend = em28xx_ir_suspend, + .resume = em28xx_ir_resume, };static int __init em28xx_rc_register (void )
Signature · 2 lines
Cheers, Mauro
RFC PATCH 5/6 media: em28xx-video - implement em28xx_ops: suspend/resume hooks
In reply to Shuah KhanImplement em28xx_ops: suspend/resume hooks. em28xx usb driver will invoke em28xx_ops: suspend and resume hooks for all its extensions from its suspend() and resume() interfaces.
--- drivers/media/usb/em28xx/em28xx-video.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+)
drivers/media/usb/em28xx/em28xx-video.c +28 -0
@@ -1933,6 +1933,32 @@ static int em28xx_v4l2_fini(struct em28xx *dev)return 0 ; } +static int em28xx_v4l2_suspend (struct em28xx *dev) +{ +if (dev->is_audio_only) +return 0 ; + +if (!dev->has_video) +return 0 ; + +em28xx_info ("Suspending video extension" ); +em28xx_stop_urbs (dev); +return 0 ; +} + +static int em28xx_v4l2_resume (struct em28xx *dev) +{ +if (dev->is_audio_only) +return 0 ; + +if (!dev->has_video) +return 0 ; + +em28xx_info ("Resuming video extension" ); +/* what do we do here */ +return 0 ; +} +/* * em28xx_v4l2_close() * stops streaming and deallocates all resources allocated by the v4l2
@@ -2504,6 +2530,8 @@ static struct em28xx_ops v4l2_ops = { .name = "Em28xx v4l2 Extension", .init = em28xx_v4l2_init, .fini = em28xx_v4l2_fini, + .suspend = em28xx_v4l2_suspend, + .resume = em28xx_v4l2_resume, };static int __init em28xx_video_register (void )
Signature · 1 line
1.8.3.2
RFC PATCH 6/6 media: em28xx - implement em28xx_usb_driver suspend, resume, reset_resume hooks
In reply to Shuah KhanImplement em28xx_usb_driver suspend, resume, and reset_resume hooks. These hooks will invoke em28xx core em28xx_suspend_extension() and em28xx_resume_extension() to suspend and resume registered extensions.
Approach:
Add power management support to em28xx usb driver. This driver works in conjunction with extensions for each of the functions on the USB device for video/audio/dvb/remote functionality that is present on media USB devices it supports. During suspend and resume each of these extensions will have to do their part in suspending the components they control.
Adding suspend and resume hooks to the existing struct em28xx_ops will enable the extensions the ability to implement suspend and resume hooks to be called from em28xx driver. The overall approach is as follows:
-- add suspend and resume hooks to em28xx_ops
-- add suspend and resume routines to em28xx-core to invoke suspend
and resume hooks for all registered extensions.
-- change em28xx dvb, audio, input, and video extensions to implement
em28xx_ops: suspend and resume hooks. These hooks do what is necessary to suspend and resume the devices they control.
--- drivers/media/usb/em28xx/em28xx-cards.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+)
drivers/media/usb/em28xx/em28xx-cards.c +26 -0
@@ -3395,10 +3395,36 @@ static void em28xx_usb_disconnect(struct usb_interface *interface) } } +static int em28xx_usb_suspend (struct usb_interface *interface, +pm_message_t message) +{ +struct em28xx *dev; + + dev =usb_get_intfdata (interface); +if (!dev) +return 0 ; +em28xx_suspend_extension (dev); +return 0 ; +} + +static int em28xx_usb_resume (struct usb_interface *interface) +{ +struct em28xx *dev; + + dev =usb_get_intfdata (interface); +if (!dev) +return 0 ; +em28xx_resume_extension (dev); +return 0 ; +} +static struct usb_driver em28xx_usb_driver = { .name ="em28xx" , .probe = em28xx_usb_probe, .disconnect = em28xx_usb_disconnect, + .suspend = em28xx_usb_suspend, + .resume = em28xx_usb_resume, + .reset_resume = em28xx_usb_resume, .id_table = em28xx_id_table, };
Signature · 1 line
1.8.3.2