*                              merged HAL layer (patches from Brian)
  */
 
-/* $Id: sa11xx-uda1341.c,v 1.26 2005/11/17 17:19:50 tiwai Exp $ */
+/* $Id: sa11xx-uda1341.c,v 1.27 2005/12/07 09:13:42 cladisch Exp $ */
 
 /***************************************************************************************************
 *
        .mask   = 0,
 };
 
+static struct platform_device *device;
+
 /* }}} */
 
 /* {{{ Clock and sample rate stuff */
 static int __init sa11xx_uda1341_init(void)
 {
        int err;
-       struct platform_device *device;
 
        if (!machine_is_h3xxx())
                return -ENODEV;
 
 static void __exit sa11xx_uda1341_exit(void)
 {
+       platform_device_unregister(device);
        platform_driver_unregister(&sa11xx_uda1341_driver);
 }
 
 
 //module_param_array(midi_devs, int, NULL, 0444);
 //MODULE_PARM_DESC(midi_devs, "MIDI devices # (0-2) for dummy driver.");
 
+static struct platform_device *devices[SNDRV_CARDS];
+
 #define MIXER_ADDR_MASTER      0
 #define MIXER_ADDR_LINE                1
 #define MIXER_ADDR_MIC         2
        },
 };
 
+static void __init_or_module snd_dummy_unregister_all(void)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(devices); ++i)
+               platform_device_unregister(devices[i]);
+       platform_driver_unregister(&snd_dummy_driver);
+}
+
 static int __init alsa_card_dummy_init(void)
 {
        int i, cards, err;
                        err = PTR_ERR(device);
                        goto errout;
                }
+               devices[i] = device;
                cards++;
        }
        if (!cards) {
        return 0;
 
  errout:
-       platform_driver_unregister(&snd_dummy_driver);
+       snd_dummy_unregister_all();
        return err;
 }
 
 static void __exit alsa_card_dummy_exit(void)
 {
-       platform_driver_unregister(&snd_dummy_driver);
+       snd_dummy_unregister_all();
 }
 
 module_init(alsa_card_dummy_init)
 
 module_param_array(irq, int, NULL, 0444);
 MODULE_PARM_DESC(irq, "IRQ # for MPU-401 device.");
 
+static struct platform_device *platform_devices[SNDRV_CARDS];
 static int pnp_registered = 0;
 
 static int snd_mpu401_create(int dev, struct snd_card **rcard)
 static struct pnp_driver snd_mpu401_pnp_driver;
 #endif
 
+static void __init_or_module snd_mpu401_unregister_all(void)
+{
+       int i;
+
+       if (pnp_registered)
+               pnp_unregister_driver(&snd_mpu401_pnp_driver);
+       for (i = 0; i < ARRAY_SIZE(platform_devices); ++i)
+               platform_device_unregister(platform_devices[i]);
+       platform_driver_unregister(&snd_mpu401_driver);
+}
+
 static int __init alsa_card_mpu401_init(void)
 {
        int i, err, devices;
                        err = PTR_ERR(device);
                        goto errout;
                }
+               platform_devices[i] = device;
                devices++;
        }
        if ((err = pnp_register_driver(&snd_mpu401_pnp_driver)) >= 0) {
        return 0;
 
  errout:
-       if (pnp_registered)
-               pnp_unregister_driver(&snd_mpu401_pnp_driver);
-       platform_driver_unregister(&snd_mpu401_driver);
+       snd_mpu401_unregister_all();
        return err;
 }
 
 static void __exit alsa_card_mpu401_exit(void)
 {
-       if (pnp_registered)
-               pnp_unregister_driver(&snd_mpu401_pnp_driver);
-       platform_driver_unregister(&snd_mpu401_driver);
+       snd_mpu401_unregister_all();
 }
 
 module_init(alsa_card_mpu401_init)
 
 module_param(hwports, int, 0444);
 MODULE_PARM_DESC(hwports, "Hardware ports # for MotuMTPAV MIDI.");
 
+static struct platform_device *device;
+
 /*
  *      defines
  */
 static int __init alsa_card_mtpav_init(void)
 {
        int err;
-       struct platform_device *device;
 
        if ((err = platform_driver_register(&snd_mtpav_driver)) < 0)
                return err;
 
 static void __exit alsa_card_mtpav_exit(void)
 {
+       platform_device_unregister(device);
        platform_driver_unregister(&snd_mtpav_driver);
 }
 
 
 
 } snd_uart16550_t;
 
