提交 1eb6dc7d 编写于 作者: M Maxim Levitsky 提交者: 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: NMaxim Levitsky <maximlevitsky@gmail.com>
Signed-off-by: NTakashi Iwai <tiwai@suse.de>
上级 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% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册