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 | |
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>
-rw-r--r-- | include/sound/core.h | 8 | ||||
-rw-r--r-- | sound/core/Kconfig | 2 | ||||
-rw-r--r-- | sound/core/init.c | 185 | ||||
-rw-r--r-- | sound/core/sound.c | 15 |
4 files changed, 121 insertions, 89 deletions
diff --git a/include/sound/core.h b/include/sound/core.h index 3dc41fd5c54d..26160adcdffc 100644 --- a/include/sound/core.h +++ b/include/sound/core.h | |||
@@ -168,6 +168,9 @@ struct _snd_card { | |||
168 | wait_queue_head_t shutdown_sleep; | 168 | wait_queue_head_t shutdown_sleep; |
169 | struct work_struct free_workq; /* for free in workqueue */ | 169 | struct work_struct free_workq; /* for free in workqueue */ |
170 | struct device *dev; | 170 | struct device *dev; |
171 | #ifdef CONFIG_SND_GENERIC_DRIVER | ||
172 | struct snd_generic_device *generic_dev; | ||
173 | #endif | ||
171 | 174 | ||
172 | #ifdef CONFIG_PM | 175 | #ifdef CONFIG_PM |
173 | int (*pm_suspend)(snd_card_t *card, pm_message_t state); | 176 | int (*pm_suspend)(snd_card_t *card, pm_message_t state); |
@@ -176,9 +179,6 @@ struct _snd_card { | |||
176 | unsigned int power_state; /* power state */ | 179 | unsigned int power_state; /* power state */ |
177 | struct semaphore power_lock; /* power lock */ | 180 | struct semaphore power_lock; /* power lock */ |
178 | wait_queue_head_t power_sleep; | 181 | wait_queue_head_t power_sleep; |
179 | #ifdef CONFIG_SND_GENERIC_PM | ||
180 | struct snd_generic_device *pm_dev; /* for ISA */ | ||
181 | #endif | ||
182 | #endif | 182 | #endif |
183 | 183 | ||
184 | #if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE) | 184 | #if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE) |
@@ -348,6 +348,8 @@ int snd_card_file_remove(snd_card_t *card, struct file *file); | |||
348 | #ifndef snd_card_set_dev | 348 | #ifndef snd_card_set_dev |
349 | #define snd_card_set_dev(card,devptr) ((card)->dev = (devptr)) | 349 | #define snd_card_set_dev(card,devptr) ((card)->dev = (devptr)) |
350 | #endif | 350 | #endif |
351 | /* register a generic device (for ISA, etc) */ | ||
352 | int snd_card_set_generic_dev(snd_card_t *card); | ||
351 | 353 | ||
352 | /* device.c */ | 354 | /* device.c */ |
353 | 355 | ||
diff --git a/sound/core/Kconfig b/sound/core/Kconfig index d1e800b9866d..6ae1d2e24b4e 100644 --- a/sound/core/Kconfig +++ b/sound/core/Kconfig | |||
@@ -128,6 +128,6 @@ config SND_DEBUG_DETECT | |||
128 | Say Y here to enable extra-verbose log messages printed when | 128 | Say Y here to enable extra-verbose log messages printed when |
129 | detecting devices. | 129 | detecting devices. |
130 | 130 | ||
131 | config SND_GENERIC_PM | 131 | config SND_GENERIC_DRIVER |
132 | bool | 132 | bool |
133 | depends on SND | 133 | depends on SND |
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) |
diff --git a/sound/core/sound.c b/sound/core/sound.c index 3271e9245490..9e76bddb2c0b 100644 --- a/sound/core/sound.c +++ b/sound/core/sound.c | |||
@@ -328,6 +328,10 @@ int __exit snd_minor_info_done(void) | |||
328 | * INIT PART | 328 | * INIT PART |
329 | */ | 329 | */ |
330 | 330 | ||
331 | #ifdef CONFIG_SND_GENERIC_DRIVER | ||
332 | extern struct device_driver snd_generic_driver; | ||
333 | #endif | ||
334 | |||
331 | static int __init alsa_sound_init(void) | 335 | static int __init alsa_sound_init(void) |
332 | { | 336 | { |
333 | short controlnum; | 337 | short controlnum; |
@@ -354,6 +358,9 @@ static int __init alsa_sound_init(void) | |||
354 | return -ENOMEM; | 358 | return -ENOMEM; |
355 | } | 359 | } |
356 | snd_info_minor_register(); | 360 | snd_info_minor_register(); |
361 | #ifdef CONFIG_SND_GENERIC_DRIVER | ||
362 | driver_register(&snd_generic_driver); | ||
363 | #endif | ||
357 | for (controlnum = 0; controlnum < cards_limit; controlnum++) | 364 | for (controlnum = 0; controlnum < cards_limit; controlnum++) |
358 | devfs_mk_cdev(MKDEV(major, controlnum<<5), S_IFCHR | device_mode, "snd/controlC%d", controlnum); | 365 | devfs_mk_cdev(MKDEV(major, controlnum<<5), S_IFCHR | device_mode, "snd/controlC%d", controlnum); |
359 | #ifndef MODULE | 366 | #ifndef MODULE |
@@ -369,6 +376,9 @@ static void __exit alsa_sound_exit(void) | |||
369 | for (controlnum = 0; controlnum < cards_limit; controlnum++) | 376 | for (controlnum = 0; controlnum < cards_limit; controlnum++) |
370 | devfs_remove("snd/controlC%d", controlnum); | 377 | devfs_remove("snd/controlC%d", controlnum); |
371 | 378 | ||
379 | #ifdef CONFIG_SND_GENERIC_DRIVER | ||
380 | driver_unregister(&snd_generic_driver); | ||
381 | #endif | ||
372 | snd_info_minor_unregister(); | 382 | snd_info_minor_unregister(); |
373 | snd_info_done(); | 383 | snd_info_done(); |
374 | snd_memory_done(); | 384 | snd_memory_done(); |
@@ -416,10 +426,13 @@ EXPORT_SYMBOL(snd_card_register); | |||
416 | EXPORT_SYMBOL(snd_component_add); | 426 | EXPORT_SYMBOL(snd_component_add); |
417 | EXPORT_SYMBOL(snd_card_file_add); | 427 | EXPORT_SYMBOL(snd_card_file_add); |
418 | EXPORT_SYMBOL(snd_card_file_remove); | 428 | EXPORT_SYMBOL(snd_card_file_remove); |
429 | #ifdef CONFIG_SND_GENERIC_DRIVER | ||
430 | EXPORT_SYMBOL(snd_card_set_generic_dev); | ||
431 | #endif | ||
419 | #ifdef CONFIG_PM | 432 | #ifdef CONFIG_PM |
420 | EXPORT_SYMBOL(snd_power_wait); | 433 | EXPORT_SYMBOL(snd_power_wait); |
421 | EXPORT_SYMBOL(snd_card_set_pm_callback); | 434 | EXPORT_SYMBOL(snd_card_set_pm_callback); |
422 | #if defined(CONFIG_PM) && defined(CONFIG_SND_GENERIC_PM) | 435 | #ifdef CONFIG_SND_GENERIC_DRIVER |
423 | EXPORT_SYMBOL(snd_card_set_generic_pm_callback); | 436 | EXPORT_SYMBOL(snd_card_set_generic_pm_callback); |
424 | #endif | 437 | #endif |
425 | #ifdef CONFIG_PCI | 438 | #ifdef CONFIG_PCI |