i2s : fix restart i2s dma cannot read/write data.
author邱建斌 <qjb@rock-chips.com>
Thu, 2 May 2013 03:19:56 +0000 (11:19 +0800)
committer邱建斌 <qjb@rock-chips.com>
Thu, 2 May 2013 03:19:56 +0000 (11:19 +0800)
sound/soc/rk29/rk29_i2s.h
sound/soc/rk29/rk30_i2s.c

index 116001a9986008ebd404469734ada55d5b7d53c1..91d09ab2c75a43d7420920f87f5ea4c154070db4 100755 (executable)
 #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
index 62bb21bd6f98e7d714ddcff2652b7f37d2cdf236..0ac35544e415e3bbea6b903423c57fcc1c5e016d 100755 (executable)
@@ -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;
 }