Commit 1eb6dc7d authored by Maxim Levitsky's avatar Maxim Levitsky Committed by Takashi Iwai

ALSA: hda - Delay switching to polling mode if an interrupt was missing

My sound codec seems sometimes (very rarely) to omit interrupts (ALC268)
However, interrupt mode still works.
Thus if we get timeout, poll the codec once.

If we get 3 such polls in a row, then switch to polling mode.

This patch is maybe an bandaid, but this might be a workaround for hardware bug.
Signed-off-by: default avatarMaxim Levitsky <maximlevitsky@gmail.com>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 8ce28d6a
...@@ -426,6 +426,7 @@ struct azx { ...@@ -426,6 +426,7 @@ struct azx {
/* flags */ /* flags */
int position_fix; int position_fix;
int poll_count;
unsigned int running :1; unsigned int running :1;
unsigned int initialized :1; unsigned int initialized :1;
unsigned int single_cmd :1; unsigned int single_cmd :1;
...@@ -506,7 +507,7 @@ static char *driver_short_names[] __devinitdata = { ...@@ -506,7 +507,7 @@ static char *driver_short_names[] __devinitdata = {
#define get_azx_dev(substream) (substream->runtime->private_data) #define get_azx_dev(substream) (substream->runtime->private_data)
static int azx_acquire_irq(struct azx *chip, int do_disconnect); static int azx_acquire_irq(struct azx *chip, int do_disconnect);
static int azx_send_cmd(struct hda_bus *bus, unsigned int val);
/* /*
* Interface for HD codec * Interface for HD codec
*/ */
...@@ -664,11 +665,12 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus, ...@@ -664,11 +665,12 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus,
{ {
struct azx *chip = bus->private_data; struct azx *chip = bus->private_data;
unsigned long timeout; unsigned long timeout;
int do_poll = 0;
again: again:
timeout = jiffies + msecs_to_jiffies(1000); timeout = jiffies + msecs_to_jiffies(1000);
for (;;) { for (;;) {
if (chip->polling_mode) { if (chip->polling_mode || do_poll) {
spin_lock_irq(&chip->reg_lock); spin_lock_irq(&chip->reg_lock);
azx_update_rirb(chip); azx_update_rirb(chip);
spin_unlock_irq(&chip->reg_lock); spin_unlock_irq(&chip->reg_lock);
...@@ -676,6 +678,9 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus, ...@@ -676,6 +678,9 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus,
if (!chip->rirb.cmds[addr]) { if (!chip->rirb.cmds[addr]) {
smp_rmb(); smp_rmb();
bus->rirb_error = 0; bus->rirb_error = 0;
if (!do_poll)
chip->poll_count = 0;
return chip->rirb.res[addr]; /* the last value */ return chip->rirb.res[addr]; /* the last value */
} }
if (time_after(jiffies, timeout)) if (time_after(jiffies, timeout))
...@@ -688,6 +693,16 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus, ...@@ -688,6 +693,16 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus,
} }
} }
if (!chip->polling_mode && chip->poll_count < 2) {
snd_printdd(SFX "azx_get_response timeout, "
"polling the codec once: last cmd=0x%08x\n",
chip->last_cmd[addr]);
do_poll = 1;
chip->poll_count++;
goto again;
}
if (!chip->polling_mode) { if (!chip->polling_mode) {
snd_printk(KERN_WARNING SFX "azx_get_response timeout, " snd_printk(KERN_WARNING SFX "azx_get_response timeout, "
"switching to polling mode: last cmd=0x%08x\n", "switching to polling mode: last cmd=0x%08x\n",
......
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