Merge branch 'apei' into apei-release
[pandora-kernel.git] / sound / pci / maestro3.c
index 3c40d72..0378126 100644 (file)
@@ -850,11 +850,10 @@ struct snd_m3 {
        struct input_dev *input_dev;
        char phys[64];                  /* physical device path */
 #else
-       spinlock_t ac97_lock;
        struct snd_kcontrol *master_switch;
        struct snd_kcontrol *master_volume;
-       struct tasklet_struct hwvol_tq;
 #endif
+       struct work_struct hwvol_work;
 
        unsigned int in_suspend;
 
@@ -1609,13 +1608,10 @@ static void snd_m3_update_ptr(struct snd_m3 *chip, struct m3_dma *s)
    (without wrap around) in response to volume button presses and then
    generating an interrupt. The pair of counters is stored in bits 1-3 and 5-7
    of a byte wide register. The meaning of bits 0 and 4 is unknown. */
-static void snd_m3_update_hw_volume(unsigned long private_data)
+static void snd_m3_update_hw_volume(struct work_struct *work)
 {
-       struct snd_m3 *chip = (struct snd_m3 *) private_data;
+       struct snd_m3 *chip = container_of(work, struct snd_m3, hwvol_work);
        int x, val;
-#ifndef CONFIG_SND_MAESTRO3_INPUT
-       unsigned long flags;
-#endif
 
        /* Figure out which volume control button was pushed,
           based on differences from the default register
@@ -1645,21 +1641,13 @@ static void snd_m3_update_hw_volume(unsigned long private_data)
        if (!chip->master_switch || !chip->master_volume)
                return;
 
-       /* FIXME: we can't call snd_ac97_* functions since here is in tasklet. */
-       spin_lock_irqsave(&chip->ac97_lock, flags);
-
-       val = chip->ac97->regs[AC97_MASTER_VOL];
+       val = snd_ac97_read(chip->ac97, AC97_MASTER);
        switch (x) {
        case 0x88:
                /* The counters have not changed, yet we've received a HV
                   interrupt. According to tests run by various people this
                   happens when pressing the mute button. */
                val ^= 0x8000;
-               chip->ac97->regs[AC97_MASTER_VOL] = val;
-               outw(val, chip->iobase + CODEC_DATA);
-               outb(AC97_MASTER_VOL, chip->iobase + CODEC_COMMAND);
-               snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
-                              &chip->master_switch->id);
                break;
        case 0xaa:
                /* counters increased by 1 -> volume up */
@@ -1667,11 +1655,6 @@ static void snd_m3_update_hw_volume(unsigned long private_data)
                        val--;
                if ((val & 0x7f00) > 0)
                        val -= 0x0100;
-               chip->ac97->regs[AC97_MASTER_VOL] = val;
-               outw(val, chip->iobase + CODEC_DATA);
-               outb(AC97_MASTER_VOL, chip->iobase + CODEC_COMMAND);
-               snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
-                              &chip->master_volume->id);
                break;
        case 0x66:
                /* counters decreased by 1 -> volume down */
@@ -1679,14 +1662,11 @@ static void snd_m3_update_hw_volume(unsigned long private_data)
                        val++;
                if ((val & 0x7f00) < 0x1f00)
                        val += 0x0100;
-               chip->ac97->regs[AC97_MASTER_VOL] = val;
-               outw(val, chip->iobase + CODEC_DATA);
-               outb(AC97_MASTER_VOL, chip->iobase + CODEC_COMMAND);
-               snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
-                              &chip->master_volume->id);
                break;
        }
-       spin_unlock_irqrestore(&chip->ac97_lock, flags);
+       if (snd_ac97_update(chip->ac97, AC97_MASTER, val))
+               snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
+                              &chip->master_switch->id);
 #else
        if (!chip->input_dev)
                return;
@@ -1730,11 +1710,7 @@ static irqreturn_t snd_m3_interrupt(int irq, void *dev_id)
                return IRQ_NONE;
 
        if (status & HV_INT_PENDING)
