From patchwork Fri Feb 28 06:56:58 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Henningsson X-Patchwork-Id: 3739111 Return-Path: X-Original-To: patchwork-alsa-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 57033BF13A for ; Fri, 28 Feb 2014 07:15:34 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 71CC72021C for ; Fri, 28 Feb 2014 07:15:33 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) by mail.kernel.org (Postfix) with ESMTP id C788920263 for ; Fri, 28 Feb 2014 07:15:31 +0000 (UTC) Received: by alsa0.perex.cz (Postfix, from userid 1000) id B1078265930; Fri, 28 Feb 2014 08:15:30 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 Received: from alsa0.perex.cz (localhost [IPv6:::1]) by alsa0.perex.cz (Postfix) with ESMTP id 302F6265931; Fri, 28 Feb 2014 08:08:47 +0100 (CET) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa0.perex.cz (Postfix, from userid 1000) id 4A4A5265931; Fri, 28 Feb 2014 08:08:46 +0100 (CET) Received: from youngberry.canonical.com (youngberry.canonical.com [91.189.89.112]) by alsa0.perex.cz (Postfix) with ESMTP id 985572659DF for ; Fri, 28 Feb 2014 07:57:01 +0100 (CET) Received: from hd9483857.selulk5.dyn.perspektivbredband.net ([217.72.56.87] helo=localhost.localdomain) by youngberry.canonical.com with esmtpsa (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1WJHNT-0007Es-EB; Fri, 28 Feb 2014 06:56:59 +0000 From: David Henningsson To: tiwai@suse.de, alsa-devel@alsa-project.org Date: Fri, 28 Feb 2014 07:56:58 +0100 Message-Id: <1393570618-13442-1-git-send-email-david.henningsson@canonical.com> X-Mailer: git-send-email 1.7.9.5 Cc: mengdong.lin@intel.com, David Henningsson Subject: [alsa-devel] [RFC PATCH] ALSA: hda - Fix CORB reset to follow specification X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: alsa-devel-bounces@alsa-project.org Sender: alsa-devel-bounces@alsa-project.org X-Virus-Scanned: ClamAV using ClamSMTP 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 --- 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. 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);