diff options
author | Takashi Iwai <tiwai@suse.de> | 2013-12-05 05:55:05 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2013-12-06 02:51:51 -0500 |
commit | f4d6a55d7be3f5b944c17e6aafb84d96c4dd09d7 (patch) | |
tree | f2d63df469db8290b4ff346cf53c7f78ee20273a | |
parent | b13a714923fe4d444977dccb7a0f7ad1346724cf (diff) |
ALSA: hda - Clean up async codec PM using standard async infrastructure
This simplifies lots of codes indeed.
Tested-by: Mengdong Lin <mengdong.lin@intel.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r-- | sound/pci/hda/hda_codec.c | 64 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.h | 6 |
2 files changed, 19 insertions, 51 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 5b7622034eee..2e090c8d7144 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/pci.h> | 26 | #include <linux/pci.h> |
27 | #include <linux/mutex.h> | 27 | #include <linux/mutex.h> |
28 | #include <linux/module.h> | 28 | #include <linux/module.h> |
29 | #include <linux/async.h> | ||
29 | #include <sound/core.h> | 30 | #include <sound/core.h> |
30 | #include "hda_codec.h" | 31 | #include "hda_codec.h" |
31 | #include <sound/asoundef.h> | 32 | #include <sound/asoundef.h> |
@@ -96,8 +97,6 @@ EXPORT_SYMBOL_HDA(snd_hda_delete_codec_preset); | |||
96 | 97 | ||
97 | #ifdef CONFIG_PM | 98 | #ifdef CONFIG_PM |
98 | #define codec_in_pm(codec) ((codec)->in_pm) | 99 | #define codec_in_pm(codec) ((codec)->in_pm) |
99 | static void hda_suspend_work(struct work_struct *work); | ||
100 | static void hda_resume_work(struct work_struct *work); | ||
101 | static void hda_power_work(struct work_struct *work); | 100 | static void hda_power_work(struct work_struct *work); |
102 | static void hda_keep_power_on(struct hda_codec *codec); | 101 | static void hda_keep_power_on(struct hda_codec *codec); |
103 | #define hda_codec_is_power_on(codec) ((codec)->power_on) | 102 | #define hda_codec_is_power_on(codec) ((codec)->power_on) |
@@ -842,11 +841,6 @@ static int snd_hda_bus_free(struct hda_bus *bus) | |||
842 | if (bus->workq) | 841 | if (bus->workq) |
843 | destroy_workqueue(bus->workq); | 842 | destroy_workqueue(bus->workq); |
844 | 843 | ||
845 | #ifdef CONFIG_PM | ||
846 | if (bus->pm_wq) | ||
847 | destroy_workqueue(bus->pm_wq); | ||
848 | #endif | ||
849 | |||
850 | kfree(bus); | 844 | kfree(bus); |
851 | return 0; | 845 | return 0; |
852 | } | 846 | } |
@@ -891,9 +885,6 @@ int snd_hda_bus_new(struct snd_card *card, | |||
891 | .dev_register = snd_hda_bus_dev_register, | 885 | .dev_register = snd_hda_bus_dev_register, |
892 | .dev_free = snd_hda_bus_dev_free, | 886 | .dev_free = snd_hda_bus_dev_free, |
893 | }; | 887 | }; |
894 | #ifdef CONFIG_PM | ||
895 | char wqname[16]; | ||
896 | #endif | ||
897 | 888 | ||
898 | if (snd_BUG_ON(!temp)) | 889 | if (snd_BUG_ON(!temp)) |
899 | return -EINVAL; | 890 | return -EINVAL; |
@@ -930,16 +921,6 @@ int snd_hda_bus_new(struct snd_card *card, | |||
930 | return -ENOMEM; | 921 | return -ENOMEM; |
931 | } | 922 | } |
932 | 923 | ||
933 | #ifdef CONFIG_PM | ||
934 | sprintf(wqname, "hda-pm-wq-%d", card->number); | ||
935 | bus->pm_wq = create_workqueue(wqname); | ||
936 | if (!bus->pm_wq) { | ||
937 | snd_printk(KERN_ERR "cannot create PM workqueue\n"); | ||
938 | snd_hda_bus_free(bus); | ||
939 | return -ENOMEM; | ||
940 | } | ||
941 | #endif | ||
942 | |||
943 | err = snd_device_new(card, SNDRV_DEV_BUS, bus, &dev_ops); | 924 | err = snd_device_new(card, SNDRV_DEV_BUS, bus, &dev_ops); |
944 | if (err < 0) { | 925 | if (err < 0) { |
945 | snd_hda_bus_free(bus); | 926 | snd_hda_bus_free(bus); |
@@ -1476,8 +1457,6 @@ int snd_hda_codec_new(struct hda_bus *bus, | |||
1476 | #ifdef CONFIG_PM | 1457 | #ifdef CONFIG_PM |
1477 | spin_lock_init(&codec->power_lock); | 1458 | spin_lock_init(&codec->power_lock); |
1478 | INIT_DELAYED_WORK(&codec->power_work, hda_power_work); | 1459 | INIT_DELAYED_WORK(&codec->power_work, hda_power_work); |
1479 | INIT_WORK(&codec->suspend_work, hda_suspend_work); | ||
1480 | INIT_WORK(&codec->resume_work, hda_resume_work); | ||
1481 | /* snd_hda_codec_new() marks the codec as power-up, and leave it as is. | 1460 | /* snd_hda_codec_new() marks the codec as power-up, and leave it as is. |
1482 | * the caller has to power down appropriatley after initialization | 1461 | * the caller has to power down appropriatley after initialization |
1483 | * phase. | 1462 | * phase. |
@@ -1495,9 +1474,6 @@ int snd_hda_codec_new(struct hda_bus *bus, | |||
1495 | 1474 | ||
1496 | list_add_tail(&codec->list, &bus->codec_list); | 1475 | list_add_tail(&codec->list, &bus->codec_list); |
1497 | bus->num_codecs++; | 1476 | bus->num_codecs++; |
1498 | #ifdef CONFIG_PM | ||
1499 | workqueue_set_max_active(bus->pm_wq, bus->num_codecs); | ||
1500 | #endif | ||
1501 | 1477 | ||
1502 | bus->caddr_tbl[codec_addr] = codec; | 1478 | bus->caddr_tbl[codec_addr] = codec; |
1503 | 1479 | ||
@@ -5120,22 +5096,6 @@ int snd_hda_check_amp_list_power(struct hda_codec *codec, | |||
5120 | return 0; | 5096 | return 0; |
5121 | } | 5097 | } |
5122 | EXPORT_SYMBOL_HDA(snd_hda_check_amp_list_power); | 5098 | EXPORT_SYMBOL_HDA(snd_hda_check_amp_list_power); |
5123 | |||
5124 | static void hda_suspend_work(struct work_struct *work) | ||
5125 | { | ||
5126 | struct hda_codec *codec = | ||
5127 | container_of(work, struct hda_codec, suspend_work); | ||
5128 | |||
5129 | hda_call_codec_suspend(codec, false); | ||
5130 | } | ||
5131 | |||
5132 | static void hda_resume_work(struct work_struct *work) | ||
5133 | { | ||
5134 | struct hda_codec *codec = | ||
5135 | container_of(work, struct hda_codec, resume_work); | ||
5136 | |||
5137 | hda_call_codec_resume(codec); | ||
5138 | } | ||
5139 | #endif | 5099 | #endif |
5140 | 5100 | ||
5141 | /* | 5101 | /* |
@@ -5699,6 +5659,17 @@ EXPORT_SYMBOL_HDA(snd_hda_add_imux_item); | |||
5699 | * power management | 5659 | * power management |
5700 | */ | 5660 | */ |
5701 | 5661 | ||
5662 | |||
5663 | static void hda_async_suspend(void *data, async_cookie_t cookie) | ||
5664 | { | ||
5665 | hda_call_codec_suspend(data, false); | ||
5666 | } | ||
5667 | |||
5668 | static void hda_async_resume(void *data, async_cookie_t cookie) | ||
5669 | { | ||
5670 | hda_call_codec_resume(data); | ||
5671 | } | ||
5672 | |||
5702 | /** | 5673 | /** |
5703 | * snd_hda_suspend - suspend the codecs | 5674 | * snd_hda_suspend - suspend the codecs |
5704 | * @bus: the HDA bus | 5675 | * @bus: the HDA bus |
@@ -5708,19 +5679,21 @@ EXPORT_SYMBOL_HDA(snd_hda_add_imux_item); | |||
5708 | int snd_hda_suspend(struct hda_bus *bus) | 5679 | int snd_hda_suspend(struct hda_bus *bus) |
5709 | { | 5680 | { |
5710 | struct hda_codec *codec; | 5681 | struct hda_codec *codec; |
5682 | ASYNC_DOMAIN_EXCLUSIVE(domain); | ||
5711 | 5683 | ||
5712 | list_for_each_entry(codec, &bus->codec_list, list) { | 5684 | list_for_each_entry(codec, &bus->codec_list, list) { |
5713 | cancel_delayed_work_sync(&codec->jackpoll_work); | 5685 | cancel_delayed_work_sync(&codec->jackpoll_work); |
5714 | if (hda_codec_is_power_on(codec)) { | 5686 | if (hda_codec_is_power_on(codec)) { |
5715 | if (bus->num_codecs > 1) | 5687 | if (bus->num_codecs > 1) |
5716 | queue_work(bus->pm_wq, &codec->suspend_work); | 5688 | async_schedule_domain(hda_async_suspend, codec, |
5689 | &domain); | ||
5717 | else | 5690 | else |
5718 | hda_call_codec_suspend(codec, false); | 5691 | hda_call_codec_suspend(codec, false); |
5719 | } | 5692 | } |
5720 | } | 5693 | } |
5721 | 5694 | ||
5722 | if (bus->num_codecs > 1) | 5695 | if (bus->num_codecs > 1) |
5723 | flush_workqueue(bus->pm_wq); | 5696 | async_synchronize_full_domain(&domain); |
5724 | 5697 | ||
5725 | return 0; | 5698 | return 0; |
5726 | } | 5699 | } |
@@ -5735,16 +5708,17 @@ EXPORT_SYMBOL_HDA(snd_hda_suspend); | |||
5735 | int snd_hda_resume(struct hda_bus *bus) | 5708 | int snd_hda_resume(struct hda_bus *bus) |
5736 | { | 5709 | { |
5737 | struct hda_codec *codec; | 5710 | struct hda_codec *codec; |
5711 | ASYNC_DOMAIN_EXCLUSIVE(domain); | ||
5738 | 5712 | ||
5739 | list_for_each_entry(codec, &bus->codec_list, list) { | 5713 | list_for_each_entry(codec, &bus->codec_list, list) { |
5740 | if (bus->num_codecs > 1) | 5714 | if (bus->num_codecs > 1) |
5741 | queue_work(bus->pm_wq, &codec->resume_work); | 5715 | async_schedule_domain(hda_async_resume, codec, &domain); |
5742 | else | 5716 | else |
5743 | hda_call_codec_resume(codec); | 5717 | hda_call_codec_resume(codec); |
5744 | } | 5718 | } |
5745 | 5719 | ||
5746 | if (bus->num_codecs > 1) | 5720 | if (bus->num_codecs > 1) |
5747 | flush_workqueue(bus->pm_wq); | 5721 | async_synchronize_full_domain(&domain); |
5748 | 5722 | ||
5749 | return 0; | 5723 | return 0; |
5750 | } | 5724 | } |
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 3ab4834761a8..260b190adf74 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h | |||
@@ -684,9 +684,6 @@ struct hda_bus { | |||
684 | struct hda_bus_unsolicited *unsol; | 684 | struct hda_bus_unsolicited *unsol; |
685 | char workq_name[16]; | 685 | char workq_name[16]; |
686 | struct workqueue_struct *workq; /* common workqueue for codecs */ | 686 | struct workqueue_struct *workq; /* common workqueue for codecs */ |
687 | #ifdef CONFIG_PM | ||
688 | struct workqueue_struct *pm_wq; /* workqueue to parallel codec PM */ | ||
689 | #endif | ||
690 | 687 | ||
691 | /* assigned PCMs */ | 688 | /* assigned PCMs */ |
692 | DECLARE_BITMAP(pcm_dev_bits, SNDRV_PCM_DEVICES); | 689 | DECLARE_BITMAP(pcm_dev_bits, SNDRV_PCM_DEVICES); |
@@ -921,9 +918,6 @@ struct hda_codec { | |||
921 | unsigned long power_off_acct; | 918 | unsigned long power_off_acct; |
922 | unsigned long power_jiffies; | 919 | unsigned long power_jiffies; |
923 | spinlock_t power_lock; | 920 | spinlock_t power_lock; |
924 | /* tasks to parallel multi-codec suspend/resume */ | ||
925 | struct work_struct suspend_work; | ||
926 | struct work_struct resume_work; | ||
927 | #endif | 921 | #endif |
928 | 922 | ||
929 | /* filter the requested power state per nid */ | 923 | /* filter the requested power state per nid */ |