mirror of https://github.com/thesofproject/sof.git
dma: simple i/f to control flow between platform and lib
Less globals. Path to dynamic dma discovery enabled on platforms that support it. Avoid linker issues as platform lib still keeps refs to dma array once probing is deferred (patch is coming). Signed-off-by: Marcin Maka <marcin.maka@linux.intel.com>
This commit is contained in:
parent
44c6402cb4
commit
a6c8c25438
|
@ -167,10 +167,25 @@ struct dma {
|
|||
uint32_t private_size;
|
||||
};
|
||||
|
||||
struct dma *dma_get(uint32_t dir, uint32_t caps, uint32_t dev, uint32_t flags);
|
||||
/**
|
||||
* \brief Plugs platform specific DMA array once initialized into the lib.
|
||||
*
|
||||
* Lib serves the DMAs to other FW elements by dma_get()
|
||||
*
|
||||
* \param[in] dma_array Array of DMAs.
|
||||
* \param[in] num_dmas Number of elements in dma_array.
|
||||
*/
|
||||
void dma_install(struct dma *dma_array, size_t num_dmas);
|
||||
|
||||
/* initialize all platform DMAC's */
|
||||
int dmac_init(void);
|
||||
/**
|
||||
* \brief API to request a platform DMAC.
|
||||
*
|
||||
* Users can request DMAC based on dev type, copy direction, capabilities
|
||||
* and access privilege.
|
||||
* For exclusive access, ret DMAC with no channels draining.
|
||||
* For shared access, ret DMAC with the least number of channels draining.
|
||||
*/
|
||||
struct dma *dma_get(uint32_t dir, uint32_t caps, uint32_t dev, uint32_t flags);
|
||||
|
||||
#define dma_set_drvdata(dma, data) \
|
||||
dma->private = data; \
|
||||
|
|
|
@ -32,57 +32,69 @@
|
|||
#include <sof/atomic.h>
|
||||
#include <platform/dma.h>
|
||||
|
||||
/*
|
||||
* API to request a platform DMAC.
|
||||
* Users can request DMAC based on dev type, copy direction, capabilities
|
||||
* and access privilege.
|
||||
* For exclusive access, ret DMAC with no channels draining.
|
||||
* For shared access, ret DMAC with the least number of channels draining.
|
||||
*/
|
||||
struct dma_info {
|
||||
struct dma *dma_array;
|
||||
size_t num_dmas;
|
||||
};
|
||||
|
||||
static struct dma_info lib_dma = {
|
||||
.dma_array = NULL,
|
||||
.num_dmas = 0
|
||||
};
|
||||
|
||||
void dma_install(struct dma *dma_array, size_t num_dmas)
|
||||
{
|
||||
lib_dma.dma_array = dma_array;
|
||||
lib_dma.num_dmas = num_dmas;
|
||||
}
|
||||
|
||||
struct dma *dma_get(uint32_t dir, uint32_t cap, uint32_t dev, uint32_t flags)
|
||||
{
|
||||
int i, ch_count;
|
||||
int ch_count;
|
||||
int min_ch_count = INT32_MAX;
|
||||
int dma_index = -1;
|
||||
|
||||
for (i = 0; i < PLATFORM_NUM_DMACS; i++) {
|
||||
struct dma *d = NULL, *dmin = NULL;
|
||||
|
||||
if (!lib_dma.num_dmas) {
|
||||
trace_error(TRACE_CLASS_DMA, "No DMAs installed");
|
||||
return NULL;
|
||||
}
|
||||
for (d = lib_dma.dma_array; d < lib_dma.dma_array + lib_dma.num_dmas;
|
||||
d++) {
|
||||
/* skip if this DMAC does not support the requested dir */
|
||||
if (dir && (dma[i].plat_data.dir & dir) == 0)
|
||||
if (dir && (d->plat_data.dir & dir) == 0)
|
||||
continue;
|
||||
|
||||
/* skip if this DMAC does not support the requested caps */
|
||||
if (cap && (dma[i].plat_data.caps & cap) == 0)
|
||||
if (cap && (d->plat_data.caps & cap) == 0)
|
||||
continue;
|
||||
|
||||
/* skip if this DMAC does not support the requested dev */
|
||||
if (dev && (dma[i].plat_data.devs & dev) == 0)
|
||||
if (dev && (d->plat_data.devs & dev) == 0)
|
||||
continue;
|
||||
|
||||
/* if exclusive access is requested */
|
||||
if (flags & DMA_ACCESS_EXCLUSIVE) {
|
||||
|
||||
/* ret DMA with no channels draining */
|
||||
if (!atomic_read(&dma[i].num_channels_busy))
|
||||
return &dma[i];
|
||||
if (!atomic_read(&d->num_channels_busy))
|
||||
return d;
|
||||
} else {
|
||||
|
||||
/* get number of channels draining in this DMAC*/
|
||||
ch_count = atomic_read(&dma[i].num_channels_busy);
|
||||
ch_count = atomic_read(&d->num_channels_busy);
|
||||
|
||||
/* pick DMAC with the least num of channels draining */
|
||||
if (ch_count < min_ch_count) {
|
||||
dma_index = i;
|
||||
dmin = d;
|
||||
min_ch_count = ch_count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* return DMAC */
|
||||
if (dma_index >= 0) {
|
||||
tracev_value(dma[dma_index].plat_data.id);
|
||||
return &dma[dma_index];
|
||||
if (dmin) {
|
||||
tracev_value(dmin->plat_data.id);
|
||||
return dmin;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
|
|
@ -37,8 +37,6 @@
|
|||
#include <arch/cache.h>
|
||||
#include <sof/dma.h>
|
||||
|
||||
#define PLATFORM_NUM_DMACS 6
|
||||
|
||||
/* available DMACs */
|
||||
#define DMA_GP_LP_DMAC0 0
|
||||
#define DMA_GP_LP_DMAC1 1
|
||||
|
@ -75,6 +73,6 @@
|
|||
#define DMA_HANDSHAKE_SSP5_TX 12
|
||||
#define DMA_HANDSHAKE_SSP5_RX 13
|
||||
|
||||
extern struct dma dma[PLATFORM_NUM_DMACS];
|
||||
int dmac_init(void);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -206,5 +206,8 @@ int dmac_init(void)
|
|||
}
|
||||
}
|
||||
|
||||
/* tell the lib DMAs are ready to use */
|
||||
dma_install(dma, ARRAY_SIZE(dma));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -60,6 +60,6 @@
|
|||
#define DMA_HANDSHAKE_SSP6_RX 12
|
||||
#define DMA_HANDSHAKE_SSP6_TX 13
|
||||
|
||||
extern struct dma dma[PLATFORM_NUM_DMACS];
|
||||
int dmac_init(void);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -35,8 +35,6 @@
|
|||
|
||||
#include <sof/dma.h>
|
||||
|
||||
#define PLATFORM_NUM_DMACS 6
|
||||
|
||||
/* available DMACs */
|
||||
#define DMA_GP_LP_DMAC0 0
|
||||
#define DMA_GP_LP_DMAC1 1
|
||||
|
@ -73,6 +71,6 @@
|
|||
#define DMA_HANDSHAKE_SSP5_TX 12
|
||||
#define DMA_HANDSHAKE_SSP5_RX 13
|
||||
|
||||
extern struct dma dma[PLATFORM_NUM_DMACS];
|
||||
int dmac_init(void);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -155,5 +155,8 @@ int dmac_init(void)
|
|||
io_reg_update_bits(SHIM_BASE + SHIM_IMRD,
|
||||
SHIM_IMRD_DMAC1, 0);
|
||||
|
||||
/* tell the lib DMAs are ready to use */
|
||||
dma_install(dma, ARRAY_SIZE(dma));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
#include <stdint.h>
|
||||
#include <sof/dma.h>
|
||||
|
||||
#define PLATFORM_NUM_DMACS 2
|
||||
#define PLATFORM_NUM_DMACS 2
|
||||
|
||||
#define DMA_ID_DMAC0 0
|
||||
#define DMA_ID_DMAC1 1
|
||||
|
@ -56,6 +56,6 @@
|
|||
#define DMA_HANDSHAKE_OBFF_10 14
|
||||
#define DMA_HANDSHAKE_OBFF_11 15
|
||||
|
||||
extern struct dma dma[PLATFORM_NUM_DMACS];
|
||||
int dmac_init(void);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -35,8 +35,6 @@
|
|||
|
||||
#include <sof/dma.h>
|
||||
|
||||
#define PLATFORM_NUM_DMACS 6
|
||||
|
||||
/* available DMACs */
|
||||
#define DMA_GP_LP_DMAC0 0
|
||||
#define DMA_GP_LP_DMAC1 1
|
||||
|
@ -73,6 +71,6 @@
|
|||
#define DMA_HANDSHAKE_SSP5_TX 12
|
||||
#define DMA_HANDSHAKE_SSP5_RX 13
|
||||
|
||||
extern struct dma dma[PLATFORM_NUM_DMACS];
|
||||
int dmac_init(void);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -40,6 +40,8 @@
|
|||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#define CAVS_PLATFORM_NUM_DMACS 6
|
||||
|
||||
#if defined(CONFIG_APOLLOLAKE)
|
||||
#define DMAC0_CLASS 1
|
||||
#define DMAC1_CLASS 2
|
||||
|
@ -124,7 +126,7 @@ static struct dw_drv_plat_data dmac1 = {
|
|||
},
|
||||
};
|
||||
|
||||
struct dma dma[PLATFORM_NUM_DMACS] = {
|
||||
static struct dma dma[CAVS_PLATFORM_NUM_DMACS] = {
|
||||
{ /* Low Power GP DMAC 0 */
|
||||
.plat_data = {
|
||||
.id = DMA_GP_LP_DMAC0,
|
||||
|
@ -222,5 +224,8 @@ int dmac_init(void)
|
|||
}
|
||||
}
|
||||
|
||||
/* tell the lib DMAs are ready to use */
|
||||
dma_install(dma, ARRAY_SIZE(dma));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue