diff options
author | Takashi Iwai <tiwai@suse.de> | 2005-09-05 11:15:37 -0400 |
---|---|---|
committer | Jaroslav Kysela <perex@suse.cz> | 2005-09-12 04:41:49 -0400 |
commit | ecbcfe36fa882e9f8f2be63ac0c42978336bf997 (patch) | |
tree | b43fe6845a9de4e077cfba15c214d66e74866486 /sound/core/init.c | |
parent | 6243008b82222d6244b055beeeba94b14f23b7e2 (diff) |
[ALSA] Introduce snd_card_set_generic_dev()
ALSA Core
A new function snd_card_set_generic_dev() is introduced to add the
'generic device' support for devices without proper bus on sysfs.
It's a last resort, and should be removed in future when they have
a proper bus, instead.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/core/init.c')
-rw-r--r-- | sound/core/init.c | 185 |
1 files changed, 101 insertions, 84 deletions
diff --git a/sound/core/init.c b/sound/core/init.c index d72f58f450ce..c9c9929121d5 100644 --- a/sound/core/init.c +++ b/sound/core/init.c | |||
@@ -226,8 +226,10 @@ int snd_card_disconnect(snd_card_t * card) | |||
226 | return 0; | 226 | return 0; |
227 | } | 227 | } |
228 | 228 | ||
229 | #if defined(CONFIG_PM) && defined(CONFIG_SND_GENERIC_PM) | 229 | #ifdef CONFIG_SND_GENERIC_DRIVER |
230 | static void snd_generic_device_unregister(struct snd_generic_device *dev); | 230 | static void snd_generic_device_unregister(snd_card_t *card); |
231 | #else | ||
232 | #define snd_generic_device_unregister(x) /*NOP*/ | ||
231 | #endif | 233 | #endif |
232 | 234 | ||
233 | /** | 235 | /** |
@@ -253,14 +255,7 @@ int snd_card_free(snd_card_t * card) | |||
253 | 255 | ||
254 | #ifdef CONFIG_PM | 256 | #ifdef CONFIG_PM |
255 | wake_up(&card->power_sleep); | 257 | wake_up(&card->power_sleep); |
256 | #ifdef CONFIG_SND_GENERIC_PM | ||
257 | if (card->pm_dev) { | ||
258 | snd_generic_device_unregister(card->pm_dev); | ||
259 | card->pm_dev = NULL; | ||
260 | } | ||
261 | #endif | ||
262 | #endif | 258 | #endif |
263 | |||
264 | /* wait, until all devices are ready for the free operation */ | 259 | /* wait, until all devices are ready for the free operation */ |
265 | wait_event(card->shutdown_sleep, card->files == NULL); | 260 | wait_event(card->shutdown_sleep, card->files == NULL); |
266 | 261 | ||
@@ -288,6 +283,7 @@ int snd_card_free(snd_card_t * card) | |||
288 | snd_printk(KERN_WARNING "unable to free card info\n"); | 283 | snd_printk(KERN_WARNING "unable to free card info\n"); |
289 | /* Not fatal error */ | 284 | /* Not fatal error */ |
290 | } | 285 | } |
286 | snd_generic_device_unregister(card); | ||
291 | while (card->s_f_ops) { | 287 | while (card->s_f_ops) { |
292 | s_f_ops = card->s_f_ops; | 288 | s_f_ops = card->s_f_ops; |
293 | card->s_f_ops = s_f_ops->next; | 289 | card->s_f_ops = s_f_ops->next; |
@@ -665,6 +661,96 @@ int snd_card_file_remove(snd_card_t *card, struct file *file) | |||
665 | return 0; | 661 | return 0; |
666 | } | 662 | } |
667 | 663 | ||
664 | #ifdef CONFIG_SND_GENERIC_DRIVER | ||
665 | /* | ||
666 | * generic device without a proper bus using platform_device | ||
667 | * (e.g. ISA) | ||
668 | */ | ||
669 | struct snd_generic_device { | ||
670 | struct platform_device pdev; | ||
671 | snd_card_t *card; | ||
672 | }; | ||
673 | |||
674 | #define get_snd_generic_card(dev) container_of(to_platform_device(dev), struct snd_generic_device, pdev)->card | ||
675 | |||
676 | #define SND_GENERIC_NAME "snd_generic" | ||
677 | |||
678 | #ifdef CONFIG_PM | ||
679 | static int snd_generic_suspend(struct device *dev, pm_message_t state, u32 level); | ||
680 | static int snd_generic_resume(struct device *dev, u32 level); | ||
681 | #endif | ||
682 | |||
683 | /* initialized in sound.c */ | ||
684 | struct device_driver snd_generic_driver = { | ||
685 | .name = SND_GENERIC_NAME, | ||
686 | .bus = &platform_bus_type, | ||
687 | #ifdef CONFIG_PM | ||
688 | .suspend = snd_generic_suspend, | ||
689 | .resume = snd_generic_resume, | ||
690 | #endif | ||
691 | }; | ||
692 | |||
693 | void snd_generic_device_release(struct device *dev) | ||
694 | { | ||
695 | } | ||
696 | |||
697 | static int snd_generic_device_register(snd_card_t *card) | ||
698 | { | ||
699 | struct snd_generic_device *dev; | ||
700 | int err; | ||
701 | |||
702 | if (card->generic_dev) | ||
703 | return 0; /* already registered */ | ||
704 | |||
705 | dev = kcalloc(1, sizeof(*dev), GFP_KERNEL); | ||
706 | if (! dev) { | ||
707 | snd_printk(KERN_ERR "can't allocate generic_device\n"); | ||
708 | return -ENOMEM; | ||
709 | } | ||
710 | |||
711 | dev->pdev.name = SND_GENERIC_NAME; | ||
712 | dev->pdev.id = card->number; | ||
713 | dev->pdev.dev.release = snd_generic_device_release; | ||
714 | dev->card = card; | ||
715 | if ((err = platform_device_register(&dev->pdev)) < 0) { | ||
716 | kfree(dev); | ||
717 | return err; | ||
718 | } | ||
719 | card->generic_dev = dev; | ||
720 | return 0; | ||
721 | } | ||
722 | |||
723 | static void snd_generic_device_unregister(snd_card_t *card) | ||
724 | { | ||
725 | struct snd_generic_device *dev = card->generic_dev; | ||
726 | if (dev) { | ||
727 | platform_device_unregister(&dev->pdev); | ||
728 | kfree(dev); | ||
729 | card->generic_dev = NULL; | ||
730 | } | ||
731 | } | ||
732 | |||
733 | /** | ||
734 | * snd_card_set_generic_dev - assign the generic device to the card | ||
735 | * @card: soundcard structure | ||
736 | * | ||
737 | * Assigns a generic device to the card. This function is provided as the | ||
738 | * last resort, for devices without any proper bus. Thus this won't override | ||
739 | * the device already assigned to the card. | ||
740 | * | ||
741 | * Returns zero if successful, or a negative error code. | ||
742 | */ | ||
743 | int snd_card_set_generic_dev(snd_card_t *card) | ||
744 | { | ||
745 | int err; | ||
746 | if ((err = snd_generic_device_register(card)) < 0) | ||
747 | return err; | ||
748 | if (! card->dev) | ||
749 | snd_card_set_dev(card, &card->generic_dev->pdev.dev); | ||
750 | return 0; | ||
751 | } | ||
752 | #endif /* CONFIG_SND_GENERIC_DRIVER */ | ||
753 | |||
668 | #ifdef CONFIG_PM | 754 | #ifdef CONFIG_PM |
669 | /** | 755 | /** |
670 | * snd_power_wait - wait until the power-state is changed. | 756 | * snd_power_wait - wait until the power-state is changed. |
@@ -730,75 +816,7 @@ int snd_card_set_pm_callback(snd_card_t *card, | |||
730 | return 0; | 816 | return 0; |
731 | } | 817 | } |
732 | 818 | ||
733 | #ifdef CONFIG_SND_GENERIC_PM | 819 | #ifdef CONFIG_SND_GENERIC_DRIVER |
734 | /* | ||
735 | * use platform_device for generic power-management without a proper bus | ||
736 | * (e.g. ISA) | ||
737 | */ | ||
738 | struct snd_generic_device { | ||
739 | struct platform_device pdev; | ||
740 | snd_card_t *card; | ||
741 | }; | ||
742 | |||
743 | #define get_snd_generic_card(dev) container_of(to_platform_device(dev), struct snd_generic_device, pdev)->card | ||
744 | |||
745 | #define SND_GENERIC_NAME "snd_generic_pm" | ||
746 | |||
747 | static int snd_generic_suspend(struct device *dev, pm_message_t state, u32 level); | ||
748 | static int snd_generic_resume(struct device *dev, u32 level); | ||
749 | |||
750 | static struct device_driver snd_generic_driver = { | ||
751 | .name = SND_GENERIC_NAME, | ||
752 | .bus = &platform_bus_type, | ||
753 | .suspend = snd_generic_suspend, | ||
754 | .resume = snd_generic_resume, | ||
755 | }; | ||
756 | |||
757 | static int generic_driver_registered; | ||
758 | |||
759 | static void generic_driver_unregister(void) | ||
760 | { | ||
761 | if (generic_driver_registered) { | ||
762 | generic_driver_registered--; | ||
763 | if (! generic_driver_registered) | ||
764 | driver_unregister(&snd_generic_driver); | ||
765 | } | ||
766 | } | ||
767 | |||
768 | static struct snd_generic_device *snd_generic_device_register(snd_card_t *card) | ||
769 | { | ||
770 | struct snd_generic_device *dev; | ||
771 | |||
772 | if (! generic_driver_registered) { | ||
773 | if (driver_register(&snd_generic_driver) < 0) | ||
774 | return NULL; | ||
775 | } | ||
776 | generic_driver_registered++; | ||
777 | |||
778 | dev = kcalloc(1, sizeof(*dev), GFP_KERNEL); | ||
779 | if (! dev) { | ||
780 | generic_driver_unregister(); | ||
781 | return NULL; | ||
782 | } | ||
783 | |||
784 | dev->pdev.name = SND_GENERIC_NAME; | ||
785 | dev->pdev.id = card->number; | ||
786 | dev->card = card; | ||
787 | if (platform_device_register(&dev->pdev) < 0) { | ||
788 | kfree(dev); | ||
789 | generic_driver_unregister(); | ||
790 | return NULL; | ||
791 | } | ||
792 | return dev; | ||
793 | } | ||
794 | |||
795 | static void snd_generic_device_unregister(struct snd_generic_device *dev) | ||
796 | { | ||
797 | platform_device_unregister(&dev->pdev); | ||
798 | kfree(dev); | ||
799 | generic_driver_unregister(); | ||
800 | } | ||
801 | |||
802 | /* suspend/resume callbacks for snd_generic platform device */ | 820 | /* suspend/resume callbacks for snd_generic platform device */ |
803 | static int snd_generic_suspend(struct device *dev, pm_message_t state, u32 level) | 821 | static int snd_generic_suspend(struct device *dev, pm_message_t state, u32 level) |
804 | { | 822 | { |
@@ -846,13 +864,12 @@ int snd_card_set_generic_pm_callback(snd_card_t *card, | |||
846 | int (*resume)(snd_card_t *), | 864 | int (*resume)(snd_card_t *), |
847 | void *private_data) | 865 | void *private_data) |
848 | { | 866 | { |
849 | card->pm_dev = snd_generic_device_register(card); | 867 | int err; |
850 | if (! card->pm_dev) | 868 | if ((err = snd_generic_device_register(card)) < 0) |
851 | return -ENOMEM; | 869 | return err; |
852 | snd_card_set_pm_callback(card, suspend, resume, private_data); | 870 | return snd_card_set_pm_callback(card, suspend, resume, private_data); |
853 | return 0; | ||
854 | } | 871 | } |
855 | #endif /* CONFIG_SND_GENERIC_PM */ | 872 | #endif /* CONFIG_SND_GENERIC_DRIVER */ |
856 | 873 | ||
857 | #ifdef CONFIG_PCI | 874 | #ifdef CONFIG_PCI |
858 | int snd_card_pci_suspend(struct pci_dev *dev, pm_message_t state) | 875 | int snd_card_pci_suspend(struct pci_dev *dev, pm_message_t state) |