aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorMaxim Levitsky <maximlevitsky@gmail.com>2010-02-04 15:21:47 -0500
committerTakashi Iwai <tiwai@suse.de>2010-02-05 03:07:21 -0500
commit1eb6dc7dabcb4aa762d96f4f6978f3ef86321d68 (patch)
treec6eee9f271d5b3ea7ca605f38ec7f8656e24e8ee /sound
parent8ce28d6abff34886d3797b25324c940471b99164 (diff)
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: Maxim Levitsky <maximlevitsky@gmail.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound')
-rw-r--r--sound/pci/hda/hda_intel.c19
1 files changed, 17 insertions, 2 deletions
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 565de38a3fc7..d853e2c33bb7 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -426,6 +426,7 @@ struct azx {
426 426
427 /* flags */ 427 /* flags */
428 int position_fix; 428 int position_fix;
429 int poll_count;
429 unsigned int running :1; 430 unsigned int running :1;
430 unsigned int initialized :1; 431 unsigned int initialized :1;
431 unsigned int single_cmd :1; 432 unsigned int single_cmd :1;
@@ -506,7 +507,7 @@ static char *driver_short_names[] __devinitdata = {
506#define get_azx_dev(substream) (substream->runtime->private_data) 507#define get_azx_dev(substream) (substream->runtime->private_data)
507 508
508static int azx_acquire_irq(struct azx *chip, int do_disconnect); 509static int azx_acquire_irq(struct azx *chip, int do_disconnect);
509 510static int azx_send_cmd(struct hda_bus *bus, unsigned int val);
510/* 511/*
511 * Interface for HD codec 512 * Interface for HD codec
512 */ 513 */
@@ -664,11 +665,12 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus,
664{ 665{
665 struct azx *chip = bus->private_data; 666 struct azx *chip = bus->private_data;
666 unsigned long timeout; 667 unsigned long timeout;
668 int do_poll = 0;
667 669
668 again: 670 again:
669 timeout = jiffies + msecs_to_jiffies(1000); 671 timeout = jiffies + msecs_to_jiffies(1000);
670 for (;;) { 672 for (;;) {
671 if (chip->polling_mode) { 673 if (chip->polling_mode || do_poll) {
672 spin_lock_irq(&chip->reg_lock); 674 spin_lock_irq(&chip->reg_lock);
673 azx_update_rirb(chip); 675 azx_update_rirb(chip);
674 spin_unlock_irq(&chip->reg_lock); 676 spin_unlock_irq(&chip->reg_lock);
@@ -676,6 +678,9 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus,
676 if (!chip->rirb.cmds[addr]) { 678 if (!chip->rirb.cmds[addr]) {
677 smp_rmb(); 679 smp_rmb();
678 bus->rirb_error = 0; 680 bus->rirb_error = 0;
681
682 if (!do_poll)
683 chip->poll_count = 0;
679 return chip->rirb.res[addr]; /* the last value */ 684 return chip->rirb.res[addr]; /* the last value */
680 } 685 }
681 if (time_after(jiffies, timeout)) 686 if (time_after(jiffies, timeout))
@@ -688,6 +693,16 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus,
688 } 693 }
689 } 694 }
690 695
696 if (!chip->polling_mode && chip->poll_count < 2) {
697 snd_printdd(SFX "azx_get_response timeout, "
698 "polling the codec once: last cmd=0x%08x\n",
699 chip->last_cmd[addr]);
700 do_poll = 1;
701 chip->poll_count++;
702 goto again;
703 }
704
705
691 if (!chip->polling_mode) { 706 if (!chip->polling_mode) {
692 snd_printk(KERN_WARNING SFX "azx_get_response timeout, " 707 snd_printk(KERN_WARNING SFX "azx_get_response timeout, "
693 "switching to polling mode: last cmd=0x%08x\n", 708 "switching to polling mode: last cmd=0x%08x\n",