add dma irq mode
author倪振宇 <nzy@rock-chips.com>
Mon, 31 May 2010 10:15:57 +0000 (10:15 +0000)
committer黄涛 <huangtao@rock-chips.com>
Mon, 21 Jun 2010 05:35:20 +0000 (13:35 +0800)
arch/arm/include/asm/dma.h
arch/arm/include/asm/mach/dma.h
arch/arm/kernel/dma.c
arch/arm/mach-rk2818/dma.c
arch/arm/mach-rk2818/include/mach/dma.h
drivers/mmc/host/rk2818-sdmmc.c
sound/soc/rk2818/rk2818_pcm.c

index 008b67fb4297287d6691bfb73e3414e99a1f1260..fcaa8e2b6b9839e84edc25f40c8f8ea35a478f5d 100644 (file)
 #define DMA_AUTOINIT    0x10
 
 
+/*
+ * The DMA irq modes 
+ */
+#define DMA_IRQ_DELAY_MODE          0x00   /*performan in software irq handleer*/
+#define DMA_IRQ_RIGHTNOW_MODE   0x01   /*performan in dwdma irq handleer*/
+
+
 /* Request a DMA channel
  *
  * Some architectures may need to do allocate an interrupt
@@ -96,10 +103,8 @@ extern void set_dma_sg(unsigned int chan, struct scatterlist *sg, int nr_sg);
  * DMA address immediately, but defer it to the enable_dma().
  */
 extern void __set_dma_addr(unsigned int chan, void *addr);
-#define set_dma_addr(chan, addr)                               \
-       __set_dma_addr(chan, addr)      
-       //__set_dma_addr(chan, bus_to_virt(addr))
-       
+
+#define set_dma_addr(chan, addr)       __set_dma_addr(chan, addr)//__set_dma_addr(chan, bus_to_virt(addr))
 
 /* Set the DMA byte count for this channel
  *
@@ -132,7 +137,12 @@ extern int  get_dma_residue(unsigned int chan);
 #endif
 /* Set dam irq callback that perform when dma transfer has completed
  */
-extern void set_dma_handler (unsigned int chan, void (*irq_handler) (int, void *), void *data);
+extern void set_dma_handler (unsigned int chan, void (*irq_handler) (int, void *), void *data, unsigned int irq_mode);
+
+
+/*
+ * get dma transfer position
+ */
+extern void get_dma_position(unsigned int chan, dma_addr_t *src_pos, dma_addr_t *dst_pos);
 
-extern int dma_getposition(unsigned int  channel, dma_addr_t *src, dma_addr_t *dst);
 #endif /* __ASM_ARM_DMA_H */
index c46ca4c5aa91d4c22b89eafc2be8055160a247b1..22ab6f20729111811dc5193dccddce14ecfe7957 100644 (file)
@@ -19,6 +19,7 @@ struct dma_ops {
        int     (*free)(unsigned int, dma_t *);                 /* optional */
        int     (*enable)(unsigned int, dma_t *);               /* mandatory */
        int     (*disable)(unsigned int, dma_t *);              /* mandatory */
+       void (*position)(unsigned int, dma_t *);
 #if 0  
        int     (*residue)(unsigned int, dma_t *);              /* optional */
        int     (*setspeed)(unsigned int, dma_t *, int);        /* optional */
@@ -42,8 +43,12 @@ struct dma_struct {
        unsigned int    lock;           /* Device is allocated          */
        const char      *device_id;     /* Device name                  */
 
-    int (*irqHandle)(int irq, void *dev_id);    /*irq callback*/
+    void (*irqHandle)(int irq, void *dev_id);    /*irq callback*/
     void *data;
+    unsigned int irq_mode;
+
+    dma_addr_t  src_pos;
+    dma_addr_t  dst_pos;
     
        const struct dma_ops *d_ops;
 };
index 478498105a8ba5764c2ae3a1efc8c24691328252..90c627011f82e3496a2ffd19c8279ab82e5b6b8d 100644 (file)
@@ -126,7 +126,7 @@ EXPORT_SYMBOL(free_dma);
  *
  * Copy irq handler to the structure
  */
- void set_dma_handler (unsigned int chan, void (*irq_handler) (int, void *), void *data)
+ void set_dma_handler (unsigned int chan, void (*irq_handler) (int, void *), void *data, unsigned int irq_mode)
 {
        dma_t *dma = dma_channel(chan);
 
@@ -136,6 +136,7 @@ EXPORT_SYMBOL(free_dma);
 
        dma->irqHandle = irq_handler;
        dma->data = data;
+       dma->irq_mode = irq_mode;
 }
 EXPORT_SYMBOL(set_dma_handler);
 
@@ -264,6 +265,26 @@ int dma_channel_active(unsigned int chan)
        dma_t *dma = dma_channel(chan);
        return dma->active;
 }
+
+/*
+ * get dma transfer position
+ */
+void get_dma_position(unsigned int chan, dma_addr_t *src_pos, dma_addr_t *dst_pos)
+{
+       dma_t *dma = dma_channel(chan);
+
+    if (dma->d_ops->position)
+        dma->d_ops->position(chan, dma);
+
+       if (src_pos) {
+        *src_pos = dma->src_pos;
+       }
+
+    if (dst_pos) {
+        *dst_pos = dma->dst_pos;
+    }
+}
+
 EXPORT_SYMBOL(dma_channel_active);
 #if 0
 void set_dma_page(unsigned int chan, char pagenr)
index fb0b3ab014a9deec68c87d7ad4a4e869ff2d601e..d9cdde936a0bb0b21a0af9d4327b32759ab2f1ee 100644 (file)
@@ -130,7 +130,7 @@ const static struct rk28_dma_dev rk28_dev_info[] = {
  * rk28_dma_ctl_for_write - set dma control register for writing mode   
  *
  */
-static inline unsigned int rk28_dma_ctl_for_write(unsigned int dma_ch, struct rk28_dma_dev *dev_info, dma_t *dma_t)
+static inline unsigned int rk28_dma_ctl_for_write(unsigned int dma_ch, const struct rk28_dma_dev *dev_info, dma_t *dma_t)
 {    
 #ifdef test_dma
     unsigned int dev_mode = B_CTLL_MEM2MEM_DMAC;
@@ -155,7 +155,7 @@ static inline unsigned int rk28_dma_ctl_for_write(unsigned int dma_ch, struct rk
  * rk28_dma_ctl_for_read - set dma control register for reading mode   
  *
  */
-static inline unsigned int rk28_dma_ctl_for_read(unsigned int dma_ch, struct rk28_dma_dev *dev_info, dma_t *dma_t)
+static inline unsigned int rk28_dma_ctl_for_read(unsigned int dma_ch, const struct rk28_dma_dev *dev_info, dma_t *dma_t)
 {    
 #ifdef test_dma
     unsigned int dev_mode = B_CTLL_MEM2MEM_DMAC;
@@ -246,7 +246,7 @@ static void rk28_dma_write_to_sg(unsigned int dma_ch, dma_t *dma_t)
     struct rk28_dma_llp * rk28llp_phy;
     struct rk28_dma_llp rk28dma_reg;
     struct scatterlist *sg;
-       unsigned int wid_off;
+       unsigned int wid_off, bk_count, bk_res, sgcount_tmp, bk_length;
        
     rk28dma = &rk2818_dma[dma_ch];
        
@@ -258,16 +258,36 @@ static void rk28_dma_write_to_sg(unsigned int dma_ch, dma_t *dma_t)
         rk28llp_vir = rk28dma->dma_llp_vir;
         rk28llp_phy = (struct rk28_dma_llp *)rk28dma->dma_llp_phy;
         sg = dma_t->sg;
+#if 1
+        bk_length = RK28_DMA_CH0A1_MAX_LEN << wid_off;
+        
+        for (sgcount_tmp = 0; sgcount_tmp < dma_t->sgcount; sgcount_tmp++, sg++) { 
+            bk_count = (sg->length >> wid_off) / RK28_DMA_CH0A1_MAX_LEN;
+            bk_res = (sg->length >> wid_off) % RK28_DMA_CH0A1_MAX_LEN;
+            for (i = 0; i < bk_count; i++) { 
+                rk28_dma_set_llp(dev_addr_w,
+                               sg->dma_address + i * bk_length, 
+                               rk28llp_vir++,
+                               ++rk28llp_phy,
+                               ctll_r,
+                               RK28_DMA_CH0A1_MAX_LEN);
+            }
+            if (bk_res > 0) {
+                rk28_dma_set_llp(dev_addr_w,
+                               sg->dma_address + bk_count * bk_length,
+                               rk28llp_vir++,
+                               ++rk28llp_phy,
+                               ctll_r,
+                               bk_res);
+            }
+        }
+#else
         for (i = 0; i < dma_t->sgcount; i++, sg++) { 
             rk28_dma_set_llp(dev_addr_w, sg->dma_address, rk28llp_vir++, ++rk28llp_phy, ctll_r, (sg->length >> wid_off));
-        } 
+        }
+#endif        
         rk28_dma_end_of_llp(rk28llp_vir - 1);
-
-        rk28dma_reg.sar = 0;//dev_addr_w;
-        rk28dma_reg.dar = 0;//dma_t->sg->dma_address;
-        rk28dma_reg.ctll = ctll_r;
         rk28dma_reg.llp = (struct rk28_dma_llp *)rk28dma->dma_llp_phy;
-        rk28dma_reg.size = 0;//dma_t->sg->length;
     } else { /*single transfer*/
         if (dma_t->buf.length > RK28_DMA_CH2_MAX_LEN) {
             rk28dma->length = RK28_DMA_CH2_MAX_LEN;
@@ -276,12 +296,12 @@ static void rk28_dma_write_to_sg(unsigned int dma_ch, dma_t *dma_t)
             rk28dma->length = dma_t->buf.length;
             rk28dma->residue = 0;
         }
-        rk28dma_reg.sar = dev_addr_w;
-        rk28dma_reg.dar = dma_t->buf.dma_address;
-        rk28dma_reg.ctll = ctll_r;
         rk28dma_reg.llp = NULL;
-        rk28dma_reg.size = rk28dma->length;
     }
+    rk28dma_reg.sar = dev_addr_w;
+    rk28dma_reg.dar = dma_t->buf.dma_address;
+    rk28dma_reg.ctll = ctll_r;
+    rk28dma_reg.size = rk28dma->length;
     rk28_dma_set_reg(dma_ch, &rk28dma_reg, rk28dma->dev_info->hd_if_r);
     /*
     printk(KERN_INFO "dma_write_to_sg: ch = %d, sar = 0x%x, dar = 0x%x, ctll = 0x%x, llp = 0x%x, size = %d, \n", 
@@ -316,10 +336,10 @@ static void rk28_dma_read_from_sg(unsigned int dma_ch, dma_t *dma_t)
     struct rk28_dma_llp * rk28llp_phy;
     struct rk28_dma_llp rk28dma_reg;
     struct scatterlist *sg;
-       unsigned int wid_off;
+       unsigned int wid_off, bk_count, bk_res, sgcount_tmp, bk_length;
 
     rk28dma = &rk2818_dma[dma_ch];
-    
+        
     /*setup linked list table end*/
     dev_addr_r = rk28dma->dev_info->dev_addr_r;
     ctll_w = rk28_dma_ctl_for_write(dma_ch, rk28dma->dev_info, dma_t);
@@ -329,16 +349,36 @@ static void rk28_dma_read_from_sg(unsigned int dma_ch, dma_t *dma_t)
         rk28llp_vir = rk28dma->dma_llp_vir;
         rk28llp_phy = (struct rk28_dma_llp *)rk28dma->dma_llp_phy;
         sg = dma_t->sg;
+#if 1
+        bk_length = RK28_DMA_CH0A1_MAX_LEN << wid_off;
+        
+        for (sgcount_tmp = 0; sgcount_tmp < dma_t->sgcount; sgcount_tmp++, sg++) { 
+            bk_count = (sg->length >> wid_off) / RK28_DMA_CH0A1_MAX_LEN;
+            bk_res = (sg->length >> wid_off) % RK28_DMA_CH0A1_MAX_LEN;
+            for (i = 0; i < bk_count; i++) { 
+                rk28_dma_set_llp(sg->dma_address + i * bk_length, 
+                               dev_addr_r,
+                               rk28llp_vir++,
+                               ++rk28llp_phy,
+                               ctll_w,
+                               RK28_DMA_CH0A1_MAX_LEN);
+            }
+            if (bk_res > 0) {
+                rk28_dma_set_llp(sg->dma_address + bk_count * bk_length,
+                               dev_addr_r,
+                               rk28llp_vir++,
+                               ++rk28llp_phy,
+                               ctll_w,
+                               bk_res);
+            }
+        }
+#else
         for (i = 0; i < dma_t->sgcount; i++, sg++) { 
             rk28_dma_set_llp(sg->dma_address, dev_addr_r, rk28llp_vir++, ++rk28llp_phy, ctll_w, (sg->length >> wid_off));
         }
+#endif        
         rk28_dma_end_of_llp(rk28llp_vir - 1);
-
-        rk28dma_reg.sar = 0;//dma_t->sg->dma_address;
-        rk28dma_reg.dar = 0;//dev_addr_r;
-        rk28dma_reg.ctll = ctll_w;
         rk28dma_reg.llp = (struct rk28_dma_llp *)rk28dma->dma_llp_phy;
-        rk28dma_reg.size = 0;//dma_t->sg->length;
     } else { /*single transfer*/
         if (dma_t->buf.length > RK28_DMA_CH2_MAX_LEN) {
             rk28dma->length = RK28_DMA_CH2_MAX_LEN;
@@ -347,12 +387,12 @@ static void rk28_dma_read_from_sg(unsigned int dma_ch, dma_t *dma_t)
             rk28dma->length = dma_t->buf.length;
             rk28dma->residue = 0;
         } 
-        rk28dma_reg.sar = dma_t->buf.dma_address;
-        rk28dma_reg.dar = dev_addr_r;
-        rk28dma_reg.ctll = ctll_w;
         rk28dma_reg.llp = NULL;
-        rk28dma_reg.size = rk28dma->length;
     }
+    rk28dma_reg.sar = dma_t->buf.dma_address;
+    rk28dma_reg.dar = dev_addr_r;
+    rk28dma_reg.ctll = ctll_w;
+    rk28dma_reg.size = rk28dma->length;
     rk28_dma_set_reg(dma_ch, &rk28dma_reg, rk28dma->dev_info->hd_if_w);
 
     //printk(KERN_INFO "read_from_sg: ch = %d, sar = 0x%x, dar = 0x%x, ctll = 0x%x, llp = 0x%x, size = %d, \n", 
@@ -430,6 +470,8 @@ static int rk28_dma_disable(unsigned int dma_ch, dma_t *dma_t)
        while (GET_DWDMA_STATUS(dma_ch))
                cpu_relax();
                
+    rk28dma->tasklet_flag = 0;
+    
        spin_unlock(&rk28dma->lock);
        
     return 0;  
@@ -471,13 +513,15 @@ static int rk28_dma_request(unsigned int dma_ch, dma_t *dma_t)
         }
     } else {
         rk28dma->dma_llp_vir = NULL;
-        rk28dma->dma_llp_phy = NULL;
+        rk28dma->dma_llp_phy = 0;
     }
     
     rk28dma->dev_info = &rk28_dev_info[i];
        
        /* clear interrupt */
     CLR_DWDMA_INTR(dma_ch);
