Skip to content

Commit ecbcfe3

Browse files
tiwaiJaroslav Kysela
authored andcommitted
[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>
1 parent 6243008 commit ecbcfe3

File tree

4 files changed

+121
-89
lines changed

4 files changed

+121
-89
lines changed

include/sound/core.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,9 @@ struct _snd_card {
168168
wait_queue_head_t shutdown_sleep;
169169
struct work_struct free_workq; /* for free in workqueue */
170170
struct device *dev;
171+
#ifdef CONFIG_SND_GENERIC_DRIVER
172+
struct snd_generic_device *generic_dev;
173+
#endif
171174

172175
#ifdef CONFIG_PM
173176
int (*pm_suspend)(snd_card_t *card, pm_message_t state);
@@ -176,9 +179,6 @@ struct _snd_card {
176179
unsigned int power_state; /* power state */
177180
struct semaphore power_lock; /* power lock */
178181
wait_queue_head_t power_sleep;
179-
#ifdef CONFIG_SND_GENERIC_PM
180-
struct snd_generic_device *pm_dev; /* for ISA */
181-
#endif
182182
#endif
183183

184184
#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);
348348
#ifndef snd_card_set_dev
349349
#define snd_card_set_dev(card,devptr) ((card)->dev = (devptr))
350350
#endif
351+
/* register a generic device (for ISA, etc) */
352+
int snd_card_set_generic_dev(snd_card_t *card);
351353

352354
/* device.c */
353355

sound/core/Kconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,6 @@ config SND_DEBUG_DETECT
128128
Say Y here to enable extra-verbose log messages printed when
129129
detecting devices.
130130

131-
config SND_GENERIC_PM
131+
config SND_GENERIC_DRIVER
132132
bool
133133
depends on SND

sound/core/init.c

Lines changed: 101 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -226,8 +226,10 @@ int snd_card_disconnect(snd_card_t * card)
226226
return 0;
227227
}
228228

229-
#if defined(CONFIG_PM) && defined(CONFIG_SND_GENERIC_PM)
230-
static void snd_generic_device_unregister(struct snd_generic_device *dev);
229+
#ifdef CONFIG_SND_GENERIC_DRIVER
230+
static void snd_generic_device_unregister(snd_card_t *card);
231+
#else
232+
#define snd_generic_device_unregister(x) /*NOP*/
231233
#endif
232234

233235
/**
@@ -253,14 +255,7 @@ int snd_card_free(snd_card_t * card)
253255

254256
#ifdef CONFIG_PM
255257
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
262258
#endif
263-
264259
/* wait, until all devices are ready for the free operation */
265260
wait_event(card->shutdown_sleep, card->files == NULL);
266261

@@ -288,6 +283,7 @@ int snd_card_free(snd_card_t * card)
288283
snd_printk(KERN_WARNING "unable to free card info\n");
289284
/* Not fatal error */
290285
}
286+
snd_generic_device_unregister(card);
291287
while (card->s_f_ops) {
292288
s_f_ops = card->s_f_ops;
293289
card->s_f_ops = s_f_ops->next;
@@ -665,6 +661,96 @@ int snd_card_file_remove(snd_card_t *card, struct file *file)
665661
return 0;
666662
}
667663

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+
668754
#ifdef CONFIG_PM
669755
/**
670756
* snd_power_wait - wait until the power-state is changed.
@@ -730,75 +816,7 @@ int snd_card_set_pm_callback(snd_card_t *card,
730816
return 0;
731817
}
732818

733-
#ifdef CONFIG_SND_GENERIC_PM
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-
819+
#ifdef CONFIG_SND_GENERIC_DRIVER
802820
/* suspend/resume callbacks for snd_generic platform device */
803821
static int snd_generic_suspend(struct device *dev, pm_message_t state, u32 level)
804822
{
@@ -846,13 +864,12 @@ int snd_card_set_generic_pm_callback(snd_card_t *card,
846864
int (*resume)(snd_card_t *),
847865
void *private_data)
848866
{
849-
card->pm_dev = snd_generic_device_register(card);
850-
if (! card->pm_dev)
851-
return -ENOMEM;
852-
snd_card_set_pm_callback(card, suspend, resume, private_data);
853-
return 0;
867+
int err;
868+
if ((err = snd_generic_device_register(card)) < 0)
869+
return err;
870+
return snd_card_set_pm_callback(card, suspend, resume, private_data);
854871
}
855-
#endif /* CONFIG_SND_GENERIC_PM */
872+
#endif /* CONFIG_SND_GENERIC_DRIVER */
856873

857874
#ifdef CONFIG_PCI
858875
int snd_card_pci_suspend(struct pci_dev *dev, pm_message_t state)

sound/core/sound.c

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,10 @@ int __exit snd_minor_info_done(void)
328328
* INIT PART
329329
*/
330330

331+
#ifdef CONFIG_SND_GENERIC_DRIVER
332+
extern struct device_driver snd_generic_driver;
333+
#endif
334+
331335
static int __init alsa_sound_init(void)
332336
{
333337
short controlnum;
@@ -354,6 +358,9 @@ static int __init alsa_sound_init(void)
354358
return -ENOMEM;
355359
}
356360
snd_info_minor_register();
361+
#ifdef CONFIG_SND_GENERIC_DRIVER
362+
driver_register(&snd_generic_driver);
363+
#endif
357364
for (controlnum = 0; controlnum < cards_limit; controlnum++)
358365
devfs_mk_cdev(MKDEV(major, controlnum<<5), S_IFCHR | device_mode, "snd/controlC%d", controlnum);
359366
#ifndef MODULE
@@ -369,6 +376,9 @@ static void __exit alsa_sound_exit(void)
369376
for (controlnum = 0; controlnum < cards_limit; controlnum++)
370377
devfs_remove("snd/controlC%d", controlnum);
371378

379+
#ifdef CONFIG_SND_GENERIC_DRIVER
380+
driver_unregister(&snd_generic_driver);
381+
#endif
372382
snd_info_minor_unregister();
373383
snd_info_done();
374384
snd_memory_done();
@@ -416,10 +426,13 @@ EXPORT_SYMBOL(snd_card_register);
416426
EXPORT_SYMBOL(snd_component_add);
417427
EXPORT_SYMBOL(snd_card_file_add);
418428
EXPORT_SYMBOL(snd_card_file_remove);
429+
#ifdef CONFIG_SND_GENERIC_DRIVER
430+
EXPORT_SYMBOL(snd_card_set_generic_dev);
431+
#endif
419432
#ifdef CONFIG_PM
420433
EXPORT_SYMBOL(snd_power_wait);
421434
EXPORT_SYMBOL(snd_card_set_pm_callback);
422-
#if defined(CONFIG_PM) && defined(CONFIG_SND_GENERIC_PM)
435+
#ifdef CONFIG_SND_GENERIC_DRIVER
423436
EXPORT_SYMBOL(snd_card_set_generic_pm_callback);
424437
#endif
425438
#ifdef CONFIG_PCI

0 commit comments

Comments
 (0)