mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-09 20:32:04 +09:00
i2s : fix restart i2s dma cannot read/write data.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user