i2s : fix restart i2s dma cannot read/write data.

This commit is contained in:
邱建斌
2013-05-02 11:19:56 +08:00
parent 47f58b4895
commit 21246987b3
2 changed files with 56 additions and 104 deletions

View File

@@ -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

View File

@@ -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)
{
clk = i2s0_clk_enter();
//if start tx & rx clk, need reset i2s
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));
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));
}
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;
}