Commit 309d6afd authored by Jaroslav Kysela's avatar Jaroslav Kysela

[ALSA] Fix sleep in h/w volume control

ES1968 driver
Fixed sleeps in h/w volume control tasklet.
Also, msleep()s in ac97 accessor callbacks are removed since the chip
works without such delays.
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 83c60443
...@@ -584,7 +584,7 @@ struct snd_es1968 { ...@@ -584,7 +584,7 @@ struct snd_es1968 {
snd_rawmidi_t *rmidi; snd_rawmidi_t *rmidi;
spinlock_t reg_lock; spinlock_t reg_lock;
struct semaphore ac97_mutex; /* ac97 lock */ spinlock_t ac97_lock;
struct tasklet_struct hwvol_tq; struct tasklet_struct hwvol_tq;
/* Maestro Stuff */ /* Maestro Stuff */
...@@ -686,35 +686,36 @@ static int snd_es1968_ac97_wait(es1968_t *chip) ...@@ -686,35 +686,36 @@ static int snd_es1968_ac97_wait(es1968_t *chip)
static void snd_es1968_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short val) static void snd_es1968_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short val)
{ {
es1968_t *chip = ac97->private_data; es1968_t *chip = ac97->private_data;
unsigned long flags;
down(&chip->ac97_mutex);
snd_es1968_ac97_wait(chip); snd_es1968_ac97_wait(chip);
/* Write the bus */ /* Write the bus */
spin_lock_irqsave(&chip->ac97_lock, flags);
outw(val, chip->io_port + ESM_AC97_DATA); outw(val, chip->io_port + ESM_AC97_DATA);
msleep(1); /*msleep(1);*/
outb(reg, chip->io_port + ESM_AC97_INDEX); outb(reg, chip->io_port + ESM_AC97_INDEX);
msleep(1); /*msleep(1);*/
spin_unlock_irqrestore(&chip->ac97_lock, flags);
up(&chip->ac97_mutex);
} }
static unsigned short snd_es1968_ac97_read(ac97_t *ac97, unsigned short reg) static unsigned short snd_es1968_ac97_read(ac97_t *ac97, unsigned short reg)
{ {
u16 data = 0; u16 data = 0;
es1968_t *chip = ac97->private_data; es1968_t *chip = ac97->private_data;
unsigned long flags;
down(&chip->ac97_mutex);
snd_es1968_ac97_wait(chip); snd_es1968_ac97_wait(chip);
spin_lock_irqsave(&chip->ac97_lock, flags);
outb(reg | 0x80, chip->io_port + ESM_AC97_INDEX); outb(reg | 0x80, chip->io_port + ESM_AC97_INDEX);
msleep(1); /*msleep(1);*/
if (! snd_es1968_ac97_wait(chip)) { if (! snd_es1968_ac97_wait(chip)) {
data = inw(chip->io_port + ESM_AC97_DATA); data = inw(chip->io_port + ESM_AC97_DATA);
msleep(1); /*msleep(1);*/
} }
up(&chip->ac97_mutex); spin_unlock_irqrestore(&chip->ac97_lock, flags);
return data; return data;
} }
...@@ -1925,6 +1926,7 @@ static void es1968_update_hw_volume(unsigned long private_data) ...@@ -1925,6 +1926,7 @@ static void es1968_update_hw_volume(unsigned long private_data)
{ {
es1968_t *chip = (es1968_t *) private_data; es1968_t *chip = (es1968_t *) private_data;
int x, val; int x, val;
unsigned long flags;
/* Figure out which volume control button was pushed, /* Figure out which volume control button was pushed,
based on differences from the default register based on differences from the default register
...@@ -1939,11 +1941,15 @@ static void es1968_update_hw_volume(unsigned long private_data) ...@@ -1939,11 +1941,15 @@ static void es1968_update_hw_volume(unsigned long private_data)
if (! chip->master_switch || ! chip->master_volume) if (! chip->master_switch || ! chip->master_volume)
return; return;
/* FIXME: more clean up is needed.. */ /* 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]; val = chip->ac97->regs[AC97_MASTER];
if (x & 1) { if (x & 1) {
/* mute */ /* mute */
snd_ac97_write_cache(chip->ac97, AC97_MASTER, val ^ 0x8000); val ^= 0x8000;
chip->ac97->regs[AC97_MASTER] = val;
outw(val, chip->io_port + ESM_AC97_DATA);
outb(AC97_MASTER, chip->io_port + ESM_AC97_INDEX);
snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
&chip->master_switch->id); &chip->master_switch->id);
} else { } else {
...@@ -1961,10 +1967,13 @@ static void es1968_update_hw_volume(unsigned long private_data) ...@@ -1961,10 +1967,13 @@ static void es1968_update_hw_volume(unsigned long private_data)
if ((val & 0xff00) < 0x1f00) if ((val & 0xff00) < 0x1f00)
val += 0x0100; val += 0x0100;
} }
snd_ac97_write_cache(chip->ac97, AC97_MASTER, val); chip->ac97->regs[AC97_MASTER] = val;
outw(val, chip->io_port + ESM_AC97_DATA);
outb(AC97_MASTER, chip->io_port + ESM_AC97_INDEX);
snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
&chip->master_volume->id); &chip->master_volume->id);
} }
spin_unlock_irqrestore(&chip->ac97_lock, flags);
} }
/* /*
...@@ -2531,7 +2540,7 @@ static int __devinit snd_es1968_create(snd_card_t * card, ...@@ -2531,7 +2540,7 @@ static int __devinit snd_es1968_create(snd_card_t * card,
spin_lock_init(&chip->substream_lock); spin_lock_init(&chip->substream_lock);
INIT_LIST_HEAD(&chip->buf_list); INIT_LIST_HEAD(&chip->buf_list);
INIT_LIST_HEAD(&chip->substream_list); INIT_LIST_HEAD(&chip->substream_list);
init_MUTEX(&chip->ac97_mutex); spin_lock_init(&chip->ac97_lock);
init_MUTEX(&chip->memory_mutex); init_MUTEX(&chip->memory_mutex);
tasklet_init(&chip->hwvol_tq, es1968_update_hw_volume, (unsigned long)chip); tasklet_init(&chip->hwvol_tq, es1968_update_hw_volume, (unsigned long)chip);
chip->card = card; chip->card = card;
......
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