+static struct platform_device *devices[SNDRV_CARDS];
+
 static inline void snd_uart16550_add_timer(snd_uart16550_t *uart)
 {
        if (! uart->timer_running) {
        },
 };
 
+static void __init_or_module snd_serial_unregister_all(void)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(devices); ++i)
+               platform_device_unregister(devices[i]);
+       platform_driver_unregister(&snd_serial_driver);
+}
+
 static int __init alsa_card_serial_init(void)
 {
        int i, cards, err;
                        err = PTR_ERR(device);
                        goto errout;
                }
+               devices[i] = device;
                cards++;
        }
        if (! cards) {
        return 0;
 
  errout:
-       platform_driver_unregister(&snd_serial_driver);
+       snd_serial_unregister_all();
        return err;
 }
 
 static void __exit alsa_card_serial_exit(void)
 {
-       platform_driver_unregister(&snd_serial_driver);
+       snd_serial_unregister_all();
 }
 
 module_init(alsa_card_serial_init)
 
        struct snd_rawmidi *midi[MAX_MIDI_DEVICES];
 };
 
+static struct platform_device *devices[SNDRV_CARDS];
+
 
 static int __init snd_virmidi_probe(struct platform_device *devptr)
 {
        },
 };
 
+static void __init_or_module snd_virmidi_unregister_all(void)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(devices); ++i)
+               platform_device_unregister(devices[i]);
+       platform_driver_unregister(&snd_virmidi_driver);
+}
+
 static int __init alsa_card_virmidi_init(void)
 {
        int i, cards, err;
                        err = PTR_ERR(device);
                        goto errout;
                }
+               devices[i] = device;
                cards++;
        }
        if (!cards) {
        return 0;
 
  errout:
-       platform_driver_unregister(&snd_virmidi_driver);
+       snd_virmidi_unregister_all();
        return err;
 }
 
 static void __exit alsa_card_virmidi_exit(void)
 {
-       platform_driver_unregister(&snd_virmidi_driver);
+       snd_virmidi_unregister_all();
 }
 
 module_init(alsa_card_virmidi_init)
 
 module_param_array(thinkpad, bool, NULL, 0444);
 MODULE_PARM_DESC(thinkpad, "Enable only for the onboard CS4248 of IBM Thinkpad 360/750/755 series.");
 
+static struct platform_device *devices[SNDRV_CARDS];
+
 
 static int __init snd_ad1848_probe(struct platform_device *pdev)
 {
        },
 };
 
+static void __init_or_module snd_ad1848_unregister_all(void)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(devices); ++i)
+               platform_device_unregister(devices[i]);
+       platform_driver_unregister(&snd_ad1848_driver);
+}
+
 static int __init alsa_card_ad1848_init(void)
 {
        int i, cards, err;
                        err = PTR_ERR(device);
                        goto errout;
                }
+               devices[i] = device;
                cards++;
        }
        if (!cards) {
        return 0;
 
  errout:
-       platform_driver_unregister(&snd_ad1848_driver);
+       snd_ad1848_unregister_all();
        return err;
 }
 
 static void __exit alsa_card_ad1848_exit(void)
 {
-       platform_driver_unregister(&snd_ad1848_driver);
+       snd_ad1848_unregister_all();
 }
 
 module_init(alsa_card_ad1848_init)
 
 module_param_array(wssdma, int, NULL, 0444);
 MODULE_PARM_DESC(wssdma, "DMA for CMI8330 WSS driver.");
 
+static struct platform_device *platform_devices[SNDRV_CARDS];
+static int pnp_registered;
+
 #define CMI8330_RMUX3D    16
 #define CMI8330_MUTEMUX   17
 #define CMI8330_OUTPUTVOL 18
 };
 #endif /* CONFIG_PNP */
 
+static void __init_or_module snd_cmi8330_unregister_all(void)
+{
+       int i;
+
+       if (pnp_registered)
+               pnp_unregister_card_driver(&cmi8330_pnpc_driver);
+       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++;
        }
 
        err = pnp_register_card_driver(&cmi8330_pnpc_driver);
