vserver 1.9.5.x5
[linux-2.6.git] / sound / pci / maestro3.c
index 26a5de0..87fae62 100644 (file)
 #include <linux/pci.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
+#include <linux/moduleparam.h>
 #include <sound/core.h>
 #include <sound/info.h>
 #include <sound/control.h>
 #include <sound/pcm.h>
 #include <sound/mpu401.h>
 #include <sound/ac97_codec.h>
-#define SNDRV_GET_ID
 #include <sound/initval.h>
 
 MODULE_AUTHOR("Zach Brown <zab@zabbo.net>, Takashi Iwai <tiwai@suse.de>");
 MODULE_DESCRIPTION("ESS Maestro3 PCI");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{ESS,Maestro3 PCI},"
+MODULE_SUPPORTED_DEVICE("{{ESS,Maestro3 PCI},"
                "{ESS,ES1988},"
                "{ESS,Allegro PCI},"
                "{ESS,Allegro-1 PCI},"
@@ -64,21 +63,16 @@ static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* all enabled */
 static int external_amp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1};
 static int amp_gpio[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = -1};
 
-MODULE_PARM(index, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
+module_param_array(index, int, NULL, 0444);
 MODULE_PARM_DESC(index, "Index value for " CARD_NAME " 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 " CARD_NAME " soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
-MODULE_PARM(enable, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
+module_param_array(enable, bool, NULL, 0444);
 MODULE_PARM_DESC(enable, "Enable this soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
-MODULE_PARM(external_amp, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
+module_param_array(external_amp, bool, NULL, 0444);
 MODULE_PARM_DESC(external_amp, "Enable external amp for " CARD_NAME " soundcard.");
-MODULE_PARM_SYNTAX(external_amp, SNDRV_ENABLED "," SNDRV_BOOLEAN_TRUE_DESC);
-MODULE_PARM(amp_gpio, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
+module_param_array(amp_gpio, int, NULL, 0444);
 MODULE_PARM_DESC(amp_gpio, "GPIO pin number for external amp. (default = -1)");
-MODULE_PARM_SYNTAX(amp_gpio, SNDRV_ENABLED);
 
 #define MAX_PLAYBACKS  2
 #define MAX_CAPTURES   1
@@ -775,8 +769,6 @@ MODULE_PARM_SYNTAX(amp_gpio, SNDRV_ENABLED);
 
 typedef struct snd_m3_dma m3_dma_t;
 typedef struct snd_m3 m3_t;
-#define chip_t m3_t
-
 
 /* quirk lists */
 struct m3_quirk {
@@ -826,7 +818,6 @@ struct snd_m3 {
        snd_card_t *card;
 
        unsigned long iobase;
-       struct resource *iobase_res;
 
        int irq;
        int allegro_flag : 1;
@@ -967,7 +958,7 @@ static struct m3_quirk m3_quirk_list[] = {
                .amp_gpio = 0x03,
        },
        /* END */
-       { 0 }
+       { NULL }
 };
 
 
@@ -1164,12 +1155,11 @@ snd_m3_pcm_trigger(snd_pcm_substream_t *subs, int cmd)
 {
        m3_t *chip = snd_pcm_substream_chip(subs);
        m3_dma_t *s = (m3_dma_t*)subs->runtime->private_data;
-       unsigned long flags;
        int err = -EINVAL;
 
        snd_assert(s != NULL, return -ENXIO);
 
-       spin_lock_irqsave(&chip->reg_lock, flags);
+       spin_lock(&chip->reg_lock);
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_START:
        case SNDRV_PCM_TRIGGER_RESUME:
@@ -1190,7 +1180,7 @@ snd_m3_pcm_trigger(snd_pcm_substream_t *subs, int cmd)
                }
                break;
        }
-       spin_unlock_irqrestore(&chip->reg_lock, flags);
+       spin_unlock(&chip->reg_lock);
        return err;
 }
 
@@ -1476,7 +1466,6 @@ snd_m3_pcm_prepare(snd_pcm_substream_t *subs)
        m3_t *chip = snd_pcm_substream_chip(subs);
        snd_pcm_runtime_t *runtime = subs->runtime;
        m3_dma_t *s = (m3_dma_t*)runtime->private_data;
-       unsigned long flags;
 
        snd_assert(s != NULL, return -ENXIO);
 
@@ -1487,7 +1476,7 @@ snd_m3_pcm_prepare(snd_pcm_substream_t *subs)
            runtime->rate < 8000)
                return -EINVAL;
 
-       spin_lock_irqsave(&chip->reg_lock, flags);
+       spin_lock_irq(&chip->reg_lock);
 
        snd_m3_pcm_setup1(chip, s, subs);
 
@@ -1498,7 +1487,7 @@ snd_m3_pcm_prepare(snd_pcm_substream_t *subs)
 
        snd_m3_pcm_setup2(chip, s, runtime);
 
-       spin_unlock_irqrestore(&chip->reg_lock, flags);
+       spin_unlock_irq(&chip->reg_lock);
 
        return 0;
 }
@@ -1572,7 +1561,7 @@ static void snd_m3_update_ptr(m3_t *chip, m3_dma_t *s)
 static irqreturn_t
 snd_m3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-       m3_t *chip = snd_magic_cast(m3_t, dev_id, );
+       m3_t *chip = dev_id;
        u8 status;
        int i;
 
@@ -1669,20 +1658,19 @@ snd_m3_substream_open(m3_t *chip, snd_pcm_substream_t *subs)
 {
        int i;
        m3_dma_t *s;
-       unsigned long flags;
 
-       spin_lock_irqsave(&chip->reg_lock, flags);
+       spin_lock_irq(&chip->reg_lock);
        for (i = 0; i < chip->num_substreams; i++) {
                s = &chip->substreams[i];
                if (! s->opened)
                        goto __found;
        }
-       spin_unlock_irqrestore(&chip->reg_lock, flags);
+       spin_unlock_irq(&chip->reg_lock);
        return -ENOMEM;
 __found:
        s->opened = 1;
        s->running = 0;
-       spin_unlock_irqrestore(&chip->reg_lock, flags);
+       spin_unlock_irq(&chip->reg_lock);
 
        subs->runtime->private_data = s;
        s->substream = subs;
@@ -1702,12 +1690,11 @@ static void
 snd_m3_substream_close(m3_t *chip, snd_pcm_substream_t *subs)
 {
        m3_dma_t *s = (m3_dma_t*) subs->runtime->private_data;
-       unsigned long flags;
 
        if (s == NULL)
                return; /* not opened properly */
 
-       spin_lock_irqsave(&chip->reg_lock, flags);
+       spin_lock_irq(&chip->reg_lock);
        if (s->substream && s->running)
                snd_m3_pcm_stop(chip, s, s->substream); /* does this happen? */
        if (s->in_lists) {
@@ -1718,7 +1705,7 @@ snd_m3_substream_close(m3_t *chip, snd_pcm_substream_t *subs)
        }
        s->running = 0;
        s->opened = 0;
-       spin_unlock_irqrestore(&chip->reg_lock, flags);
+       spin_unlock_irq(&chip->reg_lock);
 }
 
 static int
@@ -1847,35 +1834,25 @@ static int snd_m3_ac97_wait(m3_t *chip)
 static unsigned short
 snd_m3_ac97_read(ac97_t *ac97, unsigned short reg)
 {
-       m3_t *chip = snd_magic_cast(m3_t, ac97->private_data, return -ENXIO);
-       unsigned short ret = 0;
-       unsigned long flags;
+       m3_t *chip = ac97->private_data;
 
-       spin_lock_irqsave(&chip->reg_lock, flags);
        if (snd_m3_ac97_wait(chip))
-               goto __error;
-       snd_m3_outb(chip, 0x80 | (reg & 0x7f), 0x30);
+               return 0xffff;
+       snd_m3_outb(chip, 0x80 | (reg & 0x7f), CODEC_COMMAND);
        if (snd_m3_ac97_wait(chip))
-               goto __error;
-       ret = snd_m3_inw(chip, 0x32);
-__error:
-       spin_unlock_irqrestore(&chip->reg_lock, flags);
-       return ret;
+               return 0xffff;
+       return snd_m3_inw(chip, CODEC_DATA);
 }
 
 static void
 snd_m3_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short val)
 {
-       m3_t *chip = snd_magic_cast(m3_t, ac97->private_data, return);
-       unsigned long flags;
+       m3_t *chip = ac97->private_data;
 
-       spin_lock_irqsave(&chip->reg_lock, flags);
        if (snd_m3_ac97_wait(chip))
-               goto __error;
-       snd_m3_outw(chip, val, 0x32);
-       snd_m3_outb(chip, reg & 0x7f, 0x30);
-__error:
-       spin_unlock_irqrestore(&chip->reg_lock, flags);
+               return;
+       snd_m3_outw(chip, val, CODEC_DATA);
+       snd_m3_outb(chip, reg & 0x7f, CODEC_COMMAND);
 }
 
 
@@ -1982,14 +1959,15 @@ static void snd_m3_ac97_reset(m3_t *chip)
 
 static int __devinit snd_m3_mixer(m3_t *chip)
 {
-       ac97_bus_t bus, *pbus;
-       ac97_t ac97;
+       ac97_bus_t *pbus;
+       ac97_template_t ac97;
        int err;
+       static ac97_bus_ops_t ops = {
+               .write = snd_m3_ac97_write,
+               .read = snd_m3_ac97_read,
+       };
 
-       memset(&bus, 0, sizeof(bus));
-       bus.write = snd_m3_ac97_write;
-       bus.read = snd_m3_ac97_read;
-       if ((err = snd_ac97_bus(chip->card, &bus, &pbus)) < 0)
+       if ((err = snd_ac97_bus(chip->card, 0, &ops, NULL, &pbus)) < 0)
                return err;
        
        memset(&ac97, 0, sizeof(ac97));
@@ -2166,7 +2144,7 @@ static void __devinit snd_m3_assp_init(m3_t *chip)
                          KDATA_DMA_XFER0);
 
        /* write kernel into code memory.. */
-       for (i = 0 ; i < sizeof(assp_kernel_image) / 2; i++) {
+       for (i = 0 ; i < ARRAY_SIZE(assp_kernel_image); i++) {
                snd_m3_assp_write(chip, MEMTYPE_INTERNAL_CODE, 
                                  REV_B_CODE_MEMORY_BEGIN + i, 
                                  assp_kernel_image[i]);
@@ -2178,7 +2156,7 @@ static void __devinit snd_m3_assp_init(m3_t *chip)
         * drop it there.  It seems that the minisrc doesn't
         * need vectors, so we won't bother with them..
         */
-       for (i = 0; i < sizeof(assp_minisrc_image) / 2; i++) {
+       for (i = 0; i < ARRAY_SIZE(assp_minisrc_image); i++) {
                snd_m3_assp_write(chip, MEMTYPE_INTERNAL_CODE, 
                                  0x400 + i, 
                                  assp_minisrc_image[i]);
@@ -2367,41 +2345,38 @@ snd_m3_enable_ints(m3_t *chip)
 
 static int snd_m3_free(m3_t *chip)
 {
-       unsigned long flags;
        m3_dma_t *s;
        int i;
 
        if (chip->substreams) {
-               spin_lock_irqsave(&chip->reg_lock, flags);
+               spin_lock_irq(&chip->reg_lock);
                for (i = 0; i < chip->num_substreams; i++) {
                        s = &chip->substreams[i];
                        /* check surviving pcms; this should not happen though.. */
                        if (s->substream && s->running)
                                snd_m3_pcm_stop(chip, s, s->substream);
                }
-               spin_unlock_irqrestore(&chip->reg_lock, flags);
+               spin_unlock_irq(&chip->reg_lock);
                kfree(chip->substreams);
        }
-       if (chip->iobase_res) {
+       if (chip->iobase) {
                snd_m3_outw(chip, HOST_INT_CTRL, 0); /* disable ints */
        }
 
 #ifdef CONFIG_PM
-       if (chip->suspend_mem)
-               vfree(chip->suspend_mem);
+       vfree(chip->suspend_mem);
 #endif
 
-       if (chip->irq >= 0)
+       if (chip->irq >= 0) {
                synchronize_irq(chip->irq);
-
-       if (chip->iobase_res) {
-               release_resource(chip->iobase_res);
-               kfree_nocheck(chip->iobase_res);
-       }
-       if (chip->irq >= 0)
                free_irq(chip->irq, (void *)chip);
+       }
 
-       snd_magic_kfree(chip);
+       if (chip->iobase)
+               pci_release_regions(chip->pci);
+
+       pci_disable_device(chip->pci);
+       kfree(chip);
        return 0;
 }
 
@@ -2410,18 +2385,16 @@ static int snd_m3_free(m3_t *chip)
  * APM support
  */
 #ifdef CONFIG_PM
-
-static void m3_suspend(m3_t *chip)
+static int m3_suspend(snd_card_t *card, unsigned int state)
 {
-       snd_card_t *card = chip->card;
+       m3_t *chip = card->pm_private_data;
        int i, index;
 
        if (chip->suspend_mem == NULL)
-               return;
-       if (card->power_state == SNDRV_CTL_POWER_D3hot)
-               return;
+               return 0;
 
        snd_pcm_suspend_all(chip->pcm);
+       snd_ac97_suspend(chip->ac97);
 
        big_mdelay(10); /* give the assp a chance to idle.. */
 
@@ -2439,18 +2412,21 @@ static void m3_suspend(m3_t *chip)
        /* power down apci registers */
        snd_m3_outw(chip, 0xffff, 0x54);
        snd_m3_outw(chip, 0xffff, 0x56);
-       snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
+
+       pci_disable_device(chip->pci);
+       return 0;
 }
 
-static void m3_resume(m3_t *chip)
+static int m3_resume(snd_card_t *card, unsigned int state)
 {
-       snd_card_t *card = chip->card;
+       m3_t *chip = card->pm_private_data;
        int i, index;
 
        if (chip->suspend_mem == NULL)
-               return;
-       if (card->power_state == SNDRV_CTL_POWER_D0)
-               return;
+               return 0;
+
+       pci_enable_device(chip->pci);
+       pci_set_master(chip->pci);
 
        /* first lets just bring everything back. .*/
        snd_m3_outw(chip, 0, 0x54);
@@ -2480,42 +2456,8 @@ static void m3_resume(m3_t *chip)
        snd_m3_enable_ints(chip);
        snd_m3_amp_enable(chip, 1);
 
-       snd_power_change_state(card, SNDRV_CTL_POWER_D0);
-}
-
-static int snd_m3_suspend(struct pci_dev *pci, u32 state)
-{
-       m3_t *chip = snd_magic_cast(m3_t, pci_get_drvdata(pci), return -ENXIO);
-       m3_suspend(chip);
-       return 0;
-}
-static int snd_m3_resume(struct pci_dev *pci)
-{
-       m3_t *chip = snd_magic_cast(m3_t, pci_get_drvdata(pci), return -ENXIO);
-       m3_resume(chip);
        return 0;
 }
-
-/* callback */
-static int snd_m3_set_power_state(snd_card_t *card, unsigned int power_state)
-{
-       m3_t *chip = snd_magic_cast(m3_t, card->power_state_private_data, return -ENXIO);
-       switch (power_state) {
-       case SNDRV_CTL_POWER_D0:
-       case SNDRV_CTL_POWER_D1:
-       case SNDRV_CTL_POWER_D2:
-               m3_resume(chip);
-               break;
-       case SNDRV_CTL_POWER_D3hot:
-       case SNDRV_CTL_POWER_D3cold:
-               m3_suspend(chip);
-               break;
-       default:
-               return -EINVAL;
-       }
-       return 0;
-}
-
 #endif /* CONFIG_PM */
 
 
@@ -2524,7 +2466,7 @@ static int snd_m3_set_power_state(snd_card_t *card, unsigned int power_state)
 
 static int snd_m3_dev_free(snd_device_t *device)
 {
-       m3_t *chip = snd_magic_cast(m3_t, device->device_data, return -ENXIO);
+       m3_t *chip = device->device_data;
        return snd_m3_free(chip);
 }
 
@@ -2551,12 +2493,15 @@ snd_m3_create(snd_card_t *card, struct pci_dev *pci,
        if (pci_set_dma_mask(pci, 0x0fffffff) < 0 ||
            pci_set_consistent_dma_mask(pci, 0x0fffffff) < 0) {
                snd_printk("architecture does not support 28bit PCI busmaster DMA\n");
+               pci_disable_device(pci);
                return -ENXIO;
        }
 
-       chip = snd_magic_kcalloc(m3_t, 0, GFP_KERNEL);
-       if (chip == NULL)
+       chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+       if (chip == NULL) {
+               pci_disable_device(pci);
                return -ENOMEM;
+       }
 
        spin_lock_init(&chip->reg_lock);
        switch (pci->device) {
@@ -2597,18 +2542,17 @@ snd_m3_create(snd_card_t *card, struct pci_dev *pci,
        chip->num_substreams = NR_DSPS;
        chip->substreams = kmalloc(sizeof(m3_dma_t) * chip->num_substreams, GFP_KERNEL);
        if (chip->substreams == NULL) {
-               snd_magic_kfree(chip);
+               kfree(chip);
+               pci_disable_device(pci);
                return -ENOMEM;
        }
        memset(chip->substreams, 0, sizeof(m3_dma_t) * chip->num_substreams);
 
-       chip->iobase = pci_resource_start(pci, 0);
-       if ((chip->iobase_res = request_region(chip->iobase, 256,
-                                              card->driver)) == NULL) {
-               snd_printk("unable to grab i/o ports %ld\n", chip->iobase);
+       if ((err = pci_request_regions(pci, card->driver)) < 0) {
                snd_m3_free(chip);
-               return -EBUSY;
+               return err;
        }
+       chip->iobase = pci_resource_start(pci, 0);
        
        /* just to be sure */
        pci_set_master(pci);
@@ -2620,26 +2564,7 @@ snd_m3_create(snd_card_t *card, struct pci_dev *pci,
 
        snd_m3_assp_init(chip);
        snd_m3_amp_enable(chip, 1);
-    
-       if ((err = snd_m3_mixer(chip)) < 0) {
-               snd_m3_free(chip);
-               return err;
-       }
 
-       for (i = 0; i < chip->num_substreams; i++) {
-               m3_dma_t *s = &chip->substreams[i];
-               s->chip = chip;
-               if ((err = snd_m3_assp_client_init(chip, s, i)) < 0) {
-                       snd_m3_free(chip);
-                       return err;
-               }
-       }
-    
-       if ((err = snd_m3_pcm(chip, 0)) < 0) {
-               snd_m3_free(chip);
-               return err;
-       }
-    
        if (request_irq(pci->irq, snd_m3_interrupt, SA_INTERRUPT|SA_SHIRQ,
                        card->driver, (void *)chip)) {
                snd_printk("unable to grab IRQ %d\n", pci->irq);
@@ -2651,11 +2576,9 @@ snd_m3_create(snd_card_t *card, struct pci_dev *pci,
 #ifdef CONFIG_PM
        chip->suspend_mem = vmalloc(sizeof(u16) * (REV_B_CODE_MEMORY_LENGTH + REV_B_DATA_MEMORY_LENGTH));
        if (chip->suspend_mem == NULL)
-               snd_printk("can't allocate apm buffer\n");
-       else {
-               card->set_power_state = snd_m3_set_power_state;
-               card->power_state_private_data = chip;
-       }
+               snd_printk(KERN_WARNING "can't allocate apm buffer\n");
+       else
+               snd_card_set_pm_callback(card, m3_suspend, m3_resume, chip);
 #endif
 
        if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
@@ -2663,6 +2586,19 @@ snd_m3_create(snd_card_t *card, struct pci_dev *pci,
                return err;
        }
 
+       if ((err = snd_m3_mixer(chip)) < 0)
+               return err;
+
+       for (i = 0; i < chip->num_substreams; i++) {
+               m3_dma_t *s = &chip->substreams[i];
+               s->chip = chip;
+               if ((err = snd_m3_assp_client_init(chip, s, i)) < 0)
+                       return err;
+       }
+
+       if ((err = snd_m3_pcm(chip, 0)) < 0)
+               return err;
+    
        snd_m3_enable_ints(chip);
        snd_m3_assp_continue(chip);
 
@@ -2738,16 +2674,14 @@ snd_m3_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
                printk(KERN_WARNING "maestro3: no midi support.\n");
 #endif
 
-       pci_set_drvdata(pci, chip);
+       pci_set_drvdata(pci, card);
        dev++;
        return 0;
 }
 
 static void __devexit snd_m3_remove(struct pci_dev *pci)
 {
-       m3_t *chip = snd_magic_cast(m3_t, pci_get_drvdata(pci), return);
-       if (chip)
-               snd_card_free(chip->card);
+       snd_card_free(pci_get_drvdata(pci));
        pci_set_drvdata(pci, NULL);
 }
 
@@ -2756,23 +2690,12 @@ static struct pci_driver driver = {
        .id_table = snd_m3_ids,
        .probe = snd_m3_probe,
        .remove = __devexit_p(snd_m3_remove),
-#ifdef CONFIG_PM
-       .suspend = snd_m3_suspend,
-       .resume = snd_m3_resume,
-#endif
+       SND_PCI_PM_CALLBACKS
 };
        
 static int __init alsa_card_m3_init(void)
 {
-       int err;
-
-       if ((err = pci_module_init(&driver)) < 0) {
-#ifdef MODULE
-               printk(KERN_ERR "Maestro3/Allegro soundcard not found or device busy\n");
-#endif
-               return err;
-       }
-       return 0;
+       return pci_module_init(&driver);
 }
 
 static void __exit alsa_card_m3_exit(void)
@@ -2782,26 +2705,3 @@ static void __exit alsa_card_m3_exit(void)
 
 module_init(alsa_card_m3_init)
 module_exit(alsa_card_m3_exit)
-
-#ifndef MODULE
-
-/* format is: snd-maestro3=enable,index,id,external_amp,amp_gpio */
-
-static int __init alsa_card_maestro3_setup(char *str)
-{
-       static unsigned __initdata nr_dev = 0;
-
-       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(&str,&external_amp[nr_dev]) == 2 &&
-              get_option(&str,&amp_gpio[nr_dev]) == 2);
-       nr_dev++;
-       return 1;
-}
-
-__setup("snd-maestro3=", alsa_card_maestro3_setup);
-
-#endif /* ifndef MODULE */