DaVinci: EDMA: Adding 2 new APIs for allocating/freeing PARAMs

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>
This commit is contained in:
Sandeep Paulraj 2009-07-27 15:10:36 -04:00 committed by Kevin Hilman
parent 0c30e0d31b
commit 213765d7b4
2 changed files with 144 additions and 0 deletions

View 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 */

View 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);