aboutsummaryrefslogtreecommitdiffstats
path: root/sound/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'sound/drivers')
-rw-r--r--sound/drivers/dummy.c106
1 files changed, 80 insertions, 26 deletions
diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c
index 9c827b154458..a276f7c80360 100644
--- a/sound/drivers/dummy.c
+++ b/sound/drivers/dummy.c
@@ -20,6 +20,8 @@
20 20
21#include <sound/driver.h> 21#include <sound/driver.h>
22#include <linux/init.h> 22#include <linux/init.h>
23#include <linux/err.h>
24#include <linux/platform_device.h>
23#include <linux/jiffies.h> 25#include <linux/jiffies.h>
24#include <linux/slab.h> 26#include <linux/slab.h>
25#include <linux/time.h> 27#include <linux/time.h>
@@ -151,6 +153,7 @@ MODULE_PARM_DESC(pcm_substreams, "PCM substreams # (1-16) for dummy driver.");
151 153
152struct snd_dummy { 154struct snd_dummy {
153 struct snd_card *card; 155 struct snd_card *card;
156 struct snd_pcm *pcm;
154 spinlock_t mixer_lock; 157 spinlock_t mixer_lock;
155 int mixer_volume[MIXER_ADDR_LAST+1][2]; 158 int mixer_volume[MIXER_ADDR_LAST+1][2];
156 int capture_source[MIXER_ADDR_LAST+1][2]; 159 int capture_source[MIXER_ADDR_LAST+1][2];
@@ -169,8 +172,6 @@ struct snd_dummy_pcm {
169 struct snd_pcm_substream *substream; 172 struct snd_pcm_substream *substream;
170}; 173};
171 174
172static struct snd_card *snd_dummy_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
173
174 175
175static inline void snd_card_dummy_pcm_timer_start(struct snd_dummy_pcm *dpcm) 176static inline void snd_card_dummy_pcm_timer_start(struct snd_dummy_pcm *dpcm)
176{ 177{
@@ -190,15 +191,21 @@ static int snd_card_dummy_pcm_trigger(struct snd_pcm_substream *substream, int c
190 int err = 0; 191 int err = 0;
191 192
192 spin_lock(&dpcm->lock); 193 spin_lock(&dpcm->lock);
193 if (cmd == SNDRV_PCM_TRIGGER_START) { 194 switch (cmd) {
195 case SNDRV_PCM_TRIGGER_START:
196 case SNDRV_PCM_TRIGGER_RESUME:
194 snd_card_dummy_pcm_timer_start(dpcm); 197 snd_card_dummy_pcm_timer_start(dpcm);
195 } else if (cmd == SNDRV_PCM_TRIGGER_STOP) { 198 break;
199 case SNDRV_PCM_TRIGGER_STOP:
200 case SNDRV_PCM_TRIGGER_SUSPEND:
196 snd_card_dummy_pcm_timer_stop(dpcm); 201 snd_card_dummy_pcm_timer_stop(dpcm);
197 } else { 202 break;
203 default:
198 err = -EINVAL; 204 err = -EINVAL;
205 break;
199 } 206 }
200 spin_unlock(&dpcm->lock); 207 spin_unlock(&dpcm->lock);
201 return err; 208 return 0;
202} 209}
203 210
204static int snd_card_dummy_pcm_prepare(struct snd_pcm_substream *substream) 211static int snd_card_dummy_pcm_prepare(struct snd_pcm_substream *substream)
@@ -251,7 +258,7 @@ static snd_pcm_uframes_t snd_card_dummy_pcm_pointer(struct snd_pcm_substream *su
251static struct snd_pcm_hardware snd_card_dummy_playback = 258static struct snd_pcm_hardware snd_card_dummy_playback =
252{ 259{
253 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | 260 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
254 SNDRV_PCM_INFO_MMAP_VALID), 261 SNDRV_PCM_INFO_RESUME | SNDRV_PCM_INFO_MMAP_VALID),
255 .formats = USE_FORMATS, 262 .formats = USE_FORMATS,
256 .rates = USE_RATE, 263 .rates = USE_RATE,
257 .rate_min = USE_RATE_MIN, 264 .rate_min = USE_RATE_MIN,
@@ -269,7 +276,7 @@ static struct snd_pcm_hardware snd_card_dummy_playback =
269static struct snd_pcm_hardware snd_card_dummy_capture = 276static struct snd_pcm_hardware snd_card_dummy_capture =
270{ 277{
271 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | 278 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
272 SNDRV_PCM_INFO_MMAP_VALID), 279 SNDRV_PCM_INFO_RESUME | SNDRV_PCM_INFO_MMAP_VALID),
273 .formats = USE_FORMATS, 280 .formats = USE_FORMATS,
274 .rates = USE_RATE, 281 .rates = USE_RATE,
275 .rate_min = USE_RATE_MIN, 282 .rate_min = USE_RATE_MIN,
@@ -405,6 +412,7 @@ static int __init snd_card_dummy_pcm(struct snd_dummy *dummy, int device, int su
405 if ((err = snd_pcm_new(dummy->card, "Dummy PCM", device, 412 if ((err = snd_pcm_new(dummy->card, "Dummy PCM", device,
406 substreams, substreams, &pcm)) < 0) 413 substreams, substreams, &pcm)) < 0)
407 return err; 414 return err;
415 dummy->pcm = pcm;
408 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_card_dummy_playback_ops); 416 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_card_dummy_playback_ops);
409 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_card_dummy_capture_ops); 417 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_card_dummy_capture_ops);
410 pcm->private_data = dummy; 418 pcm->private_data = dummy;
@@ -547,14 +555,13 @@ static int __init snd_card_dummy_new_mixer(struct snd_dummy *dummy)
547 return 0; 555 return 0;
548} 556}
549 557
550static int __init snd_card_dummy_probe(int dev) 558static int __init snd_dummy_probe(struct platform_device *devptr)
551{ 559{
552 struct snd_card *card; 560 struct snd_card *card;
553 struct snd_dummy *dummy; 561 struct snd_dummy *dummy;
554 int idx, err; 562 int idx, err;
563 int dev = devptr->id;
555 564
556 if (!enable[dev])
557 return -ENODEV;
558 card = snd_card_new(index[dev], id[dev], THIS_MODULE, 565 card = snd_card_new(index[dev], id[dev], THIS_MODULE,
559 sizeof(struct snd_dummy)); 566 sizeof(struct snd_dummy));
560 if (card == NULL) 567 if (card == NULL)
@@ -575,11 +582,10 @@ static int __init snd_card_dummy_probe(int dev)
575 strcpy(card->shortname, "Dummy"); 582 strcpy(card->shortname, "Dummy");
576 sprintf(card->longname, "Dummy %i", dev + 1); 583 sprintf(card->longname, "Dummy %i", dev + 1);
577 584
578 if ((err = snd_card_set_generic_dev(card)) < 0) 585 snd_card_set_dev(card, &devptr->dev);
579 goto __nodev;
580 586
581 if ((err = snd_card_register(card)) == 0) { 587 if ((err = snd_card_register(card)) == 0) {
582 snd_dummy_cards[dev] = card; 588 platform_set_drvdata(devptr, card);
583 return 0; 589 return 0;
584 } 590 }
585 __nodev: 591 __nodev:
@@ -587,16 +593,62 @@ static int __init snd_card_dummy_probe(int dev)
587 return err; 593 return err;
588} 594}
589 595
590static int __init alsa_card_dummy_init(void) 596static int snd_dummy_remove(struct platform_device *devptr)
597{
598 snd_card_free(platform_get_drvdata(devptr));
599 platform_set_drvdata(devptr, NULL);
600 return 0;
601}
602
603#ifdef CONFIG_PM
604static int snd_dummy_suspend(struct platform_device *pdev, pm_message_t state)
591{ 605{
592 int dev, cards; 606 struct snd_card *card = platform_get_drvdata(pdev);
607 struct snd_dummy *dummy = card->private_data;
593 608
594 for (dev = cards = 0; dev < SNDRV_CARDS && enable[dev]; dev++) { 609 snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
595 if (snd_card_dummy_probe(dev) < 0) { 610 snd_pcm_suspend_all(dummy->pcm);
596#ifdef MODULE 611 return 0;
597 printk(KERN_ERR "Dummy soundcard #%i not found or device busy\n", dev + 1); 612}
613
614static int snd_dummy_resume(struct platform_device *pdev)
615{
616 struct snd_card *card = platform_get_drvdata(pdev);
617
618 snd_power_change_state(card, SNDRV_CTL_POWER_D0);
619 return 0;
620}
621#endif
622
623#define SND_DUMMY_DRIVER "snd_dummy"
624
625static struct platform_driver snd_dummy_driver = {
626 .probe = snd_dummy_probe,
627 .remove = snd_dummy_remove,
628#ifdef CONFIG_PM
629 .suspend = snd_dummy_suspend,
630 .resume = snd_dummy_resume,
598#endif 631#endif
599 break; 632 .driver = {
633 .name = SND_DUMMY_DRIVER
634 },
635};
636
637static int __init alsa_card_dummy_init(void)
638{
639 int i, cards, err;
640
641 if ((err = platform_driver_register(&snd_dummy_driver)) < 0)
642 return err;
643
644 cards = 0;
645 for (i = 0; i < SNDRV_CARDS && enable[i]; i++) {
646 struct platform_device *device;
647 device = platform_device_register_simple(SND_DUMMY_DRIVER,
648 i, NULL, 0);
649 if (IS_ERR(device)) {
650 err = PTR_ERR(device);
651 goto errout;
600 } 652 }
601 cards++; 653 cards++;
602 } 654 }
@@ -604,17 +656,19 @@ static int __init alsa_card_dummy_init(void)
604#ifdef MODULE 656#ifdef MODULE
605 printk(KERN_ERR "Dummy soundcard not found or device busy\n"); 657 printk(KERN_ERR "Dummy soundcard not found or device busy\n");
606#endif 658#endif
607 return -ENODEV; 659 err = -ENODEV;
660 goto errout;
608 } 661 }
609 return 0; 662 return 0;
663
664 errout:
665 platform_driver_unregister(&snd_dummy_driver);
666 return err;
610} 667}
611 668
612static void __exit alsa_card_dummy_exit(void) 669static void __exit alsa_card_dummy_exit(void)
613{ 670{
614 int idx; 671 platform_driver_unregister(&snd_dummy_driver);
615
616 for (idx = 0; idx < SNDRV_CARDS; idx++)
617 snd_card_free(snd_dummy_cards[idx]);
618} 672}
619 673
620module_init(alsa_card_dummy_init) 674module_init(alsa_card_dummy_init)