Merge branch 'fixes' into misc
[deliverable/linux.git] / drivers / dma / omap-dma.c
index 9794b073d7d74d42e74c74db625e348a3ebc6483..1e984e18c1266b74fc01c247fad36f3e132ad587 100644 (file)
@@ -48,6 +48,7 @@ struct omap_chan {
        unsigned dma_sig;
        bool cyclic;
        bool paused;
+       bool running;
 
        int dma_ch;
        struct omap_desc *desc;
@@ -294,6 +295,8 @@ static void omap_dma_start(struct omap_chan *c, struct omap_desc *d)
 
        /* Enable channel */
        omap_dma_chan_write(c, CCR, d->ccr | CCR_ENABLE);
+
+       c->running = true;
 }
 
 static void omap_dma_stop(struct omap_chan *c)
@@ -355,6 +358,8 @@ static void omap_dma_stop(struct omap_chan *c)
 
                omap_dma_chan_write(c, CLNK_CTRL, val);
        }
+
+       c->running = false;
 }
 
 static void omap_dma_start_sg(struct omap_chan *c, struct omap_desc *d,
@@ -673,15 +678,20 @@ static enum dma_status omap_dma_tx_status(struct dma_chan *chan,
        struct omap_chan *c = to_omap_dma_chan(chan);
        struct virt_dma_desc *vd;
        enum dma_status ret;
-       uint32_t ccr;
        unsigned long flags;
 
-       ccr = omap_dma_chan_read(c, CCR);
-       /* The channel is no longer active, handle the completion right away */
-       if (!(ccr & CCR_ENABLE))
-               omap_dma_callback(c->dma_ch, 0, c);
-
        ret = dma_cookie_status(chan, cookie, txstate);
+
+       if (!c->paused && c->running) {
+               uint32_t ccr = omap_dma_chan_read(c, CCR);
+               /*
+                * The channel is no longer active, set the return value
+                * accordingly
+                */
+               if (!(ccr & CCR_ENABLE))
+                       ret = DMA_COMPLETE;
+       }
+
        if (ret == DMA_COMPLETE || !txstate)
                return ret;
 
@@ -945,9 +955,7 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_memcpy(
        d->ccr = c->ccr;
        d->ccr |= CCR_DST_AMODE_POSTINC | CCR_SRC_AMODE_POSTINC;
 
-       d->cicr = CICR_DROP_IE;
-       if (tx_flags & DMA_PREP_INTERRUPT)
-               d->cicr |= CICR_FRAME_IE;
+       d->cicr = CICR_DROP_IE | CICR_FRAME_IE;
 
        d->csdp = data_type;
 
@@ -1009,6 +1017,13 @@ static int omap_dma_terminate_all(struct dma_chan *chan)
        return 0;
 }
 
+static void omap_dma_synchronize(struct dma_chan *chan)
+{
+       struct omap_chan *c = to_omap_dma_chan(chan);
+
+       vchan_synchronize(&c->vc);
+}
+
 static int omap_dma_pause(struct dma_chan *chan)
 {
        struct omap_chan *c = to_omap_dma_chan(chan);
@@ -1112,6 +1127,7 @@ static int omap_dma_probe(struct platform_device *pdev)
        od->ddev.device_pause = omap_dma_pause;
        od->ddev.device_resume = omap_dma_resume;
        od->ddev.device_terminate_all = omap_dma_terminate_all;
+       od->ddev.device_synchronize = omap_dma_synchronize;
        od->ddev.src_addr_widths = OMAP_DMA_BUSWIDTHS;
        od->ddev.dst_addr_widths = OMAP_DMA_BUSWIDTHS;
        od->ddev.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
This page took 0.026928 seconds and 5 git commands to generate.