module_param_array(opl3sa3_ymode, int, NULL, 0444);
MODULE_PARM_DESC(opl3sa3_ymode, "Speaker size selection for 3D Enhancement mode: Desktop/Large Notebook/Small Notebook/HiFi.");
+static struct platform_device *platform_devices[SNDRV_CARDS];
+#ifdef CONFIG_PNP
+static int pnp_registered;
+static int pnpc_registered;
+#endif
+static unsigned int snd_opl3sa2_devices;
+
/* control ports */
#define OPL3SA2_PM_CTRL 0x01
#define OPL3SA2_SYS_CTRL 0x02
/* reassign AUX0 to CD */
strcpy(id1.name, "Aux Playback Switch");
strcpy(id2.name, "CD Playback Switch");
- if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0)
+ if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) {
+ snd_printk(KERN_ERR "Cannot rename opl3sa2 control\n");
return err;
+ }
strcpy(id1.name, "Aux Playback Volume");
strcpy(id2.name, "CD Playback Volume");
- if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0)
+ if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) {
+ snd_printk(KERN_ERR "Cannot rename opl3sa2 control\n");
return err;
+ }
/* reassign AUX1 to FM */
strcpy(id1.name, "Aux Playback Switch"); id1.index = 1;
strcpy(id2.name, "FM Playback Switch");
- if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0)
+ if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) {
+ snd_printk(KERN_ERR "Cannot rename opl3sa2 control\n");
return err;
+ }
strcpy(id1.name, "Aux Playback Volume");
strcpy(id2.name, "FM Playback Volume");
- if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0)
+ if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) {
+ snd_printk(KERN_ERR "Cannot rename opl3sa2 control\n");
return err;
+ }
/* add OPL3SA2 controls */
for (idx = 0; idx < ARRAY_SIZE(snd_opl3sa2_controls); idx++) {
if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_opl3sa2_controls[idx], chip))) < 0)
int err;
cfg = kmalloc(sizeof(struct pnp_resource_table), GFP_KERNEL);
- if (!cfg)
+ if (!cfg) {
+ snd_printk(KERN_ERR PFX "cannot allocate pnp cfg\n");
return -ENOMEM;
+ }
/* PnP initialization */
pnp_init_resource_table(cfg);
if (sb_port[dev] != SNDRV_AUTO_PORT)
pnp_resource_change(&cfg->irq_resource[0], irq[dev], 1);
err = pnp_manual_config_dev(pdev, cfg, 0);
if (err < 0)
- snd_printk(KERN_ERR "PnP manual resources are invalid, using auto config\n");
+ snd_printk(KERN_WARNING "PnP manual resources are invalid, using auto config\n");
err = pnp_activate_dev(pdev);
if (err < 0) {
kfree(cfg);
}
sprintf(card->longname, "%s at 0x%lx, irq %d, dma %d",
card->shortname, chip->port, xirq, xdma1);
- if (dma2 >= 0)
+ if (xdma2 >= 0)
sprintf(card->longname + strlen(card->longname), "&%d", xdma2);
return snd_card_register(card);
}
pnp_set_drvdata(pdev, card);
dev++;
+ snd_opl3sa2_devices++;
return 0;
}
#endif
static struct pnp_driver opl3sa2_pnp_driver = {
- .name = "opl3sa2-pnpbios",
+ .name = "snd-opl3sa2-pnpbios",
.id_table = snd_opl3sa2_pnpbiosids,
.probe = snd_opl3sa2_pnp_detect,
.remove = __devexit_p(snd_opl3sa2_pnp_remove),
struct snd_card *card;
pdev = pnp_request_card_device(pcard, id->devs[0].id, NULL);
- if (pdev == NULL)
+ if (pdev == NULL) {
+ snd_printk(KERN_ERR PFX "can't get pnp device from id '%s'\n",
+ id->devs[0].id);
return -EBUSY;
+ }
for (; dev < SNDRV_CARDS; dev++) {
if (enable[dev] && isapnp[dev])
break;
}
pnp_set_card_drvdata(pcard, card);
dev++;
+ snd_opl3sa2_devices++;
return 0;
}
static struct pnp_card_driver opl3sa2_pnpc_driver = {
.flags = PNP_DRIVER_RES_DISABLE,
- .name = "opl3sa2",
+ .name = "snd-opl3sa2-cpnp",
.id_table = snd_opl3sa2_pnpids,
.probe = snd_opl3sa2_pnp_cdetect,
.remove = __devexit_p(snd_opl3sa2_pnp_cremove),
},
};
+static void __init_or_module snd_opl3sa2_unregister_all(void)
+{
+ int i;
+
+#ifdef CONFIG_PNP
+ if (pnpc_registered)
+ pnp_unregister_card_driver(&opl3sa2_pnpc_driver);
+ if (pnp_registered)
+ pnp_unregister_driver(&opl3sa2_pnp_driver);
+#endif
+ for (i = 0; i < ARRAY_SIZE(platform_devices); ++i)
+ platform_device_unregister(platform_devices[i]);
+ platform_driver_unregister(&snd_opl3sa2_nonpnp_driver);
+}
+
static int __init alsa_card_opl3sa2_init(void)
{
- int i, err, cards = 0;
+ int i, err;
if ((err = platform_driver_register(&snd_opl3sa2_nonpnp_driver)) < 0)
return err;
- for (i = 0; i < SNDRV_CARDS && enable[i]; i++) {
+ for (i = 0; i < SNDRV_CARDS; i++) {
struct platform_device *device;
+ if (! enable[i])
+ continue;
#ifdef CONFIG_PNP
if (isapnp[i])
continue;
i, NULL, 0);
if (IS_ERR(device)) {
err = PTR_ERR(device);
- platform_driver_unregister(&snd_opl3sa2_nonpnp_driver);
- return err;
+ goto errout;
}
- cards++;
+ platform_devices[i] = device;
+ snd_opl3sa2_devices++;
}
+#ifdef CONFIG_PNP
err = pnp_register_driver(&opl3sa2_pnp_driver);
- if (err > 0)
- cards += err;
+ if (!err)
+ pnp_registered = 1;
err = pnp_register_card_driver(&opl3sa2_pnpc_driver);
- if (err > 0)
- cards += err;
+ if (!err)
+ pnpc_registered = 1;
+#endif
- if (!cards) {
+ if (!snd_opl3sa2_devices) {
#ifdef MODULE
snd_printk(KERN_ERR "Yamaha OPL3-SA soundcard not found or device busy\n");
#endif
- pnp_unregister_card_driver(&opl3sa2_pnpc_driver);
- pnp_unregister_driver(&opl3sa2_pnp_driver);
- platform_driver_unregister(&snd_opl3sa2_nonpnp_driver);
- return -ENODEV;
+ err = -ENODEV;
+ goto errout;
}
return 0;
+
+ errout:
+ snd_opl3sa2_unregister_all();
+ return err;
}
static void __exit alsa_card_opl3sa2_exit(void)
{
- pnp_unregister_card_driver(&opl3sa2_pnpc_driver);
- pnp_unregister_driver(&opl3sa2_pnp_driver);
- platform_driver_unregister(&snd_opl3sa2_nonpnp_driver);
+ snd_opl3sa2_unregister_all();
}
module_init(alsa_card_opl3sa2_init)