+    
+       UN_MASK_DWDMA_TRF_INTR(dma_ch);
 
        spin_unlock(&rk28dma->lock);
 
@@ -500,6 +544,8 @@ static int rk28_dma_free(unsigned int dma_ch, dma_t *dma_t)
        
        /* clear interrupt */
     CLR_DWDMA_INTR(dma_ch);
+    
+       MASK_DWDMA_TRF_INTR(dma_ch);
 
        if (dma_ch < RK28_DMA_CH2) {
         if (!rk28dma->dma_llp_vir) {
@@ -515,7 +561,7 @@ static int rk28_dma_free(unsigned int dma_ch, dma_t *dma_t)
     rk28dma->dma_t.addr = NULL;
     rk28dma->dma_t.count = 0;      
     rk28dma->dma_llp_vir = NULL;
-    rk28dma->dma_llp_phy = NULL;
+    rk28dma->dma_llp_phy = 0;
     rk28dma->residue = 0;
     rk28dma->length = 0;
 
@@ -580,6 +626,27 @@ static int rk28_dma_next(unsigned int dma_ch)
  *
  */
 static void rk28_dma_tasklet(unsigned long data)
+{
+       int i;
+    struct rk2818_dma *rk28dma;
+
+    for (i = 0; i < MAX_DMA_CHANNELS; i++) {
+        rk28dma = &rk2818_dma[i];
+        if ((rk28dma->tasklet_flag) && (rk28dma->dma_t.irq_mode == DMA_IRQ_DELAY_MODE)) {
+            rk28dma->dma_t.active = 0;
+            rk28dma->tasklet_flag = 0;
+            if (rk28dma->dma_t.irqHandle)
+                rk28dma->dma_t.irqHandle(i, rk28dma->dma_t.data);
+            UN_MASK_DWDMA_TRF_INTR(i);
+        }
+    }
+}
+
+/**
+ * rk28_dma_irq_handler - irq callback function   
+ *
+ */
+static irqreturn_t rk28_dma_irq_handler(int irq, void *dev_id)
 {
        int i, raw_status;
     struct rk2818_dma *rk28dma;
@@ -596,58 +663,42 @@ static void rk28_dma_tasklet(unsigned long data)
                 //printk(KERN_WARNING "dma_irq: don't finish  for channel %d\n", i);
                 continue;
             }  
-            /* already complete transfer */
-            rk28dma->dma_t.active = 0;
-            
+
             if (rk28dma->dma_t.irqHandle) {
-                void *data = rk28dma->dma_t.data;
-                rk28dma->dma_t.irqHandle(i, data);
+                if (rk28dma->dma_t.irq_mode != DMA_IRQ_DELAY_MODE) {
+                    /* already have completed transfer */
+                    rk28dma->dma_t.active = 0;
+                    rk28dma->dma_t.irqHandle(i, rk28dma->dma_t.data);
+                } else {
+                    MASK_DWDMA_TRF_INTR(i);
+                    rk28dma->tasklet_flag = 1;
+                    tasklet_schedule(&rk2818_dma_tasklet);
+                    //printk(KERN_WARNING "dma_irq: no IRQ handler for DMA channel %d\n", i);
+                }
             } else {
-                printk(KERN_WARNING "dma_irq: no IRQ handler for DMA channel %d\n", i);
-            }
+                /* already have completed transfer */
+                rk28dma->dma_t.active = 0;
+            }   
         }
        }
