module_param_array(wssdma, int, NULL, 0444);
MODULE_PARM_DESC(wssdma, "DMA for CMI8330 WSS driver.");
+static struct platform_device *platform_devices[SNDRV_CARDS];
+#ifdef CONFIG_PNP
+static int pnp_registered;
+#endif
+
#define CMI8330_RMUX3D 16
#define CMI8330_MUTEMUX 17
#define CMI8330_OUTPUTVOL 18
#endif
-static struct ad1848_mix_elem snd_cmi8330_controls[] __initdata = {
+static struct ad1848_mix_elem snd_cmi8330_controls[] __devinitdata = {
AD1848_DOUBLE("Master Playback Volume", 0, CMI8330_MASTVOL, CMI8330_MASTVOL, 4, 0, 15, 0),
AD1848_SINGLE("Loud Playback Switch", 0, CMI8330_MUTEMUX, 6, 1, 1),
AD1848_DOUBLE("PCM Playback Switch", 0, AD1848_LEFT_OUTPUT, AD1848_RIGHT_OUTPUT, 7, 7, 1, 1),
};
#ifdef ENABLE_SB_MIXER
-static struct sbmix_elem cmi8330_sb_mixers[] __initdata = {
+static struct sbmix_elem cmi8330_sb_mixers[] __devinitdata = {
SB_DOUBLE("SB Master Playback Volume", SB_DSP4_MASTER_DEV, (SB_DSP4_MASTER_DEV + 1), 3, 3, 31),
SB_DOUBLE("Tone Control - Bass", SB_DSP4_BASS_DEV, (SB_DSP4_BASS_DEV + 1), 4, 4, 15),
SB_DOUBLE("Tone Control - Treble", SB_DSP4_TREBLE_DEV, (SB_DSP4_TREBLE_DEV + 1), 4, 4, 15),
SB_SINGLE("SB Mic Auto Gain", SB_DSP4_MIC_AGC, 0, 1),
};
-static unsigned char cmi8330_sb_init_values[][2] __initdata = {
+static unsigned char cmi8330_sb_init_values[][2] __devinitdata = {
{ SB_DSP4_MASTER_DEV + 0, 0 },
{ SB_DSP4_MASTER_DEV + 1, 0 },
{ SB_DSP4_PCM_DEV + 0, 0 },
return snd_card_register(card);
}
-static int __init snd_cmi8330_nonpnp_probe(struct platform_device *pdev)
+static int __devinit snd_cmi8330_nonpnp_probe(struct platform_device *pdev)
{
struct snd_card *card;
int err;
#ifdef CONFIG_PNP
+static unsigned int __devinitdata cmi8330_pnp_devices;
+
static int __devinit snd_cmi8330_pnp_detect(struct pnp_card_link *pcard,
const struct pnp_card_device_id *pid)
{
}
pnp_set_card_drvdata(pcard, card);
dev++;
+ cmi8330_pnp_devices++;
return 0;
}
};
#endif /* CONFIG_PNP */
+static void __init_or_module snd_cmi8330_unregister_all(void)
+{
+ int i;
+
+#ifdef CONFIG_PNP
+ if (pnp_registered)
+ pnp_unregister_card_driver(&cmi8330_pnpc_driver);
+#endif
+ for (i = 0; i < ARRAY_SIZE(platform_devices); ++i)
+ platform_device_unregister(platform_devices[i]);
+ platform_driver_unregister(&snd_cmi8330_driver);
+}
+
static int __init alsa_card_cmi8330_init(void)
{
int i, err, cards = 0;
i, NULL, 0);
if (IS_ERR(device)) {
err = PTR_ERR(device);
- platform_driver_unregister(&snd_cmi8330_driver);
- return err;
+ goto errout;
}
+ platform_devices[i] = device;
cards++;
}
+#ifdef CONFIG_PNP
err = pnp_register_card_driver(&cmi8330_pnpc_driver);
- if (err > 0)
- cards += err;
+ if (!err) {
+ pnp_registered = 1;
+ cards += cmi8330_pnp_devices;
+ }
+#endif
if (!cards) {
- pnp_unregister_card_driver(&cmi8330_pnpc_driver);
- platform_driver_unregister(&snd_cmi8330_driver);
#ifdef MODULE
snd_printk(KERN_ERR "CMI8330 not found or device busy\n");
#endif
- return -ENODEV;
+ err = -ENODEV;
+ goto errout;
}
return 0;
+
+ errout:
+ snd_cmi8330_unregister_all();
+ return err;
}
static void __exit alsa_card_cmi8330_exit(void)
{
- pnp_unregister_card_driver(&cmi8330_pnpc_driver);
- platform_driver_unregister(&snd_cmi8330_driver);
+ snd_cmi8330_unregister_all();
}
module_init(alsa_card_cmi8330_init)