-       if (err > 0)
+       if (err >= 0) {
+               pnp_registered = 1;
                cards += err;
+       }
 
        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)
 
 module_param_array(dma2, int, NULL, 0444);
 MODULE_PARM_DESC(dma2, "DMA2 # for CS4231 driver.");
 
+static struct platform_device *devices[SNDRV_CARDS];
+
 
 static int __init snd_cs4231_probe(struct platform_device *pdev)
 {
        },
 };
 
+static void __init_or_module snd_cs4231_unregister_all(void)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(devices); ++i)
+               platform_device_unregister(devices[i]);
+       platform_driver_unregister(&snd_cs4231_driver);
+}
+
 static int __init alsa_card_cs4231_init(void)
 {
        int i, cards, err;
                        err = PTR_ERR(device);
                        goto errout;
                }
+               devices[i] = device;
                cards++;
        }
        if (!cards) {
        return 0;
 
  errout:
-       platform_driver_unregister(&snd_cs4231_driver);
+       snd_cs4231_unregister_all();
        return err;
 }
 
 static void __exit alsa_card_cs4231_exit(void)
 {
-       platform_driver_unregister(&snd_cs4231_driver);
+       snd_cs4231_unregister_all();
 }
 
 module_init(alsa_card_cs4231_init)
 
 module_param_array(dma2, int, NULL, 0444);
 MODULE_PARM_DESC(dma2, "DMA2 # for " IDENT " driver.");
 
+static struct platform_device *platform_devices[SNDRV_CARDS];
+static int pnpc_registered;
+#ifdef CS4232
+static int pnp_registered;
+#endif
+
 struct snd_card_cs4236 {
        struct snd_cs4231 *chip;
        struct resource *res_sb_port;
 };
 #endif /* CONFIG_PNP */
 
+static void __init_or_module snd_cs423x_unregister_all(void)
+{
+       int i;
+
+       if (pnpc_registered)
+               pnp_unregister_card_driver(&cs423x_pnpc_driver);
+#ifdef CS4232
+       if (pnp_registered)
+               pnp_unregister_driver(&cs4232_pnp_driver);
+#endif
+       for (i = 0; i < ARRAY_SIZE(platform_devices); ++i)
+               platform_device_unregister(platform_devices[i]);
+       platform_driver_unregister(&cs423x_nonpnp_driver);
+}
+
 static int __init alsa_card_cs423x_init(void)
 {
        int i, err, cards = 0;
                                                         i, NULL, 0);
                if (IS_ERR(device)) {
                        err = PTR_ERR(device);
-                       platform_driver_unregister(&cs423x_nonpnp_driver);
-                       return err;
+                       goto errout;
                }
+               platform_devices[i] = device;
                cards++;
        }
 #ifdef CS4232
        i = pnp_register_driver(&cs4232_pnp_driver);
-       if (i > 0)
+       if (i >= 0) {
+               pnp_registered = 1;
                cards += i;
+       }
 #endif
        i = pnp_register_card_driver(&cs423x_pnpc_driver);
-       if (i > 0)
+       if (i >= 0) {
+               pnpc_registered = 1;
                cards += i;
+       }
        if (!cards) {
-#ifdef CS4232
-               pnp_unregister_driver(&cs4232_pnp_driver);
-#endif
-               pnp_unregister_card_driver(&cs423x_pnpc_driver);
-               platform_driver_unregister(&cs423x_nonpnp_driver);
 #ifdef MODULE
                printk(KERN_ERR IDENT " soundcard not found or device busy\n");
 #endif
-               return -ENODEV;
+               err = -ENODEV;
+               goto errout;
        }
        return 0;
+
+ errout:
+       snd_cs423x_unregister_all();
+       return err;
 }
 
 static void __exit alsa_card_cs423x_exit(void)
 {
-#ifdef CS4232
-       pnp_unregister_driver(&cs4232_pnp_driver);
-#endif
-       pnp_unregister_card_driver(&cs423x_pnpc_driver);
-       platform_driver_unregister(&cs423x_nonpnp_driver);
+       snd_cs423x_unregister_all();
 }
 
 module_init(alsa_card_cs423x_init)
 
 module_param_array(dma8, int, NULL, 0444);
 MODULE_PARM_DESC(dma8, "8-bit DMA # for ESx688 driver.");
 
