aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWu Fengguang <fengguang.wu@intel.com>2009-08-01 06:45:16 -0400
committerTakashi Iwai <tiwai@suse.de>2009-08-03 02:26:13 -0400
commitdeadff1665491afce124a8ff83f00f784161f660 (patch)
treeb0de54cef8d75623f5839651331b31018e1ea217
parentce577e8cf5ddb4216553c9d563a9835d6de70ffa (diff)
ALSA: hda: track CIRB/CORB command/response states for each codec
Recently we hit a bug in our dev board, whose HDMI codec#3 may emit redundant/spurious responses, which were then taken as responses to command for another onboard Realtek codec#2, and mess up both codecs. Extend the azx_rb.cmds and azx_rb.res to array and track each codec's commands/responses separately. This helps keep good codec safe from broken ones. Signed-off-by: Wu Fengguang <fengguang.wu@intel.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r--sound/pci/hda/hda_codec.c2
-rw-r--r--sound/pci/hda/hda_codec.h2
-rw-r--r--sound/pci/hda/hda_intel.c76
3 files changed, 56 insertions, 24 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 88480c0c58a0..c7df01b72cac 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -174,7 +174,7 @@ static int codec_exec_verb(struct hda_codec *codec, unsigned int cmd,
174 mutex_lock(&bus->cmd_mutex); 174 mutex_lock(&bus->cmd_mutex);
175 err = bus->ops.command(bus, cmd); 175 err = bus->ops.command(bus, cmd);
176 if (!err && res) 176 if (!err && res)
177 *res = bus->ops.get_response(bus); 177 *res = bus->ops.get_response(bus, codec->addr);
178 mutex_unlock(&bus->cmd_mutex); 178 mutex_unlock(&bus->cmd_mutex);
179 snd_hda_power_down(codec); 179 snd_hda_power_down(codec);
180 if (res && *res == -1 && bus->rirb_error) { 180 if (res && *res == -1 && bus->rirb_error) {
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index cad79efaabc9..1b75f28ed092 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -568,7 +568,7 @@ struct hda_bus_ops {
568 /* send a single command */ 568 /* send a single command */
569 int (*command)(struct hda_bus *bus, unsigned int cmd); 569 int (*command)(struct hda_bus *bus, unsigned int cmd);
570 /* get a response from the last command */ 570 /* get a response from the last command */
571 unsigned int (*get_response)(struct hda_bus *bus); 571 unsigned int (*get_response)(struct hda_bus *bus, unsigned int addr);
572 /* free the private data */ 572 /* free the private data */
573 void (*private_free)(struct hda_bus *); 573 void (*private_free)(struct hda_bus *);
574 /* attach a PCM stream */ 574 /* attach a PCM stream */
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 77c1b840ca8b..19e67a1b6026 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -253,7 +253,7 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
253 253
254/* STATESTS int mask: S3,SD2,SD1,SD0 */ 254/* STATESTS int mask: S3,SD2,SD1,SD0 */
255#define AZX_MAX_CODECS 4 255#define AZX_MAX_CODECS 4
256#define STATESTS_INT_MASK 0x0f 256#define STATESTS_INT_MASK ((1 << AZX_MAX_CODECS) - 1)
257 257
258/* SD_CTL bits */ 258/* SD_CTL bits */
259#define SD_CTL_STREAM_RESET 0x01 /* stream reset bit */ 259#define SD_CTL_STREAM_RESET 0x01 /* stream reset bit */
@@ -361,8 +361,8 @@ struct azx_rb {
361 dma_addr_t addr; /* physical address of CORB/RIRB buffer */ 361 dma_addr_t addr; /* physical address of CORB/RIRB buffer */
362 /* for RIRB */ 362 /* for RIRB */
363 unsigned short rp, wp; /* read/write pointers */ 363 unsigned short rp, wp; /* read/write pointers */
364 int cmds; /* number of pending requests */ 364 int cmds[AZX_MAX_CODECS]; /* number of pending requests */
365 u32 res; /* last read value */ 365 u32 res[AZX_MAX_CODECS]; /* last read value */
366}; 366};
367 367
368struct azx { 368struct azx {
@@ -531,7 +531,8 @@ static void azx_init_cmd_io(struct azx *chip)
531 /* RIRB set up */ 531 /* RIRB set up */
532 chip->rirb.addr = chip->rb.addr + 2048; 532 chip->rirb.addr = chip->rb.addr + 2048;
533 chip->rirb.buf = (u32 *)(chip->rb.area + 2048); 533 chip->rirb.buf = (u32 *)(chip->rb.area + 2048);
534 chip->rirb.wp = chip->rirb.rp = chip->rirb.cmds = 0; 534 chip->rirb.wp = chip->rirb.rp = 0;
535 memset(chip->rirb.cmds, 0, sizeof(chip->rirb.cmds));
535 azx_writel(chip, RIRBLBASE, (u32)chip->rirb.addr); 536 azx_writel(chip, RIRBLBASE, (u32)chip->rirb.addr);
536 azx_writel(chip, RIRBUBASE, upper_32_bits(chip->rirb.addr)); 537 azx_writel(chip, RIRBUBASE, upper_32_bits(chip->rirb.addr));
537 538
@@ -552,10 +553,35 @@ static void azx_free_cmd_io(struct azx *chip)
552 azx_writeb(chip, CORBCTL, 0); 553 azx_writeb(chip, CORBCTL, 0);
553} 554}
554 555
556static unsigned int azx_command_addr(u32 cmd)
557{
558 unsigned int addr = cmd >> 28;
559
560 if (addr >= AZX_MAX_CODECS) {
561 snd_BUG();
562 addr = 0;
563 }
564
565 return addr;
566}
567
568static unsigned int azx_response_addr(u32 res)
569{
570 unsigned int addr = res & 0xf;
571
572 if (addr >= AZX_MAX_CODECS) {
573 snd_BUG();
574 addr = 0;
575 }
576
577 return addr;
578}
579
555/* send a command */ 580/* send a command */
556static int azx_corb_send_cmd(struct hda_bus *bus, u32 val) 581static int azx_corb_send_cmd(struct hda_bus *bus, u32 val)
557{ 582{
558 struct azx *chip = bus->private_data; 583 struct azx *chip = bus->private_data;
584 unsigned int addr = azx_command_addr(val);
559 unsigned int wp; 585 unsigned int wp;
560 586
561 /* add command to corb */ 587 /* add command to corb */
@@ -564,7 +590,7 @@ static int azx_corb_send_cmd(struct hda_bus *bus, u32 val)
564 wp %= ICH6_MAX_CORB_ENTRIES; 590 wp %= ICH6_MAX_CORB_ENTRIES;
565 591
566 spin_lock_irq(&chip->reg_lock); 592 spin_lock_irq(&chip->reg_lock);
567 chip->rirb.cmds++; 593 chip->rirb.cmds[addr]++;
568 chip->corb.buf[wp] = cpu_to_le32(val); 594 chip->corb.buf[wp] = cpu_to_le32(val);
569 azx_writel(chip, CORBWP, wp); 595 azx_writel(chip, CORBWP, wp);
570 spin_unlock_irq(&chip->reg_lock); 596 spin_unlock_irq(&chip->reg_lock);
@@ -578,13 +604,14 @@ static int azx_corb_send_cmd(struct hda_bus *bus, u32 val)
578static void azx_update_rirb(struct azx *chip) 604static void azx_update_rirb(struct azx *chip)
579{ 605{
580 unsigned int rp, wp; 606 unsigned int rp, wp;
607 unsigned int addr;
581 u32 res, res_ex; 608 u32 res, res_ex;
582 609
583 wp = azx_readb(chip, RIRBWP); 610 wp = azx_readb(chip, RIRBWP);
584 if (wp == chip->rirb.wp) 611 if (wp == chip->rirb.wp)
585 return; 612 return;
586 chip->rirb.wp = wp; 613 chip->rirb.wp = wp;
587 614
588 while (chip->rirb.rp != wp) { 615 while (chip->rirb.rp != wp) {
589 chip->rirb.rp++; 616 chip->rirb.rp++;
590 chip->rirb.rp %= ICH6_MAX_RIRB_ENTRIES; 617 chip->rirb.rp %= ICH6_MAX_RIRB_ENTRIES;
@@ -592,18 +619,20 @@ static void azx_update_rirb(struct azx *chip)
592 rp = chip->rirb.rp << 1; /* an RIRB entry is 8-bytes */ 619 rp = chip->rirb.rp << 1; /* an RIRB entry is 8-bytes */
593 res_ex = le32_to_cpu(chip->rirb.buf[rp + 1]); 620 res_ex = le32_to_cpu(chip->rirb.buf[rp + 1]);
594 res = le32_to_cpu(chip->rirb.buf[rp]); 621 res = le32_to_cpu(chip->rirb.buf[rp]);
622 addr = azx_response_addr(res_ex);
595 if (res_ex & ICH6_RIRB_EX_UNSOL_EV) 623 if (res_ex & ICH6_RIRB_EX_UNSOL_EV)
596 snd_hda_queue_unsol_event(chip->bus, res, res_ex); 624 snd_hda_queue_unsol_event(chip->bus, res, res_ex);
597 else if (chip->rirb.cmds) { 625 else if (chip->rirb.cmds[addr]) {
598 chip->rirb.res = res; 626 chip->rirb.res[addr] = res;
599 smp_wmb(); 627 smp_wmb();
600 chip->rirb.cmds--; 628 chip->rirb.cmds[addr]--;
601 } 629 }
602 } 630 }
603} 631}
604 632
605/* receive a response */ 633/* receive a response */
606static unsigned int azx_rirb_get_response(struct hda_bus *bus) 634static unsigned int azx_rirb_get_response(struct hda_bus *bus,
635 unsigned int addr)
607{ 636{
608 struct azx *chip = bus->private_data; 637 struct azx *chip = bus->private_data;
609 unsigned long timeout; 638 unsigned long timeout;
@@ -616,10 +645,10 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus)
616 azx_update_rirb(chip); 645 azx_update_rirb(chip);
617 spin_unlock_irq(&chip->reg_lock); 646 spin_unlock_irq(&chip->reg_lock);
618 } 647 }
619 if (!chip->rirb.cmds) { 648 if (!chip->rirb.cmds[addr]) {
620 smp_rmb(); 649 smp_rmb();
621 bus->rirb_error = 0; 650 bus->rirb_error = 0;
622 return chip->rirb.res; /* the last value */ 651 return chip->rirb.res[addr]; /* the last value */
623 } 652 }
624 if (time_after(jiffies, timeout)) 653 if (time_after(jiffies, timeout))
625 break; 654 break;
@@ -692,7 +721,7 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus)
692 */ 721 */
693 722
694/* receive a response */ 723/* receive a response */
695static int azx_single_wait_for_response(struct azx *chip) 724static int azx_single_wait_for_response(struct azx *chip, unsigned int addr)
696{ 725{
697 int timeout = 50; 726 int timeout = 50;
698 727
@@ -700,7 +729,7 @@ static int azx_single_wait_for_response(struct azx *chip)
700 /* check IRV busy bit */ 729 /* check IRV busy bit */
701 if (azx_readw(chip, IRS) & ICH6_IRS_VALID) { 730 if (azx_readw(chip, IRS) & ICH6_IRS_VALID) {
702 /* reuse rirb.res as the response return value */ 731 /* reuse rirb.res as the response return value */
703 chip->rirb.res = azx_readl(chip, IR); 732 chip->rirb.res[addr] = azx_readl(chip, IR);
704 return 0; 733 return 0;
705 } 734 }
706 udelay(1); 735 udelay(1);
@@ -708,7 +737,7 @@ static int azx_single_wait_for_response(struct azx *chip)
708 if (printk_ratelimit()) 737 if (printk_ratelimit())
709 snd_printd(SFX "get_response timeout: IRS=0x%x\n", 738 snd_printd(SFX "get_response timeout: IRS=0x%x\n",
710 azx_readw(chip, IRS)); 739 azx_readw(chip, IRS));
711 chip->rirb.res = -1; 740 chip->rirb.res[addr] = -1;
712 return -EIO; 741 return -EIO;
713} 742}
714 743
@@ -716,6 +745,7 @@ static int azx_single_wait_for_response(struct azx *chip)
716static int azx_single_send_cmd(struct hda_bus *bus, u32 val) 745static int azx_single_send_cmd(struct hda_bus *bus, u32 val)
717{ 746{
718 struct azx *chip = bus->private_data; 747 struct azx *chip = bus->private_data;
748 unsigned int addr = azx_command_addr(val);
719 int timeout = 50; 749 int timeout = 50;
720 750
721 bus->rirb_error = 0; 751 bus->rirb_error = 0;
@@ -728,7 +758,7 @@ static int azx_single_send_cmd(struct hda_bus *bus, u32 val)
728 azx_writel(chip, IC, val); 758 azx_writel(chip, IC, val);
729 azx_writew(chip, IRS, azx_readw(chip, IRS) | 759 azx_writew(chip, IRS, azx_readw(chip, IRS) |
730 ICH6_IRS_BUSY); 760 ICH6_IRS_BUSY);
731 return azx_single_wait_for_response(chip); 761 return azx_single_wait_for_response(chip, addr);
732 } 762 }
733 udelay(1); 763 udelay(1);
734 } 764 }
@@ -739,10 +769,11 @@ static int azx_single_send_cmd(struct hda_bus *bus, u32 val)
739} 769}
740 770
741/* receive a response */ 771/* receive a response */
742static unsigned int azx_single_get_response(struct hda_bus *bus) 772static unsigned int azx_single_get_response(struct hda_bus *bus,
773 unsigned int addr)
743{ 774{
744 struct azx *chip = bus->private_data; 775 struct azx *chip = bus->private_data;
745 return chip->rirb.res; 776 return chip->rirb.res[addr];
746} 777}
747 778
748/* 779/*
@@ -765,13 +796,14 @@ static int azx_send_cmd(struct hda_bus *bus, unsigned int val)
765} 796}
766 797
767/* get a response */ 798/* get a response */
768static unsigned int azx_get_response(struct hda_bus *bus) 799static unsigned int azx_get_response(struct hda_bus *bus,
800 unsigned int addr)
769{ 801{
770 struct azx *chip = bus->private_data; 802 struct azx *chip = bus->private_data;
771 if (chip->single_cmd) 803 if (chip->single_cmd)
772 return azx_single_get_response(bus); 804 return azx_single_get_response(bus, addr);
773 else 805 else
774 return azx_rirb_get_response(bus); 806 return azx_rirb_get_response(bus, addr);
775} 807}
776 808
777#ifdef CONFIG_SND_HDA_POWER_SAVE 809#ifdef CONFIG_SND_HDA_POWER_SAVE
@@ -1245,7 +1277,7 @@ static int probe_codec(struct azx *chip, int addr)
1245 1277
1246 chip->probing = 1; 1278 chip->probing = 1;
1247 azx_send_cmd(chip->bus, cmd); 1279 azx_send_cmd(chip->bus, cmd);
1248 res = azx_get_response(chip->bus); 1280 res = azx_get_response(chip->bus, addr);
1249 chip->probing = 0; 1281 chip->probing = 0;
1250 if (res == -1) 1282 if (res == -1)
1251 return -EIO; 1283 return -EIO;