aboutsummaryrefslogtreecommitdiffstats
path: root/sound/isa/sb/sb16.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/isa/sb/sb16.c')
-rw-r--r--sound/isa/sb/sb16.c369
1 files changed, 234 insertions, 135 deletions
diff --git a/sound/isa/sb/sb16.c b/sound/isa/sb/sb16.c
index c2fa451bc8f0..c0be7a5a3425 100644
--- a/sound/isa/sb/sb16.c
+++ b/sound/isa/sb/sb16.c
@@ -24,6 +24,8 @@
24#include <linux/init.h> 24#include <linux/init.h>
25#include <linux/slab.h> 25#include <linux/slab.h>
26#include <linux/pnp.h> 26#include <linux/pnp.h>
27#include <linux/err.h>
28#include <linux/platform_device.h>
27#include <linux/moduleparam.h> 29#include <linux/moduleparam.h>
28#include <sound/core.h> 30#include <sound/core.h>
29#include <sound/sb.h> 31#include <sound/sb.h>
@@ -32,7 +34,6 @@
32#include <sound/opl3.h> 34#include <sound/opl3.h>
33#include <sound/emu8000.h> 35#include <sound/emu8000.h>
34#include <sound/seq_device.h> 36#include <sound/seq_device.h>
35#define SNDRV_LEGACY_AUTO_PROBE
36#define SNDRV_LEGACY_FIND_FREE_IRQ 37#define SNDRV_LEGACY_FIND_FREE_IRQ
37#define SNDRV_LEGACY_FIND_FREE_DMA 38#define SNDRV_LEGACY_FIND_FREE_DMA
38#include <sound/initval.h> 39#include <sound/initval.h>
@@ -127,8 +128,14 @@ module_param_array(seq_ports, int, NULL, 0444);
127MODULE_PARM_DESC(seq_ports, "Number of sequencer ports for WaveTable synth."); 128MODULE_PARM_DESC(seq_ports, "Number of sequencer ports for WaveTable synth.");
128#endif 129#endif
129 130
131static struct platform_device *platform_devices[SNDRV_CARDS];
132#ifdef CONFIG_PNP
133static int pnp_registered;
134#endif
135
130struct snd_card_sb16 { 136struct snd_card_sb16 {
131 struct resource *fm_res; /* used to block FM i/o region for legacy cards */ 137 struct resource *fm_res; /* used to block FM i/o region for legacy cards */
138 struct snd_sb *chip;
132#ifdef CONFIG_PNP 139#ifdef CONFIG_PNP
133 int dev_no; 140 int dev_no;
134 struct pnp_dev *dev; 141 struct pnp_dev *dev;
@@ -138,8 +145,6 @@ struct snd_card_sb16 {
138#endif 145#endif
139}; 146};
140 147
141static snd_card_t *snd_sb16_legacy[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
142
143#ifdef CONFIG_PNP 148#ifdef CONFIG_PNP
144 149
145static struct pnp_card_device_id snd_sb16_pnpids[] = { 150static struct pnp_card_device_id snd_sb16_pnpids[] = {
@@ -339,9 +344,9 @@ __wt_error:
339 344
340#endif /* CONFIG_PNP */ 345#endif /* CONFIG_PNP */
341 346
342static void snd_sb16_free(snd_card_t *card) 347static void snd_sb16_free(struct snd_card *card)
343{ 348{
344 struct snd_card_sb16 *acard = (struct snd_card_sb16 *)card->private_data; 349 struct snd_card_sb16 *acard = card->private_data;
345 350
346 if (acard == NULL) 351 if (acard == NULL)
347 return; 352 return;
@@ -354,73 +359,32 @@ static void snd_sb16_free(snd_card_t *card)
354#define is_isapnp_selected(dev) 0 359#define is_isapnp_selected(dev) 0
355#endif 360#endif
356 361
357static int __init snd_sb16_probe(int dev, 362static struct snd_card *snd_sb16_card_new(int dev)
358 struct pnp_card_link *pcard, 363{
359 const struct pnp_card_device_id *pid) 364 struct snd_card *card = snd_card_new(index[dev], id[dev], THIS_MODULE,
365 sizeof(struct snd_card_sb16));
366 if (card == NULL)
367 return NULL;
368 card->private_free = snd_sb16_free;
369 return card;
370}
371
372static int __init snd_sb16_probe(struct snd_card *card, int dev)
360{ 373{
361 static int possible_irqs[] = {5, 9, 10, 7, -1};
362 static int possible_dmas8[] = {1, 3, 0, -1};
363 static int possible_dmas16[] = {5, 6, 7, -1};
364 int xirq, xdma8, xdma16; 374 int xirq, xdma8, xdma16;
365 sb_t *chip; 375 struct snd_sb *chip;
366 snd_card_t *card; 376 struct snd_card_sb16 *acard = card->private_data;
367 struct snd_card_sb16 *acard; 377 struct snd_opl3 *opl3;
368 opl3_t *opl3; 378 struct snd_hwdep *synth = NULL;
369 snd_hwdep_t *synth = NULL;
370#ifdef CONFIG_SND_SB16_CSP 379#ifdef CONFIG_SND_SB16_CSP
371 snd_hwdep_t *xcsp = NULL; 380 struct snd_hwdep *xcsp = NULL;
372#endif 381#endif
373 unsigned long flags; 382 unsigned long flags;
374 int err; 383 int err;
375 384
376 card = snd_card_new(index[dev], id[dev], THIS_MODULE,
377 sizeof(struct snd_card_sb16));
378 if (card == NULL)
379 return -ENOMEM;
380 acard = (struct snd_card_sb16 *) card->private_data;
381 card->private_free = snd_sb16_free;
382#ifdef CONFIG_PNP
383 if (isapnp[dev]) {
384 if ((err = snd_card_sb16_pnp(dev, acard, pcard, pid)))
385 goto _err;
386 snd_card_set_dev(card, &pcard->card->dev);
387 }
388#endif
389
390 xirq = irq[dev]; 385 xirq = irq[dev];
391 xdma8 = dma8[dev]; 386 xdma8 = dma8[dev];
392 xdma16 = dma16[dev]; 387 xdma16 = dma16[dev];
393 if (! is_isapnp_selected(dev)) {
394 if (xirq == SNDRV_AUTO_IRQ) {
395 if ((xirq = snd_legacy_find_free_irq(possible_irqs)) < 0) {
396 snd_printk(KERN_ERR PFX "unable to find a free IRQ\n");
397 err = -EBUSY;
398 goto _err;
399 }
400 }
401 if (xdma8 == SNDRV_AUTO_DMA) {
402 if ((xdma8 = snd_legacy_find_free_dma(possible_dmas8)) < 0) {
403 snd_printk(KERN_ERR PFX "unable to find a free 8-bit DMA\n");
404 err = -EBUSY;
405 goto _err;
406 }
407 }
408 if (xdma16 == SNDRV_AUTO_DMA) {
409 if ((xdma16 = snd_legacy_find_free_dma(possible_dmas16)) < 0) {
410 snd_printk(KERN_ERR PFX "unable to find a free 16-bit DMA\n");
411 err = -EBUSY;
412 goto _err;
413 }
414 }
415 /* non-PnP FM port address is hardwired with base port address */
416 fm_port[dev] = port[dev];
417 /* block the 0x388 port to avoid PnP conflicts */
418 acard->fm_res = request_region(0x388, 4, "SoundBlaster FM");
419#ifdef SNDRV_SBAWE_EMU8000
420 /* non-PnP AWE port address is hardwired with base port address */
421 awe_port[dev] = port[dev] + 0x400;
422#endif
423 }
424 388
425 if ((err = snd_sbdsp_create(card, 389 if ((err = snd_sbdsp_create(card,
426 port[dev], 390 port[dev],
@@ -430,19 +394,19 @@ static int __init snd_sb16_probe(int dev,
430 xdma16, 394 xdma16,
431 SB_HW_AUTO, 395 SB_HW_AUTO,
432 &chip)) < 0) 396 &chip)) < 0)
433 goto _err; 397 return err;
434 398
399 acard->chip = chip;
435 if (chip->hardware != SB_HW_16) { 400 if (chip->hardware != SB_HW_16) {
436 snd_printk(KERN_ERR PFX "SB 16 chip was not detected at 0x%lx\n", port[dev]); 401 snd_printk(KERN_ERR PFX "SB 16 chip was not detected at 0x%lx\n", port[dev]);
437 err = -ENODEV; 402 return -ENODEV;
438 goto _err;
439 } 403 }
440 chip->mpu_port = mpu_port[dev]; 404 chip->mpu_port = mpu_port[dev];
441 if (! is_isapnp_selected(dev) && (err = snd_sb16dsp_configure(chip)) < 0) 405 if (! is_isapnp_selected(dev) && (err = snd_sb16dsp_configure(chip)) < 0)
442 goto _err; 406 return err;
443 407
444 if ((err = snd_sb16dsp_pcm(chip, 0, NULL)) < 0) 408 if ((err = snd_sb16dsp_pcm(chip, 0, &chip->pcm)) < 0)
445 goto _err; 409 return err;
446 410
447 strcpy(card->driver, 411 strcpy(card->driver,
448#ifdef SNDRV_SBAWE_EMU8000 412#ifdef SNDRV_SBAWE_EMU8000
@@ -464,7 +428,7 @@ static int __init snd_sb16_probe(int dev,
464 if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_SB, 428 if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_SB,
465 chip->mpu_port, 0, 429 chip->mpu_port, 0,
466 xirq, 0, &chip->rmidi)) < 0) 430 xirq, 0, &chip->rmidi)) < 0)
467 goto _err; 431 return err;
468 chip->rmidi_callback = snd_mpu401_uart_interrupt; 432 chip->rmidi_callback = snd_mpu401_uart_interrupt;
469 } 433 }
470 434
@@ -487,12 +451,12 @@ static int __init snd_sb16_probe(int dev,
487 int seqdev = 1; 451 int seqdev = 1;
488#endif 452#endif
489 if ((err = snd_opl3_hwdep_new(opl3, 0, seqdev, &synth)) < 0) 453 if ((err = snd_opl3_hwdep_new(opl3, 0, seqdev, &synth)) < 0)
490 goto _err; 454 return err;
491 } 455 }
492 } 456 }
493 457
494 if ((err = snd_sbmixer_new(chip)) < 0) 458 if ((err = snd_sbmixer_new(chip)) < 0)
495 goto _err; 459 return err;
496 460
497#ifdef CONFIG_SND_SB16_CSP 461#ifdef CONFIG_SND_SB16_CSP
498 /* CSP chip on SB16ASP/AWE32 */ 462 /* CSP chip on SB16ASP/AWE32 */
@@ -512,7 +476,7 @@ static int __init snd_sb16_probe(int dev,
512 seq_ports[dev], NULL)) < 0) { 476 seq_ports[dev], NULL)) < 0) {
513 snd_printk(KERN_ERR PFX "fatal error - EMU-8000 synthesizer not detected at 0x%lx\n", awe_port[dev]); 477 snd_printk(KERN_ERR PFX "fatal error - EMU-8000 synthesizer not detected at 0x%lx\n", awe_port[dev]);
514 478
515 goto _err; 479 return err;
516 } 480 }
517 } 481 }
518#endif 482#endif
@@ -524,56 +488,168 @@ static int __init snd_sb16_probe(int dev,
524 (mic_agc[dev] ? 0x00 : 0x01)); 488 (mic_agc[dev] ? 0x00 : 0x01));
525 spin_unlock_irqrestore(&chip->mixer_lock, flags); 489 spin_unlock_irqrestore(&chip->mixer_lock, flags);
526 490
527 if ((err = snd_card_set_generic_dev(card)) < 0)
528 goto _err;
529
530 if ((err = snd_card_register(card)) < 0) 491 if ((err = snd_card_register(card)) < 0)
531 goto _err; 492 return err;
532 493
533 if (pcard)
534 pnp_set_card_drvdata(pcard, card);
535 else
536 snd_sb16_legacy[dev] = card;
537 return 0; 494 return 0;
495}
538 496
539 _err: 497#ifdef CONFIG_PM
540 snd_card_free(card); 498static int snd_sb16_suspend(struct snd_card *card, pm_message_t state)
541 return err; 499{
500 struct snd_card_sb16 *acard = card->private_data;
501 struct snd_sb *chip = acard->chip;
502
503 snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
504 snd_pcm_suspend_all(chip->pcm);
505 snd_sbmixer_suspend(chip);
506 return 0;
542} 507}
543 508
544static int __init snd_sb16_probe_legacy_port(unsigned long xport) 509static int snd_sb16_resume(struct snd_card *card)
545{ 510{
546 static int dev; 511 struct snd_card_sb16 *acard = card->private_data;
547 int res; 512 struct snd_sb *chip = acard->chip;
548 513
549 for ( ; dev < SNDRV_CARDS; dev++) { 514 snd_sbdsp_reset(chip);
550 if (!enable[dev] || port[dev] != SNDRV_AUTO_PORT) 515 snd_sbmixer_resume(chip);
551 continue; 516 snd_power_change_state(card, SNDRV_CTL_POWER_D0);
552 if (is_isapnp_selected(dev)) 517 return 0;
553 continue; 518}
554 port[dev] = xport; 519#endif
555 res = snd_sb16_probe(dev, NULL, NULL); 520
556 if (res < 0) 521static int __init snd_sb16_nonpnp_probe1(int dev, struct platform_device *devptr)
557 port[dev] = SNDRV_AUTO_PORT; 522{
558 return res; 523 struct snd_card_sb16 *acard;
524 struct snd_card *card;
525 int err;
526
527 card = snd_sb16_card_new(dev);
528 if (! card)
529 return -ENOMEM;
530
531 acard = card->private_data;
532 /* non-PnP FM port address is hardwired with base port address */
533 fm_port[dev] = port[dev];
534 /* block the 0x388 port to avoid PnP conflicts */
535 acard->fm_res = request_region(0x388, 4, "SoundBlaster FM");
536#ifdef SNDRV_SBAWE_EMU8000
537 /* non-PnP AWE port address is hardwired with base port address */
538 awe_port[dev] = port[dev] + 0x400;
539#endif
540
541 snd_card_set_dev(card, &devptr->dev);
542 if ((err = snd_sb16_probe(card, dev)) < 0) {
543 snd_card_free(card);
544 return err;
559 } 545 }
560 return -ENODEV; 546 platform_set_drvdata(devptr, card);
547 return 0;
561} 548}
562 549
550
551static int __init snd_sb16_nonpnp_probe(struct platform_device *pdev)
552{
553 int dev = pdev->id;
554 int err;
555 static int possible_irqs[] = {5, 9, 10, 7, -1};
556 static int possible_dmas8[] = {1, 3, 0, -1};
557 static int possible_dmas16[] = {5, 6, 7, -1};
558
559 if (irq[dev] == SNDRV_AUTO_IRQ) {
560 if ((irq[dev] = snd_legacy_find_free_irq(possible_irqs)) < 0) {
561 snd_printk(KERN_ERR PFX "unable to find a free IRQ\n");
562 return -EBUSY;
563 }
564 }
565 if (dma8[dev] == SNDRV_AUTO_DMA) {
566 if ((dma8[dev] = snd_legacy_find_free_dma(possible_dmas8)) < 0) {
567 snd_printk(KERN_ERR PFX "unable to find a free 8-bit DMA\n");
568 return -EBUSY;
569 }
570 }
571 if (dma16[dev] == SNDRV_AUTO_DMA) {
572 if ((dma16[dev] = snd_legacy_find_free_dma(possible_dmas16)) < 0) {
573 snd_printk(KERN_ERR PFX "unable to find a free 16-bit DMA\n");
574 return -EBUSY;
575 }
576 }
577
578 if (port[dev] != SNDRV_AUTO_PORT)
579 return snd_sb16_nonpnp_probe1(dev, pdev);
580 else {
581 static int possible_ports[] = {0x220, 0x240, 0x260, 0x280};
582 int i;
583 for (i = 0; i < ARRAY_SIZE(possible_ports); i++) {
584 port[dev] = possible_ports[i];
585 err = snd_sb16_nonpnp_probe1(dev, pdev);
586 if (! err)
587 return 0;
588 }
589 return err;
590 }
591}
592
593static int __devexit snd_sb16_nonpnp_remove(struct platform_device *devptr)
594{
595 snd_card_free(platform_get_drvdata(devptr));
596 platform_set_drvdata(devptr, NULL);
597 return 0;
598}
599
600#ifdef CONFIG_PM
601static int snd_sb16_nonpnp_suspend(struct platform_device *dev, pm_message_t state)
602{
603 return snd_sb16_suspend(platform_get_drvdata(dev), state);
604}
605
606static int snd_sb16_nonpnp_resume(struct platform_device *dev)
607{
608 return snd_sb16_resume(platform_get_drvdata(dev));
609}
610#endif
611
612#ifdef SNDRV_SBAWE
613#define SND_SB16_DRIVER "snd_sbawe"
614#else
615#define SND_SB16_DRIVER "snd_sb16"
616#endif
617
618static struct platform_driver snd_sb16_nonpnp_driver = {
619 .probe = snd_sb16_nonpnp_probe,
620 .remove = __devexit_p(snd_sb16_nonpnp_remove),
621#ifdef CONFIG_PM
622 .suspend = snd_sb16_nonpnp_suspend,
623 .resume = snd_sb16_nonpnp_resume,
624#endif
625 .driver = {
626 .name = SND_SB16_DRIVER
627 },
628};
629
630
563#ifdef CONFIG_PNP 631#ifdef CONFIG_PNP
564 632
565static int __devinit snd_sb16_pnp_detect(struct pnp_card_link *card, 633static int __devinit snd_sb16_pnp_detect(struct pnp_card_link *pcard,
566 const struct pnp_card_device_id *id) 634 const struct pnp_card_device_id *pid)
567{ 635{
568 static int dev; 636 static int dev;
637 struct snd_card *card;
569 int res; 638 int res;
570 639
571 for ( ; dev < SNDRV_CARDS; dev++) { 640 for ( ; dev < SNDRV_CARDS; dev++) {
572 if (!enable[dev] || !isapnp[dev]) 641 if (!enable[dev] || !isapnp[dev])
573 continue; 642 continue;
574 res = snd_sb16_probe(dev, card, id); 643 card = snd_sb16_card_new(dev);
575 if (res < 0) 644 if (! card)
645 return -ENOMEM;
646 snd_card_set_dev(card, &pcard->card->dev);
647 if ((res = snd_card_sb16_pnp(dev, card->private_data, pcard, pid)) < 0 ||
648 (res = snd_sb16_probe(card, dev)) < 0) {
649 snd_card_free(card);
576 return res; 650 return res;
651 }
652 pnp_set_card_drvdata(pcard, card);
577 dev++; 653 dev++;
578 return 0; 654 return 0;
579 } 655 }
@@ -583,57 +659,82 @@ static int __devinit snd_sb16_pnp_detect(struct pnp_card_link *card,
583 659
584static void __devexit snd_sb16_pnp_remove(struct pnp_card_link * pcard) 660static void __devexit snd_sb16_pnp_remove(struct pnp_card_link * pcard)
585{ 661{
586 snd_card_t *card = (snd_card_t *) pnp_get_card_drvdata(pcard); 662 snd_card_free(pnp_get_card_drvdata(pcard));
663 pnp_set_card_drvdata(pcard, NULL);
664}
587 665
588 snd_card_disconnect(card); 666#ifdef CONFIG_PM
589 snd_card_free_in_thread(card); 667static int snd_sb16_pnp_suspend(struct pnp_card_link *pcard, pm_message_t state)
668{
669 return snd_sb16_suspend(pnp_get_card_drvdata(pcard), state);
590} 670}
671static int snd_sb16_pnp_resume(struct pnp_card_link *pcard)
672{
673 return snd_sb16_resume(pnp_get_card_drvdata(pcard));
674}
675#endif
591 676
592static struct pnp_card_driver sb16_pnpc_driver = { 677static struct pnp_card_driver sb16_pnpc_driver = {
593 .flags = PNP_DRIVER_RES_DISABLE, 678 .flags = PNP_DRIVER_RES_DISABLE,
679#ifdef SNDRV_SBAWE
680 .name = "sbawe",
681#else
594 .name = "sb16", 682 .name = "sb16",
683#endif
595 .id_table = snd_sb16_pnpids, 684 .id_table = snd_sb16_pnpids,
596 .probe = snd_sb16_pnp_detect, 685 .probe = snd_sb16_pnp_detect,
597 .remove = __devexit_p(snd_sb16_pnp_remove), 686 .remove = __devexit_p(snd_sb16_pnp_remove),
687#ifdef CONFIG_PM
688 .suspend = snd_sb16_pnp_suspend,
689 .resume = snd_sb16_pnp_resume,
690#endif
598}; 691};
599 692
600#endif /* CONFIG_PNP */ 693#endif /* CONFIG_PNP */
601 694
695static void __init_or_module snd_sb16_unregister_all(void)
696{
697 int i;
698
699#ifdef CONFIG_PNP
700 if (pnp_registered)
701 pnp_unregister_card_driver(&sb16_pnpc_driver);
702#endif
703 for (i = 0; i < ARRAY_SIZE(platform_devices); ++i)
704 platform_device_unregister(platform_devices[i]);
705 platform_driver_unregister(&snd_sb16_nonpnp_driver);
706}
707
602static int __init alsa_card_sb16_init(void) 708static int __init alsa_card_sb16_init(void)
603{ 709{
604 int dev, cards = 0, i; 710 int i, err, cards = 0;
605 static unsigned long possible_ports[] = {0x220, 0x240, 0x260, 0x280, -1};
606 711
607 /* legacy non-auto cards at first */ 712 if ((err = platform_driver_register(&snd_sb16_nonpnp_driver)) < 0)
608 for (dev = 0; dev < SNDRV_CARDS; dev++) { 713 return err;
609 if (!enable[dev] || port[dev] == SNDRV_AUTO_PORT) 714
610 continue; 715 for (i = 0; i < SNDRV_CARDS && enable[i]; i++) {
611 if (is_isapnp_selected(dev)) 716 struct platform_device *device;
612 continue; 717 if (is_isapnp_selected(i))
613 if (!snd_sb16_probe(dev, NULL, NULL)) {
614 cards++;
615 continue; 718 continue;
719 device = platform_device_register_simple(SND_SB16_DRIVER,
720 i, NULL, 0);
721 if (IS_ERR(device)) {
722 err = PTR_ERR(device);
723 goto errout;
616 } 724 }
617#ifdef MODULE 725 platform_devices[i] = device;
618 snd_printk(KERN_ERR "Sound Blaster 16+ soundcard #%i not found at 0x%lx or device busy\n", dev, port[dev]); 726 cards++;
619#endif
620 } 727 }
621 /* legacy auto configured cards */
622 i = snd_legacy_auto_probe(possible_ports, snd_sb16_probe_legacy_port);
623 if (i > 0)
624 cards += i;
625
626#ifdef CONFIG_PNP 728#ifdef CONFIG_PNP
627 /* PnP cards at last */ 729 /* PnP cards at last */
628 i = pnp_register_card_driver(&sb16_pnpc_driver); 730 i = pnp_register_card_driver(&sb16_pnpc_driver);
629 if (i >0) 731 if (i >= 0) {
732 pnp_registered = 1;
630 cards += i; 733 cards += i;
734 }
631#endif 735#endif
632 736
633 if (!cards) { 737 if (!cards) {
634#ifdef CONFIG_PNP
635 pnp_unregister_card_driver(&sb16_pnpc_driver);
636#endif
637#ifdef MODULE 738#ifdef MODULE
638 snd_printk(KERN_ERR "Sound Blaster 16 soundcard not found or device busy\n"); 739 snd_printk(KERN_ERR "Sound Blaster 16 soundcard not found or device busy\n");
639#ifdef SNDRV_SBAWE_EMU8000 740#ifdef SNDRV_SBAWE_EMU8000
@@ -642,21 +743,19 @@ static int __init alsa_card_sb16_init(void)
642 snd_printk(KERN_ERR "In case, if you have AWE card, try snd-sbawe module\n"); 743 snd_printk(KERN_ERR "In case, if you have AWE card, try snd-sbawe module\n");
643#endif 744#endif
644#endif 745#endif
645 return -ENODEV; 746 err = -ENODEV;
747 goto errout;
646 } 748 }
647 return 0; 749 return 0;
750
751 errout:
752 snd_sb16_unregister_all();
753 return err;
648} 754}
649 755
650static void __exit alsa_card_sb16_exit(void) 756static void __exit alsa_card_sb16_exit(void)
651{ 757{
652 int dev; 758 snd_sb16_unregister_all();
653
654#ifdef CONFIG_PNP
655 /* PnP cards first */
656 pnp_unregister_card_driver(&sb16_pnpc_driver);
657#endif
658 for (dev = 0; dev < SNDRV_CARDS; dev++)
659 snd_card_free(snd_sb16_legacy[dev]);
660} 759}
661 760
662module_init(alsa_card_sb16_init) 761module_init(alsa_card_sb16_init)