diff options
author | Takashi Iwai <tiwai@suse.de> | 2005-11-17 10:54:56 -0500 |
---|---|---|
committer | Jaroslav Kysela <perex@suse.cz> | 2006-01-03 06:28:05 -0500 |
commit | 6f045616aff91022966b5c37ba6845791dd125dc (patch) | |
tree | 273a962fbd5fcdd131f194cdc9b91ab0c409c98c /sound/isa/sb | |
parent | 703529140cfb774366b839f38f027f283cb948b4 (diff) |
[ALSA] sb16 - Use platform_device and add PnP support
Modules: SB16/AWE driver
Rewrite the probe/remove with platform_device.
Add PM support using PnP suspend/resume callbacks.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/isa/sb')
-rw-r--r-- | sound/isa/sb/sb16.c | 327 |
1 files changed, 204 insertions, 123 deletions
diff --git a/sound/isa/sb/sb16.c b/sound/isa/sb/sb16.c index 96e401333437..05816c5d829a 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> |
@@ -129,6 +130,7 @@ MODULE_PARM_DESC(seq_ports, "Number of sequencer ports for WaveTable synth."); | |||
129 | 130 | ||
130 | struct snd_card_sb16 { | 131 | struct snd_card_sb16 { |
131 | struct resource *fm_res; /* used to block FM i/o region for legacy cards */ | 132 | struct resource *fm_res; /* used to block FM i/o region for legacy cards */ |
133 | struct snd_sb *chip; | ||
132 | #ifdef CONFIG_PNP | 134 | #ifdef CONFIG_PNP |
133 | int dev_no; | 135 | int dev_no; |
134 | struct pnp_dev *dev; | 136 | struct pnp_dev *dev; |
@@ -138,8 +140,6 @@ struct snd_card_sb16 { | |||
138 | #endif | 140 | #endif |
139 | }; | 141 | }; |
140 | 142 | ||
141 | static struct snd_card *snd_sb16_legacy[SNDRV_CARDS] = SNDRV_DEFAULT_PTR; | ||
142 | |||
143 | #ifdef CONFIG_PNP | 143 | #ifdef CONFIG_PNP |
144 | 144 | ||
145 | static struct pnp_card_device_id snd_sb16_pnpids[] = { | 145 | static struct pnp_card_device_id snd_sb16_pnpids[] = { |
@@ -341,7 +341,7 @@ __wt_error: | |||
341 | 341 | ||
342 | static void snd_sb16_free(struct snd_card *card) | 342 | static void snd_sb16_free(struct snd_card *card) |
343 | { | 343 | { |
344 | struct snd_card_sb16 *acard = (struct snd_card_sb16 *)card->private_data; | 344 | struct snd_card_sb16 *acard = card->private_data; |
345 | 345 | ||
346 | if (acard == NULL) | 346 | if (acard == NULL) |
347 | return; | 347 | return; |
@@ -354,17 +354,21 @@ static void snd_sb16_free(struct snd_card *card) | |||
354 | #define is_isapnp_selected(dev) 0 | 354 | #define is_isapnp_selected(dev) 0 |
355 | #endif | 355 | #endif |
356 | 356 | ||
357 | static int __init snd_sb16_probe(int dev, | 357 | static struct snd_card *snd_sb16_card_new(int dev) |
358 | struct pnp_card_link *pcard, | 358 | { |
359 | const struct pnp_card_device_id *pid) | 359 | struct snd_card *card = snd_card_new(index[dev], id[dev], THIS_MODULE, |
360 | sizeof(struct snd_card_sb16)); | ||
361 | if (card == NULL) | ||
362 | return NULL; | ||
363 | card->private_free = snd_sb16_free; | ||
364 | return card; | ||
365 | } | ||
366 | |||
367 | static int __init snd_sb16_probe(struct snd_card *card, int dev) | ||
360 | { | 368 | { |
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; | 369 | int xirq, xdma8, xdma16; |
365 | struct snd_sb *chip; | 370 | struct snd_sb *chip; |
366 | struct snd_card *card; | 371 | struct snd_card_sb16 *acard = card->private_data; |
367 | struct snd_card_sb16 *acard; | ||
368 | struct snd_opl3 *opl3; | 372 | struct snd_opl3 *opl3; |
369 | struct snd_hwdep *synth = NULL; | 373 | struct snd_hwdep *synth = NULL; |
370 | #ifdef CONFIG_SND_SB16_CSP | 374 | #ifdef CONFIG_SND_SB16_CSP |
@@ -373,54 +377,9 @@ static int __init snd_sb16_probe(int dev, | |||
373 | unsigned long flags; | 377 | unsigned long flags; |
374 | int err; | 378 | int err; |
375 | 379 | ||
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]; | 380 | xirq = irq[dev]; |
391 | xdma8 = dma8[dev]; | 381 | xdma8 = dma8[dev]; |
392 | xdma16 = dma16[dev]; | 382 | 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 | 383 | ||
425 | if ((err = snd_sbdsp_create(card, | 384 | if ((err = snd_sbdsp_create(card, |
426 | port[dev], | 385 | port[dev], |
@@ -430,19 +389,19 @@ static int __init snd_sb16_probe(int dev, | |||
430 | xdma16, | 389 | xdma16, |
431 | SB_HW_AUTO, | 390 | SB_HW_AUTO, |
432 | &chip)) < 0) | 391 | &chip)) < 0) |
433 | goto _err; | 392 | return err; |
434 | 393 | ||
394 | acard->chip = chip; | ||
435 | if (chip->hardware != SB_HW_16) { | 395 | if (chip->hardware != SB_HW_16) { |
436 | snd_printk(KERN_ERR PFX "SB 16 chip was not detected at 0x%lx\n", port[dev]); | 396 | snd_printk(KERN_ERR PFX "SB 16 chip was not detected at 0x%lx\n", port[dev]); |
437 | err = -ENODEV; | 397 | return -ENODEV; |
438 | goto _err; | ||
439 | } | 398 | } |
440 | chip->mpu_port = mpu_port[dev]; | 399 | chip->mpu_port = mpu_port[dev]; |
441 | if (! is_isapnp_selected(dev) && (err = snd_sb16dsp_configure(chip)) < 0) | 400 | if (! is_isapnp_selected(dev) && (err = snd_sb16dsp_configure(chip)) < 0) |
442 | goto _err; | 401 | return err; |
443 | 402 | ||
444 | if ((err = snd_sb16dsp_pcm(chip, 0, NULL)) < 0) | 403 | if ((err = snd_sb16dsp_pcm(chip, 0, &chip->pcm)) < 0) |
445 | goto _err; | 404 | return err; |
446 | 405 | ||
447 | strcpy(card->driver, | 406 | strcpy(card->driver, |
448 | #ifdef SNDRV_SBAWE_EMU8000 | 407 | #ifdef SNDRV_SBAWE_EMU8000 |
@@ -464,7 +423,7 @@ static int __init snd_sb16_probe(int dev, | |||
464 | if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_SB, | 423 | if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_SB, |
465 | chip->mpu_port, 0, | 424 | chip->mpu_port, 0, |
466 | xirq, 0, &chip->rmidi)) < 0) | 425 | xirq, 0, &chip->rmidi)) < 0) |
467 | goto _err; | 426 | return err; |
468 | chip->rmidi_callback = snd_mpu401_uart_interrupt; | 427 | chip->rmidi_callback = snd_mpu401_uart_interrupt; |
469 | } | 428 | } |
470 | 429 | ||
@@ -487,12 +446,12 @@ static int __init snd_sb16_probe(int dev, | |||
487 | int seqdev = 1; | 446 | int seqdev = 1; |
488 | #endif | 447 | #endif |
489 | if ((err = snd_opl3_hwdep_new(opl3, 0, seqdev, &synth)) < 0) | 448 | if ((err = snd_opl3_hwdep_new(opl3, 0, seqdev, &synth)) < 0) |
490 | goto _err; | 449 | return err; |
491 | } | 450 | } |
492 | } | 451 | } |
493 | 452 | ||
494 | if ((err = snd_sbmixer_new(chip)) < 0) | 453 | if ((err = snd_sbmixer_new(chip)) < 0) |
495 | goto _err; | 454 | return err; |
496 | 455 | ||
497 | #ifdef CONFIG_SND_SB16_CSP | 456 | #ifdef CONFIG_SND_SB16_CSP |
498 | /* CSP chip on SB16ASP/AWE32 */ | 457 | /* CSP chip on SB16ASP/AWE32 */ |
@@ -512,7 +471,7 @@ static int __init snd_sb16_probe(int dev, | |||
512 | seq_ports[dev], NULL)) < 0) { | 471 | 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]); | 472 | snd_printk(KERN_ERR PFX "fatal error - EMU-8000 synthesizer not detected at 0x%lx\n", awe_port[dev]); |
514 | 473 | ||
515 | goto _err; | 474 | return err; |
516 | } | 475 | } |
517 | } | 476 | } |
518 | #endif | 477 | #endif |
@@ -524,56 +483,168 @@ static int __init snd_sb16_probe(int dev, | |||
524 | (mic_agc[dev] ? 0x00 : 0x01)); | 483 | (mic_agc[dev] ? 0x00 : 0x01)); |
525 | spin_unlock_irqrestore(&chip->mixer_lock, flags); | 484 | spin_unlock_irqrestore(&chip->mixer_lock, flags); |
526 | 485 | ||
527 | if ((err = snd_card_set_generic_dev(card)) < 0) | ||
528 | goto _err; | ||
529 | |||
530 | if ((err = snd_card_register(card)) < 0) | 486 | if ((err = snd_card_register(card)) < 0) |
531 | goto _err; | 487 | return err; |
532 | 488 | ||
533 | if (pcard) | ||
534 | pnp_set_card_drvdata(pcard, card); | ||
535 | else | ||
536 | snd_sb16_legacy[dev] = card; | ||
537 | return 0; | 489 | return 0; |
490 | } | ||
491 | |||
492 | #ifdef CONFIG_PM | ||
493 | static int snd_sb16_suspend(struct snd_card *card, pm_message_t state) | ||
494 | { | ||
495 | struct snd_card_sb16 *acard = card->private_data; | ||
496 | struct snd_sb *chip = acard->chip; | ||
538 | 497 | ||
539 | _err: | 498 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); |
540 | snd_card_free(card); | 499 | snd_pcm_suspend_all(chip->pcm); |
541 | return err; | 500 | snd_sbmixer_suspend(chip); |
501 | return 0; | ||
542 | } | 502 | } |
543 | 503 | ||
544 | static int __init snd_sb16_probe_legacy_port(unsigned long xport) | 504 | static int snd_sb16_resume(struct snd_card *card) |
545 | { | 505 | { |
546 | static int dev; | 506 | struct snd_card_sb16 *acard = card->private_data; |
547 | int res; | 507 | struct snd_sb *chip = acard->chip; |
548 | 508 | ||
549 | for ( ; dev < SNDRV_CARDS; dev++) { | 509 | snd_sbdsp_reset(chip); |
550 | if (!enable[dev] || port[dev] != SNDRV_AUTO_PORT) | 510 | snd_sbmixer_resume(chip); |
551 | continue; | 511 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); |
552 | if (is_isapnp_selected(dev)) | 512 | return 0; |
553 | continue; | 513 | } |
554 | port[dev] = xport; | 514 | #endif |
555 | res = snd_sb16_probe(dev, NULL, NULL); | 515 | |
556 | if (res < 0) | 516 | static int __init snd_sb16_nonpnp_probe1(int dev, struct platform_device *devptr) |
557 | port[dev] = SNDRV_AUTO_PORT; | 517 | { |
558 | return res; | 518 | struct snd_card_sb16 *acard; |
519 | struct snd_card *card; | ||
520 | int err; | ||
521 | |||
522 | card = snd_sb16_card_new(dev); | ||
523 | if (! card) | ||
524 | return -ENOMEM; | ||
525 | |||
526 | acard = card->private_data; | ||
527 | /* non-PnP FM port address is hardwired with base port address */ | ||
528 | fm_port[dev] = port[dev]; | ||
529 | /* block the 0x388 port to avoid PnP conflicts */ | ||
530 | acard->fm_res = request_region(0x388, 4, "SoundBlaster FM"); | ||
531 | #ifdef SNDRV_SBAWE_EMU8000 | ||
532 | /* non-PnP AWE port address is hardwired with base port address */ | ||
533 | awe_port[dev] = port[dev] + 0x400; | ||
534 | #endif | ||
535 | |||
536 | snd_card_set_dev(card, &devptr->dev); | ||
537 | if ((err = snd_sb16_probe(card, dev)) < 0) { | ||
538 | snd_card_free(card); | ||
539 | return err; | ||
559 | } | 540 | } |
560 | return -ENODEV; | 541 | platform_set_drvdata(devptr, card); |
542 | return 0; | ||
561 | } | 543 | } |
562 | 544 | ||
545 | |||
546 | static int __init snd_sb16_nonpnp_probe(struct platform_device *pdev) | ||
547 | { | ||
548 | int dev = pdev->id; | ||
549 | int err; | ||
550 | static int possible_irqs[] = {5, 9, 10, 7, -1}; | ||
551 | static int possible_dmas8[] = {1, 3, 0, -1}; | ||
552 | static int possible_dmas16[] = {5, 6, 7, -1}; | ||
553 | |||
554 | if (irq[dev] == SNDRV_AUTO_IRQ) { | ||
555 | if ((irq[dev] = snd_legacy_find_free_irq(possible_irqs)) < 0) { | ||
556 | snd_printk(KERN_ERR PFX "unable to find a free IRQ\n"); | ||
557 | return -EBUSY; | ||
558 | } | ||
559 | } | ||
560 | if (dma8[dev] == SNDRV_AUTO_DMA) { | ||
561 | if ((dma8[dev] = snd_legacy_find_free_dma(possible_dmas8)) < 0) { | ||
562 | snd_printk(KERN_ERR PFX "unable to find a free 8-bit DMA\n"); | ||
563 | return -EBUSY; | ||
564 | } | ||
565 | } | ||
566 | if (dma16[dev] == SNDRV_AUTO_DMA) { | ||
567 | if ((dma16[dev] = snd_legacy_find_free_dma(possible_dmas16)) < 0) { | ||
568 | snd_printk(KERN_ERR PFX "unable to find a free 16-bit DMA\n"); | ||
569 | return -EBUSY; | ||
570 | } | ||
571 | } | ||
572 | |||
573 | if (port[dev] != SNDRV_AUTO_PORT) | ||
574 | return snd_sb16_nonpnp_probe1(dev, pdev); | ||
575 | else { | ||
576 | static int possible_ports[] = {0x220, 0x240, 0x260, 0x280}; | ||
577 | int i; | ||
578 | for (i = 0; i < ARRAY_SIZE(possible_ports); i++) { | ||
579 | port[dev] = possible_ports[i]; | ||
580 | err = snd_sb16_nonpnp_probe1(dev, pdev); | ||
581 | if (! err) | ||
582 | return 0; | ||
583 | } | ||
584 | return err; | ||
585 | } | ||
586 | } | ||
587 | |||
588 | static int __devexit snd_sb16_nonpnp_remove(struct platform_device *devptr) | ||
589 | { | ||
590 | snd_card_free(platform_get_drvdata(devptr)); | ||
591 | platform_set_drvdata(devptr, NULL); | ||
592 | return 0; | ||
593 | } | ||
594 | |||
595 | #ifdef CONFIG_PM | ||
596 | static int snd_sb16_nonpnp_suspend(struct platform_device *dev, pm_message_t state) | ||
597 | { | ||
598 | return snd_sb16_suspend(platform_get_drvdata(dev), state); | ||
599 | } | ||
600 | |||
601 | static int snd_sb16_nonpnp_resume(struct platform_device *dev) | ||
602 | { | ||
603 | return snd_sb16_resume(platform_get_drvdata(dev)); | ||
604 | } | ||
605 | #endif | ||
606 | |||
607 | #ifdef SNDRV_SBAWE | ||
608 | #define SND_SB16_DRIVER "snd_sbawe" | ||
609 | #else | ||
610 | #define SND_SB16_DRIVER "snd_sb16" | ||
611 | #endif | ||
612 | |||
613 | static struct platform_driver snd_sb16_nonpnp_driver = { | ||
614 | .probe = snd_sb16_nonpnp_probe, | ||
615 | .remove = __devexit_p(snd_sb16_nonpnp_remove), | ||
616 | #ifdef CONFIG_PM | ||
617 | .suspend = snd_sb16_nonpnp_suspend, | ||
618 | .resume = snd_sb16_nonpnp_resume, | ||
619 | #endif | ||
620 | .driver = { | ||
621 | .name = SND_SB16_DRIVER | ||
622 | }, | ||
623 | }; | ||
624 | |||
625 | |||
563 | #ifdef CONFIG_PNP | 626 | #ifdef CONFIG_PNP |
564 | 627 | ||
565 | static int __devinit snd_sb16_pnp_detect(struct pnp_card_link *card, | 628 | static int __devinit snd_sb16_pnp_detect(struct pnp_card_link *pcard, |
566 | const struct pnp_card_device_id *id) | 629 | const struct pnp_card_device_id *pid) |
567 | { | 630 | { |
568 | static int dev; | 631 | static int dev; |
632 | struct snd_card *card; | ||
569 | int res; | 633 | int res; |
570 | 634 | ||
571 | for ( ; dev < SNDRV_CARDS; dev++) { | 635 | for ( ; dev < SNDRV_CARDS; dev++) { |
572 | if (!enable[dev] || !isapnp[dev]) | 636 | if (!enable[dev] || !isapnp[dev]) |
573 | continue; | 637 | continue; |
574 | res = snd_sb16_probe(dev, card, id); | 638 | card = snd_sb16_card_new(dev); |
575 | if (res < 0) | 639 | if (! card) |
640 | return -ENOMEM; | ||
641 | snd_card_set_dev(card, &pcard->card->dev); | ||
642 | if ((res = snd_card_sb16_pnp(dev, card->private_data, pcard, pid)) < 0 || | ||
643 | (res = snd_sb16_probe(card, dev)) < 0) { | ||
644 | snd_card_free(card); | ||
576 | return res; | 645 | return res; |
646 | } | ||
647 | pnp_set_card_drvdata(pcard, card); | ||
577 | dev++; | 648 | dev++; |
578 | return 0; | 649 | return 0; |
579 | } | 650 | } |
@@ -583,50 +654,63 @@ static int __devinit snd_sb16_pnp_detect(struct pnp_card_link *card, | |||
583 | 654 | ||
584 | static void __devexit snd_sb16_pnp_remove(struct pnp_card_link * pcard) | 655 | static void __devexit snd_sb16_pnp_remove(struct pnp_card_link * pcard) |
585 | { | 656 | { |
586 | struct snd_card *card = (struct snd_card *) pnp_get_card_drvdata(pcard); | 657 | snd_card_free(pnp_get_card_drvdata(pcard)); |
658 | pnp_set_card_drvdata(pcard, NULL); | ||
659 | } | ||
587 | 660 | ||
588 | snd_card_disconnect(card); | 661 | #ifdef CONFIG_PM |
589 | snd_card_free_in_thread(card); | 662 | static int snd_sb16_pnp_suspend(struct pnp_card_link *pcard, pm_message_t state) |
663 | { | ||
664 | return snd_sb16_suspend(pnp_get_card_drvdata(pcard), state); | ||
590 | } | 665 | } |
666 | static int snd_sb16_pnp_resume(struct pnp_card_link *pcard) | ||
667 | { | ||
668 | return snd_sb16_resume(pnp_get_card_drvdata(pcard)); | ||
669 | } | ||
670 | #endif | ||
591 | 671 | ||
592 | static struct pnp_card_driver sb16_pnpc_driver = { | 672 | static struct pnp_card_driver sb16_pnpc_driver = { |
593 | .flags = PNP_DRIVER_RES_DISABLE, | 673 | .flags = PNP_DRIVER_RES_DISABLE, |
674 | #ifdef SNDRV_SBAWE | ||
675 | .name = "sbawe", | ||
676 | #else | ||
594 | .name = "sb16", | 677 | .name = "sb16", |
678 | #endif | ||
595 | .id_table = snd_sb16_pnpids, | 679 | .id_table = snd_sb16_pnpids, |
596 | .probe = snd_sb16_pnp_detect, | 680 | .probe = snd_sb16_pnp_detect, |
597 | .remove = __devexit_p(snd_sb16_pnp_remove), | 681 | .remove = __devexit_p(snd_sb16_pnp_remove), |
682 | #ifdef CONFIG_PM | ||
683 | .suspend = snd_sb16_pnp_suspend, | ||
684 | .resume = snd_sb16_pnp_resume, | ||
685 | #endif | ||
598 | }; | 686 | }; |
599 | 687 | ||
600 | #endif /* CONFIG_PNP */ | 688 | #endif /* CONFIG_PNP */ |
601 | 689 | ||
602 | static int __init alsa_card_sb16_init(void) | 690 | static int __init alsa_card_sb16_init(void) |
603 | { | 691 | { |
604 | int dev, cards = 0, i; | 692 | int i, err, cards = 0; |
605 | static unsigned long possible_ports[] = {0x220, 0x240, 0x260, 0x280, -1}; | ||
606 | 693 | ||
607 | /* legacy non-auto cards at first */ | 694 | if ((err = platform_driver_register(&snd_sb16_nonpnp_driver)) < 0) |
608 | for (dev = 0; dev < SNDRV_CARDS; dev++) { | 695 | return err; |
609 | if (!enable[dev] || port[dev] == SNDRV_AUTO_PORT) | 696 | |
610 | continue; | 697 | for (i = 0; i < SNDRV_CARDS && enable[i]; i++) { |
611 | if (is_isapnp_selected(dev)) | 698 | struct platform_device *device; |
612 | continue; | 699 | if (is_isapnp_selected(i)) |
613 | if (!snd_sb16_probe(dev, NULL, NULL)) { | ||
614 | cards++; | ||
615 | continue; | 700 | continue; |
701 | device = platform_device_register_simple(SND_SB16_DRIVER, | ||
702 | i, NULL, 0); | ||
703 | if (IS_ERR(device)) { | ||
704 | err = PTR_ERR(device); | ||
705 | platform_driver_unregister(&snd_sb16_nonpnp_driver); | ||
706 | return err; | ||
616 | } | 707 | } |
617 | #ifdef MODULE | 708 | cards++; |
618 | snd_printk(KERN_ERR "Sound Blaster 16+ soundcard #%i not found at 0x%lx or device busy\n", dev, port[dev]); | ||
619 | #endif | ||
620 | } | 709 | } |
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 | 710 | #ifdef CONFIG_PNP |
627 | /* PnP cards at last */ | 711 | /* PnP cards at last */ |
628 | i = pnp_register_card_driver(&sb16_pnpc_driver); | 712 | i = pnp_register_card_driver(&sb16_pnpc_driver); |
629 | if (i >0) | 713 | if (i > 0) |
630 | cards += i; | 714 | cards += i; |
631 | #endif | 715 | #endif |
632 | 716 | ||
@@ -634,6 +718,7 @@ static int __init alsa_card_sb16_init(void) | |||
634 | #ifdef CONFIG_PNP | 718 | #ifdef CONFIG_PNP |
635 | pnp_unregister_card_driver(&sb16_pnpc_driver); | 719 | pnp_unregister_card_driver(&sb16_pnpc_driver); |
636 | #endif | 720 | #endif |
721 | platform_driver_unregister(&snd_sb16_nonpnp_driver); | ||
637 | #ifdef MODULE | 722 | #ifdef MODULE |
638 | snd_printk(KERN_ERR "Sound Blaster 16 soundcard not found or device busy\n"); | 723 | snd_printk(KERN_ERR "Sound Blaster 16 soundcard not found or device busy\n"); |
639 | #ifdef SNDRV_SBAWE_EMU8000 | 724 | #ifdef SNDRV_SBAWE_EMU8000 |
@@ -649,14 +734,10 @@ static int __init alsa_card_sb16_init(void) | |||
649 | 734 | ||
650 | static void __exit alsa_card_sb16_exit(void) | 735 | static void __exit alsa_card_sb16_exit(void) |
651 | { | 736 | { |
652 | int dev; | ||
653 | |||
654 | #ifdef CONFIG_PNP | 737 | #ifdef CONFIG_PNP |
655 | /* PnP cards first */ | ||
656 | pnp_unregister_card_driver(&sb16_pnpc_driver); | 738 | pnp_unregister_card_driver(&sb16_pnpc_driver); |
657 | #endif | 739 | #endif |
658 | for (dev = 0; dev < SNDRV_CARDS; dev++) | 740 | platform_driver_unregister(&snd_sb16_nonpnp_driver); |
659 | snd_card_free(snd_sb16_legacy[dev]); | ||
660 | } | 741 | } |
661 | 742 | ||
662 | module_init(alsa_card_sb16_init) | 743 | module_init(alsa_card_sb16_init) |