mirror of https://github.com/thesofproject/sof.git
dma: Introduce new API for dma_get()
This patch introduces a new API for allocating DMAC's by taking into account the dma dev type, copy direction, capabilities and access control requested by the user. It also updates also users to use the new API. It also consolidates the new API in a common file for all platforms. Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
This commit is contained in:
parent
af3acc8b7f
commit
700197d49f
|
@ -65,6 +65,7 @@ sof_LDADD = \
|
|||
../../lib/libcore.a \
|
||||
../../platform/$(PLATFORM)/libplatform.a \
|
||||
../../ipc/libsof_ipc.a \
|
||||
../../lib/libdma.a \
|
||||
../../audio/libaudio.a \
|
||||
../../drivers/libdrivers.a \
|
||||
../../math/libsof_math.a \
|
||||
|
|
|
@ -176,6 +176,7 @@ static struct comp_dev *dai_new(struct sof_ipc_comp *comp)
|
|||
struct sof_ipc_comp_dai *dai;
|
||||
struct sof_ipc_comp_dai *ipc_dai = (struct sof_ipc_comp_dai *)comp;
|
||||
struct dai_data *dd;
|
||||
uint32_t dir, caps, dma_dev;
|
||||
|
||||
trace_dai("new");
|
||||
|
||||
|
@ -201,7 +202,11 @@ static struct comp_dev *dai_new(struct sof_ipc_comp *comp)
|
|||
goto error;
|
||||
}
|
||||
|
||||
dd->dma = dma_get(ipc_dai->dmac_id);
|
||||
/* request GP LP DMA with shared access privilege */
|
||||
dir = DMA_DIR_MEM_TO_DEV | DMA_DIR_DEV_TO_MEM;
|
||||
caps = DMA_CAP_GP_LP | DMA_CAP_GP_HP;
|
||||
dma_dev = DMA_DEV_SSP | DMA_DEV_DMIC;
|
||||
dd->dma = dma_get(dir, caps, dma_dev, DMA_ACCESS_SHARED);
|
||||
if (dd->dma == NULL) {
|
||||
trace_dai_error("eDd");
|
||||
goto error;
|
||||
|
|
|
@ -503,6 +503,7 @@ static struct comp_dev *host_new(struct sof_ipc_comp *comp)
|
|||
struct sof_ipc_comp_host *host;
|
||||
struct sof_ipc_comp_host *ipc_host = (struct sof_ipc_comp_host *)comp;
|
||||
struct dma_sg_elem *elem;
|
||||
uint32_t dir, caps, dma_dev;
|
||||
|
||||
trace_host("new");
|
||||
|
||||
|
@ -529,15 +530,15 @@ static struct comp_dev *host_new(struct sof_ipc_comp *comp)
|
|||
|
||||
comp_set_drvdata(dev, hd);
|
||||
|
||||
#if !defined CONFIG_DMA_GW
|
||||
hd->dma = dma_get(ipc_host->dmac_id);
|
||||
#else
|
||||
/* request HDA DMA with shared access privilege */
|
||||
if (ipc_host->direction == SOF_IPC_STREAM_PLAYBACK)
|
||||
hd->dma = dma_get(DMA_HOST_OUT_DMAC);
|
||||
dir = DMA_DIR_HMEM_TO_LMEM;
|
||||
else
|
||||
hd->dma = dma_get(DMA_HOST_IN_DMAC);
|
||||
#endif
|
||||
dir = DMA_DIR_LMEM_TO_HMEM;
|
||||
|
||||
caps = 0;
|
||||
dma_dev = DMA_DEV_HDA;
|
||||
hd->dma = dma_get(dir, caps, dma_dev, DMA_ACCESS_SHARED);
|
||||
if (hd->dma == NULL) {
|
||||
trace_host_error("eDM");
|
||||
goto error;
|
||||
|
|
|
@ -200,7 +200,7 @@ struct dai *dai_get(uint32_t type, uint32_t index)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
struct dma *dma_get(int dmac_id)
|
||||
struct dma *dma_get(uint32_t dir, uint32_t caps, uint32_t dev, uint32_t flags)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -56,6 +56,10 @@
|
|||
#define DMA_DEV_SSP (1 << 1)
|
||||
#define DMA_DEV_DMIC (1 << 2)
|
||||
|
||||
/* DMA access privilege flag */
|
||||
#define DMA_ACCESS_EXCLUSIVE 1
|
||||
#define DMA_ACCESS_SHARED 0
|
||||
|
||||
/* DMA IRQ types */
|
||||
#define DMA_IRQ_TYPE_BLOCK (1 << 0)
|
||||
#define DMA_IRQ_TYPE_LLIST (1 << 1)
|
||||
|
@ -150,7 +154,7 @@ struct dma_int {
|
|||
uint32_t irq;
|
||||
};
|
||||
|
||||
struct dma *dma_get(int dmac_id);
|
||||
struct dma *dma_get(uint32_t dir, uint32_t caps, uint32_t dev, uint32_t flags);
|
||||
|
||||
/* initialize all platform DMAC's */
|
||||
int dmac_init(void);
|
||||
|
|
|
@ -177,6 +177,7 @@ out:
|
|||
int platform_ipc_init(struct ipc *ipc)
|
||||
{
|
||||
struct intel_ipc_data *iipc;
|
||||
uint32_t dir, caps, dev;
|
||||
int i;
|
||||
|
||||
_ipc = ipc;
|
||||
|
@ -198,8 +199,11 @@ int platform_ipc_init(struct ipc *ipc)
|
|||
if (iipc->page_table)
|
||||
bzero(iipc->page_table, HOST_PAGE_SIZE);
|
||||
|
||||
/* dma */
|
||||
iipc->dmac = dma_get(DMA_GP_LP_DMAC0);
|
||||
/* request GP DMA with shared access privilege */
|
||||
caps = 0;
|
||||
dir = DMA_DIR_HMEM_TO_LMEM;
|
||||
dev = DMA_DEV_HDA;
|
||||
iipc->dmac = dma_get(dir, caps, dev, DMA_ACCESS_SHARED);
|
||||
|
||||
/* PM */
|
||||
iipc->pm_prepare_D3 = 0;
|
||||
|
|
|
@ -202,7 +202,7 @@ out:
|
|||
int platform_ipc_init(struct ipc *ipc)
|
||||
{
|
||||
struct intel_ipc_data *iipc;
|
||||
uint32_t imrd;
|
||||
uint32_t imrd, dir, caps, dev;
|
||||
int i;
|
||||
|
||||
_ipc = ipc;
|
||||
|
@ -225,8 +225,11 @@ int platform_ipc_init(struct ipc *ipc)
|
|||
if (iipc->page_table)
|
||||
bzero(iipc->page_table, PLATFORM_PAGE_TABLE_SIZE);
|
||||
|
||||
/* dma */
|
||||
iipc->dmac = dma_get(DMA_ID_DMAC0);
|
||||
/* request HDA DMA with shared access privilege */
|
||||
caps = 0;
|
||||
dir = DMA_DIR_HMEM_TO_LMEM;
|
||||
dev = DMA_DEV_HDA;
|
||||
iipc->dmac = dma_get(dir, caps, dev, DMA_ACCESS_SHARED);
|
||||
|
||||
/* PM */
|
||||
iipc->pm_prepare_D3 = 0;
|
||||
|
|
|
@ -177,6 +177,7 @@ out:
|
|||
int platform_ipc_init(struct ipc *ipc)
|
||||
{
|
||||
struct intel_ipc_data *iipc;
|
||||
uint32_t dir, caps, dev;
|
||||
int i;
|
||||
|
||||
_ipc = ipc;
|
||||
|
@ -198,8 +199,11 @@ int platform_ipc_init(struct ipc *ipc)
|
|||
if (iipc->page_table)
|
||||
bzero(iipc->page_table, HOST_PAGE_SIZE);
|
||||
|
||||
/* dma */
|
||||
iipc->dmac = dma_get(DMA_GP_LP_DMAC0);
|
||||
/* request GP DMA with shared access privilege */
|
||||
caps = 0;
|
||||
dir = DMA_DIR_HMEM_TO_LMEM;
|
||||
dev = DMA_DEV_HDA;
|
||||
iipc->dmac = dma_get(dir, caps, dev, DMA_ACCESS_SHARED);
|
||||
|
||||
/* PM */
|
||||
iipc->pm_prepare_D3 = 0;
|
||||
|
|
|
@ -375,7 +375,13 @@ int dma_copy_from_host_nowait(struct dma_copy *dc, struct dma_sg_config *host_sg
|
|||
|
||||
int dma_copy_new(struct dma_copy *dc, int dmac)
|
||||
{
|
||||
dc->dmac = dma_get(dmac);
|
||||
uint32_t dir, cap, dev;
|
||||
|
||||
/* request HDA DMA in the dir LMEM->HMEM with shared access */
|
||||
dir = DMA_DIR_LMEM_TO_HMEM;
|
||||
dev = DMA_DEV_HDA;
|
||||
cap = 0;
|
||||
dc->dmac = dma_get(dir, cap, dev, DMA_ACCESS_SHARED);
|
||||
if (dc->dmac == NULL) {
|
||||
trace_dma_error("ec0");
|
||||
return -ENODEV;
|
||||
|
|
|
@ -198,7 +198,7 @@ out:
|
|||
int platform_ipc_init(struct ipc *ipc)
|
||||
{
|
||||
struct intel_ipc_data *iipc;
|
||||
uint32_t imrd;
|
||||
uint32_t imrd, dir, caps, dev;
|
||||
int i;
|
||||
|
||||
_ipc = ipc;
|
||||
|
@ -221,8 +221,11 @@ int platform_ipc_init(struct ipc *ipc)
|
|||
if (iipc->page_table)
|
||||
bzero(iipc->page_table, PLATFORM_PAGE_TABLE_SIZE);
|
||||
|
||||
/* dma */
|
||||
iipc->dmac = dma_get(DMA_ID_DMAC1);
|
||||
/* request GP DMA with shared access privilege */
|
||||
caps = 0;
|
||||
dir = DMA_DIR_HMEM_TO_LMEM;
|
||||
dev = DMA_DEV_HDA;
|
||||
iipc->dmac = dma_get(dir, caps, dev, DMA_ACCESS_SHARED);
|
||||
|
||||
/* PM */
|
||||
iipc->pm_prepare_D3 = 0;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
noinst_LIBRARIES = libcore.a
|
||||
noinst_LIBRARIES = libcore.a libdma.a
|
||||
|
||||
libcore_a_SOURCES = \
|
||||
lib.c \
|
||||
|
@ -16,3 +16,12 @@ libcore_a_CFLAGS = \
|
|||
$(ARCH_INCDIR) \
|
||||
$(SOF_INCDIR) \
|
||||
$(PLATFORM_INCDIR)
|
||||
|
||||
libdma_a_SOURCES = \
|
||||
dma.c
|
||||
|
||||
libdma_a_CFLAGS = \
|
||||
$(ARCH_CFLAGS) \
|
||||
$(ARCH_INCDIR) \
|
||||
$(SOF_INCDIR) \
|
||||
$(PLATFORM_INCDIR)
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the Intel Corporation nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Author: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
|
||||
*/
|
||||
|
||||
#include <sof/dma.h>
|
||||
#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 *dma_get(uint32_t dir, uint32_t cap, uint32_t dev, uint32_t flags)
|
||||
{
|
||||
int i, ch_count;
|
||||
int min_ch_count = INT32_MAX;
|
||||
int dma_index = -1;
|
||||
|
||||
for (i = 0; i < PLATFORM_NUM_DMACS; i++) {
|
||||
|
||||
/* skip if this DMAC does not support the requested dir */
|
||||
if (dir && (dma[i].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)
|
||||
continue;
|
||||
|
||||
/* skip if this DMAC does not support the requested dev */
|
||||
if (dev && (dma[i].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];
|
||||
} else {
|
||||
|
||||
/* get number of channels draining in this DMAC*/
|
||||
ch_count = atomic_read(&dma[i].num_channels_busy);
|
||||
|
||||
/* pick DMAC with the least num of channels draining */
|
||||
if (ch_count < min_ch_count) {
|
||||
dma_index = i;
|
||||
min_ch_count = ch_count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* return DMAC */
|
||||
if (dma_index >= 0) {
|
||||
tracev_value(dma[dma_index].plat_data.id);
|
||||
return &dma[dma_index];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
|
@ -190,18 +190,6 @@ struct dma dma[PLATFORM_NUM_DMACS] = {
|
|||
.ops = &hda_link_dma_ops,
|
||||
},};
|
||||
|
||||
struct dma *dma_get(int dmac_id)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(dma); i++) {
|
||||
if (dma[i].plat_data.id == dmac_id)
|
||||
return &dma[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Initialize all platform DMAC's */
|
||||
int dmac_init(void)
|
||||
{
|
||||
|
|
|
@ -190,18 +190,6 @@ struct dma dma[PLATFORM_NUM_DMACS] = {
|
|||
#endif
|
||||
};
|
||||
|
||||
struct dma *dma_get(int dmac_id)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(dma); i++) {
|
||||
if (dma[i].plat_data.id == dmac_id)
|
||||
return &dma[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Initialize all platform DMAC's */
|
||||
int dmac_init(void)
|
||||
{
|
||||
|
|
|
@ -191,18 +191,6 @@ struct dma dma[PLATFORM_NUM_DMACS] = {
|
|||
.ops = &hda_link_dma_ops,
|
||||
},};
|
||||
|
||||
struct dma *dma_get(int dmac_id)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(dma); i++) {
|
||||
if (dma[i].plat_data.id == dmac_id)
|
||||
return &dma[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Initialize all platform DMAC's */
|
||||
int dmac_init(void)
|
||||
{
|
||||
|
|
|
@ -132,18 +132,6 @@ struct dma dma[PLATFORM_NUM_DMACS] = {
|
|||
.ops = &dw_dma_ops,
|
||||
},};
|
||||
|
||||
struct dma *dma_get(int dmac_id)
|
||||
{
|
||||
switch (dmac_id) {
|
||||
case DMA_ID_DMAC0:
|
||||
return &dma[0];
|
||||
case DMA_ID_DMAC1:
|
||||
return &dma[1];
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialize all platform DMAC's */
|
||||
int dmac_init(void)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue