Commit 1e821dd2 authored by Clemens Ladisch's avatar Clemens Ladisch Committed by Jaroslav Kysela

[ALSA] oxygen: use AC97 interrupt

After an AC97 register read or write, use the AC97 interrupt instead of
polling to wait for the access to be completed.
Signed-off-by: default avatarClemens Ladisch <clemens@ladisch.de>
Signed-off-by: default avatarJaroslav Kysela <perex@perex.cz>
parent 911b499a
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/wait.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include "oxygen_regs.h" #include "oxygen_regs.h"
...@@ -65,6 +66,7 @@ struct oxygen { ...@@ -65,6 +66,7 @@ struct oxygen {
struct snd_pcm_substream *streams[PCM_COUNT]; struct snd_pcm_substream *streams[PCM_COUNT];
struct snd_kcontrol *controls[CONTROL_COUNT]; struct snd_kcontrol *controls[CONTROL_COUNT];
struct work_struct spdif_input_bits_work; struct work_struct spdif_input_bits_work;
wait_queue_head_t ac97_waitqueue;
}; };
struct oxygen_model { struct oxygen_model {
......
...@@ -85,14 +85,22 @@ EXPORT_SYMBOL(oxygen_write32_masked); ...@@ -85,14 +85,22 @@ EXPORT_SYMBOL(oxygen_write32_masked);
static int oxygen_ac97_wait(struct oxygen *chip, unsigned int mask) static int oxygen_ac97_wait(struct oxygen *chip, unsigned int mask)
{ {
unsigned long timeout = jiffies + msecs_to_jiffies(1); u8 status = 0;
do {
udelay(5); /*
cond_resched(); * Reading the status register also clears the bits, so we have to save
if (oxygen_read8(chip, OXYGEN_AC97_INTERRUPT_STATUS) & mask) * the read bits in status.
return 0; */
} while (time_after_eq(timeout, jiffies)); wait_event_timeout(chip->ac97_waitqueue,
return -EIO; ({ status |= oxygen_read8(chip, OXYGEN_AC97_INTERRUPT_STATUS);
status & mask; }),
msecs_to_jiffies(1) + 1);
/*
* Check even after a timeout because this function should not require
* the AC'97 interrupt to be enabled.
*/
status |= oxygen_read8(chip, OXYGEN_AC97_INTERRUPT_STATUS);
return status & mask ? 0 : -EIO;
} }
/* /*
......
...@@ -53,7 +53,8 @@ static irqreturn_t oxygen_interrupt(int dummy, void *dev_id) ...@@ -53,7 +53,8 @@ static irqreturn_t oxygen_interrupt(int dummy, void *dev_id)
OXYGEN_CHANNEL_MULTICH | OXYGEN_CHANNEL_MULTICH |
OXYGEN_CHANNEL_AC97 | OXYGEN_CHANNEL_AC97 |
OXYGEN_INT_SPDIF_IN_DETECT | OXYGEN_INT_SPDIF_IN_DETECT |
OXYGEN_INT_GPIO); OXYGEN_INT_GPIO |
OXYGEN_INT_AC97);
if (clear) { if (clear) {
if (clear & OXYGEN_INT_SPDIF_IN_DETECT) if (clear & OXYGEN_INT_SPDIF_IN_DETECT)
chip->interrupt_mask &= ~OXYGEN_INT_SPDIF_IN_DETECT; chip->interrupt_mask &= ~OXYGEN_INT_SPDIF_IN_DETECT;
...@@ -89,6 +90,9 @@ static irqreturn_t oxygen_interrupt(int dummy, void *dev_id) ...@@ -89,6 +90,9 @@ static irqreturn_t oxygen_interrupt(int dummy, void *dev_id)
if ((status & OXYGEN_INT_MIDI) && chip->midi) if ((status & OXYGEN_INT_MIDI) && chip->midi)
snd_mpu401_uart_interrupt(0, chip->midi->private_data); snd_mpu401_uart_interrupt(0, chip->midi->private_data);
if (status & OXYGEN_INT_AC97)
wake_up(&chip->ac97_waitqueue);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -306,7 +310,9 @@ static void __devinit oxygen_init(struct oxygen *chip) ...@@ -306,7 +310,9 @@ static void __devinit oxygen_init(struct oxygen *chip)
(2 << OXYGEN_A_MONITOR_ROUTE_2_SHIFT) | (2 << OXYGEN_A_MONITOR_ROUTE_2_SHIFT) |
(3 << OXYGEN_A_MONITOR_ROUTE_3_SHIFT)); (3 << OXYGEN_A_MONITOR_ROUTE_3_SHIFT));
oxygen_write8(chip, OXYGEN_AC97_INTERRUPT_MASK, 0); oxygen_write8(chip, OXYGEN_AC97_INTERRUPT_MASK,
OXYGEN_AC97_INT_READ_DONE |
OXYGEN_AC97_INT_WRITE_DONE);
oxygen_write32(chip, OXYGEN_AC97_OUT_CONFIG, 0); oxygen_write32(chip, OXYGEN_AC97_OUT_CONFIG, 0);
oxygen_write32(chip, OXYGEN_AC97_IN_CONFIG, 0); oxygen_write32(chip, OXYGEN_AC97_IN_CONFIG, 0);
if (!(chip->has_ac97_0 | chip->has_ac97_1)) if (!(chip->has_ac97_0 | chip->has_ac97_1))
...@@ -408,6 +414,7 @@ int __devinit oxygen_pci_probe(struct pci_dev *pci, int index, char *id, ...@@ -408,6 +414,7 @@ int __devinit oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
mutex_init(&chip->mutex); mutex_init(&chip->mutex);
INIT_WORK(&chip->spdif_input_bits_work, INIT_WORK(&chip->spdif_input_bits_work,
oxygen_spdif_input_bits_changed); oxygen_spdif_input_bits_changed);
init_waitqueue_head(&chip->ac97_waitqueue);
err = pci_enable_device(pci); err = pci_enable_device(pci);
if (err < 0) if (err < 0)
...@@ -471,7 +478,7 @@ int __devinit oxygen_pci_probe(struct pci_dev *pci, int index, char *id, ...@@ -471,7 +478,7 @@ int __devinit oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
oxygen_proc_init(chip); oxygen_proc_init(chip);
spin_lock_irq(&chip->reg_lock); spin_lock_irq(&chip->reg_lock);
chip->interrupt_mask |= OXYGEN_INT_SPDIF_IN_DETECT; chip->interrupt_mask |= OXYGEN_INT_SPDIF_IN_DETECT | OXYGEN_INT_AC97;
oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, chip->interrupt_mask); oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, chip->interrupt_mask);
spin_unlock_irq(&chip->reg_lock); spin_unlock_irq(&chip->reg_lock);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment