*/
#include <sound/driver.h>
-#include <asm/dma.h>
#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/time.h>
-#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/moduleparam.h>
+#include <asm/dma.h>
#include <sound/core.h>
#include <sound/sb.h>
#include <sound/ad1848.h>
#include <sound/control.h>
#define SNDRV_LEGACY_FIND_FREE_IRQ
#define SNDRV_LEGACY_FIND_FREE_DMA
-#define SNDRV_GET_ID
#include <sound/initval.h>
MODULE_AUTHOR("Christopher Butler <chrisb@sandy.force9.co.uk>");
MODULE_DESCRIPTION("Aztech Sound Galaxy");
MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{Aztech Systems,Sound Galaxy}}");
+MODULE_SUPPORTED_DEVICE("{{Aztech Systems,Sound Galaxy}}");
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 7,9,10,11 */
static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3 */
-MODULE_PARM(index, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
+module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for Sound Galaxy soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
-MODULE_PARM(id, "1-" __MODULE_STRING(SNDRV_CARDS) "s");
+module_param_array(id, charp, NULL, 0444);
MODULE_PARM_DESC(id, "ID string for Sound Galaxy soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
-MODULE_PARM(sbport, "1-" __MODULE_STRING(SNDRV_CARDS) "l");
+module_param_array(sbport, long, NULL, 0444);
MODULE_PARM_DESC(sbport, "Port # for Sound Galaxy SB driver.");
-MODULE_PARM_SYNTAX(sbport, SNDRV_ENABLED ",allows:{{0x220},{0x240}},dialog:list");
-MODULE_PARM(wssport, "1-" __MODULE_STRING(SNDRV_CARDS) "l");
+module_param_array(wssport, long, NULL, 0444);
MODULE_PARM_DESC(wssport, "Port # for Sound Galaxy WSS driver.");
-MODULE_PARM_SYNTAX(wssport, SNDRV_ENABLED ",allows:{{0x530},{0xe80},{0xf40},{0x604}},dialog:list");
-MODULE_PARM(irq, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
+module_param_array(irq, int, NULL, 0444);
MODULE_PARM_DESC(irq, "IRQ # for Sound Galaxy driver.");
-MODULE_PARM_SYNTAX(irq, SNDRV_ENABLED ",allows:{{7},{9},{10},{11}},dialog:list");
-MODULE_PARM(dma1, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
+module_param_array(dma1, int, NULL, 0444);
MODULE_PARM_DESC(dma1, "DMA1 # for Sound Galaxy driver.");
-MODULE_PARM_SYNTAX(dma1, SNDRV_DMA8_DESC);
+
+static struct platform_device *devices[SNDRV_CARDS];
#define SGALAXY_AUXC_LEFT 18
#define SGALAXY_AUXC_RIGHT 19
-static snd_card_t *snd_sgalaxy_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
+#define PFX "sgalaxy: "
/*
#define AD1848P1( port, x ) ( port + c_d_c_AD1848##x )
-/* from lowlevel/sb/sb.c - to avoid having to allocate a sb_t for the */
+/* from lowlevel/sb/sb.c - to avoid having to allocate a struct snd_sb for the */
/* short time we actually need it.. */
static int snd_sgalaxy_sbdsp_reset(unsigned long port)
}
#if 0
- snd_printdd("sgalaxy - setting up IRQ/DMA for WSS\n");
+ snd_printdd(PFX "setting up IRQ/DMA for WSS\n");
#endif
/* initialize IRQ for WSS codec */
static int __init snd_sgalaxy_detect(int dev, int irq, int dma)
{
#if 0
- snd_printdd("sgalaxy - switching to WSS mode\n");
+ snd_printdd(PFX "switching to WSS mode\n");
#endif
/* switch to WSS mode */
AD1848_DOUBLE("Aux Playback Volume", 0, SGALAXY_AUXC_LEFT, SGALAXY_AUXC_RIGHT, 0, 0, 31, 0)
};
-static int __init snd_sgalaxy_mixer(ad1848_t *chip)
+static int __init snd_sgalaxy_mixer(struct snd_ad1848 *chip)
{
- snd_card_t *card = chip->card;
- snd_ctl_elem_id_t id1, id2;
+ struct snd_card *card = chip->card;
+ struct snd_ctl_elem_id id1, id2;
unsigned int idx;
int err;
return 0;
}
-static int __init snd_sgalaxy_probe(int dev)
+static int __init snd_sgalaxy_probe(struct platform_device *devptr)
{
+ int dev = devptr->id;
static int possible_irqs[] = {7, 9, 10, 11, -1};
static int possible_dmas[] = {1, 3, 0, -1};
int err, xirq, xdma1;
- snd_card_t *card;
- ad1848_t *chip;
+ struct snd_card *card;
+ struct snd_ad1848 *chip;
if (sbport[dev] == SNDRV_AUTO_PORT) {
- snd_printk("specify SB port\n");
+ snd_printk(KERN_ERR PFX "specify SB port\n");
return -EINVAL;
}
if (wssport[dev] == SNDRV_AUTO_PORT) {
- snd_printk("specify WSS port\n");
+ snd_printk(KERN_ERR PFX "specify WSS port\n");
return -EINVAL;
}
card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
xirq = irq[dev];
if (xirq == SNDRV_AUTO_IRQ) {
if ((xirq = snd_legacy_find_free_irq(possible_irqs)) < 0) {
- snd_card_free(card);
- snd_printk("unable to find a free IRQ\n");
- return -EBUSY;
+ snd_printk(KERN_ERR PFX "unable to find a free IRQ\n");
+ err = -EBUSY;
+ goto _err;
}
}
xdma1 = dma1[dev];
if (xdma1 == SNDRV_AUTO_DMA) {
if ((xdma1 = snd_legacy_find_free_dma(possible_dmas)) < 0) {
- snd_card_free(card);
- snd_printk("unable to find a free DMA\n");
- return -EBUSY;
+ snd_printk(KERN_ERR PFX "unable to find a free DMA\n");
+ err = -EBUSY;
+ goto _err;
}
}
- if ((err = snd_sgalaxy_detect(dev, xirq, xdma1)) < 0) {
- snd_card_free(card);
- return err;
- }
+ if ((err = snd_sgalaxy_detect(dev, xirq, xdma1)) < 0)
+ goto _err;
if ((err = snd_ad1848_create(card, wssport[dev] + 4,
xirq, xdma1,
- AD1848_HW_DETECT, &chip)) < 0) {
- snd_card_free(card);
- return err;
- }
+ AD1848_HW_DETECT, &chip)) < 0)
+ goto _err;
+ card->private_data = chip;
if ((err = snd_ad1848_pcm(chip, 0, NULL)) < 0) {
- snd_printdd("sgalaxy - error creating new ad1848 PCM device\n");
- snd_card_free(card);
- return err;
+ snd_printdd(PFX "error creating new ad1848 PCM device\n");
+ goto _err;
}
if ((err = snd_ad1848_mixer(chip)) < 0) {
- snd_printdd("sgalaxy - error creating new ad1848 mixer\n");
- snd_card_free(card);
- return err;
+ snd_printdd(PFX "error creating new ad1848 mixer\n");
+ goto _err;
}
- if (snd_sgalaxy_mixer(chip) < 0) {
- snd_printdd("sgalaxy - the mixer rewrite failed\n");
- snd_card_free(card);
- return err;
+ if ((err = snd_sgalaxy_mixer(chip)) < 0) {
+ snd_printdd(PFX "the mixer rewrite failed\n");
+ goto _err;
}
strcpy(card->driver, "Sound Galaxy");
sprintf(card->longname, "Sound Galaxy at 0x%lx, irq %d, dma %d",
wssport[dev], xirq, xdma1);
- if ((err = snd_card_register(card)) < 0) {
- snd_card_free(card);
- return err;
- }
- snd_sgalaxy_cards[dev] = card;
+ snd_card_set_dev(card, &devptr->dev);
+
+ if ((err = snd_card_register(card)) < 0)
+ goto _err;
+
+ platform_set_drvdata(devptr, card);
return 0;
+
+ _err:
+ snd_card_free(card);
+ return err;
}
-static int __init alsa_card_sgalaxy_init(void)
+static int __devexit snd_sgalaxy_remove(struct platform_device *devptr)
{
- int dev, cards;
+ snd_card_free(platform_get_drvdata(devptr));
+ platform_set_drvdata(devptr, NULL);
+ return 0;
+}
- for (dev = cards = 0; dev < SNDRV_CARDS && enable[dev]; dev++) {
- if (snd_sgalaxy_probe(dev) >= 0)
- cards++;
- }
- if (!cards) {
-#ifdef MODULE
- snd_printk(KERN_ERR "Sound Galaxy soundcard not found or device busy\n");
-#endif
- return -ENODEV;
- }
+#ifdef CONFIG_PM
+static int snd_sgalaxy_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct snd_card *card = platform_get_drvdata(pdev);
+ struct snd_ad1848 *chip = card->private_data;
+ snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
+ chip->suspend(chip);
return 0;
}
-static void __exit alsa_card_sgalaxy_exit(void)
+static int snd_sgalaxy_resume(struct platform_device *pdev)
{
- int idx;
+ struct snd_card *card = platform_get_drvdata(pdev);
+ struct snd_ad1848 *chip = card->private_data;
+
+ chip->resume(chip);
+ snd_ad1848_out(chip, SGALAXY_AUXC_LEFT, chip->image[SGALAXY_AUXC_LEFT]);
+ snd_ad1848_out(chip, SGALAXY_AUXC_RIGHT, chip->image[SGALAXY_AUXC_RIGHT]);
- for (idx = 0; idx < SNDRV_CARDS; idx++)
- snd_card_free(snd_sgalaxy_cards[idx]);
+ snd_power_change_state(card, SNDRV_CTL_POWER_D0);
+ return 0;
}
+#endif
-module_init(alsa_card_sgalaxy_init)
-module_exit(alsa_card_sgalaxy_exit)
+#define SND_SGALAXY_DRIVER "snd_sgalaxy"
+
+static struct platform_driver snd_sgalaxy_driver = {
+ .probe = snd_sgalaxy_probe,
+ .remove = __devexit_p(snd_sgalaxy_remove),
+#ifdef CONFIG_PM
+ .suspend = snd_sgalaxy_suspend,
+ .resume = snd_sgalaxy_resume,
+#endif
+ .driver = {
+ .name = SND_SGALAXY_DRIVER
+ },
+};
-#ifndef MODULE
+static void __init_or_module snd_sgalaxy_unregister_all(void)
+{
+ int i;
-/* format is: snd-sgalaxy=enable,index,id,
- sbport,wssport,
- irq,dma1 */
+ 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_setup(char *str)
+static int __init alsa_card_sgalaxy_init(void)
{
- static unsigned __initdata nr_dev = 0;
+ int i, cards, err;
- if (nr_dev >= SNDRV_CARDS)
- return 0;
- (void)(get_option(&str,&enable[nr_dev]) == 2 &&
- get_option(&str,&index[nr_dev]) == 2 &&
- get_id(&str,&id[nr_dev]) == 2 &&
- get_option_long(&str,&sbport[nr_dev]) == 2 &&
- get_option_long(&str,&wssport[nr_dev]) == 2 &&
- get_option(&str,&irq[nr_dev]) == 2 &&
- get_option(&str,&dma1[nr_dev]) == 2);
- nr_dev++;
- return 1;
+ err = platform_driver_register(&snd_sgalaxy_driver);
+ if (err < 0)
+ return err;
+
+ cards = 0;
+ for (i = 0; i < SNDRV_CARDS && enable[i]; i++) {
+ struct platform_device *device;
+ device = platform_device_register_simple(SND_SGALAXY_DRIVER,
+ i, NULL, 0);
+ if (IS_ERR(device)) {
+ err = PTR_ERR(device);
+ goto errout;
+ }
+ devices[i] = device;
+ cards++;
+ }
+ if (!cards) {
+#ifdef MODULE
+ snd_printk(KERN_ERR "Sound Galaxy soundcard not found or device busy\n");
+#endif
+ err = -ENODEV;
+ goto errout;
+ }
+ return 0;
+
+ errout:
+ snd_sgalaxy_unregister_all();
+ return err;
}
-__setup("snd-sgalaxy=", alsa_card_sgalaxy_setup);
+static void __exit alsa_card_sgalaxy_exit(void)
+{
+ snd_sgalaxy_unregister_all();
+}
-#endif /* ifndef MODULE */
+module_init(alsa_card_sgalaxy_init)
+module_exit(alsa_card_sgalaxy_exit)