dw_dmac: Change value of DWC_MAX_COUNT to 4095.
[pandora-kernel.git] / drivers / dma / dw_dmac.c
index a3991ab..711ebe9 100644 (file)
  * which does not support descriptor writeback.
  */
 
-/* NOTE:  DMS+SMS is system-specific. We should get this information
- * from the platform code somehow.
- */
-#define DWC_DEFAULT_CTLLO      (DWC_CTLL_DST_MSIZE(0)          \
-                               | DWC_CTLL_SRC_MSIZE(0)         \
-                               | DWC_CTLL_DMS(0)               \
-                               | DWC_CTLL_SMS(1)               \
-                               | DWC_CTLL_LLP_D_EN             \
-                               | DWC_CTLL_LLP_S_EN)
+#define DWC_DEFAULT_CTLLO(private) ({                          \
+               struct dw_dma_slave *__slave = (private);       \
+               int dms = __slave ? __slave->dst_master : 0;    \
+               int sms = __slave ? __slave->src_master : 1;    \
+                                                               \
+               (DWC_CTLL_DST_MSIZE(0)                          \
+                | DWC_CTLL_SRC_MSIZE(0)                        \
+                | DWC_CTLL_LLP_D_EN                            \
+                | DWC_CTLL_LLP_S_EN                            \
+                | DWC_CTLL_DMS(dms)                            \
+                | DWC_CTLL_SMS(sms));                          \
+       })
 
 /*
  * This is configuration-dependent and usually a funny size like 4095.
- * Let's round it down to the nearest power of two.
  *
  * Note that this is a transfer count, i.e. if we transfer 32-bit
- * words, we can do 8192 bytes per descriptor.
+ * words, we can do 16380 bytes per descriptor.
  *
  * This parameter is also system-specific.
  */
-#define DWC_MAX_COUNT  2048U
+#define DWC_MAX_COUNT  4095U
 
 /*
  * Number of descriptors to allocate for each channel. This should be
@@ -84,11 +86,6 @@ static struct dw_desc *dwc_first_active(struct dw_dma_chan *dwc)
        return list_entry(dwc->active_list.next, struct dw_desc, desc_node);
 }
 
-static struct dw_desc *dwc_first_queued(struct dw_dma_chan *dwc)
-{
-       return list_entry(dwc->queue.next, struct dw_desc, desc_node);
-}
-
 static struct dw_desc *dwc_desc_get(struct dw_dma_chan *dwc)
 {
        struct dw_desc *desc, *_desc;
@@ -259,10 +256,11 @@ static void dwc_complete_all(struct dw_dma *dw, struct dw_dma_chan *dwc)
         * Submit queued descriptors ASAP, i.e. before we go through
         * the completed ones.
         */
-       if (!list_empty(&dwc->queue))
-               dwc_dostart(dwc, dwc_first_queued(dwc));
        list_splice_init(&dwc->active_list, &list);
-       list_splice_init(&dwc->queue, &dwc->active_list);
+       if (!list_empty(&dwc->queue)) {
+               list_move(dwc->queue.next, &dwc->active_list);
+               dwc_dostart(dwc, dwc_first_active(dwc));
+       }
 
        list_for_each_entry_safe(desc, _desc, &list, desc_node)
                dwc_descriptor_complete(dwc, desc);
@@ -291,6 +289,9 @@ static void dwc_scan_descriptors(struct dw_dma *dw, struct dw_dma_chan *dwc)
                return;
        }
 
+       if (list_empty(&dwc->active_list))
+               return;
+
        dev_vdbg(chan2dev(&dwc->chan), "scan_descriptors: llp=0x%x\n", llp);
 
        list_for_each_entry_safe(desc, _desc, &dwc->active_list, desc_node) {
@@ -319,8 +320,8 @@ static void dwc_scan_descriptors(struct dw_dma *dw, struct dw_dma_chan *dwc)
                cpu_relax();
 
        if (!list_empty(&dwc->queue)) {
-               dwc_dostart(dwc, dwc_first_queued(dwc));
-               list_splice_init(&dwc->queue, &dwc->active_list);
+               list_move(dwc->queue.next, &dwc->active_list);
+               dwc_dostart(dwc, dwc_first_active(dwc));
        }
 }
 
@@ -346,7 +347,7 @@ static void dwc_handle_error(struct dw_dma *dw, struct dw_dma_chan *dwc)
         */
        bad_desc = dwc_first_active(dwc);
        list_del_init(&bad_desc->desc_node);
-       list_splice_init(&dwc->queue, dwc->active_list.prev);
+       list_move(dwc->queue.next, dwc->active_list.prev);
 
        /* Clear the error flag and try to restart the controller */
        dma_writel(dw, CLEAR.ERROR, dwc->mask);