+static struct platform_device *devices[SNDRV_CARDS];
+
 #define PFX    "es1688: "
 
 static int __init snd_es1688_probe(struct platform_device *pdev)
        },
 };
 
+static void __init_or_module snd_es1688_unregister_all(void)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(devices); ++i)
+               platform_device_unregister(devices[i]);
+       platform_driver_unregister(&snd_es1688_driver);
+}
+
 static int __init alsa_card_es1688_init(void)
 {
        int i, cards, err;
                        err = PTR_ERR(device);
                        goto errout;
                }
+               devices[i] = device;
                cards++;
        }
        if (!cards) {
        return 0;
 
  errout:
-       platform_driver_unregister(&snd_es1688_driver);
+       snd_es1688_unregister_all();
        return err;
 }
 
 static void __exit alsa_card_es1688_exit(void)
 {
-       platform_driver_unregister(&snd_es1688_driver);
+       snd_es1688_unregister_all();
 }
 
 module_init(alsa_card_es1688_init)
 
 module_param_array(dma2, int, NULL, 0444);
 MODULE_PARM_DESC(dma2, "DMA 2 # for ES18xx driver.");
 
+static struct platform_device *platform_devices[SNDRV_CARDS];
+static int pnp_registered;
+
 #ifdef CONFIG_PNP
 
 static struct pnp_card_device_id snd_audiodrive_pnpids[] = {
 };
 #endif /* CONFIG_PNP */
 
+static void __init_or_module snd_es18xx_unregister_all(void)
+{
+       int i;
+
+       if (pnp_registered)
+               pnp_unregister_card_driver(&es18xx_pnpc_driver);
+       for (i = 0; i < ARRAY_SIZE(platform_devices); ++i)
+               platform_device_unregister(platform_devices[i]);
+       platform_driver_unregister(&snd_es18xx_nonpnp_driver);
+}
+
 static int __init alsa_card_es18xx_init(void)
 {
        int i, err, cards = 0;
                                                         i, NULL, 0);
                if (IS_ERR(device)) {
                        err = PTR_ERR(device);
-                       platform_driver_unregister(&snd_es18xx_nonpnp_driver);
-                       return err;
+                       goto errout;
                }
+               platform_devices[i] = device;
                cards++;
        }
 
        i = pnp_register_card_driver(&es18xx_pnpc_driver);
-       if (i > 0)
+       if (i >= 0) {
+               pnp_registered = 1;
                cards += i;
+       }
 
        if(!cards) {
-               pnp_unregister_card_driver(&es18xx_pnpc_driver);
-               platform_driver_unregister(&snd_es18xx_nonpnp_driver);
 #ifdef MODULE
                snd_printk(KERN_ERR "ESS AudioDrive ES18xx soundcard not found or device busy\n");
 #endif
-               return -ENODEV;
+               err = -ENODEV;
+               goto errout;
        }
        return 0;
+
+ errout:
+       snd_es18xx_unregister_all();
+       return err;
 }
 
 static void __exit alsa_card_es18xx_exit(void)
 {
-       pnp_unregister_card_driver(&es18xx_pnpc_driver);
-       platform_driver_unregister(&snd_es18xx_nonpnp_driver);
+       snd_es18xx_unregister_all();
 }
 
 module_init(alsa_card_es18xx_init)
 
 module_param_array(pcm_channels, int, NULL, 0444);
 MODULE_PARM_DESC(pcm_channels, "Reserved PCM channels for GUS Classic driver.");
 
+static struct platform_device *devices[SNDRV_CARDS];
+
 
 #define PFX    "gusclassic: "
 
        },
 };
 
+static void __init_or_module snd_gusclassic_unregister_all(void)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(devices); ++i)
+               platform_device_unregister(devices[i]);
+       platform_driver_unregister(&snd_gusclassic_driver);
+}
+
 static int __init alsa_card_gusclassic_init(void)
 {
        int i, cards, err;
                        err = PTR_ERR(device);
                        goto errout;
                }