-#ifdef CONFIG_SND_MAESTRO3_INPUT
-               snd_m3_update_hw_volume((unsigned long)chip);
-#else
-               tasklet_schedule(&chip->hwvol_tq);
-#endif
+               schedule_work(&chip->hwvol_work);
 
        /*
         * ack an assp int if its running
@@ -2000,24 +1976,14 @@ static unsigned short
 snd_m3_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
 {
        struct snd_m3 *chip = ac97->private_data;
-#ifndef CONFIG_SND_MAESTRO3_INPUT
-       unsigned long flags;
-#endif
        unsigned short data = 0xffff;
 
        if (snd_m3_ac97_wait(chip))
                goto fail;
-#ifndef CONFIG_SND_MAESTRO3_INPUT
-       spin_lock_irqsave(&chip->ac97_lock, flags);
-#endif
        snd_m3_outb(chip, 0x80 | (reg & 0x7f), CODEC_COMMAND);
        if (snd_m3_ac97_wait(chip))
-               goto fail_unlock;
+               goto fail;
        data = snd_m3_inw(chip, CODEC_DATA);
-fail_unlock:
-#ifndef CONFIG_SND_MAESTRO3_INPUT
-       spin_unlock_irqrestore(&chip->ac97_lock, flags);
-#endif
 fail:
        return data;
 }
@@ -2026,20 +1992,11 @@ static void
 snd_m3_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short val)
 {
        struct snd_m3 *chip = ac97->private_data;
-#ifndef CONFIG_SND_MAESTRO3_INPUT
-       unsigned long flags;
-#endif
 
        if (snd_m3_ac97_wait(chip))
                return;
-#ifndef CONFIG_SND_MAESTRO3_INPUT
-       spin_lock_irqsave(&chip->ac97_lock, flags);
-#endif
        snd_m3_outw(chip, val, CODEC_DATA);
        snd_m3_outb(chip, reg & 0x7f, CODEC_COMMAND);
-#ifndef CONFIG_SND_MAESTRO3_INPUT
-       spin_unlock_irqrestore(&chip->ac97_lock, flags);
-#endif
 }
 
 
@@ -2458,6 +2415,7 @@ static int snd_m3_free(struct snd_m3 *chip)
        struct m3_dma *s;
        int i;
 
+       cancel_work_sync(&chip->hwvol_work);
 #ifdef CONFIG_SND_MAESTRO3_INPUT
        if (chip->input_dev)
                input_unregister_device(chip->input_dev);
@@ -2511,6 +2469,7 @@ static int m3_suspend(struct pci_dev *pci, pm_message_t state)
                return 0;
 
        chip->in_suspend = 1;
+       cancel_work_sync(&chip->hwvol_work);
        snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
        snd_pcm_suspend_all(chip->pcm);
        snd_ac97_suspend(chip->ac97);
@@ -2667,9 +2626,6 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci,
        }
 
        spin_lock_init(&chip->reg_lock);
-#ifndef CONFIG_SND_MAESTRO3_INPUT
-       spin_lock_init(&chip->ac97_lock);
-#endif
 
        switch (pci->device) {
        case PCI_DEVICE_ID_ESS_ALLEGRO:
@@ -2683,6 +2639,7 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci,
        chip->card = card;
        chip->pci = pci;
        chip->irq = -1;
+       INIT_WORK(&chip->hwvol_work, snd_m3_update_hw_volume);
 
        chip->external_amp = enable_amp;
        if (amp_gpio >= 0 && amp_gpio <= 0x0f)
@@ -2752,12 +2709,8 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci,
 
        snd_m3_hv_init(chip);
 
-#ifndef CONFIG_SND_MAESTRO3_INPUT
-       tasklet_init(&chip->hwvol_tq, snd_m3_update_hw_volume, (unsigned long)chip);
-#endif
-
        if (request_irq(pci->irq, snd_m3_interrupt, IRQF_SHARED,
-                       card->driver, chip)) {
+                       KBUILD_MODNAME, chip)) {
                snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
                snd_m3_free(chip);
                return -ENOMEM;
@@ -2885,7 +2838,7 @@ static void __devexit snd_m3_remove(struct pci_dev *pci)
 }
 
 static struct pci_driver driver = {
-       .name = "Maestro3",
+       .name = KBUILD_MODNAME,
        .id_table = snd_m3_ids,
        .probe = snd_m3_probe,
        .remove = __devexit_p(snd_m3_remove),