@@ -541,8 +542,8 @@ static dma_cookie_t dwc_tx_submit(struct dma_async_tx_descriptor *tx)
        if (list_empty(&dwc->active_list)) {
                dev_vdbg(chan2dev(tx->chan), "tx_submit: started %u\n",
                                desc->txd.cookie);
-               dwc_dostart(dwc, desc);
                list_add_tail(&desc->desc_node, &dwc->active_list);
+               dwc_dostart(dwc, dwc_first_active(dwc));
        } else {
                dev_vdbg(chan2dev(tx->chan), "tx_submit: queued %u\n",
                                desc->txd.cookie);
@@ -581,14 +582,16 @@ dwc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
         * We can be a lot more clever here, but this should take care
         * of the most common optimization.
         */
-       if (!((src | dest  | len) & 3))
+       if (!((src | dest  | len) & 7))
+               src_width = dst_width = 3;
+       else if (!((src | dest  | len) & 3))
                src_width = dst_width = 2;
        else if (!((src | dest | len) & 1))
                src_width = dst_width = 1;
        else
                src_width = dst_width = 0;
 
-       ctllo = DWC_DEFAULT_CTLLO
+       ctllo = DWC_DEFAULT_CTLLO(chan->private)
                        | DWC_CTLL_DST_WIDTH(dst_width)
                        | DWC_CTLL_SRC_WIDTH(src_width)
                        | DWC_CTLL_DST_INC
@@ -669,7 +672,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
 
        switch (direction) {
        case DMA_TO_DEVICE:
-               ctllo = (DWC_DEFAULT_CTLLO
+               ctllo = (DWC_DEFAULT_CTLLO(chan->private)
                                | DWC_CTLL_DST_WIDTH(reg_width)
                                | DWC_CTLL_DST_FIX
                                | DWC_CTLL_SRC_INC
@@ -714,7 +717,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
                }
                break;
        case DMA_FROM_DEVICE:
-               ctllo = (DWC_DEFAULT_CTLLO
+               ctllo = (DWC_DEFAULT_CTLLO(chan->private)
                                | DWC_CTLL_SRC_WIDTH(reg_width)
                                | DWC_CTLL_DST_INC
                                | DWC_CTLL_SRC_FIX
@@ -834,7 +837,9 @@ dwc_tx_status(struct dma_chan *chan,
 
        ret = dma_async_is_complete(cookie, last_complete, last_used);
        if (ret != DMA_SUCCESS) {
+               spin_lock_bh(&dwc->lock);
                dwc_scan_descriptors(to_dw_dma(chan->device), dwc);
+               spin_unlock_bh(&dwc->lock);
 
                last_complete = dwc->completed;
                last_used = chan->cookie;
@@ -1126,7 +1131,7 @@ struct dw_cyclic_desc *dw_dma_cyclic_prep(struct dma_chan *chan,
                case DMA_TO_DEVICE:
                        desc->lli.dar = dws->tx_reg;
                        desc->lli.sar = buf_addr + (period_len * i);
-                       desc->lli.ctllo = (DWC_DEFAULT_CTLLO
+                       desc->lli.ctllo = (DWC_DEFAULT_CTLLO(chan->private)
                                        | DWC_CTLL_DST_WIDTH(reg_width)
                                        | DWC_CTLL_SRC_WIDTH(reg_width)
                                        | DWC_CTLL_DST_FIX
@@ -1137,7 +1142,7 @@ struct dw_cyclic_desc *dw_dma_cyclic_prep(struct dma_chan *chan,
                case DMA_FROM_DEVICE:
                        desc->lli.dar = buf_addr + (period_len * i);
                        desc->lli.sar = dws->rx_reg;
-                       desc->lli.ctllo = (DWC_DEFAULT_CTLLO
+                       desc->lli.ctllo = (DWC_DEFAULT_CTLLO(chan->private)
                                        | DWC_CTLL_SRC_WIDTH(reg_width)
                                        | DWC_CTLL_DST_WIDTH(reg_width)
                                        | DWC_CTLL_DST_INC
@@ -1335,6 +1340,8 @@ static int __init dw_probe(struct platform_device *pdev)
 
        dma_cap_set(DMA_MEMCPY, dw->dma.cap_mask);
        dma_cap_set(DMA_SLAVE, dw->dma.cap_mask);
+       if (pdata->is_private)
+               dma_cap_set(DMA_PRIVATE, dw->dma.cap_mask);
        dw->dma.dev = &pdev->dev;
        dw->dma.device_alloc_chan_resources = dwc_alloc_chan_resources;
        dw->dma.device_free_chan_resources = dwc_free_chan_resources;
@@ -1447,7 +1454,7 @@ static int __init dw_init(void)
 {
        return platform_driver_probe(&dw_driver, dw_probe);
 }
-module_init(dw_init);
+subsys_initcall(dw_init);
 
 static void __exit dw_exit(void)
 {