+               devices[i] = device;
                cards++;
        }
        if (!cards) {
        return 0;
 
  errout:
-       platform_driver_unregister(&snd_gusclassic_driver);
+       snd_gusclassic_unregister_all();
        return err;
 }
 
 static void __exit alsa_card_gusclassic_exit(void)
 {
-       platform_driver_unregister(&snd_gusclassic_driver);
+       snd_gusclassic_unregister_all();
 }
 
 module_init(alsa_card_gusclassic_init)
 
 module_param_array(pcm_channels, int, NULL, 0444);
 MODULE_PARM_DESC(pcm_channels, "Reserved PCM channels for GUS Extreme driver.");
 
+struct platform_device *devices[SNDRV_CARDS];
+
 
 #define PFX    "gusextreme: "
 
        },
 };
 
+static void __init_or_module snd_gusextreme_unregister_all(void)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(devices); ++i)
+               platform_device_unregister(devices[i]);
+       platform_driver_unregister(&snd_gusextreme_driver);
+}
+
 static int __init alsa_card_gusextreme_init(void)
 {
        int i, cards, err;
                        err = PTR_ERR(device);
                        goto errout;
                }
+               devices[i] = device;
                cards++;
        }
        if (!cards) {
        return 0;
 
  errout:
-       platform_driver_unregister(&snd_gusextreme_driver);
+       snd_gusextreme_unregister_all();
        return err;
 }
 
 static void __exit alsa_card_gusextreme_exit(void)
 {
-       platform_driver_unregister(&snd_gusextreme_driver);
+       snd_gusextreme_unregister_all();
 }
 
 module_init(alsa_card_gusextreme_init)
 
 module_param_array(pcm_channels, int, NULL, 0444);
 MODULE_PARM_DESC(pcm_channels, "Reserved PCM channels for GUS MAX driver.");
 
+static struct platform_device *devices[SNDRV_CARDS];
+
 struct snd_gusmax {
        int irq;
        struct snd_card *card;
        },
 };
 
+static void __init_or_module snd_gusmax_unregister_all(void)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(devices); ++i)
+               platform_device_unregister(devices[i]);
+       platform_driver_unregister(&snd_gusmax_driver);
+}
+
 static int __init alsa_card_gusmax_init(void)
 {
        int i, cards, err;
                        err = PTR_ERR(device);
                        goto errout;
                }
+               devices[i] = device;
                cards++;
        }
        if (!cards) {
        return 0;
 
  errout:
-       platform_driver_unregister(&snd_gusmax_driver);
+       snd_gusmax_unregister_all();
        return err;
 }
 
 static void __exit alsa_card_gusmax_exit(void)
 {
-       platform_driver_unregister(&snd_gusmax_driver);
+       snd_gusmax_unregister_all();
 }
 
 module_init(alsa_card_gusmax_init)
 
 module_param_array(effect, int, NULL, 0444);
 MODULE_PARM_DESC(effect, "Effects enable for InterWave driver.");
 
+static struct platform_device *platform_devices[SNDRV_CARDS];
+static int pnp_registered;
+
 struct snd_interwave {
        int irq;
        struct snd_card *card;
 
 #endif /* CONFIG_PNP */
 
+static void __init_or_module snd_interwave_unregister_all(void)
+{
+       int i;
+
+       if (pnp_registered)
+               pnp_unregister_card_driver(&interwave_pnpc_driver);
+       for (i = 0; i < ARRAY_SIZE(platform_devices); ++i)
+               platform_device_unregister(platform_devices[i]);
+       platform_driver_unregister(&snd_interwave_driver);
+}
+
 static int __init alsa_card_interwave_init(void)
 {
        int i, err, cards = 0;
                                                         i, NULL, 0);
                if (IS_ERR(device)) {
                        err = PTR_ERR(device);
-                       platform_driver_unregister(&snd_interwave_driver);
-                       return err;
+                       goto errout;
                }
+               platform_devices[i] = device;
                cards++;
        }
 
        /* ISA PnP cards */
        i = pnp_register_card_driver(&interwave_pnpc_driver);
-       if (i > 0)
+       if (i >= 0) {
+               pnp_registered = 1;
                cards += i;
+       }
 
        if (!cards) {
-               pnp_unregister_card_driver(&interwave_pnpc_driver);
-               platform_driver_unregister(&snd_interwave_driver);
 #ifdef MODULE
                printk(KERN_ERR "InterWave soundcard not found or device busy\n");
 #endif
-               return -ENODEV;
+               err = -ENODEV;
+               goto errout;
        }
        return 0;
