vserver 1.9.3
[linux-2.6.git] / sound / pci / cs4281.c
index 86430a0..65bc9ba 100644 (file)
@@ -40,8 +40,7 @@
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("Cirrus Logic CS4281");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{Cirrus Logic,CS4281}}");
+MODULE_SUPPORTED_DEVICE("{{Cirrus Logic,CS4281}}");
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;     /* Index 0-MAX */
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;      /* ID for this card */
@@ -51,16 +50,12 @@ static int boot_devs;
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for CS4281 soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for CS4281 soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable CS4281 soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(dual_codec, bool, boot_devs, 0444);
 MODULE_PARM_DESC(dual_codec, "Secondary Codec ID (0 = disabled).");
-MODULE_PARM_SYNTAX(dual_codec, SNDRV_ENABLED ",allows:{{0,3}}");
 
 /*
  *
@@ -441,8 +436,6 @@ MODULE_PARM_SYNTAX(dual_codec, SNDRV_ENABLED ",allows:{{0,3}}");
  *
  */
 
-#define chip_t cs4281_t
-
 typedef struct snd_cs4281 cs4281_t;
 typedef struct snd_cs4281_dma cs4281_dma_t;
 
@@ -475,8 +468,6 @@ struct snd_cs4281 {
        unsigned long ba1;              /* virtual (accessible) address */
        unsigned long ba0_addr;
        unsigned long ba1_addr;
-       struct resource *ba0_res;
-       struct resource *ba1_res;
 
        int dual_codec;
 
@@ -575,7 +566,7 @@ static void snd_cs4281_ac97_write(ac97_t *ac97,
         *  4. Read ACCTL = 460h, DCV should be reset by now and 460h = 07h
         *  5. if DCV not cleared, break and return error
         */
-       cs4281_t *chip = snd_magic_cast(cs4281_t, ac97->private_data, return);
+       cs4281_t *chip = ac97->private_data;
        int count;
 
        /*
@@ -613,7 +604,7 @@ static void snd_cs4281_ac97_write(ac97_t *ac97,
 static unsigned short snd_cs4281_ac97_read(ac97_t *ac97,
                                           unsigned short reg)
 {
-       cs4281_t *chip = snd_magic_cast(cs4281_t, ac97->private_data, return -ENXIO);
+       cs4281_t *chip = ac97->private_data;
        int count;
        unsigned short result;
        // FIXME: volatile is necessary in the following due to a bug of
@@ -709,9 +700,8 @@ static int snd_cs4281_trigger(snd_pcm_substream_t *substream, int cmd)
 {
        cs4281_dma_t *dma = (cs4281_dma_t *)substream->runtime->private_data;
        cs4281_t *chip = snd_pcm_substream_chip(substream);
-       unsigned long flags;
 
-       spin_lock_irqsave(&chip->reg_lock, flags);
+       spin_lock(&chip->reg_lock);
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
                dma->valDCR |= BA0_DCR_MSK;
@@ -738,13 +728,13 @@ static int snd_cs4281_trigger(snd_pcm_substream_t *substream, int cmd)
                        dma->valFCR &= ~BA0_FCR_FEN;
                break;
        default:
-               spin_unlock_irqrestore(&chip->reg_lock, flags);
+               spin_unlock(&chip->reg_lock);
                return -EINVAL;
        }
        snd_cs4281_pokeBA0(chip, dma->regDMR, dma->valDMR);
        snd_cs4281_pokeBA0(chip, dma->regFCR, dma->valFCR);
        snd_cs4281_pokeBA0(chip, dma->regDCR, dma->valDCR);
-       spin_unlock_irqrestore(&chip->reg_lock, flags);
+       spin_unlock(&chip->reg_lock);
        return 0;
 }
 
@@ -851,11 +841,10 @@ static int snd_cs4281_playback_prepare(snd_pcm_substream_t * substream)
        snd_pcm_runtime_t *runtime = substream->runtime;
        cs4281_dma_t *dma = (cs4281_dma_t *)runtime->private_data;
        cs4281_t *chip = snd_pcm_substream_chip(substream);
-       unsigned long flags;
 
-       spin_lock_irqsave(&chip->reg_lock, flags);
+       spin_lock_irq(&chip->reg_lock);
        snd_cs4281_mode(chip, dma, runtime, 0, 1);
-       spin_unlock_irqrestore(&chip->reg_lock, flags);
+       spin_unlock_irq(&chip->reg_lock);
        return 0;
 }
 
@@ -864,11 +853,10 @@ static int snd_cs4281_capture_prepare(snd_pcm_substream_t * substream)
        snd_pcm_runtime_t *runtime = substream->runtime;
        cs4281_dma_t *dma = (cs4281_dma_t *)runtime->private_data;
        cs4281_t *chip = snd_pcm_substream_chip(substream);
-       unsigned long flags;
 
-       spin_lock_irqsave(&chip->reg_lock, flags);
+       spin_lock_irq(&chip->reg_lock);
        snd_cs4281_mode(chip, dma, runtime, 1, 1);
-       spin_unlock_irqrestore(&chip->reg_lock, flags);
+       spin_unlock_irq(&chip->reg_lock);
        return 0;
 }
 
@@ -1015,7 +1003,7 @@ static snd_pcm_ops_t snd_cs4281_capture_ops = {
 
 static void snd_cs4281_pcm_free(snd_pcm_t *pcm)
 {
-       cs4281_t *chip = snd_magic_cast(cs4281_t, pcm->private_data, return);
+       cs4281_t *chip = pcm->private_data;
        chip->pcm = NULL;
        snd_pcm_lib_preallocate_free_for_all(pcm);
 }
@@ -1124,13 +1112,13 @@ static snd_kcontrol_new_t snd_cs4281_pcm_vol =
 
 static void snd_cs4281_mixer_free_ac97_bus(ac97_bus_t *bus)
 {
-       cs4281_t *chip = snd_magic_cast(cs4281_t, bus->private_data, return);
+       cs4281_t *chip = bus->private_data;
        chip->ac97_bus = NULL;
 }
 
 static void snd_cs4281_mixer_free_ac97(ac97_t *ac97)
 {
-       cs4281_t *chip = snd_magic_cast(cs4281_t, ac97->private_data, return);
+       cs4281_t *chip = ac97->private_data;
        if (ac97->num)
                chip->ac97_secondary = NULL;
        else
@@ -1140,17 +1128,16 @@ static void snd_cs4281_mixer_free_ac97(ac97_t *ac97)
 static int __devinit snd_cs4281_mixer(cs4281_t * chip)
 {
        snd_card_t *card = chip->card;
-       ac97_bus_t bus;
-       ac97_t ac97;
+       ac97_template_t ac97;
        int err;
+       static ac97_bus_ops_t ops = {
+               .write = snd_cs4281_ac97_write,
+               .read = snd_cs4281_ac97_read,
+       };
 
-       memset(&bus, 0, sizeof(bus));
-       bus.write = snd_cs4281_ac97_write;
-       bus.read = snd_cs4281_ac97_read;
-       bus.private_data = chip;
-       bus.private_free = snd_cs4281_mixer_free_ac97_bus;
-       if ((err = snd_ac97_bus(card, &bus, &chip->ac97_bus)) < 0)
+       if ((err = snd_ac97_bus(card, 0, &ops, chip, &chip->ac97_bus)) < 0)
                return err;
+       chip->ac97_bus->private_free = snd_cs4281_mixer_free_ac97_bus;
 
        memset(&ac97, 0, sizeof(ac97));
        ac97.private_data = chip;
@@ -1177,7 +1164,7 @@ static int __devinit snd_cs4281_mixer(cs4281_t * chip)
 static void snd_cs4281_proc_read(snd_info_entry_t *entry, 
                                  snd_info_buffer_t * buffer)
 {
-       cs4281_t *chip = snd_magic_cast(cs4281_t, entry->private_data, return);
+       cs4281_t *chip = entry->private_data;
 
        snd_iprintf(buffer, "Cirrus Logic CS4281\n\n");
        snd_iprintf(buffer, "Spurious half IRQs   : %u\n", chip->spurious_dhtc_irq);
@@ -1189,7 +1176,7 @@ static long snd_cs4281_BA0_read(snd_info_entry_t *entry, void *file_private_data
                                unsigned long count, unsigned long pos)
 {
        long size;
-       cs4281_t *chip = snd_magic_cast(cs4281_t, entry->private_data, return -ENXIO);
+       cs4281_t *chip = entry->private_data;
        
        size = count;
        if (pos + size > CS4281_BA0_SIZE)
@@ -1206,7 +1193,7 @@ static long snd_cs4281_BA1_read(snd_info_entry_t *entry, void *file_private_data
                                unsigned long count, unsigned long pos)
 {
        long size;
-       cs4281_t *chip = snd_magic_cast(cs4281_t, entry->private_data, return -ENXIO);
+       cs4281_t *chip = entry->private_data;
        
        size = count;
        if (pos + size > CS4281_BA1_SIZE)
@@ -1262,7 +1249,7 @@ static void snd_cs4281_gameport_trigger(struct gameport *gameport)
        cs4281_gameport_t *gp = (cs4281_gameport_t *)gameport;
        cs4281_t *chip;
        snd_assert(gp, return);
-       chip = snd_magic_cast(cs4281_t, gp->chip, return);
+       chip = gp->chip;
        snd_cs4281_pokeBA0(chip, BA0_JSPT, 0xff);
 }
 
@@ -1271,7 +1258,7 @@ static unsigned char snd_cs4281_gameport_read(struct gameport *gameport)
        cs4281_gameport_t *gp = (cs4281_gameport_t *)gameport;
        cs4281_t *chip;
        snd_assert(gp, return 0);
-       chip = snd_magic_cast(cs4281_t, gp->chip, return 0);
+       chip = gp->chip;
        return snd_cs4281_peekBA0(chip, BA0_JSPT);
 }
 
@@ -1283,7 +1270,7 @@ static int snd_cs4281_gameport_cooked_read(struct gameport *gameport, int *axes,
        unsigned js1, js2, jst;
        
        snd_assert(gp, return 0);
-       chip = snd_magic_cast(cs4281_t, gp->chip, return 0);
+       chip = gp->chip;
 
        js1 = snd_cs4281_peekBA0(chip, BA0_JSC1);
        js2 = snd_cs4281_peekBA0(chip, BA0_JSC2);
@@ -1369,28 +1356,21 @@ static int snd_cs4281_free(cs4281_t *chip)
        /* PCI interface - D3 state */
        pci_set_power_state(chip->pci, 3);
 
+       if (chip->irq >= 0)
+               free_irq(chip->irq, (void *)chip);
        if (chip->ba0)
                iounmap((void *) chip->ba0);
        if (chip->ba1)
                iounmap((void *) chip->ba1);
-       if (chip->ba0_res) {
-               release_resource(chip->ba0_res);
-               kfree_nocheck(chip->ba0_res);
-       }
-       if (chip->ba1_res) {
-               release_resource(chip->ba1_res);
-               kfree_nocheck(chip->ba1_res);
-       }
-       if (chip->irq >= 0)
-               free_irq(chip->irq, (void *)chip);
+       pci_release_regions(chip->pci);
 
-       snd_magic_kfree(chip);
+       kfree(chip);
        return 0;
 }
 
 static int snd_cs4281_dev_free(snd_device_t *device)
 {
-       cs4281_t *chip = snd_magic_cast(cs4281_t, device->device_data, return -ENXIO);
+       cs4281_t *chip = device->device_data;
        return snd_cs4281_free(chip);
 }
 
@@ -1415,15 +1395,13 @@ static int __devinit snd_cs4281_create(snd_card_t * card,
        *rchip = NULL;
        if ((err = pci_enable_device(pci)) < 0)
                return err;
-       chip = snd_magic_kcalloc(cs4281_t, 0, GFP_KERNEL);
+       chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
        if (chip == NULL)
                return -ENOMEM;
        spin_lock_init(&chip->reg_lock);
        chip->card = card;
        chip->pci = pci;
        chip->irq = -1;
-       chip->ba0_addr = pci_resource_start(pci, 0);
-       chip->ba1_addr = pci_resource_start(pci, 1);
        pci_set_master(pci);
        if (dual_codec < 0 || dual_codec > 3) {
                snd_printk(KERN_ERR "invalid dual_codec option %d\n", dual_codec);
@@ -1431,16 +1409,13 @@ static int __devinit snd_cs4281_create(snd_card_t * card,
        }
        chip->dual_codec = dual_codec;
 
-       if ((chip->ba0_res = request_mem_region(chip->ba0_addr, CS4281_BA0_SIZE, "CS4281 BA0")) == NULL) {
-               snd_printk(KERN_ERR "unable to grab memory region 0x%lx-0x%lx\n", chip->ba0_addr, chip->ba0_addr + CS4281_BA0_SIZE - 1);
-               snd_cs4281_free(chip);
-               return -ENOMEM;
-       }
-       if ((chip->ba1_res = request_mem_region(chip->ba1_addr, CS4281_BA1_SIZE, "CS4281 BA1")) == NULL) {
-               snd_printk(KERN_ERR "unable to grab memory region 0x%lx-0x%lx\n", chip->ba1_addr, chip->ba1_addr + CS4281_BA1_SIZE - 1);
-               snd_cs4281_free(chip);
-               return -ENOMEM;
+       if ((err = pci_request_regions(pci, "CS4281")) < 0) {
+               kfree(chip);
+               return err;
        }
+       chip->ba0_addr = pci_resource_start(pci, 0);
+       chip->ba1_addr = pci_resource_start(pci, 1);
+
        if (request_irq(pci->irq, snd_cs4281_interrupt, SA_INTERRUPT|SA_SHIRQ, "CS4281", (void *)chip)) {
                snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
                snd_cs4281_free(chip);
@@ -1448,8 +1423,8 @@ static int __devinit snd_cs4281_create(snd_card_t * card,
        }
        chip->irq = pci->irq;
 
-       chip->ba0 = (unsigned long) ioremap_nocache(chip->ba0_addr, CS4281_BA0_SIZE);
-       chip->ba1 = (unsigned long) ioremap_nocache(chip->ba1_addr, CS4281_BA1_SIZE);
+       chip->ba0 = (unsigned long) ioremap_nocache(chip->ba0_addr, pci_resource_len(pci, 0));
+       chip->ba1 = (unsigned long) ioremap_nocache(chip->ba1_addr, pci_resource_len(pci, 1));
        if (!chip->ba0 || !chip->ba1) {
                snd_cs4281_free(chip);
                return -ENOMEM;
@@ -1713,10 +1688,9 @@ static void snd_cs4281_midi_reset(cs4281_t *chip)
 
 static int snd_cs4281_midi_input_open(snd_rawmidi_substream_t * substream)
 {
-       unsigned long flags;
-       cs4281_t *chip = snd_magic_cast(cs4281_t, substream->rmidi->private_data, return -ENXIO);
+       cs4281_t *chip = substream->rmidi->private_data;
 
-       spin_lock_irqsave(&chip->reg_lock, flags);
+       spin_lock_irq(&chip->reg_lock);
        chip->midcr |= BA0_MIDCR_RXE;
        chip->midi_input = substream;
        if (!(chip->uartm & CS4281_MODE_OUTPUT)) {
@@ -1724,16 +1698,15 @@ static int snd_cs4281_midi_input_open(snd_rawmidi_substream_t * substream)
        } else {
                snd_cs4281_pokeBA0(chip, BA0_MIDCR, chip->midcr);
        }
-       spin_unlock_irqrestore(&chip->reg_lock, flags);
+       spin_unlock_irq(&chip->reg_lock);
        return 0;
 }
 
 static int snd_cs4281_midi_input_close(snd_rawmidi_substream_t * substream)
 {
-       unsigned long flags;
-       cs4281_t *chip = snd_magic_cast(cs4281_t, substream->rmidi->private_data, return -ENXIO);
+       cs4281_t *chip = substream->rmidi->private_data;
 
-       spin_lock_irqsave(&chip->reg_lock, flags);
+       spin_lock_irq(&chip->reg_lock);
        chip->midcr &= ~(BA0_MIDCR_RXE | BA0_MIDCR_RIE);
        chip->midi_input = NULL;
        if (!(chip->uartm & CS4281_MODE_OUTPUT)) {
@@ -1742,16 +1715,15 @@ static int snd_cs4281_midi_input_close(snd_rawmidi_substream_t * substream)
                snd_cs4281_pokeBA0(chip, BA0_MIDCR, chip->midcr);
        }
        chip->uartm &= ~CS4281_MODE_INPUT;
-       spin_unlock_irqrestore(&chip->reg_lock, flags);
+       spin_unlock_irq(&chip->reg_lock);
        return 0;
 }
 
 static int snd_cs4281_midi_output_open(snd_rawmidi_substream_t * substream)
 {
-       unsigned long flags;
-       cs4281_t *chip = snd_magic_cast(cs4281_t, substream->rmidi->private_data, return -ENXIO);
+       cs4281_t *chip = substream->rmidi->private_data;
 
-       spin_lock_irqsave(&chip->reg_lock, flags);
+       spin_lock_irq(&chip->reg_lock);
        chip->uartm |= CS4281_MODE_OUTPUT;
        chip->midcr |= BA0_MIDCR_TXE;
        chip->midi_output = substream;
@@ -1760,16 +1732,15 @@ static int snd_cs4281_midi_output_open(snd_rawmidi_substream_t * substream)
        } else {
                snd_cs4281_pokeBA0(chip, BA0_MIDCR, chip->midcr);
        }
-       spin_unlock_irqrestore(&chip->reg_lock, flags);
+       spin_unlock_irq(&chip->reg_lock);
        return 0;
 }
 
 static int snd_cs4281_midi_output_close(snd_rawmidi_substream_t * substream)
 {
-       unsigned long flags;
-       cs4281_t *chip = snd_magic_cast(cs4281_t, substream->rmidi->private_data, return -ENXIO);
+       cs4281_t *chip = substream->rmidi->private_data;
 
-       spin_lock_irqsave(&chip->reg_lock, flags);
+       spin_lock_irq(&chip->reg_lock);
        chip->midcr &= ~(BA0_MIDCR_TXE | BA0_MIDCR_TIE);
        chip->midi_output = NULL;
        if (!(chip->uartm & CS4281_MODE_INPUT)) {
@@ -1778,14 +1749,14 @@ static int snd_cs4281_midi_output_close(snd_rawmidi_substream_t * substream)
                snd_cs4281_pokeBA0(chip, BA0_MIDCR, chip->midcr);
        }
        chip->uartm &= ~CS4281_MODE_OUTPUT;
-       spin_unlock_irqrestore(&chip->reg_lock, flags);
+       spin_unlock_irq(&chip->reg_lock);
        return 0;
 }
 
 static void snd_cs4281_midi_input_trigger(snd_rawmidi_substream_t * substream, int up)
 {
        unsigned long flags;
-       cs4281_t *chip = snd_magic_cast(cs4281_t, substream->rmidi->private_data, return);
+       cs4281_t *chip = substream->rmidi->private_data;
 
        spin_lock_irqsave(&chip->reg_lock, flags);
        if (up) {
@@ -1805,7 +1776,7 @@ static void snd_cs4281_midi_input_trigger(snd_rawmidi_substream_t * substream, i
 static void snd_cs4281_midi_output_trigger(snd_rawmidi_substream_t * substream, int up)
 {
        unsigned long flags;
-       cs4281_t *chip = snd_magic_cast(cs4281_t, substream->rmidi->private_data, return);
+       cs4281_t *chip = substream->rmidi->private_data;
        unsigned char byte;
 
        spin_lock_irqsave(&chip->reg_lock, flags);
@@ -1872,7 +1843,7 @@ static int __devinit snd_cs4281_midi(cs4281_t * chip, int device, snd_rawmidi_t
 
 static irqreturn_t snd_cs4281_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-       cs4281_t *chip = snd_magic_cast(cs4281_t, dev_id, return IRQ_NONE);
+       cs4281_t *chip = dev_id;
        unsigned int status, dma, val;
        cs4281_dma_t *cdma;
 
@@ -1919,7 +1890,9 @@ static irqreturn_t snd_cs4281_interrupt(int irq, void *dev_id, struct pt_regs *r
                        c = snd_cs4281_peekBA0(chip, BA0_MIDRP);
                        if ((chip->midcr & BA0_MIDCR_RIE) == 0)
                                continue;
+                       spin_unlock(&chip->reg_lock);
                        snd_rawmidi_receive(chip->midi_input, &c, 1);
+                       spin_lock(&chip->reg_lock);
                }
                while ((snd_cs4281_peekBA0(chip, BA0_MIDSR) & BA0_MIDSR_TBF) == 0) {
                        if ((chip->midcr & BA0_MIDCR_TIE) == 0)
@@ -2034,13 +2007,11 @@ static int saved_regs[SUSPEND_REGISTERS] = {
        BA0_PPRVC,
 };
 
-#define number_of(array)       (sizeof(array) / sizeof(array[0]))
-
 #define CLKCR1_CKRA                             0x00010000L
 
 static int cs4281_suspend(snd_card_t *card, unsigned int state)
 {
-       cs4281_t *chip = snd_magic_cast(cs4281_t, card->pm_private_data, return -EINVAL);
+       cs4281_t *chip = card->pm_private_data;
        u32 ulCLK;
        unsigned int i;
 
@@ -2059,7 +2030,7 @@ static int cs4281_suspend(snd_card_t *card, unsigned int state)
        snd_cs4281_pokeBA0(chip, BA0_HICR, BA0_HICR_CHGM);
 
        /* remember the status registers */
-       for (i = 0; i < number_of(saved_regs); i++)
+       for (i = 0; i < ARRAY_SIZE(saved_regs); i++)
                if (saved_regs[i])
                        chip->suspend_regs[i] = snd_cs4281_peekBA0(chip, saved_regs[i]);
 
@@ -2085,7 +2056,7 @@ static int cs4281_suspend(snd_card_t *card, unsigned int state)
 
 static int cs4281_resume(snd_card_t *card, unsigned int state)
 {
-       cs4281_t *chip = snd_magic_cast(cs4281_t, card->pm_private_data, return -EINVAL);
+       cs4281_t *chip = card->pm_private_data;
        unsigned int i;
        u32 ulCLK;
 
@@ -2098,7 +2069,7 @@ static int cs4281_resume(snd_card_t *card, unsigned int state)
        snd_cs4281_chip_init(chip);
 
        /* restore the status registers */
-       for (i = 0; i < number_of(saved_regs); i++)
+       for (i = 0; i < ARRAY_SIZE(saved_regs); i++)
                if (saved_regs[i])
                        snd_cs4281_pokeBA0(chip, saved_regs[i], chip->suspend_regs[i]);