[alsa-devel] [RFC PATCH] ALSA: hda - Fix CORB reset to follow specification
Takashi Iwai
tiwai at suse.de
Fri Feb 28 08:19:06 CET 2014
At Fri, 28 Feb 2014 07:56:58 +0100,
David Henningsson wrote:
>
> According to the HDA spec, we must write 1 to bit 15 on a CORBRP
> reset, read back 1, then write 0, then read back 0. This must be
> done while the DMA is not running.
>
> We accidentaly ended up writing back the 0 by using a writel
> instead of a writew to CORBWP.
>
> This caused occasional controller failure on Bay Trail hardware.
>
> Signed-off-by: David Henningsson <david.henningsson at canonical.com>
> ---
> sound/pci/hda/hda_intel.c | 24 +++++++++++++++++++++++-
> 1 file changed, 23 insertions(+), 1 deletion(-)
>
> Hi Takashi,
>
> A while ago I researched a spurious response on some Bay Trail hardware,
> so I proofread some of our CORB/RIRB code and found the below.
>
> When applied, the spurious responses disappeared but other problems might
> have appeared instead. I don't have the hardware here so I'm not 100% sure.
> So I'm hesitant to actually apply it, especially as the existing non-compliant
> way seems to work for all other chips. Still wanted to show the issue to you.
>
> Also the timeout (1 ms) is completely arbitrarily as there are no time limits
> written in the HDA specification.
OK, the changes look good to me. I'm going to apply it once after
checking it with some other chips.
thanks,
Takashi
>
> diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
> index d8d9bf3..59156f1 100644
> --- a/sound/pci/hda/hda_intel.c
> +++ b/sound/pci/hda/hda_intel.c
> @@ -775,6 +775,8 @@ static int azx_alloc_cmd_io(struct azx *chip)
>
> static void azx_init_cmd_io(struct azx *chip)
> {
> + int timeout;
> +
> spin_lock_irq(&chip->reg_lock);
> /* CORB set up */
> chip->corb.addr = chip->rb.addr;
> @@ -786,8 +788,28 @@ static void azx_init_cmd_io(struct azx *chip)
> azx_writeb(chip, CORBSIZE, 0x02);
> /* set the corb write pointer to 0 */
> azx_writew(chip, CORBWP, 0);
> +
> /* reset the corb hw read pointer */
> azx_writew(chip, CORBRP, ICH6_CORBRP_RST);
> + for (timeout = 1000; timeout > 0; timeout--) {
> + if ((azx_readw(chip, CORBRP) & ICH6_CORBRP_RST) == ICH6_CORBRP_RST)
> + break;
> + udelay(1);
> + }
> + if (timeout <= 0)
> + snd_printk(KERN_ERR SFX "%s: CORB reset timeout - CORBRP = %d\n",
> + pci_name(chip->pci), (int) azx_readw(chip, CORBRP));
> +
> + azx_writew(chip, CORBRP, 0);
> + for (timeout = 1000; timeout > 0; timeout--) {
> + if (azx_readw(chip, CORBRP) == 0)
> + break;
> + udelay(1);
> + }
> + if (timeout <= 0)
> + snd_printk(KERN_ERR SFX "%s: CORB reset timeout, CORBRP = %d\n",
> + pci_name(chip->pci), azx_readw(chip, CORBRP));
> +
> /* enable corb dma */
> azx_writeb(chip, CORBCTL, ICH6_CORBCTL_RUN);
>
> @@ -862,7 +884,7 @@ static int azx_corb_send_cmd(struct hda_bus *bus, u32 val)
>
> chip->rirb.cmds[addr]++;
> chip->corb.buf[wp] = cpu_to_le32(val);
> - azx_writel(chip, CORBWP, wp);
> + azx_writew(chip, CORBWP, wp);
>
> spin_unlock_irq(&chip->reg_lock);
>
> --
> 1.7.9.5
>
More information about the Alsa-devel
mailing list