-       /*
-        * Re-enable interrupts
-        */
-       UN_MASK_DWDMA_ALL_TRF_INTR;
-}
-
-/**
- * rk28_dma_irq_handler - irq callback function   
- *
- */
-static irqreturn_t rk28_dma_irq_handler(int irq, void *dev_id)
-{
-       /*
-        * Just disable the interrupts. We'll turn them back on in the
-        * softirq handler.
-        */
-       MASK_DWDMA_ALL_TRF_INTR;
        
-    tasklet_schedule(&rk2818_dma_tasklet);
+    //tasklet_schedule(&rk2818_dma_tasklet);
 
        return IRQ_HANDLED;
 }
 
-
-int dma_getposition(unsigned int  channel, dma_addr_t *src, dma_addr_t *dst)
+static void rk28_dma_position(unsigned int dma_ch, dma_t *dma_t)
 {
-       u32 phy_ch = channel;
-    if (src != NULL)
-        *src = read_dma_reg(DWDMA_SAR(phy_ch));
-    if (dst != NULL)     
-        *dst = read_dma_reg(DWDMA_DAR(phy_ch)); 
-    
-       return 0;
+    dma_t->src_pos = read_dma_reg(DWDMA_SAR(dma_ch));
+    dma_t->dst_pos = read_dma_reg(DWDMA_DAR(dma_ch));
 }
