diff options
author | Takashi Iwai <tiwai@suse.de> | 2005-11-17 11:11:53 -0500 |
---|---|---|
committer | Jaroslav Kysela <perex@suse.cz> | 2006-01-03 06:28:27 -0500 |
commit | 704e05204c623136ea12411dc4286d1caea6cd7c (patch) | |
tree | 3527413100be5eb599325eca50a933539fab6cf2 /sound/isa | |
parent | acdcbc15426b91b0041756a92ea4932c60def189 (diff) |
[ALSA] opl3sa2 - Use platform_device
Modules: OPL3SA2 driver
Rewrite the probe/remove with platform_device.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/isa')
-rw-r--r-- | sound/isa/opl3sa2.c | 428 |
1 files changed, 228 insertions, 200 deletions
diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c index a343af70f519..b923de9b321d 100644 --- a/sound/isa/opl3sa2.c +++ b/sound/isa/opl3sa2.c | |||
@@ -21,6 +21,8 @@ | |||
21 | 21 | ||
22 | #include <sound/driver.h> | 22 | #include <sound/driver.h> |
23 | #include <linux/init.h> | 23 | #include <linux/init.h> |
24 | #include <linux/err.h> | ||
25 | #include <linux/platform_device.h> | ||
24 | #include <linux/interrupt.h> | 26 | #include <linux/interrupt.h> |
25 | #include <linux/pm.h> | 27 | #include <linux/pm.h> |
26 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
@@ -126,21 +128,12 @@ struct snd_opl3sa2 { | |||
126 | struct snd_hwdep *synth; | 128 | struct snd_hwdep *synth; |
127 | struct snd_rawmidi *rmidi; | 129 | struct snd_rawmidi *rmidi; |
128 | struct snd_cs4231 *cs4231; | 130 | struct snd_cs4231 *cs4231; |
129 | #ifdef CONFIG_PNP | ||
130 | struct pnp_dev *dev; | ||
131 | #endif | ||
132 | unsigned char ctlregs[0x20]; | 131 | unsigned char ctlregs[0x20]; |
133 | int ymode; /* SL added */ | 132 | int ymode; /* SL added */ |
134 | struct snd_kcontrol *master_switch; | 133 | struct snd_kcontrol *master_switch; |
135 | struct snd_kcontrol *master_volume; | 134 | struct snd_kcontrol *master_volume; |
136 | #ifdef CONFIG_PM | ||
137 | void (*cs4231_suspend)(struct snd_cs4231 *); | ||
138 | void (*cs4231_resume)(struct snd_cs4231 *); | ||
139 | #endif | ||
140 | }; | 135 | }; |
141 | 136 | ||
142 | static struct snd_card *snd_opl3sa2_legacy[SNDRV_CARDS] = SNDRV_DEFAULT_PTR; | ||
143 | |||
144 | #define PFX "opl3sa2: " | 137 | #define PFX "opl3sa2: " |
145 | 138 | ||
146 | #ifdef CONFIG_PNP | 139 | #ifdef CONFIG_PNP |
@@ -539,11 +532,10 @@ static int __init snd_opl3sa2_mixer(struct snd_opl3sa2 *chip) | |||
539 | #ifdef CONFIG_PM | 532 | #ifdef CONFIG_PM |
540 | static int snd_opl3sa2_suspend(struct snd_card *card, pm_message_t state) | 533 | static int snd_opl3sa2_suspend(struct snd_card *card, pm_message_t state) |
541 | { | 534 | { |
542 | struct snd_opl3sa2 *chip = card->pm_private_data; | 535 | struct snd_opl3sa2 *chip = card->private_data; |
543 | |||
544 | snd_pcm_suspend_all(chip->cs4231->pcm); /* stop before saving regs */ | ||
545 | chip->cs4231_suspend(chip->cs4231); | ||
546 | 536 | ||
537 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); | ||
538 | chip->cs4231->suspend(chip->cs4231); | ||
547 | /* power down */ | 539 | /* power down */ |
548 | snd_opl3sa2_write(chip, OPL3SA2_PM_CTRL, OPL3SA2_PM_D3); | 540 | snd_opl3sa2_write(chip, OPL3SA2_PM_CTRL, OPL3SA2_PM_D3); |
549 | 541 | ||
@@ -552,7 +544,7 @@ static int snd_opl3sa2_suspend(struct snd_card *card, pm_message_t state) | |||
552 | 544 | ||
553 | static int snd_opl3sa2_resume(struct snd_card *card) | 545 | static int snd_opl3sa2_resume(struct snd_card *card) |
554 | { | 546 | { |
555 | struct snd_opl3sa2 *chip = card->pm_private_data; | 547 | struct snd_opl3sa2 *chip = card->private_data; |
556 | int i; | 548 | int i; |
557 | 549 | ||
558 | /* power up */ | 550 | /* power up */ |
@@ -568,23 +560,20 @@ static int snd_opl3sa2_resume(struct snd_card *card) | |||
568 | snd_opl3sa2_write(chip, i, chip->ctlregs[i]); | 560 | snd_opl3sa2_write(chip, i, chip->ctlregs[i]); |
569 | } | 561 | } |
570 | /* restore cs4231 */ | 562 | /* restore cs4231 */ |
571 | chip->cs4231_resume(chip->cs4231); | 563 | chip->cs4231->resume(chip->cs4231); |
572 | 564 | ||
565 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); | ||
573 | return 0; | 566 | return 0; |
574 | } | 567 | } |
575 | #endif /* CONFIG_PM */ | 568 | #endif /* CONFIG_PM */ |
576 | 569 | ||
577 | #ifdef CONFIG_PNP | 570 | #ifdef CONFIG_PNP |
578 | static int __init snd_opl3sa2_pnp(int dev, struct snd_opl3sa2 *chip, | 571 | static int __init snd_opl3sa2_pnp(int dev, struct snd_opl3sa2 *chip, |
579 | struct pnp_dev *pdev, | 572 | struct pnp_dev *pdev) |
580 | int isapnp) | ||
581 | { | 573 | { |
582 | struct pnp_resource_table * cfg; | 574 | struct pnp_resource_table * cfg; |
583 | int err; | 575 | int err; |
584 | 576 | ||
585 | if (!isapnp && pnp_device_is_isapnp(pdev)) | ||
586 | return -ENOENT; /* we have another procedure - card */ | ||
587 | |||
588 | cfg = kmalloc(sizeof(struct pnp_resource_table), GFP_KERNEL); | 577 | cfg = kmalloc(sizeof(struct pnp_resource_table), GFP_KERNEL); |
589 | if (!cfg) | 578 | if (!cfg) |
590 | return -ENOMEM; | 579 | return -ENOMEM; |
@@ -607,7 +596,7 @@ static int __init snd_opl3sa2_pnp(int dev, struct snd_opl3sa2 *chip, | |||
607 | if (irq[dev] != SNDRV_AUTO_IRQ) | 596 | if (irq[dev] != SNDRV_AUTO_IRQ) |
608 | pnp_resource_change(&cfg->irq_resource[0], irq[dev], 1); | 597 | pnp_resource_change(&cfg->irq_resource[0], irq[dev], 1); |
609 | err = pnp_manual_config_dev(pdev, cfg, 0); | 598 | err = pnp_manual_config_dev(pdev, cfg, 0); |
610 | if (err < 0 && isapnp) | 599 | if (err < 0) |
611 | snd_printk(KERN_ERR "PnP manual resources are invalid, using auto config\n"); | 600 | snd_printk(KERN_ERR "PnP manual resources are invalid, using auto config\n"); |
612 | err = pnp_activate_dev(pdev); | 601 | err = pnp_activate_dev(pdev); |
613 | if (err < 0) { | 602 | if (err < 0) { |
@@ -628,111 +617,47 @@ static int __init snd_opl3sa2_pnp(int dev, struct snd_opl3sa2 *chip, | |||
628 | snd_printdd("%sPnP OPL3-SA: control port=0x%lx, dma1=%i, dma2=%i, irq=%i\n", | 617 | snd_printdd("%sPnP OPL3-SA: control port=0x%lx, dma1=%i, dma2=%i, irq=%i\n", |
629 | pnp_device_is_pnpbios(pdev) ? "BIOS" : "ISA", port[dev], dma1[dev], dma2[dev], irq[dev]); | 618 | pnp_device_is_pnpbios(pdev) ? "BIOS" : "ISA", port[dev], dma1[dev], dma2[dev], irq[dev]); |
630 | kfree(cfg); | 619 | kfree(cfg); |
631 | chip->dev = pdev; | ||
632 | return 0; | 620 | return 0; |
633 | } | 621 | } |
634 | |||
635 | static int __init snd_opl3sa2_cpnp(int dev, struct snd_opl3sa2 *chip, | ||
636 | struct pnp_card_link *card, | ||
637 | const struct pnp_card_device_id *id) | ||
638 | { | ||
639 | struct pnp_dev *pdev; | ||
640 | struct pnp_resource_table * cfg = kmalloc(sizeof(struct pnp_resource_table), GFP_KERNEL); | ||
641 | |||
642 | if (!cfg) | ||
643 | return -ENOMEM; | ||
644 | pdev = pnp_request_card_device(card, id->devs[0].id, NULL); | ||
645 | if (pdev == NULL) { | ||
646 | kfree(cfg); | ||
647 | return -EBUSY; | ||
648 | } | ||
649 | return snd_opl3sa2_pnp(dev, chip, pdev, 1); | ||
650 | } | ||
651 | #endif /* CONFIG_PNP */ | 622 | #endif /* CONFIG_PNP */ |
652 | 623 | ||
653 | static int snd_opl3sa2_free(struct snd_opl3sa2 *chip) | 624 | static void snd_opl3sa2_free(struct snd_card *card) |
654 | { | 625 | { |
626 | struct snd_opl3sa2 *chip = card->private_data; | ||
655 | if (chip->irq >= 0) | 627 | if (chip->irq >= 0) |
656 | free_irq(chip->irq, (void *)chip); | 628 | free_irq(chip->irq, (void *)chip); |
657 | release_and_free_resource(chip->res_port); | 629 | release_and_free_resource(chip->res_port); |
658 | kfree(chip); | ||
659 | return 0; | ||
660 | } | 630 | } |
661 | 631 | ||
662 | static int snd_opl3sa2_dev_free(struct snd_device *device) | 632 | static struct snd_card *snd_opl3sa2_card_new(int dev) |
663 | { | 633 | { |
664 | struct snd_opl3sa2 *chip = device->device_data; | ||
665 | return snd_opl3sa2_free(chip); | ||
666 | } | ||
667 | |||
668 | #ifdef CONFIG_PNP | ||
669 | #define is_isapnp_selected(dev) isapnp[dev] | ||
670 | #else | ||
671 | #define is_isapnp_selected(dev) 0 | ||
672 | #endif | ||
673 | |||
674 | static int __devinit snd_opl3sa2_probe(int dev, | ||
675 | struct pnp_dev *pdev, | ||
676 | struct pnp_card_link *pcard, | ||
677 | const struct pnp_card_device_id *pid) | ||
678 | { | ||
679 | int xirq, xdma1, xdma2; | ||
680 | struct snd_card *card; | 634 | struct snd_card *card; |
681 | struct snd_opl3sa2 *chip; | 635 | struct snd_opl3sa2 *chip; |
682 | struct snd_cs4231 *cs4231; | ||
683 | struct snd_opl3 *opl3; | ||
684 | static struct snd_device_ops ops = { | ||
685 | .dev_free = snd_opl3sa2_dev_free, | ||
686 | }; | ||
687 | int err; | ||
688 | 636 | ||
689 | if (! is_isapnp_selected(dev)) { | 637 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, sizeof(struct snd_opl3sa2)); |
690 | if (port[dev] == SNDRV_AUTO_PORT) { | ||
691 | snd_printk(KERN_ERR PFX "specify port\n"); | ||
692 | return -EINVAL; | ||
693 | } | ||
694 | if (wss_port[dev] == SNDRV_AUTO_PORT) { | ||
695 | snd_printk(KERN_ERR PFX "specify wss_port\n"); | ||
696 | return -EINVAL; | ||
697 | } | ||
698 | if (fm_port[dev] == SNDRV_AUTO_PORT) { | ||
699 | snd_printk(KERN_ERR PFX "specify fm_port\n"); | ||
700 | return -EINVAL; | ||
701 | } | ||
702 | if (midi_port[dev] == SNDRV_AUTO_PORT) { | ||
703 | snd_printk(KERN_ERR PFX "specify midi_port\n"); | ||
704 | return -EINVAL; | ||
705 | } | ||
706 | } | ||
707 | |||
708 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); | ||
709 | if (card == NULL) | 638 | if (card == NULL) |
710 | return -ENOMEM; | 639 | return NULL; |
711 | strcpy(card->driver, "OPL3SA2"); | 640 | strcpy(card->driver, "OPL3SA2"); |
712 | strcpy(card->shortname, "Yamaha OPL3-SA2"); | 641 | strcpy(card->shortname, "Yamaha OPL3-SA2"); |
713 | chip = kzalloc(sizeof(*chip), GFP_KERNEL); | 642 | chip = card->private_data; |
714 | if (chip == NULL) { | ||
715 | err = -ENOMEM; | ||
716 | goto __error; | ||
717 | } | ||
718 | spin_lock_init(&chip->reg_lock); | 643 | spin_lock_init(&chip->reg_lock); |
719 | chip->irq = -1; | 644 | chip->irq = -1; |
720 | if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) | ||
721 | goto __error; | ||
722 | #ifdef CONFIG_PNP | ||
723 | if (pdev) { | ||
724 | if ((err = snd_opl3sa2_pnp(dev, chip, pdev, 0)) < 0) | ||
725 | goto __error; | ||
726 | snd_card_set_dev(card, &pdev->dev); | ||
727 | } | ||
728 | if (pcard) { | ||
729 | if ((err = snd_opl3sa2_cpnp(dev, chip, pcard, pid)) < 0) | ||
730 | goto __error; | ||
731 | snd_card_set_dev(card, &pcard->card->dev); | ||
732 | } | ||
733 | #endif | ||
734 | chip->ymode = opl3sa3_ymode[dev] & 0x03 ; /* initialise this card from supplied (or default) parameter*/ | ||
735 | chip->card = card; | 645 | chip->card = card; |
646 | card->private_free = snd_opl3sa2_free; | ||
647 | return card; | ||
648 | } | ||
649 | |||
650 | static int __devinit snd_opl3sa2_probe(struct snd_card *card, int dev) | ||
651 | { | ||
652 | int xirq, xdma1, xdma2; | ||
653 | struct snd_opl3sa2 *chip; | ||
654 | struct snd_cs4231 *cs4231; | ||
655 | struct snd_opl3 *opl3; | ||
656 | int err; | ||
657 | |||
658 | /* initialise this card from supplied (or default) parameter*/ | ||
659 | chip = card->private_data; | ||
660 | chip->ymode = opl3sa3_ymode[dev] & 0x03 ; | ||
736 | chip->port = port[dev]; | 661 | chip->port = port[dev]; |
737 | xirq = irq[dev]; | 662 | xirq = irq[dev]; |
738 | xdma1 = dma1[dev]; | 663 | xdma1 = dma1[dev]; |
@@ -740,11 +665,10 @@ static int __devinit snd_opl3sa2_probe(int dev, | |||
740 | if (xdma2 < 0) | 665 | if (xdma2 < 0) |
741 | chip->single_dma = 1; | 666 | chip->single_dma = 1; |
742 | if ((err = snd_opl3sa2_detect(chip)) < 0) | 667 | if ((err = snd_opl3sa2_detect(chip)) < 0) |
743 | goto __error; | 668 | return err; |
744 | if (request_irq(xirq, snd_opl3sa2_interrupt, SA_INTERRUPT, "OPL3-SA2", (void *)chip)) { | 669 | if (request_irq(xirq, snd_opl3sa2_interrupt, SA_INTERRUPT, "OPL3-SA2", chip)) { |
745 | snd_printk(KERN_ERR PFX "can't grab IRQ %d\n", xirq); | 670 | snd_printk(KERN_ERR PFX "can't grab IRQ %d\n", xirq); |
746 | err = -ENODEV; | 671 | return -ENODEV; |
747 | goto __error; | ||
748 | } | 672 | } |
749 | chip->irq = xirq; | 673 | chip->irq = xirq; |
750 | if ((err = snd_cs4231_create(card, | 674 | if ((err = snd_cs4231_create(card, |
@@ -754,163 +678,273 @@ static int __devinit snd_opl3sa2_probe(int dev, | |||
754 | CS4231_HWSHARE_IRQ, | 678 | CS4231_HWSHARE_IRQ, |
755 | &cs4231)) < 0) { | 679 | &cs4231)) < 0) { |
756 | snd_printd("Oops, WSS not detected at 0x%lx\n", wss_port[dev] + 4); | 680 | snd_printd("Oops, WSS not detected at 0x%lx\n", wss_port[dev] + 4); |
757 | goto __error; | 681 | return err; |
758 | } | 682 | } |
759 | chip->cs4231 = cs4231; | 683 | chip->cs4231 = cs4231; |
760 | if ((err = snd_cs4231_pcm(cs4231, 0, NULL)) < 0) | 684 | if ((err = snd_cs4231_pcm(cs4231, 0, NULL)) < 0) |
761 | goto __error; | 685 | return err; |
762 | if ((err = snd_cs4231_mixer(cs4231)) < 0) | 686 | if ((err = snd_cs4231_mixer(cs4231)) < 0) |
763 | goto __error; | 687 | return err; |
764 | if ((err = snd_opl3sa2_mixer(chip)) < 0) | 688 | if ((err = snd_opl3sa2_mixer(chip)) < 0) |
765 | goto __error; | 689 | return err; |
766 | if ((err = snd_cs4231_timer(cs4231, 0, NULL)) < 0) | 690 | if ((err = snd_cs4231_timer(cs4231, 0, NULL)) < 0) |
767 | goto __error; | 691 | return err; |
768 | if (fm_port[dev] >= 0x340 && fm_port[dev] < 0x400) { | 692 | if (fm_port[dev] >= 0x340 && fm_port[dev] < 0x400) { |
769 | if ((err = snd_opl3_create(card, fm_port[dev], | 693 | if ((err = snd_opl3_create(card, fm_port[dev], |
770 | fm_port[dev] + 2, | 694 | fm_port[dev] + 2, |
771 | OPL3_HW_OPL3, 0, &opl3)) < 0) | 695 | OPL3_HW_OPL3, 0, &opl3)) < 0) |
772 | goto __error; | 696 | return err; |
773 | if ((err = snd_opl3_timer_new(opl3, 1, 2)) < 0) | 697 | if ((err = snd_opl3_timer_new(opl3, 1, 2)) < 0) |
774 | goto __error; | 698 | return err; |
775 | if ((err = snd_opl3_hwdep_new(opl3, 0, 1, &chip->synth)) < 0) | 699 | if ((err = snd_opl3_hwdep_new(opl3, 0, 1, &chip->synth)) < 0) |
776 | goto __error; | 700 | return err; |
777 | } | 701 | } |
778 | if (midi_port[dev] >= 0x300 && midi_port[dev] < 0x340) { | 702 | if (midi_port[dev] >= 0x300 && midi_port[dev] < 0x340) { |
779 | if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_OPL3SA2, | 703 | if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_OPL3SA2, |
780 | midi_port[dev], 0, | 704 | midi_port[dev], 0, |
781 | xirq, 0, &chip->rmidi)) < 0) | 705 | xirq, 0, &chip->rmidi)) < 0) |
782 | goto __error; | 706 | return err; |
783 | } | 707 | } |
784 | #ifdef CONFIG_PM | ||
785 | chip->cs4231_suspend = chip->cs4231->suspend; | ||
786 | chip->cs4231_resume = chip->cs4231->resume; | ||
787 | /* now clear callbacks for cs4231 */ | ||
788 | chip->cs4231->suspend = NULL; | ||
789 | chip->cs4231->resume = NULL; | ||
790 | snd_card_set_isa_pm_callback(card, snd_opl3sa2_suspend, snd_opl3sa2_resume, chip); | ||
791 | #endif | ||
792 | |||
793 | sprintf(card->longname, "%s at 0x%lx, irq %d, dma %d", | 708 | sprintf(card->longname, "%s at 0x%lx, irq %d, dma %d", |
794 | card->shortname, chip->port, xirq, xdma1); | 709 | card->shortname, chip->port, xirq, xdma1); |
795 | if (dma2 >= 0) | 710 | if (dma2 >= 0) |
796 | sprintf(card->longname + strlen(card->longname), "&%d", xdma2); | 711 | sprintf(card->longname + strlen(card->longname), "&%d", xdma2); |
797 | 712 | ||
798 | if ((err = snd_card_set_generic_dev(card)) < 0) | 713 | return snd_card_register(card); |
799 | goto __error; | ||
800 | |||
801 | if ((err = snd_card_register(card)) < 0) | ||
802 | goto __error; | ||
803 | |||
804 | if (pdev) | ||
805 | pnp_set_drvdata(pdev, card); | ||
806 | else if (pcard) | ||
807 | pnp_set_card_drvdata(pcard, card); | ||
808 | else | ||
809 | snd_opl3sa2_legacy[dev] = card; | ||
810 | return 0; | ||
811 | |||
812 | __error: | ||
813 | snd_card_free(card); | ||
814 | return err; | ||
815 | } | 714 | } |
816 | 715 | ||
817 | #ifdef CONFIG_PNP | 716 | #ifdef CONFIG_PNP |
818 | static int __devinit snd_opl3sa2_pnp_detect(struct pnp_dev *pdev, | 717 | static int __devinit snd_opl3sa2_pnp_detect(struct pnp_dev *pdev, |
819 | const struct pnp_device_id *id) | 718 | const struct pnp_device_id *id) |
820 | { | 719 | { |
821 | static int dev; | 720 | static int dev; |
822 | int res; | 721 | int err; |
722 | struct snd_card *card; | ||
723 | |||
724 | if (pnp_device_is_isapnp(pdev)) | ||
725 | return -ENOENT; /* we have another procedure - card */ | ||
726 | for (; dev < SNDRV_CARDS; dev++) { | ||
727 | if (enable[dev] && isapnp[dev]) | ||
728 | break; | ||
729 | } | ||
730 | if (dev >= SNDRV_CARDS) | ||
731 | return -ENODEV; | ||
823 | 732 | ||
824 | for ( ; dev < SNDRV_CARDS; dev++) { | 733 | card = snd_opl3sa2_card_new(dev); |
825 | if (!enable[dev] || !isapnp[dev]) | 734 | if (! card) |
826 | continue; | 735 | return -ENOMEM; |
827 | res = snd_opl3sa2_probe(dev, pdev, NULL, NULL); | 736 | if ((err = snd_opl3sa2_pnp(dev, card->private_data, pdev)) < 0) { |
828 | if (res < 0) | 737 | snd_card_free(card); |
829 | return res; | 738 | return err; |
830 | dev++; | 739 | } |
831 | return 0; | 740 | snd_card_set_dev(card, &pdev->dev); |
832 | } | 741 | if ((err = snd_opl3sa2_probe(card, dev)) < 0) { |
833 | return -ENODEV; | 742 | snd_card_free(card); |
743 | return err; | ||
744 | } | ||
745 | pnp_set_drvdata(pdev, card); | ||
746 | dev++; | ||
747 | return 0; | ||
834 | } | 748 | } |
835 | 749 | ||
836 | static void __devexit snd_opl3sa2_pnp_remove(struct pnp_dev * pdev) | 750 | static void __devexit snd_opl3sa2_pnp_remove(struct pnp_dev * pdev) |
837 | { | 751 | { |
838 | struct snd_card *card = (struct snd_card *) pnp_get_drvdata(pdev); | 752 | snd_card_free(pnp_get_drvdata(pdev)); |
839 | 753 | pnp_set_drvdata(pdev, NULL); | |
840 | snd_card_disconnect(card); | ||
841 | snd_card_free_in_thread(card); | ||
842 | } | 754 | } |
843 | 755 | ||
756 | #ifdef CONFIG_PM | ||
757 | static int snd_opl3sa2_pnp_suspend(struct pnp_dev *pdev, pm_message_t state) | ||
758 | { | ||
759 | return snd_opl3sa2_suspend(pnp_get_drvdata(pdev), state); | ||
760 | } | ||
761 | static int snd_opl3sa2_pnp_resume(struct pnp_dev *pdev) | ||
762 | { | ||
763 | return snd_opl3sa2_resume(pnp_get_drvdata(pdev)); | ||
764 | } | ||
765 | #endif | ||
766 | |||
844 | static struct pnp_driver opl3sa2_pnp_driver = { | 767 | static struct pnp_driver opl3sa2_pnp_driver = { |
845 | .name = "opl3sa2-pnpbios", | 768 | .name = "opl3sa2-pnpbios", |
846 | .id_table = snd_opl3sa2_pnpbiosids, | 769 | .id_table = snd_opl3sa2_pnpbiosids, |
847 | .probe = snd_opl3sa2_pnp_detect, | 770 | .probe = snd_opl3sa2_pnp_detect, |
848 | .remove = __devexit_p(snd_opl3sa2_pnp_remove), | 771 | .remove = __devexit_p(snd_opl3sa2_pnp_remove), |
772 | #ifdef CONFIG_PM | ||
773 | .suspend = snd_opl3sa2_pnp_suspend, | ||
774 | .resume = snd_opl3sa2_pnp_resume, | ||
775 | #endif | ||
849 | }; | 776 | }; |
850 | 777 | ||
851 | static int __devinit snd_opl3sa2_pnp_cdetect(struct pnp_card_link *card, | 778 | static int __devinit snd_opl3sa2_pnp_cdetect(struct pnp_card_link *pcard, |
852 | const struct pnp_card_device_id *id) | 779 | const struct pnp_card_device_id *id) |
853 | { | 780 | { |
854 | static int dev; | 781 | static int dev; |
855 | int res; | 782 | struct pnp_dev *pdev; |
783 | int err; | ||
784 | struct snd_card *card; | ||
856 | 785 | ||
857 | for ( ; dev < SNDRV_CARDS; dev++) { | 786 | pdev = pnp_request_card_device(pcard, id->devs[0].id, NULL); |
858 | if (!enable[dev]) | 787 | if (pdev == NULL) |
859 | continue; | 788 | return -EBUSY; |
860 | if (is_isapnp_selected(dev)) | 789 | for (; dev < SNDRV_CARDS; dev++) { |
861 | continue; | 790 | if (enable[dev] && isapnp[dev]) |
862 | res = snd_opl3sa2_probe(dev, NULL, card, id); | 791 | break; |
863 | if (res < 0) | 792 | } |
864 | return res; | 793 | if (dev >= SNDRV_CARDS) |
865 | dev++; | 794 | return -ENODEV; |
866 | return 0; | 795 | |
867 | } | 796 | card = snd_opl3sa2_card_new(dev); |
868 | return -ENODEV; | 797 | if (! card) |
798 | return -ENOMEM; | ||
799 | if ((err = snd_opl3sa2_pnp(dev, card->private_data, pdev)) < 0) { | ||
800 | snd_card_free(card); | ||
801 | return err; | ||
802 | } | ||
803 | snd_card_set_dev(card, &pdev->dev); | ||
804 | if ((err = snd_opl3sa2_probe(card, dev)) < 0) { | ||
805 | snd_card_free(card); | ||
806 | return err; | ||
807 | } | ||
808 | pnp_set_card_drvdata(pcard, card); | ||
809 | dev++; | ||
810 | return 0; | ||
869 | } | 811 | } |
870 | 812 | ||
871 | static void __devexit snd_opl3sa2_pnp_cremove(struct pnp_card_link * pcard) | 813 | static void __devexit snd_opl3sa2_pnp_cremove(struct pnp_card_link * pcard) |
872 | { | 814 | { |
873 | struct snd_card *card = (struct snd_card *) pnp_get_card_drvdata(pcard); | 815 | snd_card_free(pnp_get_card_drvdata(pcard)); |
874 | 816 | pnp_set_card_drvdata(pcard, NULL); | |
875 | snd_card_disconnect(card); | ||
876 | snd_card_free_in_thread(card); | ||
877 | } | 817 | } |
878 | 818 | ||
819 | #ifdef CONFIG_PM | ||
820 | static int snd_opl3sa2_pnp_csuspend(struct pnp_card_link *pcard, pm_message_t state) | ||
821 | { | ||
822 | return snd_opl3sa2_suspend(pnp_get_card_drvdata(pcard), state); | ||
823 | } | ||
824 | static int snd_opl3sa2_pnp_cresume(struct pnp_card_link *pcard) | ||
825 | { | ||
826 | return snd_opl3sa2_resume(pnp_get_card_drvdata(pcard)); | ||
827 | } | ||
828 | #endif | ||
829 | |||
879 | static struct pnp_card_driver opl3sa2_pnpc_driver = { | 830 | static struct pnp_card_driver opl3sa2_pnpc_driver = { |
880 | .flags = PNP_DRIVER_RES_DISABLE, | 831 | .flags = PNP_DRIVER_RES_DISABLE, |
881 | .name = "opl3sa2", | 832 | .name = "opl3sa2", |
882 | .id_table = snd_opl3sa2_pnpids, | 833 | .id_table = snd_opl3sa2_pnpids, |
883 | .probe = snd_opl3sa2_pnp_cdetect, | 834 | .probe = snd_opl3sa2_pnp_cdetect, |
884 | .remove = __devexit_p(snd_opl3sa2_pnp_cremove), | 835 | .remove = __devexit_p(snd_opl3sa2_pnp_cremove), |
836 | #ifdef CONFIG_PM | ||
837 | .suspend = snd_opl3sa2_pnp_csuspend, | ||
838 | .resume = snd_opl3sa2_pnp_cresume, | ||
839 | #endif | ||
885 | }; | 840 | }; |
886 | #endif /* CONFIG_PNP */ | 841 | #endif /* CONFIG_PNP */ |
887 | 842 | ||
843 | static int __init snd_opl3sa2_nonpnp_probe(struct platform_device *pdev) | ||
844 | { | ||
845 | struct snd_card *card; | ||
846 | int err; | ||
847 | int dev = pdev->id; | ||
848 | |||
849 | if (port[dev] == SNDRV_AUTO_PORT) { | ||
850 | snd_printk(KERN_ERR PFX "specify port\n"); | ||
851 | return -EINVAL; | ||
852 | } | ||
853 | if (wss_port[dev] == SNDRV_AUTO_PORT) { | ||
854 | snd_printk(KERN_ERR PFX "specify wss_port\n"); | ||
855 | return -EINVAL; | ||
856 | } | ||
857 | if (fm_port[dev] == SNDRV_AUTO_PORT) { | ||
858 | snd_printk(KERN_ERR PFX "specify fm_port\n"); | ||
859 | return -EINVAL; | ||
860 | } | ||
861 | if (midi_port[dev] == SNDRV_AUTO_PORT) { | ||
862 | snd_printk(KERN_ERR PFX "specify midi_port\n"); | ||
863 | return -EINVAL; | ||
864 | } | ||
865 | |||
866 | card = snd_opl3sa2_card_new(dev); | ||
867 | if (! card) | ||
868 | return -ENOMEM; | ||
869 | snd_card_set_dev(card, &pdev->dev); | ||
870 | if ((err = snd_opl3sa2_probe(card, dev)) < 0) { | ||
871 | snd_card_free(card); | ||
872 | return err; | ||
873 | } | ||
874 | platform_set_drvdata(pdev, card); | ||
875 | return 0; | ||
876 | } | ||
877 | |||
878 | static int snd_opl3sa2_nonpnp_remove(struct platform_device *devptr) | ||
879 | { | ||
880 | snd_card_free(platform_get_drvdata(devptr)); | ||
881 | platform_set_drvdata(devptr, NULL); | ||
882 | return 0; | ||
883 | } | ||
884 | |||
885 | #ifdef CONFIG_PM | ||
886 | static int snd_opl3sa2_nonpnp_suspend(struct platform_device *dev, pm_message_t state) | ||
887 | { | ||
888 | return snd_opl3sa2_suspend(platform_get_drvdata(dev), state); | ||
889 | } | ||
890 | |||
891 | static int snd_opl3sa2_nonpnp_resume(struct platform_device *dev) | ||
892 | { | ||
893 | return snd_opl3sa2_resume(platform_get_drvdata(dev)); | ||
894 | } | ||
895 | #endif | ||
896 | |||
897 | #define OPL3SA2_DRIVER "snd_opl3sa2" | ||
898 | |||
899 | static struct platform_driver snd_opl3sa2_nonpnp_driver = { | ||
900 | .probe = snd_opl3sa2_nonpnp_probe, | ||
901 | .remove = snd_opl3sa2_nonpnp_remove, | ||
902 | #ifdef CONFIG_PM | ||
903 | .suspend = snd_opl3sa2_nonpnp_suspend, | ||
904 | .resume = snd_opl3sa2_nonpnp_resume, | ||
905 | #endif | ||
906 | .driver = { | ||
907 | .name = OPL3SA2_DRIVER | ||
908 | }, | ||
909 | }; | ||
910 | |||
888 | static int __init alsa_card_opl3sa2_init(void) | 911 | static int __init alsa_card_opl3sa2_init(void) |
889 | { | 912 | { |
890 | int dev, cards = 0; | 913 | int i, err, cards = 0; |
891 | 914 | ||
892 | for (dev = 0; dev < SNDRV_CARDS; dev++) { | 915 | if ((err = platform_driver_register(&snd_opl3sa2_nonpnp_driver)) < 0) |
893 | if (!enable[dev]) | 916 | return err; |
894 | continue; | 917 | |
918 | for (i = 0; i < SNDRV_CARDS && enable[i]; i++) { | ||
919 | struct platform_device *device; | ||
895 | #ifdef CONFIG_PNP | 920 | #ifdef CONFIG_PNP |
896 | if (isapnp[dev]) | 921 | if (isapnp[i]) |
897 | continue; | 922 | continue; |
898 | #endif | 923 | #endif |
899 | if (snd_opl3sa2_probe(dev, NULL, NULL, NULL) >= 0) | 924 | device = platform_device_register_simple(OPL3SA2_DRIVER, |
900 | cards++; | 925 | i, NULL, 0); |
926 | if (IS_ERR(device)) { | ||
927 | err = PTR_ERR(device); | ||
928 | platform_driver_unregister(&snd_opl3sa2_nonpnp_driver); | ||
929 | return err; | ||
930 | } | ||
931 | cards++; | ||
901 | } | 932 | } |
902 | #ifdef CONFIG_PNP | 933 | |
903 | cards += pnp_register_driver(&opl3sa2_pnp_driver); | 934 | err = pnp_register_driver(&opl3sa2_pnp_driver); |
904 | cards += pnp_register_card_driver(&opl3sa2_pnpc_driver); | 935 | if (err > 0) |
905 | #endif | 936 | cards += err; |
937 | err = pnp_register_card_driver(&opl3sa2_pnpc_driver); | ||
938 | if (err > 0) | ||
939 | cards += err; | ||
940 | |||
906 | if (!cards) { | 941 | if (!cards) { |
907 | #ifdef MODULE | 942 | #ifdef MODULE |
908 | snd_printk(KERN_ERR "Yamaha OPL3-SA soundcard not found or device busy\n"); | 943 | snd_printk(KERN_ERR "Yamaha OPL3-SA soundcard not found or device busy\n"); |
909 | #endif | 944 | #endif |
910 | #ifdef CONFIG_PNP | ||
911 | pnp_unregister_card_driver(&opl3sa2_pnpc_driver); | 945 | pnp_unregister_card_driver(&opl3sa2_pnpc_driver); |
912 | pnp_unregister_driver(&opl3sa2_pnp_driver); | 946 | pnp_unregister_driver(&opl3sa2_pnp_driver); |
913 | #endif | 947 | platform_driver_unregister(&snd_opl3sa2_nonpnp_driver); |
914 | return -ENODEV; | 948 | return -ENODEV; |
915 | } | 949 | } |
916 | return 0; | 950 | return 0; |
@@ -918,15 +952,9 @@ static int __init alsa_card_opl3sa2_init(void) | |||
918 | 952 | ||
919 | static void __exit alsa_card_opl3sa2_exit(void) | 953 | static void __exit alsa_card_opl3sa2_exit(void) |
920 | { | 954 | { |
921 | int idx; | ||
922 | |||
923 | #ifdef CONFIG_PNP | ||
924 | /* PnP cards first */ | ||
925 | pnp_unregister_card_driver(&opl3sa2_pnpc_driver); | 955 | pnp_unregister_card_driver(&opl3sa2_pnpc_driver); |
926 | pnp_unregister_driver(&opl3sa2_pnp_driver); | 956 | pnp_unregister_driver(&opl3sa2_pnp_driver); |
927 | #endif | 957 | platform_driver_unregister(&snd_opl3sa2_nonpnp_driver); |
928 | for (idx = 0; idx < SNDRV_CARDS; idx++) | ||
929 | snd_card_free(snd_opl3sa2_legacy[idx]); | ||
930 | } | 958 | } |
931 | 959 | ||
932 | module_init(alsa_card_opl3sa2_init) | 960 | module_init(alsa_card_opl3sa2_init) |