From 21246987b3cfcd2f2b894bc540c2bf1390eab874 Mon Sep 17 00:00:00 2001 From: =?utf8?q?=E9=82=B1=E5=BB=BA=E6=96=8C?= <qjb@rock-chips.com> Date: Thu, 2 May 2013 11:19:56 +0800 Subject: [PATCH] i2s : fix restart i2s dma cannot read/write data. --- sound/soc/rk29/rk29_i2s.h | 5 ++ sound/soc/rk29/rk30_i2s.c | 153 +++++++++++++------------------------- 2 files changed, 55 insertions(+), 103 deletions(-) diff --git a/sound/soc/rk29/rk29_i2s.h b/sound/soc/rk29/rk29_i2s.h index 116001a99860..91d09ab2c75a 100755 --- a/sound/soc/rk29/rk29_i2s.h +++ b/sound/soc/rk29/rk29_i2s.h @@ -199,6 +199,11 @@ #define I2S_TX_TRAN_STOP (0<<0) #define I2S_TX_TRAN_START (1<<0) +//I2S_CLR +#define I2S_RX_CLEAR (1<<1) +#define I2S_TX_CLEAR 1 + + #ifdef CONFIG_ARCH_RK29 #define I2S_TXR_BUFF 0x20 #define I2S_RXR_BUFF 0x24 diff --git a/sound/soc/rk29/rk30_i2s.c b/sound/soc/rk29/rk30_i2s.c index 62bb21bd6f98..0ac35544e415 100755 --- a/sound/soc/rk29/rk30_i2s.c +++ b/sound/soc/rk29/rk30_i2s.c @@ -87,116 +87,75 @@ static struct rk29_i2s_info rk29_i2s[MAX_I2S]; struct snd_soc_dai_driver rk29_i2s_dai[MAX_I2S]; EXPORT_SYMBOL_GPL(rk29_i2s_dai); -static u32 i2s0_clk_enter(void) -{ - return 0; -} - -static void i2s0_clk_exit(u32 clk) -{ -} - /* *Turn on or off the transmission path. */ - static int flag_i2s_tx = 0; static int flag_i2s_rx = 0; -static void rockchip_snd_txctrl(struct rk29_i2s_info *i2s, int on, bool stopI2S) +static void rockchip_snd_txctrl(struct rk29_i2s_info *i2s, int on) { - u32 opr,xfer; - u32 clk; - + u32 opr,xfer,clr; opr = readl(&(pheadi2s->I2S_DMACR)); xfer = readl(&(pheadi2s->I2S_XFER)); - + clr = readl(&(pheadi2s->I2S_CLR)); if (on) { I2S_DBG("rockchip_snd_txctrl: on\n"); - - //start tx - //if ((flag_i2s_tx == 0) && (flag_i2s_rx == 0)) - if ((xfer&I2S_TX_TRAN_START)==0 || (xfer&I2S_RX_TRAN_START)==0) + if ((opr & I2S_TRAN_DMA_ENABLE) == 0) { - clk = i2s0_clk_enter(); - - //if start tx & rx clk, need reset i2s + opr |= I2S_TRAN_DMA_ENABLE; + writel(opr, &(pheadi2s->I2S_DMACR)); + } + if ((xfer&I2S_TX_TRAN_START)==0 || (xfer&I2S_RX_TRAN_START)==0) + { xfer |= I2S_TX_TRAN_START; xfer |= I2S_RX_TRAN_START; writel(xfer, &(pheadi2s->I2S_XFER)); - - i2s0_clk_exit(clk); - } - - if ((opr & I2S_TRAN_DMA_ENABLE) == 0) - { - opr |= I2S_TRAN_DMA_ENABLE; - writel(opr, &(pheadi2s->I2S_DMACR)); } - flag_i2s_tx = 1; } else { //stop tx flag_i2s_tx = 0; + I2S_DBG("rockchip_snd_txctrl: off\n"); + opr &= ~I2S_TRAN_DMA_ENABLE; + writel(opr, &(pheadi2s->I2S_DMACR)); if ((flag_i2s_rx == 0) && (flag_i2s_tx == 0)) { - opr &= ~I2S_TRAN_DMA_ENABLE; - writel(opr, &(pheadi2s->I2S_DMACR)); - if(stopI2S) - { - clk = i2s0_clk_enter(); - - xfer &= ~I2S_RX_TRAN_START; - xfer &= ~I2S_TX_TRAN_START; - writel(xfer, &(pheadi2s->I2S_XFER)); - - i2s0_clk_exit(clk); - } - - //after stop rx & tx clk, reset i2s - //writel(0x001,&(pheadi2s->I2S_TXRST)); - //writel(0x001,&(pheadi2s->I2S_RXRST)); - } - - I2S_DBG("rockchip_snd_txctrl: off\n"); - } + xfer &= ~I2S_TX_TRAN_START; + xfer &= ~I2S_RX_TRAN_START; + writel(xfer, &(pheadi2s->I2S_XFER)); + I2S_DBG("rockchip_snd_txctrl: off clr = %d\n",clr); + clr |= I2S_TX_CLEAR; + I2S_DBG("rockchip_snd_txctrl: off clr = %d\n",clr); + writel(clr, &(pheadi2s->I2S_CLR)); + udelay(1); + } + } } - -static void rockchip_snd_rxctrl(struct rk29_i2s_info *i2s, int on, bool stopI2S) +static void rockchip_snd_rxctrl(struct rk29_i2s_info *i2s, int on) { - u32 opr,xfer; - u32 clk; - + u32 opr,xfer,clr; opr = readl(&(pheadi2s->I2S_DMACR)); xfer = readl(&(pheadi2s->I2S_XFER)); - + clr = readl(&(pheadi2s->I2S_CLR)); if (on) { I2S_DBG("rockchip_snd_rxctrl: on\n"); - - //start rx - //if ((flag_i2s_tx == 0) && (flag_i2s_rx == 0)) - if ((xfer&I2S_TX_TRAN_START)==0 || (xfer&I2S_RX_TRAN_START)==0) - { - clk = i2s0_clk_enter(); - - xfer |= I2S_TX_TRAN_START; - xfer |= I2S_RX_TRAN_START; - writel(xfer, &(pheadi2s->I2S_XFER)); - - i2s0_clk_exit(clk); - } - if ((opr & I2S_RECE_DMA_ENABLE) == 0) { opr |= I2S_RECE_DMA_ENABLE; - writel(opr, &(pheadi2s->I2S_DMACR)); + writel(opr, &(pheadi2s->I2S_DMACR)); } - - flag_i2s_rx = 1; + if ((xfer&I2S_TX_TRAN_START)==0 || (xfer&I2S_RX_TRAN_START)==0) + { + xfer |= I2S_RX_TRAN_START; + xfer |= I2S_TX_TRAN_START; + writel(xfer, &(pheadi2s->I2S_XFER)); + } + flag_i2s_rx = 1; #ifdef CONFIG_SND_SOC_RT5631 //bard 7-16 s schedule_delayed_work(&rt5631_delay_cap,HZ/4); @@ -207,28 +166,18 @@ static void rockchip_snd_rxctrl(struct rk29_i2s_info *i2s, int on, bool stopI2S) { //stop rx flag_i2s_rx = 0; - if ((flag_i2s_rx == 0) && (flag_i2s_tx == 0)) - { - opr &= ~I2S_RECE_DMA_ENABLE; - writel(opr, &(pheadi2s->I2S_DMACR)); - - if(stopI2S) - { - clk = i2s0_clk_enter(); - - xfer &= ~I2S_RX_TRAN_START; - xfer &= ~I2S_TX_TRAN_START; - writel(xfer, &(pheadi2s->I2S_XFER)); - - i2s0_clk_exit(clk); - } - - //after stop rx & tx clk, reset i2s - //writel(0x001,&(pheadi2s->I2S_TXRST)); - //writel(0x001,&(pheadi2s->I2S_RXRST)); - } - I2S_DBG("rockchip_snd_rxctrl: off\n"); + opr &= ~I2S_RECE_DMA_ENABLE; + writel(opr, &(pheadi2s->I2S_DMACR)); + if ((flag_i2s_rx == 0) && (flag_i2s_tx == 0)) + { + xfer &= ~I2S_RX_TRAN_START; + xfer &= ~I2S_TX_TRAN_START; + writel(xfer, &(pheadi2s->I2S_XFER)); + clr |= I2S_RX_CLEAR; + writel(clr, &(pheadi2s->I2S_CLR)); + udelay(1); + } } } @@ -367,7 +316,6 @@ static int rockchip_i2s_trigger(struct snd_pcm_substream *substream, int cmd, st int ret = 0; struct snd_soc_pcm_runtime *rtd = substream->private_data; struct rk29_i2s_info *i2s = to_info(rtd->cpu_dai); - bool stopI2S = false; I2S_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); switch (cmd) { @@ -375,19 +323,18 @@ static int rockchip_i2s_trigger(struct snd_pcm_substream *substream, int cmd, st case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) - rockchip_snd_rxctrl(i2s, 1, stopI2S); + rockchip_snd_rxctrl(i2s, 1); else - rockchip_snd_txctrl(i2s, 1, stopI2S); + rockchip_snd_txctrl(i2s, 1); break; case SNDRV_PCM_TRIGGER_SUSPEND: - stopI2S = true; case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) - rockchip_snd_rxctrl(i2s, 0, stopI2S); + rockchip_snd_rxctrl(i2s, 0); else - rockchip_snd_txctrl(i2s, 0, stopI2S); + rockchip_snd_txctrl(i2s, 0); break; default: ret = -EINVAL; @@ -599,8 +546,8 @@ static int rk29_i2s_probe(struct platform_device *pdev, /* Mark ourselves as in TXRX mode so we can run through our cleanup * process without warnings. */ - rockchip_snd_txctrl(i2s, 0, true); - rockchip_snd_rxctrl(i2s, 0, true); + rockchip_snd_txctrl(i2s, 0); + rockchip_snd_rxctrl(i2s, 0); return 0; } -- 2.34.1