+
+ errout:
+       snd_interwave_unregister_all();
+       return err;
 }
 
 static void __exit alsa_card_interwave_exit(void)
 {
-       pnp_unregister_card_driver(&interwave_pnpc_driver);
-       platform_driver_unregister(&snd_interwave_driver);
+       snd_interwave_unregister_all();
 }
 
 module_init(alsa_card_interwave_init)
 
 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];
+static int pnp_registered;
+static int pnpc_registered;
+
 /* control ports */
 #define OPL3SA2_PM_CTRL                0x01
 #define OPL3SA2_SYS_CTRL               0x02
        },
 };
 
+static void __init_or_module snd_opl3sa2_unregister_all(void)
+{
+       int i;
+
+       if (pnpc_registered)
+               pnp_unregister_card_driver(&opl3sa2_pnpc_driver);
+       if (pnp_registered)
+               pnp_unregister_driver(&opl3sa2_pnp_driver);
+       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;
                                                         i, NULL, 0);
                if (IS_ERR(device)) {
                        err = PTR_ERR(device);
-                       platform_driver_unregister(&snd_opl3sa2_nonpnp_driver);
-                       return err;
+                       goto errout;
                }
+               platform_devices[i] = device;
                cards++;
        }
 
        err = pnp_register_driver(&opl3sa2_pnp_driver);
-       if (err > 0)
+       if (err >= 0) {
+               pnp_registered = 1;
                cards += err;
+       }
        err = pnp_register_card_driver(&opl3sa2_pnpc_driver);
-       if (err > 0)
+       if (err >= 0) {
+               pnpc_registered = 1;
                cards += err;
+       }
 
        if (!cards) {
 #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)
 
 };
 
 static int snd_opti9xx_pnp_is_probed;
+static struct platform_device *snd_opti9xx_platform_device;
 
 #ifdef CONFIG_PNP
 
                if (error < 0)
                        return error;
                device = platform_device_register_simple(DRIVER_NAME, -1, NULL, 0);
-               if (! IS_ERR(device))
+               if (!IS_ERR(device)) {
+                       snd_opti9xx_platform_device = device;
                        return 0;
+               }
                platform_driver_unregister(&snd_opti9xx_driver);
        }
        pnp_unregister_card_driver(&opti9xx_pnpc_driver);
 
 static void __exit alsa_card_opti9xx_exit(void)
 {
-       if (! snd_opti9xx_pnp_is_probed)
+       if (!snd_opti9xx_pnp_is_probed) {
+               platform_device_unregister(snd_opti9xx_platform_device);
                platform_driver_unregister(&snd_opti9xx_driver);
+       }
        pnp_unregister_card_driver(&opti9xx_pnpc_driver);
 }
 
 
 MODULE_PARM_DESC(seq_ports, "Number of sequencer ports for WaveTable synth.");
 #endif
 
+static struct platform_device *platform_devices[SNDRV_CARDS];
+#ifdef CONFIG_PNP
+static int pnp_registered;
+#endif
+
 struct snd_card_sb16 {
        struct resource *fm_res;        /* used to block FM i/o region for legacy cards */
        struct snd_sb *chip;
 
 #endif /* CONFIG_PNP */
 
+static void __init_or_module snd_sb16_unregister_all(void)
+{
+       int i;
+
+#ifdef CONFIG_PNP
+       if (pnp_registered)
+               pnp_unregister_card_driver(&sb16_pnpc_driver);
+#endif
+       for (i = 0; i < ARRAY_SIZE(platform_devices); ++i)
+               platform_device_unregister(platform_devices[i]);
+       platform_driver_unregister(&snd_sb16_nonpnp_driver);
+}
+
 static int __init alsa_card_sb16_init(void)
 {
        int i, err, cards = 0;
                                                         i, NULL, 0);
                if (IS_ERR(device)) {
                        err = PTR_ERR(device);
-                       platform_driver_unregister(&snd_sb16_nonpnp_driver);
-                       return err;
+                       goto errout;
                }
+               platform_devices[i] = device;
                cards++;
        }
 #ifdef CONFIG_PNP
        /* PnP cards at last */
        i = pnp_register_card_driver(&sb16_pnpc_driver);
