This patch introduces a new API for allocating DMAC's by taking into account the dma copy capability and access control requested by the user.
At the moment, all users use the shared access privilege for requesting DMAC but this might change in future.
Signed-off-by: Ranjani Sridharan ranjani.sridharan@linux.intel.com --- src/arch/xtensa/Makefile.am | 1 + src/include/sof/dma.h | 4 ++ src/lib/Makefile.am | 11 +++++ src/lib/dma.c | 80 +++++++++++++++++++++++++++++++++++ src/platform/apollolake/dma.c | 12 ------ src/platform/baytrail/dma.c | 12 ------ src/platform/cannonlake/dma.c | 12 ------ src/platform/haswell/dma.c | 12 ------ 8 files changed, 96 insertions(+), 48 deletions(-) create mode 100644 src/lib/dma.c
diff --git a/src/arch/xtensa/Makefile.am b/src/arch/xtensa/Makefile.am index 4ffe15f..88dc8c6 100644 --- a/src/arch/xtensa/Makefile.am +++ b/src/arch/xtensa/Makefile.am @@ -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 \ diff --git a/src/include/sof/dma.h b/src/include/sof/dma.h index 0babbd3..cef5e02 100644 --- a/src/include/sof/dma.h +++ b/src/include/sof/dma.h @@ -64,6 +64,10 @@ enum dma_copy_dir { #define DMA_CAP_HDA_HOST (1 << 8) #define DMA_CAP_HDA_LINK (1 << 9)
+/* 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) diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am index 825bfbd..28f8f6f 100644 --- a/src/lib/Makefile.am +++ b/src/lib/Makefile.am @@ -16,3 +16,14 @@ libcore_a_CFLAGS = \ $(ARCH_INCDIR) \ $(SOF_INCDIR) \ $(PLATFORM_INCDIR) + +noinst_LIBRARIES = libdma.a + +libdma_a_SOURCES = \ + dma.c + +libdma_a_CFLAGS = \ + $(ARCH_CFLAGS) \ + $(ARCH_INCDIR) \ + $(SOF_INCDIR) \ + $(PLATFORM_INCDIR) diff --git a/src/lib/dma.c b/src/lib/dma.c new file mode 100644 index 0000000..f4f9b40 --- /dev/null +++ b/src/lib/dma.c @@ -0,0 +1,80 @@ +/* + * 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 type, copy 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 dma_cap, 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 cap */ + if ((dma[i].plat_data.dma_cap & dma_cap) != dma_cap) + 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; +} diff --git a/src/platform/apollolake/dma.c b/src/platform/apollolake/dma.c index 9790ed8..acabc5b 100644 --- a/src/platform/apollolake/dma.c +++ b/src/platform/apollolake/dma.c @@ -180,18 +180,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) { diff --git a/src/platform/baytrail/dma.c b/src/platform/baytrail/dma.c index 04ed41a..ca7350a 100644 --- a/src/platform/baytrail/dma.c +++ b/src/platform/baytrail/dma.c @@ -190,18 +190,6 @@ struct dma dma[] = { #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) { diff --git a/src/platform/cannonlake/dma.c b/src/platform/cannonlake/dma.c index eadc475..9fb50a9 100644 --- a/src/platform/cannonlake/dma.c +++ b/src/platform/cannonlake/dma.c @@ -181,18 +181,6 @@ struct dma dma[] = { .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) { diff --git a/src/platform/haswell/dma.c b/src/platform/haswell/dma.c index 35c88be..d1039fb 100644 --- a/src/platform/haswell/dma.c +++ b/src/platform/haswell/dma.c @@ -131,18 +131,6 @@ struct dma dma[] = { .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) {