diff options
author | Mengdong Lin <mengdong.lin@intel.com> | 2013-11-26 23:32:23 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2013-11-27 06:37:07 -0500 |
commit | 12edb893082b89f4d3af85ab9f4750aa8d3c34f3 (patch) | |
tree | 078aa14e02d8c49a9cb416d711c6fe218be840e9 /sound/pci/hda/hda_codec.c | |
parent | 351892a8278b50f723974ad42ce591aae57b41e7 (diff) |
ALSA: hda - resume codecs in parallel
To reduce driver resume time, this patch resumes the codecs in parallel
if there are multiple codecs on the bus.
- The PM workqueue of bus is also used to parallel resuming multiple codecs.
- The work item 'pm_work' is renamed to 'suspend_work' to parallel suspending
codecs.
- Add a work item 'resume_work' to parallel resuming codecs.
Signed-off-by: Mengdong Lin <mengdong.lin@intel.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/hda/hda_codec.c')
-rw-r--r-- | sound/pci/hda/hda_codec.c | 29 |
1 files changed, 23 insertions, 6 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 85886220ee74..472e5d04701e 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -96,7 +96,8 @@ EXPORT_SYMBOL_HDA(snd_hda_delete_codec_preset); | |||
96 | 96 | ||
97 | #ifdef CONFIG_PM | 97 | #ifdef CONFIG_PM |
98 | #define codec_in_pm(codec) ((codec)->in_pm) | 98 | #define codec_in_pm(codec) ((codec)->in_pm) |
99 | static void hda_pm_work(struct work_struct *work); | 99 | static void hda_suspend_work(struct work_struct *work); |
100 | static void hda_resume_work(struct work_struct *work); | ||
100 | static void hda_power_work(struct work_struct *work); | 101 | static void hda_power_work(struct work_struct *work); |
101 | static void hda_keep_power_on(struct hda_codec *codec); | 102 | static void hda_keep_power_on(struct hda_codec *codec); |
102 | #define hda_codec_is_power_on(codec) ((codec)->power_on) | 103 | #define hda_codec_is_power_on(codec) ((codec)->power_on) |
@@ -1474,7 +1475,8 @@ int snd_hda_codec_new(struct hda_bus *bus, | |||
1474 | #ifdef CONFIG_PM | 1475 | #ifdef CONFIG_PM |
1475 | spin_lock_init(&codec->power_lock); | 1476 | spin_lock_init(&codec->power_lock); |
1476 | INIT_DELAYED_WORK(&codec->power_work, hda_power_work); | 1477 | INIT_DELAYED_WORK(&codec->power_work, hda_power_work); |
1477 | INIT_WORK(&codec->pm_work, hda_pm_work); | 1478 | INIT_WORK(&codec->suspend_work, hda_suspend_work); |
1479 | INIT_WORK(&codec->resume_work, hda_resume_work); | ||
1478 | /* snd_hda_codec_new() marks the codec as power-up, and leave it as is. | 1480 | /* snd_hda_codec_new() marks the codec as power-up, and leave it as is. |
1479 | * the caller has to power down appropriatley after initialization | 1481 | * the caller has to power down appropriatley after initialization |
1480 | * phase. | 1482 | * phase. |
@@ -5116,13 +5118,21 @@ int snd_hda_check_amp_list_power(struct hda_codec *codec, | |||
5116 | } | 5118 | } |
5117 | EXPORT_SYMBOL_HDA(snd_hda_check_amp_list_power); | 5119 | EXPORT_SYMBOL_HDA(snd_hda_check_amp_list_power); |
5118 | 5120 | ||
5119 | static void hda_pm_work(struct work_struct *work) | 5121 | static void hda_suspend_work(struct work_struct *work) |
5120 | { | 5122 | { |
5121 | struct hda_codec *codec = | 5123 | struct hda_codec *codec = |
5122 | container_of(work, struct hda_codec, pm_work); | 5124 | container_of(work, struct hda_codec, suspend_work); |
5123 | 5125 | ||
5124 | hda_call_codec_suspend(codec, false); | 5126 | hda_call_codec_suspend(codec, false); |
5125 | } | 5127 | } |
5128 | |||
5129 | static void hda_resume_work(struct work_struct *work) | ||
5130 | { | ||
5131 | struct hda_codec *codec = | ||
5132 | container_of(work, struct hda_codec, resume_work); | ||
5133 | |||
5134 | hda_call_codec_resume(codec); | ||
5135 | } | ||
5126 | #endif | 5136 | #endif |
5127 | 5137 | ||
5128 | /* | 5138 | /* |
@@ -5700,7 +5710,7 @@ int snd_hda_suspend(struct hda_bus *bus) | |||
5700 | cancel_delayed_work_sync(&codec->jackpoll_work); | 5710 | cancel_delayed_work_sync(&codec->jackpoll_work); |
5701 | if (hda_codec_is_power_on(codec)) { | 5711 | if (hda_codec_is_power_on(codec)) { |
5702 | if (bus->num_codecs > 1) | 5712 | if (bus->num_codecs > 1) |
5703 | queue_work(bus->pm_wq, &codec->pm_work); | 5713 | queue_work(bus->pm_wq, &codec->suspend_work); |
5704 | else | 5714 | else |
5705 | hda_call_codec_suspend(codec, false); | 5715 | hda_call_codec_suspend(codec, false); |
5706 | } | 5716 | } |
@@ -5724,8 +5734,15 @@ int snd_hda_resume(struct hda_bus *bus) | |||
5724 | struct hda_codec *codec; | 5734 | struct hda_codec *codec; |
5725 | 5735 | ||
5726 | list_for_each_entry(codec, &bus->codec_list, list) { | 5736 | list_for_each_entry(codec, &bus->codec_list, list) { |
5727 | hda_call_codec_resume(codec); | 5737 | if (bus->num_codecs > 1) |
5738 | queue_work(bus->pm_wq, &codec->resume_work); | ||
5739 | else | ||
5740 | hda_call_codec_resume(codec); | ||
5728 | } | 5741 | } |
5742 | |||
5743 | if (bus->num_codecs > 1) | ||
5744 | flush_workqueue(bus->pm_wq); | ||
5745 | |||
5729 | return 0; | 5746 | return 0; |
5730 | } | 5747 | } |
5731 | EXPORT_SYMBOL_HDA(snd_hda_resume); | 5748 | EXPORT_SYMBOL_HDA(snd_hda_resume); |