-       if (i > 0)
+       if (i >= 0) {
+               pnp_registered = 1;
                cards += i;
+       }
 #endif
 
        if (!cards) {
-#ifdef CONFIG_PNP
-               pnp_unregister_card_driver(&sb16_pnpc_driver);
-#endif
-               platform_driver_unregister(&snd_sb16_nonpnp_driver);
 #ifdef MODULE
                snd_printk(KERN_ERR "Sound Blaster 16 soundcard not found or device busy\n");
 #ifdef SNDRV_SBAWE_EMU8000
                snd_printk(KERN_ERR "In case, if you have AWE card, try snd-sbawe module\n");
 #endif
 #endif
-               return -ENODEV;
+               err = -ENODEV;
+               goto errout;
        }
        return 0;
+
+ errout:
+       snd_sb16_unregister_all();
+       return err;
 }
 
 static void __exit alsa_card_sb16_exit(void)
 {
-#ifdef CONFIG_PNP
-       pnp_unregister_card_driver(&sb16_pnpc_driver);
-#endif
-       platform_driver_unregister(&snd_sb16_nonpnp_driver);
+       snd_sb16_unregister_all();
 }
 
 module_init(alsa_card_sb16_init)
 
 module_param_array(dma8, int, NULL, 0444);
 MODULE_PARM_DESC(dma8, "8-bit DMA # for SB8 driver.");
 
+static struct platform_device *devices[SNDRV_CARDS];
+
 struct snd_sb8 {
        struct resource *fm_res;        /* used to block FM i/o region for legacy cards */
        struct snd_sb *chip;
        },
 };
 
+static void __init_or_module snd_sb8_unregister_all(void)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(devices); ++i)
+               platform_device_unregister(devices[i]);
+       platform_driver_unregister(&snd_sb8_driver);
+}
+
 static int __init alsa_card_sb8_init(void)
 {
        int i, cards, err;
                        err = PTR_ERR(device);
                        goto errout;
                }
+               devices[i] = device;
                cards++;
        }
        if (!cards) {
        return 0;
 
  errout:
-       platform_driver_unregister(&snd_sb8_driver);
+       snd_sb8_unregister_all();
        return err;
 }
 
 static void __exit alsa_card_sb8_exit(void)
 {
-       platform_driver_unregister(&snd_sb8_driver);
+       snd_sb8_unregister_all();
 }
 
 module_init(alsa_card_sb8_init)
 
 module_param_array(dma1, int, NULL, 0444);
 MODULE_PARM_DESC(dma1, "DMA1 # for Sound Galaxy driver.");
 
+static struct platform_device *devices[SNDRV_CARDS];
+
 #define SGALAXY_AUXC_LEFT 18
 #define SGALAXY_AUXC_RIGHT 19
 
        },
 };
 
+static void __init_or_module snd_sgalaxy_unregister_all(void)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(devices); ++i)
+               platform_device_unregister(devices[i]);
+       platform_driver_unregister(&snd_sgalaxy_driver);
+}
+
 static int __init alsa_card_sgalaxy_init(void)
 {
        int i, cards, err;
                        err = PTR_ERR(device);
                        goto errout;
                }
+               devices[i] = device;
                cards++;
        }
        if (!cards) {
        return 0;
 
  errout:
-       platform_driver_unregister(&snd_sgalaxy_driver);
+       snd_sgalaxy_unregister_all();
        return err;
 }
 
 static void __exit alsa_card_sgalaxy_exit(void)
 {
-       platform_driver_unregister(&snd_sgalaxy_driver);
+       snd_sgalaxy_unregister_all();
 }
 
 module_init(alsa_card_sgalaxy_init)
 
 
 module_param_array(dma, int, NULL, 0444);
 MODULE_PARM_DESC(dma, "DMA # for SoundScape driver.");
