DaVinci: EDMA: Adding 2 new APIs for allocating/freeing PARAMs
authorSandeep Paulraj <s-paulraj@ti.com>
Mon, 27 Jul 2009 19:10:36 +0000 (15:10 -0400)
committerKevin Hilman <khilman@deeprootsystems.com>
Wed, 26 Aug 2009 08:55:59 +0000 (11:55 +0300)
For best performance, codecs often setup linked triggered
transfers with a contiguous block of params, and that is when
this API is used. Setup/configuration of these parameter RAMs
is most efficient if they are contiguous.
There is an API to allocate a set of contiguous parameter RAMs and
a corresponding API to free a set of contiguous parameter RAMs

Signed-off-by: Sandeep Paulraj <s-paulraj@ti.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
arch/arm/mach-davinci/dma.c
arch/arm/mach-davinci/include/mach/edma.h

index e6d7e6aca3369336a6ee90f60e0b7fdaafd1217b..f2e57d2729583f0c430d02a745e5c4779e6f10e0 100644 (file)
@@ -509,6 +509,45 @@ static irqreturn_t dma_tc1err_handler(int irq, void *data)
        return IRQ_HANDLED;
 }
 
+static int reserve_contiguous_params(int ctlr, unsigned int id,
+                                    unsigned int num_params,
+                                    unsigned int start_param)
+{
+       int i, j;
+       unsigned int count = num_params;
+
+       for (i = start_param; i < edma_info[ctlr]->num_slots; ++i) {
+               j = EDMA_CHAN_SLOT(i);
+               if (!test_and_set_bit(j, edma_info[ctlr]->edma_inuse))
+                       count--;
+                       if (count == 0)
+                               break;
+               else if (id == EDMA_CONT_PARAMS_FIXED_EXACT)
+                       break;
+               else
+                       count = num_params;
+       }
+
+       /*
+        * We have to clear any bits that we set
+        * if we run out parameter RAMs, i.e we do find a set
+        * of contiguous parameter RAMs but do not find the exact number
+        * requested as we may reach the total number of parameter RAMs
+        */
+       if (count) {
+               for (j = i - num_params + count + 1; j <= i ; ++j)
+                       clear_bit(j, edma_info[ctlr]->edma_inuse);
+
+               return -EBUSY;
+       }
+
+       for (j = i - num_params + 1; j <= i; ++j)
+               memcpy_toio(edmacc_regs_base[ctlr] + PARM_OFFSET(j),
+                       &dummy_paramset, PARM_SIZE);
+
+       return EDMA_CTLR_CHAN(ctlr, i - num_params + 1);
+}
+
 /*-----------------------------------------------------------------------*/
 
 /* Resource alloc/free:  dma channels, parameter RAM slots */
@@ -700,6 +739,104 @@ void edma_free_slot(unsigned slot)
 }
 EXPORT_SYMBOL(edma_free_slot);
 
