Received: by 2002:a25:ad19:0:0:0:0:0 with SMTP id y25csp10758332ybi; Thu, 11 Jul 2019 10:28:38 -0700 (PDT) X-Google-Smtp-Source: APXvYqzVdjChMqL4NrMfJwLUrNLU79EU6jERJI72QWBb+jeSGlbZ4XW4X+h8OzXuIXQH4jwaPxx8 X-Received: by 2002:a65:4505:: with SMTP id n5mr5046837pgq.301.1562866118159; Thu, 11 Jul 2019 10:28:38 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1562866118; cv=none; d=google.com; s=arc-20160816; b=fHxLyih4YHFDEBLBUpA2RJBNJCwIQcsXUkktctvIqYSUcndf1MHKLB7+FmtvXH2NrX qhIOueWn6e71V0YfoZf/tRx7uqxHXKxMb/9R5Pd2FJ8qfx4dyA/fB8tYM3nVtmcKzOBY tKqKj5mQIGQFWPwHCYoe4uHs5uHPHVejhiheFCFLoDrCk3zf4zpO819/wpML5p6+8qsM iBEYiAh9ynFAcCPVT4tbf/c2d4UUz2QeayqGOVD2Gtn4tWZUBasrv8W8oTa3KONNuprM EGG5VEpwXgfJVRjo2ofrve0opdTmZ4YCaPcttdu6MWhGIb9ON+nTUEJKWPc/Yj01Sf0n 52iQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:user-agent:in-reply-to :content-disposition:mime-version:references:message-id:subject:cc :to:from:date:dkim-signature; bh=fq6WHQqIPWVCMU7ZkFfC4oSgGVvcorBZ3Dq6pBzcxHo=; b=POZy9uULkADoyWxEW0llO/viJ+Ls/hWZEjwCTQE3AjEKQVZNZNCNjrJ60Fl0LPP0Dz RkOA4l2gQU98hvwMW3JCDniyYaYTg5/1VpYuPZ1wRkHbzL4oYYD/re7i59FTmwVkRNCp HOaDn9u9qv5o0R8Cf/r5LE6dSg8+ozXYgw+o9/XRUDKjlmnvIMrfvMjOYGY4X71rIif7 J/VKmpNcC6D1P/RTCWSbcT3ETBHaUKKbgmRTyhsfUl9BRwpwAGDOc/ly3Mv+4naXGcTV 04rId9Zgwv9XABTNIjffxiTTtNJeqz/qFSXpLhOFkGt5xSOKTeTY2PmQdgMlKTQzoWfo 5HSw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b="LA7j/cO4"; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id i9si5145543plb.284.2019.07.11.10.28.22; Thu, 11 Jul 2019 10:28:38 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b="LA7j/cO4"; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728655AbfGKQy2 (ORCPT + 99 others); Thu, 11 Jul 2019 12:54:28 -0400 Received: from mail-pg1-f194.google.com ([209.85.215.194]:33235 "EHLO mail-pg1-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728294AbfGKQy2 (ORCPT ); Thu, 11 Jul 2019 12:54:28 -0400 Received: by mail-pg1-f194.google.com with SMTP id m4so3234203pgk.0 for ; Thu, 11 Jul 2019 09:54:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:in-reply-to:user-agent; bh=fq6WHQqIPWVCMU7ZkFfC4oSgGVvcorBZ3Dq6pBzcxHo=; b=LA7j/cO4M89kcVx3e6n4nfhoFhINbRv6vd7JT7WJFzQOUPxwSckcJ2rYqU0v25WI5S Nyu5P+fdvPArJtJiIRE4OtkE0R1mRE53Oy+cJ7vQhTEvC5EcUfIVHjn5ivS0d3IMVvSn H5paRse+u29OFk6/lI0zgNuYMtXB+YcG+hOn+ogRkN85B2ldAtfhs7Su1fS9QqNyRq2I Cg9cDAGjAy34fvB0WMKnUbGuLtm5YeIehXbJbqyRZYJ7yRXHl6WAjgPk+i22kMxSv12N vaaJdmrwDM30Ly4SACH6+d0qgs1QMUEif0V+ygVHgVxTGla7U5Vtfnfqy3l5MiRbjsOj wyGg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to:user-agent; bh=fq6WHQqIPWVCMU7ZkFfC4oSgGVvcorBZ3Dq6pBzcxHo=; b=HnexGZX382421w2oeQlDcZnFsfaCYtblcUAjXXgfNkoSBSC6y3VHd67dZpcRgcN9s7 W7ZyZu3vvd0nAXl9ODD3TwUYcJEqoYIhbYZFj3qUGz3Pyzvv5ZiPUPCxIZfO1mNvzLwK EKmjeTbGQlMvFSuDUKjbQR7y1IIpJvCTza0PEjNIkfc3fvgEoPUItQfw8skaaoAF1muY oL2Iy38VH9swQ4xdIFiZ+BDDv0PpkCXQF/OQnIll9fbP4TbhFMtpBYgIIU352GO4fT7+ VRidQx2ZUjvt1WNlWpVf7BmRzmk7Gyh1bo8RtvhYNryswxDXqUWhQu7WXY+dSsdoN5CH ixVQ== X-Gm-Message-State: APjAAAWqndwDz11mNU8S0EUfAuFoveOouqMWst+oDYm6iAwYoeaw6/x3 bSG31xHneOjoGrp2NZ649zs= X-Received: by 2002:a17:90a:f488:: with SMTP id bx8mr5899804pjb.91.1562864067277; Thu, 11 Jul 2019 09:54:27 -0700 (PDT) Received: from Asurada-Nvidia.nvidia.com (thunderhill.nvidia.com. [216.228.112.22]) by smtp.gmail.com with ESMTPSA id h26sm6256695pfq.64.2019.07.11.09.54.26 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 11 Jul 2019 09:54:27 -0700 (PDT) Date: Thu, 11 Jul 2019 09:54:58 -0700 From: Nicolin Chen To: shengjiu.wang@nxp.com Cc: timur@kernel.org, Xiubo.Lee@gmail.com, festevam@gmail.com, lgirdwood@gmail.com, perex@perex.cz, tiwai@suse.com, broonie@kernel.org, alsa-devel@alsa-project.org, linuxppc-dev@lists.ozlabs.org, linux-kernel@vger.kernel.org Subject: Re: [PATCH V4 2/2] ASoC: fsl_esai: recover the channel swap after xrun Message-ID: <20190711165458.GA17728@Asurada-Nvidia.nvidia.com> References: <326035cb99975361699d9ed748054b08bc06a341.1562842206.git.shengjiu.wang@nxp.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <326035cb99975361699d9ed748054b08bc06a341.1562842206.git.shengjiu.wang@nxp.com> User-Agent: Mutt/1.9.4 (2018-02-28) Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Thu, Jul 11, 2019 at 06:49:46PM +0800, shengjiu.wang@nxp.com wrote: > From: Shengjiu Wang > > There is chip errata ERR008000, the reference doc is > (https://www.nxp.com/docs/en/errata/IMX6DQCE.pdf), > > The issue is "While using ESAI transmit or receive and > an underrun/overrun happens, channel swap may occur. > The only recovery mechanism is to reset the ESAI." > > This issue exist in imx3/imx5/imx6(partial) series. > > In this commit add a tasklet to handle reset of ESAI > after xrun happens to recover the channel swap. > > Signed-off-by: Shengjiu Wang Acked-by: Nicolin Chen Thanks > --- > sound/soc/fsl/fsl_esai.c | 74 ++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 74 insertions(+) > > diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c > index ab460d6d7432..4ce8ac769244 100644 > --- a/sound/soc/fsl/fsl_esai.c > +++ b/sound/soc/fsl/fsl_esai.c > @@ -32,6 +32,7 @@ > * @extalclk: esai clock source to derive HCK, SCK and FS > * @fsysclk: system clock source to derive HCK, SCK and FS > * @spbaclk: SPBA clock (optional, depending on SoC design) > + * @task: tasklet to handle the reset operation > * @fifo_depth: depth of tx/rx FIFO > * @slot_width: width of each DAI slot > * @slots: number of slots > @@ -42,6 +43,7 @@ > * @sck_div: if using PSR/PM dividers for SCKx clock > * @slave_mode: if fully using DAI slave mode > * @synchronous: if using tx/rx synchronous mode > + * @reset_at_xrun: flags for enable reset operaton > * @name: driver name > */ > struct fsl_esai { > @@ -53,6 +55,7 @@ struct fsl_esai { > struct clk *extalclk; > struct clk *fsysclk; > struct clk *spbaclk; > + struct tasklet_struct task; > u32 fifo_depth; > u32 slot_width; > u32 slots; > @@ -65,6 +68,7 @@ struct fsl_esai { > bool sck_div[2]; > bool slave_mode; > bool synchronous; > + bool reset_at_xrun; > char name[32]; > }; > > @@ -73,8 +77,16 @@ static irqreturn_t esai_isr(int irq, void *devid) > struct fsl_esai *esai_priv = (struct fsl_esai *)devid; > struct platform_device *pdev = esai_priv->pdev; > u32 esr; > + u32 saisr; > > regmap_read(esai_priv->regmap, REG_ESAI_ESR, &esr); > + regmap_read(esai_priv->regmap, REG_ESAI_SAISR, &saisr); > + > + if ((saisr & (ESAI_SAISR_TUE | ESAI_SAISR_ROE)) && > + esai_priv->reset_at_xrun) { > + dev_dbg(&pdev->dev, "reset module for xrun\n"); > + tasklet_schedule(&esai_priv->task); > + } > > if (esr & ESAI_ESR_TINIT_MASK) > dev_dbg(&pdev->dev, "isr: Transmission Initialized\n"); > @@ -635,10 +647,17 @@ static void fsl_esai_trigger_start(struct fsl_esai *esai_priv, bool tx) > ESAI_xSMB_xS_MASK, ESAI_xSMB_xS(mask)); > regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMA(tx), > ESAI_xSMA_xS_MASK, ESAI_xSMA_xS(mask)); > + > + /* Enable Exception interrupt */ > + regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx), > + ESAI_xCR_xEIE_MASK, ESAI_xCR_xEIE); > } > > static void fsl_esai_trigger_stop(struct fsl_esai *esai_priv, bool tx) > { > + regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx), > + ESAI_xCR_xEIE_MASK, 0); > + > regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx), > tx ? ESAI_xCR_TE_MASK : ESAI_xCR_RE_MASK, 0); > regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMA(tx), > @@ -653,6 +672,51 @@ static void fsl_esai_trigger_stop(struct fsl_esai *esai_priv, bool tx) > ESAI_xFCR_xFR, 0); > } > > +static void fsl_esai_hw_reset(unsigned long arg) > +{ > + struct fsl_esai *esai_priv = (struct fsl_esai *)arg; > + bool tx = true, rx = false, enabled[2]; > + u32 tfcr, rfcr; > + > + /* Save the registers */ > + regmap_read(esai_priv->regmap, REG_ESAI_TFCR, &tfcr); > + regmap_read(esai_priv->regmap, REG_ESAI_RFCR, &rfcr); > + enabled[tx] = tfcr & ESAI_xFCR_xFEN; > + enabled[rx] = rfcr & ESAI_xFCR_xFEN; > + > + /* Stop the tx & rx */ > + fsl_esai_trigger_stop(esai_priv, tx); > + fsl_esai_trigger_stop(esai_priv, rx); > + > + /* Reset the esai, and ignore return value */ > + fsl_esai_hw_init(esai_priv); > + > + /* Enforce ESAI personal resets for both TX and RX */ > + regmap_update_bits(esai_priv->regmap, REG_ESAI_TCR, > + ESAI_xCR_xPR_MASK, ESAI_xCR_xPR); > + regmap_update_bits(esai_priv->regmap, REG_ESAI_RCR, > + ESAI_xCR_xPR_MASK, ESAI_xCR_xPR); > + > + /* Restore registers by regcache_sync, and ignore return value */ > + fsl_esai_register_restore(esai_priv); > + > + /* Remove ESAI personal resets by configuring PCRC and PRRC also */ > + regmap_update_bits(esai_priv->regmap, REG_ESAI_TCR, > + ESAI_xCR_xPR_MASK, 0); > + regmap_update_bits(esai_priv->regmap, REG_ESAI_RCR, > + ESAI_xCR_xPR_MASK, 0); > + regmap_update_bits(esai_priv->regmap, REG_ESAI_PRRC, > + ESAI_PRRC_PDC_MASK, ESAI_PRRC_PDC(ESAI_GPIO)); > + regmap_update_bits(esai_priv->regmap, REG_ESAI_PCRC, > + ESAI_PCRC_PC_MASK, ESAI_PCRC_PC(ESAI_GPIO)); > + > + /* Restart tx / rx, if they already enabled */ > + if (enabled[tx]) > + fsl_esai_trigger_start(esai_priv, tx); > + if (enabled[rx]) > + fsl_esai_trigger_start(esai_priv, rx); > +} > + > static int fsl_esai_trigger(struct snd_pcm_substream *substream, int cmd, > struct snd_soc_dai *dai) > { > @@ -857,6 +921,10 @@ static int fsl_esai_probe(struct platform_device *pdev) > esai_priv->pdev = pdev; > snprintf(esai_priv->name, sizeof(esai_priv->name), "%pOFn", np); > > + if (of_device_is_compatible(np, "fsl,vf610-esai") || > + of_device_is_compatible(np, "fsl,imx35-esai")) > + esai_priv->reset_at_xrun = true; > + > /* Get the addresses and IRQ */ > res = platform_get_resource(pdev, IORESOURCE_MEM, 0); > regs = devm_ioremap_resource(&pdev->dev, res); > @@ -956,6 +1024,9 @@ static int fsl_esai_probe(struct platform_device *pdev) > return ret; > } > > + tasklet_init(&esai_priv->task, fsl_esai_hw_reset, > + (unsigned long)esai_priv); > + > pm_runtime_enable(&pdev->dev); > > regcache_cache_only(esai_priv->regmap, true); > @@ -969,7 +1040,10 @@ static int fsl_esai_probe(struct platform_device *pdev) > > static int fsl_esai_remove(struct platform_device *pdev) > { > + struct fsl_esai *esai_priv = platform_get_drvdata(pdev); > + > pm_runtime_disable(&pdev->dev); > + tasklet_kill(&esai_priv->task); > > return 0; > } > -- > 2.21.0 >