[Sound-open-firmware] [PATCH v4 0/5] New API for dma_get()
This set of patches proposes a new API for dma_get() that procures a DMAC based on the requested copy dir, caps, dev type and flags indicating shared/exclusive access. It also updates the existing user of dma_get() to use the new API based on the specific usage. The API uses the number of channels draning in each DMAC to balance the load between the platform DMAC's for users requesting shared access privilege. This provides a primitive level of QoS and prevents overloading any DMAC.
The platform DMAC definitions have also been updated to include information about copy capabilities supported and the type of DMA.
Test Results: 1. Minnowboard Turbot w 5651: Passed all feature tests 2. Up Squared Board w Hifiberry DAC+: Passed all playback feature tests
v4 changes: 1. Modified platform DMAC definition with copy cap, copy dir dev types supported 2. Modified dma_get() API to request DMAC based on above criteria
Ranjani Sridharan (5): platform: dma: move dmac initialization dma: update platform DMAC definitions with the supported dev types, dir and capabilities dma: introduce parameter to store the number of channels draining dma: Introduce new API for dma_get() dma:trace: dma_copy_new() does not need DMAC ID anymore
src/arch/xtensa/Makefile.am | 1 + src/audio/dai.c | 7 +- src/audio/host.c | 14 +-- src/drivers/dw-dma.c | 13 ++- src/drivers/hda-dma.c | 10 ++- src/host/common_test.c | 2 +- src/include/sof/dma.h | 43 ++++++--- src/ipc/apl-ipc.c | 8 +- src/ipc/byt-ipc.c | 9 +- src/ipc/cnl-ipc.c | 8 +- src/ipc/dma-copy.c | 10 ++- src/ipc/hsw-ipc.c | 9 +- src/lib/Makefile.am | 11 ++- src/lib/dma-trace.c | 2 +- src/lib/dma.c | 89 +++++++++++++++++++ src/platform/apollolake/dma.c | 39 ++++++-- .../apollolake/include/platform/dma.h | 5 ++ .../apollolake/include/platform/platform.h | 3 - src/platform/apollolake/platform.c | 22 +---- src/platform/baytrail/dma.c | 34 +++++-- src/platform/baytrail/include/platform/dma.h | 9 ++ .../baytrail/include/platform/platform.h | 3 - src/platform/baytrail/platform.c | 23 +---- src/platform/cannonlake/dma.c | 39 ++++++-- .../cannonlake/include/platform/dma.h | 6 ++ .../cannonlake/include/platform/platform.h | 3 - src/platform/cannonlake/platform.c | 23 +---- src/platform/haswell/dma.c | 40 +++++++-- src/platform/haswell/include/platform/dma.h | 5 ++ .../haswell/include/platform/platform.h | 3 - src/platform/haswell/platform.c | 21 +---- 31 files changed, 362 insertions(+), 152 deletions(-) create mode 100644 src/lib/dma.c
This patch proposes to move the platform DMAC initialization code to the dmac_init() routine.
Signed-off-by: Ranjani Sridharan ranjani.sridharan@linux.intel.com --- src/include/sof/dma.h | 3 +++ src/platform/apollolake/dma.c | 19 +++++++++++++++++++ src/platform/apollolake/platform.c | 22 +++------------------- src/platform/baytrail/dma.c | 19 +++++++++++++++++++ src/platform/baytrail/platform.c | 23 +++-------------------- src/platform/cannonlake/dma.c | 19 +++++++++++++++++++ src/platform/cannonlake/platform.c | 23 +++-------------------- src/platform/haswell/dma.c | 26 ++++++++++++++++++++++++++ src/platform/haswell/platform.c | 21 +++------------------ 9 files changed, 98 insertions(+), 77 deletions(-)
diff --git a/src/include/sof/dma.h b/src/include/sof/dma.h index 7ba1298..af15d14 100644 --- a/src/include/sof/dma.h +++ b/src/include/sof/dma.h @@ -140,6 +140,9 @@ struct dma_int {
struct dma *dma_get(int dmac_id);
+/* initialize all platform DMAC's */ +int dmac_init(void); + #define dma_set_drvdata(dma, data) \ dma->private = data #define dma_get_drvdata(dma) \ diff --git a/src/platform/apollolake/dma.c b/src/platform/apollolake/dma.c index 90dde96..00d19d5 100644 --- a/src/platform/apollolake/dma.c +++ b/src/platform/apollolake/dma.c @@ -181,3 +181,22 @@ struct dma *dma_get(int dmac_id)
return NULL; } + +/* Initialize all platform DMAC's */ +int dmac_init(void) +{ + int i, ret; + + for (i = 0; i < ARRAY_SIZE(dma); i++) { + ret = dma_probe(&dma[i]); + if (ret < 0) { + + /* trace failed DMAC ID */ + trace_error(TRACE_CLASS_DMA, "edi"); + trace_error_value(dma[i].plat_data.id); + return ret; + } + } + + return 0; +} diff --git a/src/platform/apollolake/platform.c b/src/platform/apollolake/platform.c index 0b26ae5..a523b46 100644 --- a/src/platform/apollolake/platform.c +++ b/src/platform/apollolake/platform.c @@ -186,10 +186,9 @@ static void platform_memory_windows_init(void)
int platform_init(struct sof *sof) { - struct dma *dmac; struct dai *ssp; struct dai *dmic0; - int i; + int i, ret;
platform_interrupt_init();
@@ -244,25 +243,10 @@ int platform_init(struct sof *sof)
/* init DMACs */ trace_point(TRACE_BOOT_PLATFORM_DMA); - dmac = dma_get(DMA_GP_LP_DMAC0); - if (dmac == NULL) + ret = dmac_init(); + if (ret < 0) return -ENODEV; - dma_probe(dmac);
- dmac = dma_get(DMA_GP_LP_DMAC1); - if (dmac == NULL) - return -ENODEV; - dma_probe(dmac); - - dmac = dma_get(DMA_HOST_OUT_DMAC); - if (dmac == NULL) - return -ENODEV; - dma_probe(dmac); - - dmac = dma_get(DMA_HOST_IN_DMAC); - if (dmac == NULL) - return -ENODEV; - dma_probe(dmac);
/* init SSP ports */ trace_point(TRACE_BOOT_PLATFORM_SSP); diff --git a/src/platform/baytrail/dma.c b/src/platform/baytrail/dma.c index 53602f5..78fbf14 100644 --- a/src/platform/baytrail/dma.c +++ b/src/platform/baytrail/dma.c @@ -186,3 +186,22 @@ struct dma *dma_get(int dmac_id)
return NULL; } + +/* Initialize all platform DMAC's */ +int dmac_init(void) +{ + int i, ret; + + for (i = 0; i < ARRAY_SIZE(dma); i++) { + ret = dma_probe(&dma[i]); + if (ret < 0) { + + /* trace failed DMAC ID */ + trace_error(TRACE_CLASS_DMA, "edi"); + trace_error_value(dma[i].plat_data.id); + return ret; + } + } + + return 0; +} diff --git a/src/platform/baytrail/platform.c b/src/platform/baytrail/platform.c index 562fabf..3b0d381 100644 --- a/src/platform/baytrail/platform.c +++ b/src/platform/baytrail/platform.c @@ -290,15 +290,10 @@ void platform_interrupt_unmask(uint32_t irq, uint32_t mask) int platform_init(struct sof *sof) { #if defined CONFIG_BAYTRAIL - struct dma *dmac0; - struct dma *dmac1; struct dai *ssp0; struct dai *ssp1; struct dai *ssp2; #elif defined CONFIG_CHERRYTRAIL - struct dma *dmac0; - struct dma *dmac1; - struct dma *dmac2; struct dai *ssp0; struct dai *ssp1; struct dai *ssp2; @@ -308,6 +303,7 @@ int platform_init(struct sof *sof) #else #error Undefined platform #endif + int ret;
trace_point(TRACE_BOOT_PLATFORM_MBOX);
@@ -356,22 +352,9 @@ int platform_init(struct sof *sof)
/* init DMACs */ trace_point(TRACE_BOOT_PLATFORM_DMA); - dmac0 = dma_get(DMA_ID_DMAC0); - if (dmac0 == NULL) + ret = dmac_init(); + if (ret < 0) return -ENODEV; - dma_probe(dmac0); - - dmac1 = dma_get(DMA_ID_DMAC1); - if (dmac1 == NULL) - return -ENODEV; - dma_probe(dmac1); - -#if defined CONFIG_CHERRYTRAIL - dmac2 = dma_get(DMA_ID_DMAC1); - if (dmac2 == NULL) - return -ENODEV; - dma_probe(dmac2); -#endif
/* mask SSP 0 - 2 interrupts */ shim_write(SHIM_PIMR, shim_read(SHIM_PIMR) | 0x00000038); diff --git a/src/platform/cannonlake/dma.c b/src/platform/cannonlake/dma.c index 3f9d6cb..c560b86 100644 --- a/src/platform/cannonlake/dma.c +++ b/src/platform/cannonlake/dma.c @@ -182,3 +182,22 @@ struct dma *dma_get(int dmac_id)
return NULL; } + +/* Initialize all platform DMAC's */ +int dmac_init(void) +{ + int i, ret; + + for (i = 0; i < ARRAY_SIZE(dma); i++) { + ret = dma_probe(&dma[i]); + if (ret < 0) { + + /* trace failed DMAC ID */ + trace_error(TRACE_CLASS_DMA, "edi"); + trace_error_value(dma[i].plat_data.id); + return ret; + } + } + + return 0; +} diff --git a/src/platform/cannonlake/platform.c b/src/platform/cannonlake/platform.c index 2e85088..54c146c 100644 --- a/src/platform/cannonlake/platform.c +++ b/src/platform/cannonlake/platform.c @@ -208,10 +208,9 @@ static struct timer platform_ext_timer = {
int platform_init(struct sof *sof) { - struct dma *dmac; struct dai *ssp; struct dai *dmic0; - int i; + int i, ret;
trace_point(TRACE_BOOT_PLATFORM_ENTRY); platform_init_hw(); @@ -261,25 +260,9 @@ int platform_init(struct sof *sof)
/* init DMACs */ trace_point(TRACE_BOOT_PLATFORM_DMA); - dmac = dma_get(DMA_GP_LP_DMAC0); - if (!dmac) + ret = dmac_init(); + if (ret < 0) return -ENODEV; - dma_probe(dmac); - - dmac = dma_get(DMA_GP_LP_DMAC1); - if (!dmac) - return -ENODEV; - dma_probe(dmac); - - dmac = dma_get(DMA_HOST_OUT_DMAC); - if (!dmac) - return -ENODEV; - dma_probe(dmac); - - dmac = dma_get(DMA_HOST_IN_DMAC); - if (!dmac) - return -ENODEV; - dma_probe(dmac);
/* init SSP ports */ trace_point(TRACE_BOOT_PLATFORM_SSP); diff --git a/src/platform/haswell/dma.c b/src/platform/haswell/dma.c index 42df546..0ae935d 100644 --- a/src/platform/haswell/dma.c +++ b/src/platform/haswell/dma.c @@ -135,3 +135,29 @@ struct dma *dma_get(int dmac_id) return NULL; } } + +/* Initialize all platform DMAC's */ +int dmac_init(void) +{ + int i, ret; + + for (i = 0; i < ARRAY_SIZE(dma); i++) { + ret = dma_probe(&dma[i]); + if (ret < 0) { + + /* trace failed DMAC ID */ + trace_error(TRACE_CLASS_DMA, "edi"); + trace_error_value(dma[i].plat_data.id); + return ret; + } + } + + /* clear the masks for dsp of the dmacs */ + io_reg_update_bits(SHIM_BASE + SHIM_IMRD, + SHIM_IMRD_DMAC0, 0); + + io_reg_update_bits(SHIM_BASE + SHIM_IMRD, + SHIM_IMRD_DMAC1, 0); + + return 0; +} diff --git a/src/platform/haswell/platform.c b/src/platform/haswell/platform.c index 81ce67a..0c0bf06 100644 --- a/src/platform/haswell/platform.c +++ b/src/platform/haswell/platform.c @@ -240,10 +240,9 @@ static void platform_init_shim(void)
int platform_init(struct sof *sof) { - struct dma *dmac0; - struct dma *dmac1; struct dai *ssp0; struct dai *ssp1; + int ret;
trace_point(TRACE_BOOT_PLATFORM_MBOX);
@@ -280,23 +279,9 @@ int platform_init(struct sof *sof)
/* init DMACs */ trace_point(TRACE_BOOT_PLATFORM_DMA); - dmac0 = dma_get(DMA_ID_DMAC0); - if (dmac0 == NULL) + ret = dmac_init(); + if (ret < 0) return -ENODEV; - dma_probe(dmac0); - - /* clear the masks for dsp of the dmac*/ - io_reg_update_bits(SHIM_BASE + SHIM_IMRD, - SHIM_IMRD_DMAC0, 0); - - dmac1 = dma_get(DMA_ID_DMAC1); - if (dmac1 == NULL) - return -ENODEV; - dma_probe(dmac1); - - /* clear the masks for dsp of the dmac*/ - io_reg_update_bits(SHIM_BASE + SHIM_IMRD, - SHIM_IMRD_DMAC1, 0);
/* init SSP ports */ trace_point(TRACE_BOOT_PLATFORM_SSP);
This patch updates the platform DMAC definitions to include information about the supported dev types, copy directions and capabilities.
It also replaces the copy_dir enum with a bitmask and adds the copy capabilities and dev type bitmasks.
Signed-off-by: Ranjani Sridharan ranjani.sridharan@linux.intel.com --- src/audio/host.c | 1 + src/drivers/dw-dma.c | 2 +- src/drivers/hda-dma.c | 2 +- src/include/sof/dma.h | 30 ++++++++++++------- src/platform/apollolake/dma.c | 22 +++++++++++++- .../apollolake/include/platform/dma.h | 5 ++++ src/platform/baytrail/dma.c | 17 ++++++++++- src/platform/baytrail/include/platform/dma.h | 9 ++++++ src/platform/cannonlake/dma.c | 22 +++++++++++++- .../cannonlake/include/platform/dma.h | 6 ++++ src/platform/haswell/dma.c | 10 ++++++- src/platform/haswell/include/platform/dma.h | 5 ++++ 12 files changed, 115 insertions(+), 16 deletions(-)
diff --git a/src/audio/host.c b/src/audio/host.c index c0f4e1b..0285e4a 100644 --- a/src/audio/host.c +++ b/src/audio/host.c @@ -537,6 +537,7 @@ static struct comp_dev *host_new(struct sof_ipc_comp *comp) else hd->dma = dma_get(DMA_HOST_IN_DMAC); #endif + if (hd->dma == NULL) { trace_host_error("eDM"); goto error; diff --git a/src/drivers/dw-dma.c b/src/drivers/dw-dma.c index c064330..70ddb96 100644 --- a/src/drivers/dw-dma.c +++ b/src/drivers/dw-dma.c @@ -249,7 +249,7 @@ /* data for each DMA channel */ struct dma_chan_data { uint32_t status; - enum dma_copy_dir direction; + uint32_t direction; struct dw_lli2 *lli; struct dw_lli2 *lli_current; uint32_t desc_count; diff --git a/src/drivers/hda-dma.c b/src/drivers/hda-dma.c index 97ea0ef..bef0b17 100644 --- a/src/drivers/hda-dma.c +++ b/src/drivers/hda-dma.c @@ -84,7 +84,7 @@ struct hda_chan_data { uint32_t status; uint32_t desc_count; uint32_t desc_avail; - enum dma_copy_dir direction; + uint32_t direction; };
struct dma_pdata { diff --git a/src/include/sof/dma.h b/src/include/sof/dma.h index af15d14..fd0024f 100644 --- a/src/include/sof/dma.h +++ b/src/include/sof/dma.h @@ -38,15 +38,22 @@ #include <sof/sof.h> #include <sof/wait.h>
-/* types of DMA directions */ -enum dma_copy_dir { - DMA_DIR_MEM_TO_MEM = 0, /* local memcpy */ - DMA_DIR_HMEM_TO_LMEM, /* host to local memcpy */ - DMA_DIR_LMEM_TO_HMEM, /* local to host memcpy */ - DMA_DIR_MEM_TO_DEV, - DMA_DIR_DEV_TO_MEM, - DMA_DIR_DEV_TO_DEV, -}; +/* DMA direction bitmasks used to define DMA copy direction */ +#define DMA_DIR_MEM_TO_MEM (1 << 0) /* local memory copy */ +#define DMA_DIR_HMEM_TO_LMEM (1 << 1) /* host memory to local mem copy */ +#define DMA_DIR_LMEM_TO_HMEM (1 << 2) /* local mem to host mem copy */ +#define DMA_DIR_MEM_TO_DEV (1 << 3) /* local mem to dev copy */ +#define DMA_DIR_DEV_TO_MEM (1 << 4) /* dev to local mem copy */ +#define DMA_DIR_DEV_TO_DEV (1 << 5) /* dev to dev copy */ + +/* DMA capabilities bitmasks used to define the type of DMA */ +#define DMA_CAP_GP_LP (1 << 0) +#define DMA_CAP_GP_HP (1 << 1) + +/* DMA dev type bitmasks used to define the type of DMA */ +#define DMA_DEV_HDA (1 << 0) +#define DMA_DEV_SSP (1 << 1) +#define DMA_DEV_DMIC (1 << 2)
/* DMA IRQ types */ #define DMA_IRQ_TYPE_BLOCK (1 << 0) @@ -73,7 +80,7 @@ struct dma_sg_config { uint32_t src_width; /* in bytes */ uint32_t dest_width; /* in bytes */ uint32_t burst_elems; - enum dma_copy_dir direction; + uint32_t direction; uint32_t src_dev; uint32_t dest_dev; uint32_t cyclic; /* circular buffer */ @@ -118,6 +125,9 @@ struct dma_ops { /* DMA platform data */ struct dma_plat_data { uint32_t id; + uint32_t dir; /* bitmask of supported copy directions */ + uint32_t caps; /* bitmask of supported capabilities */ + uint32_t devs; /* bitmask of supported devs */ uint32_t base; uint32_t channels; uint32_t irq; diff --git a/src/platform/apollolake/dma.c b/src/platform/apollolake/dma.c index 00d19d5..b014259 100644 --- a/src/platform/apollolake/dma.c +++ b/src/platform/apollolake/dma.c @@ -108,10 +108,14 @@ static struct dw_drv_plat_data dmac1 = { }, };
-static struct dma dma[] = { +struct dma dma[PLATFORM_NUM_DMACS] = { { /* Low Power GP DMAC 0 */ .plat_data = { .id = DMA_GP_LP_DMAC0, + .dir = DMA_DIR_MEM_TO_MEM | DMA_DIR_MEM_TO_DEV | + DMA_DIR_DEV_TO_MEM | DMA_DIR_DEV_TO_DEV, + .caps = DMA_CAP_GP_LP | DMA_CAP_GP_HP, + .devs = DMA_DEV_SSP | DMA_DEV_DMIC, .base = LP_GP_DMA_BASE(0), .channels = 8, .irq = IRQ_EXT_LP_GPDMA0_LVL5(0, 0), @@ -122,6 +126,10 @@ static struct dma dma[] = { { /* Low Power GP DMAC 1 */ .plat_data = { .id = DMA_GP_LP_DMAC1, + .dir = DMA_DIR_MEM_TO_MEM | DMA_DIR_MEM_TO_DEV | + DMA_DIR_DEV_TO_MEM | DMA_DIR_DEV_TO_DEV, + .caps = DMA_CAP_GP_LP | DMA_CAP_GP_HP, + .devs = DMA_DEV_SSP | DMA_DEV_DMIC, .base = LP_GP_DMA_BASE(1), .channels = 8, .irq = IRQ_EXT_LP_GPDMA1_LVL5(0, 0), @@ -132,6 +140,9 @@ static struct dma dma[] = { { /* Host In DMAC */ .plat_data = { .id = DMA_HOST_IN_DMAC, + .dir = DMA_DIR_LMEM_TO_HMEM, + .caps = 0, + .devs = DMA_DEV_HDA, .base = GTW_HOST_IN_STREAM_BASE(0), .channels = 7, .irq = IRQ_EXT_HOST_DMA_IN_LVL3(0, 0), @@ -142,6 +153,9 @@ static struct dma dma[] = { { /* Host out DMAC */ .plat_data = { .id = DMA_HOST_OUT_DMAC, + .dir = DMA_DIR_HMEM_TO_LMEM, + .caps = 0, + .devs = DMA_DEV_HDA, .base = GTW_HOST_OUT_STREAM_BASE(0), .channels = 6, .irq = IRQ_EXT_HOST_DMA_OUT_LVL3(0, 0), @@ -152,6 +166,9 @@ static struct dma dma[] = { { /* Link In DMAC */ .plat_data = { .id = DMA_LINK_IN_DMAC, + .dir = DMA_DIR_MEM_TO_DEV, + .caps = 0, + .devs = DMA_DEV_HDA, .base = GTW_LINK_IN_STREAM_BASE(0), .channels = 8, .irq = IRQ_EXT_LINK_DMA_IN_LVL4(0, 0), @@ -162,6 +179,9 @@ static struct dma dma[] = { { /* Link out DMAC */ .plat_data = { .id = DMA_LINK_OUT_DMAC, + .dir = DMA_DIR_DEV_TO_MEM, + .caps = 0, + .devs = DMA_DEV_HDA, .base = GTW_LINK_OUT_STREAM_BASE(0), .channels = 8, .irq = IRQ_EXT_LINK_DMA_OUT_LVL4(0, 0), diff --git a/src/platform/apollolake/include/platform/dma.h b/src/platform/apollolake/include/platform/dma.h index 916a455..7243c03 100644 --- a/src/platform/apollolake/include/platform/dma.h +++ b/src/platform/apollolake/include/platform/dma.h @@ -35,6 +35,9 @@ #include <stdint.h> #include <sof/io.h> #include <arch/cache.h> +#include <sof/dma.h> + +#define PLATFORM_NUM_DMACS 6
/* available DMACs */ #define DMA_GP_LP_DMAC0 0 @@ -72,4 +75,6 @@ #define DMA_HANDSHAKE_SSP5_TX 12 #define DMA_HANDSHAKE_SSP5_RX 13
+extern struct dma dma[PLATFORM_NUM_DMACS]; + #endif diff --git a/src/platform/baytrail/dma.c b/src/platform/baytrail/dma.c index 78fbf14..f82cc55 100644 --- a/src/platform/baytrail/dma.c +++ b/src/platform/baytrail/dma.c @@ -143,10 +143,15 @@ static struct dw_drv_plat_data dmac2 = { }; #endif
-static struct dma dma[] = { +struct dma dma[PLATFORM_NUM_DMACS] = { { .plat_data = { .id = DMA_ID_DMAC0, + .dir = DMA_DIR_MEM_TO_MEM | DMA_DIR_MEM_TO_DEV | + DMA_DIR_DEV_TO_MEM | DMA_DIR_DEV_TO_DEV | + DMA_DIR_HMEM_TO_LMEM | DMA_DIR_LMEM_TO_HMEM, + .caps = DMA_CAP_GP_HP, + .devs = DMA_DEV_SSP | DMA_DEV_DMIC | DMA_DEV_HDA, .base = DMA0_BASE, .irq = IRQ_NUM_EXT_DMAC0, .drv_plat_data = &dmac0, @@ -156,6 +161,11 @@ static struct dma dma[] = { { .plat_data = { .id = DMA_ID_DMAC1, + .dir = DMA_DIR_MEM_TO_MEM | DMA_DIR_MEM_TO_DEV | + DMA_DIR_DEV_TO_MEM | DMA_DIR_DEV_TO_DEV | + DMA_DIR_HMEM_TO_LMEM | DMA_DIR_LMEM_TO_HMEM, + .caps = DMA_CAP_GP_HP, + .devs = DMA_DEV_SSP | DMA_DEV_DMIC | DMA_DEV_HDA, .base = DMA1_BASE, .irq = IRQ_NUM_EXT_DMAC1, .drv_plat_data = &dmac1, @@ -166,6 +176,11 @@ static struct dma dma[] = { { .plat_data = { .id = DMA_ID_DMAC2, + .dir = DMA_DIR_MEM_TO_MEM | DMA_DIR_MEM_TO_DEV | + DMA_DIR_DEV_TO_MEM | DMA_DIR_DEV_TO_DEV | + DMA_DIR_HMEM_TO_LMEM | DMA_DIR_LMEM_TO_HMEM, + .caps = DMA_CAP_GP_HP, + .devs = DMA_DEV_SSP | DMA_DEV_DMIC | DMA_DEV_HDA, .base = DMA2_BASE, .irq = IRQ_NUM_EXT_DMAC2, .drv_plat_data = &dmac2, diff --git a/src/platform/baytrail/include/platform/dma.h b/src/platform/baytrail/include/platform/dma.h index eec501a..5084dad 100644 --- a/src/platform/baytrail/include/platform/dma.h +++ b/src/platform/baytrail/include/platform/dma.h @@ -33,6 +33,13 @@ #define __PLATFORM_DMA_H__
#include <stdint.h> +#include <sof/dma.h> + +#if defined CONFIG_CHERRYTRAIL +#define PLATFORM_NUM_DMACS 3 +#else +#define PLATFORM_NUM_DMACS 2 +#endif
#define DMA_ID_DMAC0 0 #define DMA_ID_DMAC1 1 @@ -53,4 +60,6 @@ #define DMA_HANDSHAKE_SSP6_RX 12 #define DMA_HANDSHAKE_SSP6_TX 13
+extern struct dma dma[PLATFORM_NUM_DMACS]; + #endif diff --git a/src/platform/cannonlake/dma.c b/src/platform/cannonlake/dma.c index c560b86..e46ff07 100644 --- a/src/platform/cannonlake/dma.c +++ b/src/platform/cannonlake/dma.c @@ -109,10 +109,14 @@ static struct dw_drv_plat_data dmac1 = { }, };
-static struct dma dma[] = { +struct dma dma[PLATFORM_NUM_DMACS] = { { /* Low Power GP DMAC 0 */ .plat_data = { .id = DMA_GP_LP_DMAC0, + .dir = DMA_DIR_MEM_TO_MEM | DMA_DIR_MEM_TO_DEV | + DMA_DIR_DEV_TO_MEM | DMA_DIR_DEV_TO_DEV, + .caps = DMA_CAP_GP_LP | DMA_CAP_GP_HP, + .devs = DMA_DEV_SSP | DMA_DEV_DMIC, .base = LP_GP_DMA_BASE(0), .channels = 8, .irq = IRQ_EXT_LP_GPDMA0_LVL5(0, 0), @@ -123,6 +127,10 @@ static struct dma dma[] = { { /* Low Power GP DMAC 1 */ .plat_data = { .id = DMA_GP_LP_DMAC1, + .dir = DMA_DIR_MEM_TO_MEM | DMA_DIR_MEM_TO_DEV | + DMA_DIR_DEV_TO_MEM | DMA_DIR_DEV_TO_DEV, + .caps = DMA_CAP_GP_LP | DMA_CAP_GP_HP, + .devs = DMA_DEV_SSP | DMA_DEV_DMIC, .base = LP_GP_DMA_BASE(1), .channels = 8, .irq = IRQ_EXT_LP_GPDMA1_LVL5(0, 0), @@ -133,6 +141,9 @@ static struct dma dma[] = { { /* Host In DMAC */ .plat_data = { .id = DMA_HOST_IN_DMAC, + .dir = DMA_DIR_LMEM_TO_HMEM, + .caps = 0, + .devs = DMA_DEV_HDA, .base = GTW_HOST_IN_STREAM_BASE(0), .channels = 7, .irq = IRQ_EXT_HOST_DMA_IN_LVL3(0, 0), @@ -143,6 +154,9 @@ static struct dma dma[] = { { /* Host out DMAC */ .plat_data = { .id = DMA_HOST_OUT_DMAC, + .dir = DMA_DIR_HMEM_TO_LMEM, + .caps = 0, + .devs = DMA_DEV_HDA, .base = GTW_HOST_OUT_STREAM_BASE(0), .channels = 9, .irq = IRQ_EXT_HOST_DMA_OUT_LVL3(0, 0), @@ -153,6 +167,9 @@ static struct dma dma[] = { { /* Link In DMAC */ .plat_data = { .id = DMA_LINK_IN_DMAC, + .dir = DMA_DIR_MEM_TO_DEV, + .caps = 0, + .devs = DMA_DEV_HDA, .base = GTW_LINK_IN_STREAM_BASE(0), .channels = 9, .irq = IRQ_EXT_LINK_DMA_IN_LVL4(0, 0), @@ -163,6 +180,9 @@ static struct dma dma[] = { { /* Link out DMAC */ .plat_data = { .id = DMA_LINK_OUT_DMAC, + .dir = DMA_DIR_DEV_TO_MEM, + .caps = 0, + .devs = DMA_DEV_HDA, .base = GTW_LINK_OUT_STREAM_BASE(0), .channels = 7, .irq = IRQ_EXT_LINK_DMA_OUT_LVL4(0, 0), diff --git a/src/platform/cannonlake/include/platform/dma.h b/src/platform/cannonlake/include/platform/dma.h index 00dcda8..b6366a0 100644 --- a/src/platform/cannonlake/include/platform/dma.h +++ b/src/platform/cannonlake/include/platform/dma.h @@ -33,6 +33,10 @@ #ifndef __PLATFORM_DMA_H__ #define __PLATFORM_DMA_H__
+#include <sof/dma.h> + +#define PLATFORM_NUM_DMACS 6 + /* available DMACs */ #define DMA_GP_LP_DMAC0 0 #define DMA_GP_LP_DMAC1 1 @@ -69,4 +73,6 @@ #define DMA_HANDSHAKE_SSP5_TX 12 #define DMA_HANDSHAKE_SSP5_RX 13
+extern struct dma dma[PLATFORM_NUM_DMACS]; + #endif diff --git a/src/platform/haswell/dma.c b/src/platform/haswell/dma.c index 0ae935d..90c834c 100644 --- a/src/platform/haswell/dma.c +++ b/src/platform/haswell/dma.c @@ -106,10 +106,13 @@ static struct dw_drv_plat_data dmac1 = { }, };
-static struct dma dma[] = { +struct dma dma[PLATFORM_NUM_DMACS] = { { .plat_data = { .base = DMA0_BASE, + .dir = DMA_DIR_MEM_TO_MEM, + .caps = DMA_CAP_GP_HP | DMA_CAP_GP_LP, + .devs = DMA_DEV_SSP | DMA_DEV_DMIC | DMA_DEV_HDA, .irq = IRQ_NUM_EXT_DMAC0, .drv_plat_data = &dmac0, }, @@ -118,6 +121,11 @@ static struct dma dma[] = { { .plat_data = { .base = DMA1_BASE, + .dir = DMA_DIR_MEM_TO_MEM | DMA_DIR_MEM_TO_DEV | + DMA_DIR_DEV_TO_MEM | DMA_DIR_DEV_TO_DEV | + DMA_DIR_HMEM_TO_LMEM | DMA_DIR_LMEM_TO_HMEM, + .caps = DMA_CAP_GP_HP | DMA_CAP_GP_LP, + .devs = DMA_DEV_SSP | DMA_DEV_DMIC | DMA_DEV_HDA, .irq = IRQ_NUM_EXT_DMAC1, .drv_plat_data = &dmac1, }, diff --git a/src/platform/haswell/include/platform/dma.h b/src/platform/haswell/include/platform/dma.h index 4780f92..c926672 100644 --- a/src/platform/haswell/include/platform/dma.h +++ b/src/platform/haswell/include/platform/dma.h @@ -32,6 +32,9 @@ #define __PLATFORM_DMA_H__
#include <stdint.h> +#include <sof/dma.h> + +#define PLATFORM_NUM_DMACS 2
#define DMA_ID_DMAC0 0 #define DMA_ID_DMAC1 1 @@ -53,4 +56,6 @@ #define DMA_HANDSHAKE_OBFF_10 14 #define DMA_HANDSHAKE_OBFF_11 15
+extern struct dma dma[PLATFORM_NUM_DMACS]; + #endif
This patch adds the num_channels_busy member to the dma structure which will be helpful in determining DMAC to be allocated to users based on the number of channels draining. This is help provide a primitive level of QoS and prevent DMAC overuse.
Signed-off-by: Ranjani Sridharan ranjani.sridharan@linux.intel.com --- src/drivers/dw-dma.c | 11 +++++++++++ src/drivers/hda-dma.c | 8 ++++++++ src/include/sof/dma.h | 2 ++ 3 files changed, 21 insertions(+)
diff --git a/src/drivers/dw-dma.c b/src/drivers/dw-dma.c index 70ddb96..f0d48d9 100644 --- a/src/drivers/dw-dma.c +++ b/src/drivers/dw-dma.c @@ -43,6 +43,7 @@ * used to construct the DMA configuration for the host client 1 above. */
+#include <sof/atomic.h> #include <sof/debug.h> #include <sof/sof.h> #include <sof/dma.h> @@ -309,6 +310,8 @@ static int dw_dma_channel_get(struct dma *dma, int req_chan)
p->chan[i].status = COMP_STATE_READY;
+ atomic_add(&dma->num_channels_busy, 1); + /* unmask block, transfer and error interrupts for channel */ dw_write(dma, DW_MASK_TFR, INT_UNMASK(i)); dw_write(dma, DW_MASK_BLOCK, INT_UNMASK(i)); @@ -347,6 +350,8 @@ static void dw_dma_channel_put_unlocked(struct dma *dma, int channel) p->chan[channel].status = COMP_STATE_INIT; p->chan[channel].cb = NULL; p->chan[channel].desc_count = 0; + + atomic_sub(&dma->num_channels_busy, 1); }
/* channel must not be running when this is called */ @@ -1033,6 +1038,9 @@ static int dw_dma_probe(struct dma *dma) interrupt_enable(dma_int[i]->irq); }
+ /* init number of channels draining */ + atomic_init(&dma->num_channels_busy, 0); + return 0; }
@@ -1170,6 +1178,9 @@ static int dw_dma_probe(struct dma *dma) interrupt_register(dma_irq(dma), dw_dma_irq_handler, dma); interrupt_enable(dma_irq(dma));
+ /* init number of channels draining */ + atomic_init(&dma->num_channels_busy, 0); + return 0; } #endif diff --git a/src/drivers/hda-dma.c b/src/drivers/hda-dma.c index bef0b17..974ee80 100644 --- a/src/drivers/hda-dma.c +++ b/src/drivers/hda-dma.c @@ -29,6 +29,7 @@ * Liam Girdwood liam.r.girdwood@linux.intel.com */
+#include <sof/atomic.h> #include <stdint.h> #include <stddef.h> #include <errno.h> @@ -145,6 +146,8 @@ static int hda_dma_channel_get(struct dma *dma, int channel) if (p->chan[channel].status == COMP_STATE_INIT) { p->chan[channel].status = COMP_STATE_READY;
+ atomic_add(&dma->num_channels_busy, 1); + /* return channel */ spin_unlock_irq(&dma->lock, flags); return channel; @@ -173,6 +176,8 @@ static void hda_dma_channel_put(struct dma *dma, int channel) spin_lock_irq(&dma->lock, flags); hda_dma_channel_put_unlocked(dma, channel); spin_unlock_irq(&dma->lock, flags); + + atomic_sub(&dma->num_channels_busy, 1); }
static int hda_dma_start(struct dma *dma, int channel) @@ -400,6 +405,9 @@ static int hda_dma_probe(struct dma *dma) for (i = 0; i < HDA_DMA_MAX_CHANS; i++) hda_pdata->chan[i].status = COMP_STATE_INIT;
+ /* init number of channels draining */ + atomic_init(&dma->num_channels_busy, 0); + return 0; }
diff --git a/src/include/sof/dma.h b/src/include/sof/dma.h index fd0024f..ae39bd8 100644 --- a/src/include/sof/dma.h +++ b/src/include/sof/dma.h @@ -37,6 +37,7 @@ #include <sof/lock.h> #include <sof/sof.h> #include <sof/wait.h> +#include <arch/atomic.h>
/* DMA direction bitmasks used to define DMA copy direction */ #define DMA_DIR_MEM_TO_MEM (1 << 0) /* local memory copy */ @@ -139,6 +140,7 @@ struct dma { struct dma_plat_data plat_data; spinlock_t lock; const struct dma_ops *ops; + atomic_t num_channels_busy; /* number of channels draining */ void *private; };
On Mon, 2018-06-11 at 20:37 -0700, Ranjani Sridharan wrote:
+#include <arch/atomic.h>
/* DMA direction bitmasks used to define DMA copy direction */ #define DMA_DIR_MEM_TO_MEM (1 << 0) /* local memory copy */ @@ -139,6 +140,7 @@ struct dma { struct dma_plat_data plat_data; spinlock_t lock; const struct dma_ops *ops;
atomic_t num_channels_busy; /* number of channels draining */ void *private;
};
All applied, but the comment looks wrong ? Shouldn't it be /* number of busy channels */ ? Can you fix incrementally.
Thanks
Liam
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 --- src/arch/xtensa/Makefile.am | 1 + src/audio/dai.c | 7 ++- src/audio/host.c | 13 ++--- src/host/common_test.c | 2 +- src/include/sof/dma.h | 6 ++- src/ipc/apl-ipc.c | 8 +++- src/ipc/byt-ipc.c | 9 ++-- src/ipc/cnl-ipc.c | 8 +++- src/ipc/dma-copy.c | 8 +++- src/ipc/hsw-ipc.c | 9 ++-- src/lib/Makefile.am | 11 ++++- src/lib/dma.c | 89 +++++++++++++++++++++++++++++++++++ src/platform/apollolake/dma.c | 12 ----- src/platform/baytrail/dma.c | 12 ----- src/platform/cannonlake/dma.c | 12 ----- src/platform/haswell/dma.c | 12 ----- 16 files changed, 150 insertions(+), 69 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/audio/dai.c b/src/audio/dai.c index 1eeecd2..21a3b80 100644 --- a/src/audio/dai.c +++ b/src/audio/dai.c @@ -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; diff --git a/src/audio/host.c b/src/audio/host.c index 0285e4a..e374a2f 100644 --- a/src/audio/host.c +++ b/src/audio/host.c @@ -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; diff --git a/src/host/common_test.c b/src/host/common_test.c index e286883..0851085 100644 --- a/src/host/common_test.c +++ b/src/host/common_test.c @@ -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; } diff --git a/src/include/sof/dma.h b/src/include/sof/dma.h index ae39bd8..77da305 100644 --- a/src/include/sof/dma.h +++ b/src/include/sof/dma.h @@ -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); diff --git a/src/ipc/apl-ipc.c b/src/ipc/apl-ipc.c index 78291d0..ca19752 100644 --- a/src/ipc/apl-ipc.c +++ b/src/ipc/apl-ipc.c @@ -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; diff --git a/src/ipc/byt-ipc.c b/src/ipc/byt-ipc.c index 87e7949..fe2be6b 100644 --- a/src/ipc/byt-ipc.c +++ b/src/ipc/byt-ipc.c @@ -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; diff --git a/src/ipc/cnl-ipc.c b/src/ipc/cnl-ipc.c index ba65164..e5fed55 100644 --- a/src/ipc/cnl-ipc.c +++ b/src/ipc/cnl-ipc.c @@ -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; diff --git a/src/ipc/dma-copy.c b/src/ipc/dma-copy.c index be72eb8..81388b9 100644 --- a/src/ipc/dma-copy.c +++ b/src/ipc/dma-copy.c @@ -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; diff --git a/src/ipc/hsw-ipc.c b/src/ipc/hsw-ipc.c index aa4d9e1..7b54032 100644 --- a/src/ipc/hsw-ipc.c +++ b/src/ipc/hsw-ipc.c @@ -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; diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am index 825bfbd..874d2fb 100644 --- a/src/lib/Makefile.am +++ b/src/lib/Makefile.am @@ -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) diff --git a/src/lib/dma.c b/src/lib/dma.c new file mode 100644 index 0000000..29028f4 --- /dev/null +++ b/src/lib/dma.c @@ -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; +} diff --git a/src/platform/apollolake/dma.c b/src/platform/apollolake/dma.c index b014259..a591e8b 100644 --- a/src/platform/apollolake/dma.c +++ b/src/platform/apollolake/dma.c @@ -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) { diff --git a/src/platform/baytrail/dma.c b/src/platform/baytrail/dma.c index f82cc55..c3c7772 100644 --- a/src/platform/baytrail/dma.c +++ b/src/platform/baytrail/dma.c @@ -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) { diff --git a/src/platform/cannonlake/dma.c b/src/platform/cannonlake/dma.c index e46ff07..afb87bc 100644 --- a/src/platform/cannonlake/dma.c +++ b/src/platform/cannonlake/dma.c @@ -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) { diff --git a/src/platform/haswell/dma.c b/src/platform/haswell/dma.c index 90c834c..ca7d06b 100644 --- a/src/platform/haswell/dma.c +++ b/src/platform/haswell/dma.c @@ -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) {
Update dma_copy_new() to be compatible with dma_get(). Remove the DMAC ID argument and the corresponding PLATFORM_TRACE_DMAC definitions.
Signed-off-by: Ranjani Sridharan ranjani.sridharan@linux.intel.com --- src/include/sof/dma.h | 2 +- src/ipc/dma-copy.c | 2 +- src/lib/dma-trace.c | 2 +- src/platform/apollolake/include/platform/platform.h | 3 --- src/platform/baytrail/include/platform/platform.h | 3 --- src/platform/cannonlake/include/platform/platform.h | 3 --- src/platform/haswell/include/platform/platform.h | 3 --- 7 files changed, 3 insertions(+), 15 deletions(-)
diff --git a/src/include/sof/dma.h b/src/include/sof/dma.h index 77da305..e0424b2 100644 --- a/src/include/sof/dma.h +++ b/src/include/sof/dma.h @@ -277,7 +277,7 @@ struct dma_copy { };
/* init dma copy context */ -int dma_copy_new(struct dma_copy *dc, int dmac); +int dma_copy_new(struct dma_copy *dc);
/* free dma copy context resources */ static inline void dma_copy_free(struct dma_copy *dc) diff --git a/src/ipc/dma-copy.c b/src/ipc/dma-copy.c index 81388b9..263123a 100644 --- a/src/ipc/dma-copy.c +++ b/src/ipc/dma-copy.c @@ -373,7 +373,7 @@ int dma_copy_from_host_nowait(struct dma_copy *dc, struct dma_sg_config *host_sg return local_sg_elem.size; }
-int dma_copy_new(struct dma_copy *dc, int dmac) +int dma_copy_new(struct dma_copy *dc) { uint32_t dir, cap, dev;
diff --git a/src/lib/dma-trace.c b/src/lib/dma-trace.c index 01a9925..cff9171 100644 --- a/src/lib/dma-trace.c +++ b/src/lib/dma-trace.c @@ -180,7 +180,7 @@ int dma_trace_init_complete(struct dma_trace_data *d) trace_buffer("dtn");
/* init DMA copy context */ - ret = dma_copy_new(&d->dc, PLATFORM_TRACE_DMAC); + ret = dma_copy_new(&d->dc); if (ret < 0) { trace_buffer_error("edm"); rfree(buffer->addr); diff --git a/src/platform/apollolake/include/platform/platform.h b/src/platform/apollolake/include/platform/platform.h index 1321f1f..eeb5927 100644 --- a/src/platform/apollolake/include/platform/platform.h +++ b/src/platform/apollolake/include/platform/platform.h @@ -105,9 +105,6 @@ struct sof; */ #define DMA_TRACE_RESCHEDULE_TIME 5000
-/* DMAC used for trace DMA */ -#define PLATFORM_TRACE_DMAC DMA_HOST_IN_DMAC - /* DSP should be idle in this time frame */ #define PLATFORM_IDLE_TIME 750000
diff --git a/src/platform/baytrail/include/platform/platform.h b/src/platform/baytrail/include/platform/platform.h index 1defe27..b860356 100644 --- a/src/platform/baytrail/include/platform/platform.h +++ b/src/platform/baytrail/include/platform/platform.h @@ -96,9 +96,6 @@ struct sof; */ #define DMA_TRACE_RESCHEDULE_TIME 5000
-/* DMAC used for trace DMA */ -#define PLATFORM_TRACE_DMAC DMA_ID_DMAC0 - /* DSP should be idle in this time frame */ #define PLATFORM_IDLE_TIME 750000
diff --git a/src/platform/cannonlake/include/platform/platform.h b/src/platform/cannonlake/include/platform/platform.h index c7d4a82..a5d28cf 100644 --- a/src/platform/cannonlake/include/platform/platform.h +++ b/src/platform/cannonlake/include/platform/platform.h @@ -111,9 +111,6 @@ struct sof; */ #define DMA_TRACE_RESCHEDULE_TIME 5000
-/* DMAC used for trace DMA */ -#define PLATFORM_TRACE_DMAC DMA_HOST_IN_DMAC - /* DSP should be idle in this time frame */ #define PLATFORM_IDLE_TIME 750000
diff --git a/src/platform/haswell/include/platform/platform.h b/src/platform/haswell/include/platform/platform.h index c5d8187..c2b9a4c 100644 --- a/src/platform/haswell/include/platform/platform.h +++ b/src/platform/haswell/include/platform/platform.h @@ -95,9 +95,6 @@ struct sof; */ #define DMA_TRACE_RESCHEDULE_TIME 5000
-/* DMAC used for trace DMA */ -#define PLATFORM_TRACE_DMAC DMA_ID_DMAC1 - /* DSP should be idle in this time frame */ #define PLATFORM_IDLE_TIME 750000
participants (2)
-
Liam Girdwood
-
Ranjani Sridharan