+
+/**
+ * edma_alloc_cont_slots- alloc contiguous parameter RAM slots
+ * The API will return the starting point of a set of
+ * contiguous PARAM's that have been requested
+ *
+ * @id: can only be EDMA_CONT_PARAMS_ANY or EDMA_CONT_PARAMS_FIXED_EXACT
+ * or EDMA_CONT_PARAMS_FIXED_NOT_EXACT
+ * @count: number of contiguous Paramter RAM's
+ * @param  - the start value of Parameter RAM that should be passed if id
+ * is EDMA_CONT_PARAMS_FIXED_EXACT or EDMA_CONT_PARAMS_FIXED_NOT_EXACT
+ *
+ * If id is EDMA_CONT_PARAMS_ANY then the API starts looking for a set of
+ * contiguous Parameter RAMs from parameter RAM 64 in the case of DaVinci SOCs
+ * and 32 in the case of Primus
+ *
+ * If id is EDMA_CONT_PARAMS_FIXED_EXACT then the API starts looking for a
+ * set of contiguous parameter RAMs from the "param" that is passed as an
+ * argument to the API.
+ *
+ * If id is EDMA_CONT_PARAMS_FIXED_NOT_EXACT then the API initially tries
+ * starts looking for a set of contiguous parameter RAMs from the "param"
+ * that is passed as an argument to the API. On failure the API will try to
+ * find a set of contiguous Parameter RAMs in the remaining Parameter RAMs
+ */
+int edma_alloc_cont_slots(unsigned ctlr, unsigned int id, int slot, int count)
+{
+       /*
+        * The start slot requested should be greater than
+        * the number of channels and lesser than the total number
+        * of slots
+        */
+       if (slot < edma_info[ctlr]->num_channels ||
+               slot >= edma_info[ctlr]->num_slots)
+               return -EINVAL;
+
+       /*
+        * The number of parameter RAMs requested cannot be less than 1
+        * and cannot be more than the number of slots minus the number of
+        * channels
+        */
+       if (count < 1 || count >
+               (edma_info[ctlr]->num_slots - edma_info[ctlr]->num_channels))
+               return -EINVAL;
+
+       switch (id) {
+       case EDMA_CONT_PARAMS_ANY:
+               return reserve_contiguous_params(ctlr, id, count,
+                                                edma_info[ctlr]->num_channels);
+       case EDMA_CONT_PARAMS_FIXED_EXACT:
+       case EDMA_CONT_PARAMS_FIXED_NOT_EXACT:
+               return reserve_contiguous_params(ctlr, id, count, slot);
+       default:
+               return -EINVAL;
+       }
+
+}
+EXPORT_SYMBOL(edma_alloc_cont_slots);
+
+/**
+ * edma_free_cont_slots - deallocate DMA parameter RAMs
+ * @slot: first parameter RAM of a set of parameter RAMs to be freed
+ * @count: the number of contiguous parameter RAMs to be freed
+ *
+ * This deallocates the parameter RAM slots allocated by
+ * edma_alloc_cont_slots.
+ * Callers/applications need to keep track of sets of contiguous
+ * parameter RAMs that have been allocated using the edma_alloc_cont_slots
+ * API.
+ * Callers are responsible for ensuring the slots are inactive, and will
+ * not be activated.
+ */
+int edma_free_cont_slots(unsigned slot, int count)
+{
+       unsigned ctlr;
+       int i;
+
+       ctlr = EDMA_CTLR(slot);
+       slot = EDMA_CHAN_SLOT(slot);
+
+       if (slot < edma_info[ctlr]->num_channels ||
+               slot >= edma_info[ctlr]->num_slots ||
+               count < 1)
+               return -EINVAL;
+
+       for (i = slot; i < slot + count; ++i) {
+               ctlr = EDMA_CTLR(i);
+               slot = EDMA_CHAN_SLOT(i);
+
+               memcpy_toio(edmacc_regs_base[ctlr] + PARM_OFFSET(slot),
+                       &dummy_paramset, PARM_SIZE);
+               clear_bit(slot, edma_info[ctlr]->edma_inuse);
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(edma_free_cont_slots);
+
 /*-----------------------------------------------------------------------*/
 
 /* Parameter RAM operations (i) -- read/write partial slots */
index 3c7dc2db70e4c118b0ad3425121932bacdabb5e9..eb8bfd7925e78cc49b163debac7a6149c8f10ad7 100644 (file)
@@ -226,6 +226,9 @@ enum sync_dimension {
 
 #define EDMA_CHANNEL_ANY               -1      /* for edma_alloc_channel() */
 #define EDMA_SLOT_ANY                  -1      /* for edma_alloc_slot() */
+#define EDMA_CONT_PARAMS_ANY            1001
+#define EDMA_CONT_PARAMS_FIXED_EXACT    1002
+#define EDMA_CONT_PARAMS_FIXED_NOT_EXACT 1003
 
 /* alloc/free DMA channels and their dedicated parameter RAM slots */
 int edma_alloc_channel(int channel,
@@ -237,6 +240,10 @@ void edma_free_channel(unsigned channel);
 int edma_alloc_slot(unsigned ctlr, int slot);
 void edma_free_slot(unsigned slot);
 
+/* alloc/free a set of contiguous parameter RAM slots */
+int edma_alloc_cont_slots(unsigned ctlr, unsigned int id, int slot, int count);
+int edma_free_cont_slots(unsigned slot, int count);
+
 /* calls that operate on part of a parameter RAM slot */
 void edma_set_src(unsigned slot, dma_addr_t src_port,
                                enum address_mode mode, enum fifo_width);
This page took 0.027699 seconds and 5 git commands to generate.