-EXPORT_SYMBOL(dma_getposition);
 
 static struct dma_ops rk2818_dma_ops = {
     .request = rk28_dma_request,
     .free = rk28_dma_free,
     .enable = rk28_dma_enable,
     .disable = rk28_dma_disable,
+    .position = rk28_dma_position,
 };
 
 /**
@@ -671,9 +722,10 @@ static int __init rk28_dma_init(void)
            dma_add(i, &rk2818_dma[i].dma_t);
 
         rk2818_dma[i].dma_llp_vir = NULL;
-        rk2818_dma[i].dma_llp_phy = NULL;
+        rk2818_dma[i].dma_llp_phy = 0;
         rk2818_dma[i].residue = 0;
         rk2818_dma[i].length = 0;
+        rk2818_dma[i].tasklet_flag = 0;
        }
        
        /* clear all interrupts */
@@ -690,7 +742,8 @@ static int __init rk28_dma_init(void)
        write_dma_reg(DWDMA_MaskErr, 0x3f00);
 
     /*unmask transfer completion interrupt*/
-       UN_MASK_DWDMA_ALL_TRF_INTR;
+       //UN_MASK_DWDMA_ALL_TRF_INTR;
+       MASK_DWDMA_ALL_TRF_INTR;
 
        ret = request_irq(RK28_DMA_IRQ_NUM, rk28_dma_irq_handler, 0, "DMA", NULL);
        if (ret < 0) {
@@ -698,7 +751,7 @@ static int __init rk28_dma_init(void)
                return ret;
        }
 