+
+static struct platform_device *platform_devices[SNDRV_CARDS];
+static int pnp_registered;
   
 #ifdef CONFIG_PNP
 static struct pnp_card_device_id sscape_pnpids[] = {
 
 #endif /* CONFIG_PNP */
 
+static void __init_or_module sscape_unregister_all(void)
+{
+       int i;
+
+       if (pnp_registered)
+               pnp_unregister_card_driver(&sscape_pnpc_driver);
+       for (i = 0; i < ARRAY_SIZE(platform_devices); ++i)
+               platform_device_unregister(platform_devices[i]);
+       platform_driver_unregister(&snd_sscape_driver);
+}
+
 static int __init sscape_manual_probe(void)
 {
        struct platform_device *device;
                    dma[i] == SNDRV_AUTO_DMA) {
                        printk(KERN_INFO
                               "sscape: insufficient parameters, need IO, IRQ, MPU-IRQ and DMA\n");
-                       platform_driver_unregister(&snd_sscape_driver);
-                       return -ENXIO;
+                       ret = -ENXIO;
+                       goto errout;
                }
 
                /*
                device = platform_device_register_simple(SSCAPE_DRIVER,
                                                         i, NULL, 0);
                if (IS_ERR(device)) {
-                       platform_driver_unregister(&snd_sscape_driver);
-                       return PTR_ERR(device);
+                       ret = PTR_ERR(device);
+                       goto errout;
                }
+               platform_devices[i] = device;
        }
        return 0;
+
+ errout:
+       sscape_unregister_all();
+       return ret;
 }
 
 static void sscape_exit(void)
 {
-       pnp_unregister_card_driver(&sscape_pnpc_driver);
-       platform_driver_unregister(&snd_sscape_driver);
+       sscape_unregister_all();
 }
 
 
        ret = sscape_manual_probe();
        if (ret < 0)
                return ret;
-       pnp_register_card_driver(&sscape_pnpc_driver);
+       if (pnp_register_card_driver(&sscape_pnpc_driver) >= 0)
+               pnp_registered = 1;
        return 0;
 }
 
 
 module_param_array(use_cs4232_midi, bool, NULL, 0444);
 MODULE_PARM_DESC(use_cs4232_midi, "Use CS4232 MPU-401 interface (inaccessibly located inside your computer)");
 
+static struct platform_device *platform_devices[SNDRV_CARDS];
+static int pnp_registered;
+
 
 #ifdef CONFIG_PNP
 
 
 #endif /* CONFIG_PNP */
 
+static void __init_or_module snd_wavefront_unregister_all(void)
+{
+       int i;
+
+       if (pnp_registered)
+               pnp_unregister_card_driver(&wavefront_pnpc_driver);
+       for (i = 0; i < ARRAY_SIZE(platform_devices); ++i)
+               platform_device_unregister(platform_devices[i]);
+       platform_driver_unregister(&snd_wavefront_driver);
+}
+
 static int __init alsa_card_wavefront_init(void)
 {
        int i, err, cards = 0;
                device = platform_device_register_simple(WAVEFRONT_DRIVER,
                                                         i, NULL, 0);
                if (IS_ERR(device)) {
-                       platform_driver_unregister(&snd_wavefront_driver);
-                       return PTR_ERR(device);
+                       err = PTR_ERR(device);
+                       goto errout;
                }
+               platform_devices[i] = device;
                cards++;
        }
 
        i = pnp_register_card_driver(&wavefront_pnpc_driver);
-       if (i > 0)
+       if (i >= 0) {
+               pnp_registered = 1;
                cards += i;
+       }
 
        if (!cards) {
-               pnp_unregister_card_driver(&wavefront_pnpc_driver);
-               platform_driver_unregister(&snd_wavefront_driver);
 #ifdef MODULE
                printk (KERN_ERR "No WaveFront cards found or devices busy\n");
 #endif
-               return -ENODEV;
+               err = -ENODEV;
+               goto errout;
        }
        return 0;
+
+ errout:
+       snd_wavefront_unregister_all();
+       return err;
 }
 
 static void __exit alsa_card_wavefront_exit(void)
 {
-       pnp_unregister_card_driver(&wavefront_pnpc_driver);
-       platform_driver_unregister(&snd_wavefront_driver);
+       snd_wavefront_unregister_all();
 }
 
 module_init(alsa_card_wavefront_init)
 
 module_param(enable_beep, bool, 0444);
 MODULE_PARM_DESC(enable_beep, "Enable beep using PCM.");
 
+static struct platform_device *device;
+
 
 /*
  */
 static int __init alsa_card_pmac_init(void)
 {
        int err;
-       struct platform_device *device;
 
        if ((err = platform_driver_register(&snd_pmac_driver)) < 0)
                return err;
 
 static void __exit alsa_card_pmac_exit(void)
 {
+       platform_device_unregister(device);
        platform_driver_unregister(&snd_pmac_driver);
 }