-       tasklet_init(&rk2818_dma_tasklet, rk28_dma_tasklet, NULL);
+       tasklet_init(&rk2818_dma_tasklet, rk28_dma_tasklet, 0);
 
        /* enable DMA module */
        write_dma_reg(DWDMA_DmaCfgReg, 0x01);
index 0ac2ea8c6f06f7ff84dfb6641abad047d1e58b0e..f0cdfb2666c1b87332fbe0059cf6435dce22ce1c 100644 (file)
 
    /* Unmask interrupt */
 #define UN_MASK_DWDMA_ALL_TRF_INTR        write_dma_reg(DWDMA_MaskTfr, 0x3f3f)//mask_dma_reg(DWDMA_MaskTfr, 0x101<<dma_ch, 0x101<<dma_ch)
+#define UN_MASK_DWDMA_TRF_INTR(dma_ch)    mask_dma_reg(DWDMA_MaskTfr, 0x101<<dma_ch, 0x101<<dma_ch)
 
    /* Mask interrupt */
 #define MASK_DWDMA_ALL_TRF_INTR           write_dma_reg(DWDMA_MaskTfr, 0x3f00)//mask_dma_reg(DWDMA_MaskTfr, 0x101<<dma_ch, 0x100<<dma_ch)
+#define MASK_DWDMA_TRF_INTR(dma_ch)       mask_dma_reg(DWDMA_MaskTfr, 0x101<<dma_ch, 0x100<<dma_ch)
 
    /* Enable channel */
 #define ENABLE_DWDMA(dma_ch)              mask_dma_reg(DWDMA_ChEnReg, 0x101<<dma_ch, 0x101<<dma_ch)
@@ -197,11 +199,12 @@ struct rk28_dma_dev {
 
 struct rk2818_dma {
     dma_t  dma_t;
-       struct rk28_dma_dev *dev_info;/* basic address of sg in memory */
+       const struct rk28_dma_dev *dev_info;/* basic address of sg in memory */
     struct rk28_dma_llp *dma_llp_vir;  /* virtual cpu addrress of linked list */
     unsigned int dma_llp_phy;                   /* physical bus address of linked list */
        unsigned int length;     /* current transfer block */ 
        unsigned int residue;     /* residue block of current dma transfer */
+       unsigned int tasklet_flag;
        spinlock_t              lock;
 };
 
index 783d14603998f9e44f22698b70227264a0b436b7..7ac258e65b768f85572b03bc2b6e59644ec50d89 100644 (file)
@@ -402,7 +402,7 @@ static int rk2818_sdmmc_submit_data_dma(struct rk2818_sdmmc_host *host, struct m
        set_dma_sg(host->dma_chn, data->sg, data->sg_len);
        set_dma_mode(host->dma_chn,
                                (data->flags & MMC_DATA_READ)? DMA_MODE_READ : DMA_MODE_WRITE);
-       set_dma_handler(host->dma_chn, rk2818_sdmmc_dma_complete, (void *)host);
+       set_dma_handler(host->dma_chn, rk2818_sdmmc_dma_complete, (void *)host, DMA_IRQ_DELAY_MODE);
        writel(readl(host->regs + SDMMC_CTRL) | SDMMC_CTRL_DMA_ENABLE,
                                host->regs +SDMMC_CTRL);
        enable_dma(host->dma_chn);
index bcdd924d1fbf8c8931c94c671a1d0b68ef29822e..5d2519cdf030270f1e0e4e5b32627b5d766d4e2f 100755 (executable)
@@ -155,7 +155,7 @@ void audio_start_dma(struct snd_pcm_substream *substream, int mode)
                        disable_dma(prtd->params->channel);
                        //set_dma_sg(prtd->params->channel, &(sg_buf->sg), 1);
                        set_dma_mode(prtd->params->channel, DMA_MODE_WRITE);
-                       set_dma_handler(prtd->params->channel, rockchip_pcm_dma_irq, substream);
+                       set_dma_handler(prtd->params->channel, rockchip_pcm_dma_irq, substream, DMA_IRQ_RIGHTNOW_MODE);
                        __set_dma_addr(prtd->params->channel, (void *)(sg_buf->sg.dma_address));
                        set_dma_count(prtd->params->channel, sg_buf->sg.length);
                        enable_dma(prtd->params->channel);
@@ -185,7 +185,7 @@ void audio_start_dma(struct snd_pcm_substream *substream, int mode)
                        disable_dma(prtd->params->channel);
                        //set_dma_sg(prtd->params->channel, &(sg_buf->sg), 1);
                        set_dma_mode(prtd->params->channel, DMA_MODE_READ);
-                       set_dma_handler(prtd->params->channel, rockchip_pcm_dma_irq, substream);                        
+                       set_dma_handler(prtd->params->channel, rockchip_pcm_dma_irq, substream, DMA_IRQ_RIGHTNOW_MODE);                 
                        __set_dma_addr(prtd->params->channel, (void *)(sg_buf->sg.dma_address));
                        set_dma_count(prtd->params->channel, sg_buf->sg.length);
                        enable_dma(prtd->params->channel);
@@ -418,7 +418,9 @@ rockchip_pcm_pointer(struct snd_pcm_substream *substream)
     
        DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
        spin_lock(&prtd->lock);
-       dma_getposition(prtd->params->channel, &src, &dst);
+
+    get_dma_position(prtd->params->channel, &src, &dst);                       
+       //dma_getposition(prtd->params->channel, &src, &dst);
        
        if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
                res = dst - prtd->dma_start;