[Sound-open-firmware] [RFC PATCH 0/6] Introducing a new API for dma_get()
This set of patches proposes a new API for dma_get() that procures a DMAC based on the requested user type, copy direction 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 platform DMAC definitions have also been updated to include information about usage and copy direction to support the new API.
This has only been tested on the BYT platform with a Minnowboard Turbot board and a RT5651 codec. Further testing is required on other platforms to ensure there are no regressions. Looking for feedback on initial implementation.
The corresponding DMAC/DMAC channel definitions from topology/kernel driver need to be removed. This is still work in progress.
Ranjani Sridharan (6): platform: dma: consolidate dmac initialization dma: ops: introduce channel_status() op to retrieve number of channels in use dma: introduce new API for requesting DMAC dma: use newly defined API for request DMAC dma: remove dmac id argument from dma_copy_context() trace: remove trace dmac id definition
src/audio/dai.c | 7 ++- src/audio/host.c | 28 +++++++-- src/drivers/dw-dma.c | 19 ++++++ src/drivers/hda-dma.c | 20 ++++++ src/host/common_test.c | 2 +- src/include/sof/dma.h | 38 +++++++++++- src/ipc/apl-ipc.c | 3 +- src/ipc/byt-ipc.c | 4 +- src/ipc/cnl-ipc.c | 4 +- src/ipc/dma-copy.c | 9 ++- src/ipc/hsw-ipc.c | 4 +- src/lib/dma-trace.c | 2 +- src/platform/apollolake/dma.c | 62 +++++++++++++++++-- .../apollolake/include/platform/platform.h | 3 - src/platform/apollolake/platform.c | 21 +------ src/platform/baytrail/dma.c | 50 +++++++++++++-- .../baytrail/include/platform/platform.h | 3 - src/platform/baytrail/platform.c | 22 +------ src/platform/cannonlake/dma.c | 62 +++++++++++++++++-- .../cannonlake/include/platform/platform.h | 3 - src/platform/cannonlake/platform.c | 21 +------ src/platform/haswell/dma.c | 58 ++++++++++++++--- .../haswell/include/platform/platform.h | 3 - src/platform/haswell/platform.c | 16 +---- 24 files changed, 337 insertions(+), 127 deletions(-)
This patch proposes to create a DMAC initialization routine in dma.c where it can access the platform DMAC definitions.
Signed-off-by: Ranjani Sridharan ranjani.sridharan@linux.intel.com --- src/include/sof/dma.h | 3 +++ src/platform/apollolake/dma.c | 9 +++++++++ src/platform/apollolake/platform.c | 21 +-------------------- src/platform/baytrail/dma.c | 9 +++++++++ src/platform/baytrail/platform.c | 22 +--------------------- src/platform/cannonlake/dma.c | 9 +++++++++ src/platform/cannonlake/platform.c | 21 +-------------------- src/platform/haswell/dma.c | 9 +++++++++ src/platform/haswell/platform.c | 16 +--------------- 9 files changed, 43 insertions(+), 76 deletions(-)
diff --git a/src/include/sof/dma.h b/src/include/sof/dma.h index 7ba1298..80ca880 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 */ +void 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..001bb67 100644 --- a/src/platform/apollolake/dma.c +++ b/src/platform/apollolake/dma.c @@ -181,3 +181,12 @@ struct dma *dma_get(int dmac_id)
return NULL; } + +/* Initialize all platform DMAC's */ +void dmac_init(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(dma); i++) + dma_probe(&dma[i]); +} diff --git a/src/platform/apollolake/platform.c b/src/platform/apollolake/platform.c index 0b26ae5..589c77e 100644 --- a/src/platform/apollolake/platform.c +++ b/src/platform/apollolake/platform.c @@ -186,7 +186,6 @@ static void platform_memory_windows_init(void)
int platform_init(struct sof *sof) { - struct dma *dmac; struct dai *ssp; struct dai *dmic0; int i; @@ -244,25 +243,7 @@ int platform_init(struct sof *sof)
/* init DMACs */ trace_point(TRACE_BOOT_PLATFORM_DMA); - dmac = dma_get(DMA_GP_LP_DMAC0); - if (dmac == NULL) - 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); + dmac_init();
/* 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..5a0b650 100644 --- a/src/platform/baytrail/dma.c +++ b/src/platform/baytrail/dma.c @@ -186,3 +186,12 @@ struct dma *dma_get(int dmac_id)
return NULL; } + +/* Initialize all platform DMAC's */ +void dmac_init(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(dma); i++) + dma_probe(&dma[i]); +} diff --git a/src/platform/baytrail/platform.c b/src/platform/baytrail/platform.c index 562fabf..50acda9 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; @@ -356,22 +351,7 @@ int platform_init(struct sof *sof)
/* init DMACs */ trace_point(TRACE_BOOT_PLATFORM_DMA); - dmac0 = dma_get(DMA_ID_DMAC0); - if (dmac0 == NULL) - 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 + dmac_init();
/* 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..9031c17 100644 --- a/src/platform/cannonlake/dma.c +++ b/src/platform/cannonlake/dma.c @@ -182,3 +182,12 @@ struct dma *dma_get(int dmac_id)
return NULL; } + +/* Initialize all platform DMAC's */ +void dmac_init(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(dma); i++) + dma_probe(&dma[i]); +} diff --git a/src/platform/cannonlake/platform.c b/src/platform/cannonlake/platform.c index 2e85088..3ca48e5 100644 --- a/src/platform/cannonlake/platform.c +++ b/src/platform/cannonlake/platform.c @@ -208,7 +208,6 @@ static struct timer platform_ext_timer = {
int platform_init(struct sof *sof) { - struct dma *dmac; struct dai *ssp; struct dai *dmic0; int i; @@ -261,25 +260,7 @@ int platform_init(struct sof *sof)
/* init DMACs */ trace_point(TRACE_BOOT_PLATFORM_DMA); - dmac = dma_get(DMA_GP_LP_DMAC0); - if (!dmac) - 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); + dmac_init();
/* 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..5d1e308 100644 --- a/src/platform/haswell/dma.c +++ b/src/platform/haswell/dma.c @@ -135,3 +135,12 @@ struct dma *dma_get(int dmac_id) return NULL; } } + +/* Initialize all platform DMAC's */ +void dmac_init(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(dma); i++) + dma_probe(&dma[i]); +} diff --git a/src/platform/haswell/platform.c b/src/platform/haswell/platform.c index 81ce67a..8ffb370 100644 --- a/src/platform/haswell/platform.c +++ b/src/platform/haswell/platform.c @@ -240,8 +240,6 @@ static void platform_init_shim(void)
int platform_init(struct sof *sof) { - struct dma *dmac0; - struct dma *dmac1; struct dai *ssp0; struct dai *ssp1;
@@ -280,19 +278,7 @@ int platform_init(struct sof *sof)
/* init DMACs */ trace_point(TRACE_BOOT_PLATFORM_DMA); - dmac0 = dma_get(DMA_ID_DMAC0); - if (dmac0 == NULL) - 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); + dmac_init();
/* clear the masks for dsp of the dmac*/ io_reg_update_bits(SHIM_BASE + SHIM_IMRD,
On 6/5/2018 12:23 PM, Ranjani Sridharan wrote:
This patch proposes to create a DMAC initialization routine in dma.c where it can access the platform DMAC definitions.
Signed-off-by: Ranjani Sridharan ranjani.sridharan@linux.intel.com
src/include/sof/dma.h | 3 +++ src/platform/apollolake/dma.c | 9 +++++++++ src/platform/apollolake/platform.c | 21 +-------------------- src/platform/baytrail/dma.c | 9 +++++++++ src/platform/baytrail/platform.c | 22 +--------------------- src/platform/cannonlake/dma.c | 9 +++++++++ src/platform/cannonlake/platform.c | 21 +-------------------- src/platform/haswell/dma.c | 9 +++++++++ src/platform/haswell/platform.c | 16 +--------------- 9 files changed, 43 insertions(+), 76 deletions(-)
diff --git a/src/include/sof/dma.h b/src/include/sof/dma.h index 7ba1298..80ca880 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 */ +void 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..001bb67 100644 --- a/src/platform/apollolake/dma.c +++ b/src/platform/apollolake/dma.c @@ -181,3 +181,12 @@ struct dma *dma_get(int dmac_id)
return NULL; }
+/* Initialize all platform DMAC's */ +void dmac_init(void) +{
- int i;
- for (i = 0; i < ARRAY_SIZE(dma); i++)
dma_probe(&dma[i]);
+} diff --git a/src/platform/apollolake/platform.c b/src/platform/apollolake/platform.c index 0b26ae5..589c77e 100644 --- a/src/platform/apollolake/platform.c +++ b/src/platform/apollolake/platform.c @@ -186,7 +186,6 @@ static void platform_memory_windows_init(void)
int platform_init(struct sof *sof) {
- struct dma *dmac; struct dai *ssp; struct dai *dmic0; int i;
@@ -244,25 +243,7 @@ int platform_init(struct sof *sof)
/* init DMACs */ trace_point(TRACE_BOOT_PLATFORM_DMA);
- dmac = dma_get(DMA_GP_LP_DMAC0);
- if (dmac == NULL)
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);
dmac_init();
/* 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..5a0b650 100644 --- a/src/platform/baytrail/dma.c +++ b/src/platform/baytrail/dma.c @@ -186,3 +186,12 @@ struct dma *dma_get(int dmac_id)
return NULL; }
+/* Initialize all platform DMAC's */ +void dmac_init(void) +{
- int i;
- for (i = 0; i < ARRAY_SIZE(dma); i++)
dma_probe(&dma[i]);
+} diff --git a/src/platform/baytrail/platform.c b/src/platform/baytrail/platform.c index 562fabf..50acda9 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;
@@ -356,22 +351,7 @@ int platform_init(struct sof *sof)
/* init DMACs */ trace_point(TRACE_BOOT_PLATFORM_DMA);
- dmac0 = dma_get(DMA_ID_DMAC0);
- if (dmac0 == NULL)
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
dmac_init();
/* 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..9031c17 100644 --- a/src/platform/cannonlake/dma.c +++ b/src/platform/cannonlake/dma.c @@ -182,3 +182,12 @@ struct dma *dma_get(int dmac_id)
return NULL; }
+/* Initialize all platform DMAC's */ +void dmac_init(void) +{
- int i;
- for (i = 0; i < ARRAY_SIZE(dma); i++)
dma_probe(&dma[i]);
+} diff --git a/src/platform/cannonlake/platform.c b/src/platform/cannonlake/platform.c index 2e85088..3ca48e5 100644 --- a/src/platform/cannonlake/platform.c +++ b/src/platform/cannonlake/platform.c @@ -208,7 +208,6 @@ static struct timer platform_ext_timer = {
int platform_init(struct sof *sof) {
- struct dma *dmac; struct dai *ssp; struct dai *dmic0; int i;
@@ -261,25 +260,7 @@ int platform_init(struct sof *sof)
/* init DMACs */ trace_point(TRACE_BOOT_PLATFORM_DMA);
- dmac = dma_get(DMA_GP_LP_DMAC0);
- if (!dmac)
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);
dmac_init();
/* 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..5d1e308 100644 --- a/src/platform/haswell/dma.c +++ b/src/platform/haswell/dma.c @@ -135,3 +135,12 @@ struct dma *dma_get(int dmac_id) return NULL; } }
+/* Initialize all platform DMAC's */ +void dmac_init(void) +{
- int i;
- for (i = 0; i < ARRAY_SIZE(dma); i++)
dma_probe(&dma[i]);
+} diff --git a/src/platform/haswell/platform.c b/src/platform/haswell/platform.c index 81ce67a..8ffb370 100644 --- a/src/platform/haswell/platform.c +++ b/src/platform/haswell/platform.c @@ -240,8 +240,6 @@ static void platform_init_shim(void)
int platform_init(struct sof *sof) {
- struct dma *dmac0;
- struct dma *dmac1; struct dai *ssp0; struct dai *ssp1;
@@ -280,19 +278,7 @@ int platform_init(struct sof *sof)
/* init DMACs */ trace_point(TRACE_BOOT_PLATFORM_DMA);
- dmac0 = dma_get(DMA_ID_DMAC0);
- if (dmac0 == NULL)
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);
here, it should be added to dmac_init ?
- dmac1 = dma_get(DMA_ID_DMAC1);
- if (dmac1 == NULL)
return -ENODEV;
- dma_probe(dmac1);
dmac_init();
/* clear the masks for dsp of the dmac*/ io_reg_update_bits(SHIM_BASE + SHIM_IMRD,
On Tue, 2018-06-05 at 15:54 +0800, rander.wang wrote:
On 6/5/2018 12:23 PM, Ranjani Sridharan wrote:
This patch proposes to create a DMAC initialization routine in dma.c where it can access the platform DMAC definitions.
Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com
src/include/sof/dma.h | 3 +++ src/platform/apollolake/dma.c | 9 +++++++++ src/platform/apollolake/platform.c | 21 +-------------------- src/platform/baytrail/dma.c | 9 +++++++++ src/platform/baytrail/platform.c | 22 +--------------------- src/platform/cannonlake/dma.c | 9 +++++++++ src/platform/cannonlake/platform.c | 21 +-------------------- src/platform/haswell/dma.c | 9 +++++++++ src/platform/haswell/platform.c | 16 +--------------- 9 files changed, 43 insertions(+), 76 deletions(-)
diff --git a/src/include/sof/dma.h b/src/include/sof/dma.h index 7ba1298..80ca880 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 */ +void 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..001bb67 100644 --- a/src/platform/apollolake/dma.c +++ b/src/platform/apollolake/dma.c @@ -181,3 +181,12 @@ struct dma *dma_get(int dmac_id)
return NULL; }
+/* Initialize all platform DMAC's */ +void dmac_init(void) +{
- int i;
- for (i = 0; i < ARRAY_SIZE(dma); i++)
dma_probe(&dma[i]);
+} diff --git a/src/platform/apollolake/platform.c b/src/platform/apollolake/platform.c index 0b26ae5..589c77e 100644 --- a/src/platform/apollolake/platform.c +++ b/src/platform/apollolake/platform.c @@ -186,7 +186,6 @@ static void platform_memory_windows_init(void)
int platform_init(struct sof *sof) {
- struct dma *dmac; struct dai *ssp; struct dai *dmic0; int i;
@@ -244,25 +243,7 @@ int platform_init(struct sof *sof)
/* init DMACs */ trace_point(TRACE_BOOT_PLATFORM_DMA);
- dmac = dma_get(DMA_GP_LP_DMAC0);
- if (dmac == NULL)
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);
dmac_init();
/* 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..5a0b650 100644 --- a/src/platform/baytrail/dma.c +++ b/src/platform/baytrail/dma.c @@ -186,3 +186,12 @@ struct dma *dma_get(int dmac_id)
return NULL; }
+/* Initialize all platform DMAC's */ +void dmac_init(void) +{
- int i;
- for (i = 0; i < ARRAY_SIZE(dma); i++)
dma_probe(&dma[i]);
+} diff --git a/src/platform/baytrail/platform.c b/src/platform/baytrail/platform.c index 562fabf..50acda9 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;
@@ -356,22 +351,7 @@ int platform_init(struct sof *sof)
/* init DMACs */ trace_point(TRACE_BOOT_PLATFORM_DMA);
- dmac0 = dma_get(DMA_ID_DMAC0);
- if (dmac0 == NULL)
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
dmac_init();
/* 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..9031c17 100644 --- a/src/platform/cannonlake/dma.c +++ b/src/platform/cannonlake/dma.c @@ -182,3 +182,12 @@ struct dma *dma_get(int dmac_id)
return NULL; }
+/* Initialize all platform DMAC's */ +void dmac_init(void) +{
- int i;
- for (i = 0; i < ARRAY_SIZE(dma); i++)
dma_probe(&dma[i]);
+} diff --git a/src/platform/cannonlake/platform.c b/src/platform/cannonlake/platform.c index 2e85088..3ca48e5 100644 --- a/src/platform/cannonlake/platform.c +++ b/src/platform/cannonlake/platform.c @@ -208,7 +208,6 @@ static struct timer platform_ext_timer = {
int platform_init(struct sof *sof) {
- struct dma *dmac; struct dai *ssp; struct dai *dmic0; int i;
@@ -261,25 +260,7 @@ int platform_init(struct sof *sof)
/* init DMACs */ trace_point(TRACE_BOOT_PLATFORM_DMA);
- dmac = dma_get(DMA_GP_LP_DMAC0);
- if (!dmac)
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);
dmac_init();
/* 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..5d1e308 100644 --- a/src/platform/haswell/dma.c +++ b/src/platform/haswell/dma.c @@ -135,3 +135,12 @@ struct dma *dma_get(int dmac_id) return NULL; } }
+/* Initialize all platform DMAC's */ +void dmac_init(void) +{
- int i;
- for (i = 0; i < ARRAY_SIZE(dma); i++)
dma_probe(&dma[i]);
+} diff --git a/src/platform/haswell/platform.c b/src/platform/haswell/platform.c index 81ce67a..8ffb370 100644 --- a/src/platform/haswell/platform.c +++ b/src/platform/haswell/platform.c @@ -240,8 +240,6 @@ static void platform_init_shim(void)
int platform_init(struct sof *sof) {
- struct dma *dmac0;
- struct dma *dmac1; struct dai *ssp0; struct dai *ssp1;
@@ -280,19 +278,7 @@ int platform_init(struct sof *sof)
/* init DMACs */ trace_point(TRACE_BOOT_PLATFORM_DMA);
- dmac0 = dma_get(DMA_ID_DMAC0);
- if (dmac0 == NULL)
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);
here, it should be added to dmac_init ?
Yes, thanks for pointing out, Rander!
- dmac1 = dma_get(DMA_ID_DMAC1);
- if (dmac1 == NULL)
return -ENODEV;
- dma_probe(dmac1);
dmac_init();
/* clear the masks for dsp of the dmac*/ io_reg_update_bits(SHIM_BASE + SHIM_IMRD,
On Mon, 2018-06-04 at 21:23 -0700, Ranjani Sridharan wrote:
This patch proposes to create a DMAC initialization routine in dma.c where it can access the platform DMAC definitions.
Signed-off-by: Ranjani Sridharan ranjani.sridharan@linux.intel.com
src/include/sof/dma.h | 3 +++ src/platform/apollolake/dma.c | 9 +++++++++ src/platform/apollolake/platform.c | 21 +-------------------- src/platform/baytrail/dma.c | 9 +++++++++ src/platform/baytrail/platform.c | 22 +--------------------- src/platform/cannonlake/dma.c | 9 +++++++++ src/platform/cannonlake/platform.c | 21 +-------------------- src/platform/haswell/dma.c | 9 +++++++++ src/platform/haswell/platform.c | 16 +--------------- 9 files changed, 43 insertions(+), 76 deletions(-)
diff --git a/src/include/sof/dma.h b/src/include/sof/dma.h index 7ba1298..80ca880 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 */ +void 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..001bb67 100644 --- a/src/platform/apollolake/dma.c +++ b/src/platform/apollolake/dma.c @@ -181,3 +181,12 @@ struct dma *dma_get(int dmac_id)
return NULL; }
+/* Initialize all platform DMAC's */ +void dmac_init(void) +{
- int i;
- for (i = 0; i < ARRAY_SIZE(dma); i++)
dma_probe(&dma[i]);
Can you check for failure here and report it via trace_error. ditto for rest.
Liam
On Tue, 2018-06-05 at 10:14 +0100, Liam Girdwood wrote:
On Mon, 2018-06-04 at 21:23 -0700, Ranjani Sridharan wrote:
This patch proposes to create a DMAC initialization routine in dma.c where it can access the platform DMAC definitions.
Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com
src/include/sof/dma.h | 3 +++ src/platform/apollolake/dma.c | 9 +++++++++ src/platform/apollolake/platform.c | 21 +-------------------- src/platform/baytrail/dma.c | 9 +++++++++ src/platform/baytrail/platform.c | 22 +--------------------- src/platform/cannonlake/dma.c | 9 +++++++++ src/platform/cannonlake/platform.c | 21 +-------------------- src/platform/haswell/dma.c | 9 +++++++++ src/platform/haswell/platform.c | 16 +--------------- 9 files changed, 43 insertions(+), 76 deletions(-)
diff --git a/src/include/sof/dma.h b/src/include/sof/dma.h index 7ba1298..80ca880 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 */ +void 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..001bb67 100644 --- a/src/platform/apollolake/dma.c +++ b/src/platform/apollolake/dma.c @@ -181,3 +181,12 @@ struct dma *dma_get(int dmac_id)
return NULL; }
+/* Initialize all platform DMAC's */ +void dmac_init(void) +{
- int i;
- for (i = 0; i < ARRAY_SIZE(dma); i++)
dma_probe(&dma[i]);
Can you check for failure here and report it via trace_error. ditto for rest.
dma_probe() seems to always return 0 though. Never returns an error. Let me look into it.
Liam
On 2018年06月05日 12:23, Ranjani Sridharan wrote:
This patch proposes to create a DMAC initialization routine in dma.c where it can access the platform DMAC definitions.
Signed-off-by: Ranjani Sridharan ranjani.sridharan@linux.intel.com
src/include/sof/dma.h | 3 +++ src/platform/apollolake/dma.c | 9 +++++++++ src/platform/apollolake/platform.c | 21 +-------------------- src/platform/baytrail/dma.c | 9 +++++++++ src/platform/baytrail/platform.c | 22 +--------------------- src/platform/cannonlake/dma.c | 9 +++++++++ src/platform/cannonlake/platform.c | 21 +-------------------- src/platform/haswell/dma.c | 9 +++++++++ src/platform/haswell/platform.c | 16 +--------------- 9 files changed, 43 insertions(+), 76 deletions(-)
diff --git a/src/include/sof/dma.h b/src/include/sof/dma.h index 7ba1298..80ca880 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 */ +void 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..001bb67 100644 --- a/src/platform/apollolake/dma.c +++ b/src/platform/apollolake/dma.c @@ -181,3 +181,12 @@ struct dma *dma_get(int dmac_id)
return NULL; }
+/* Initialize all platform DMAC's */ +void dmac_init(void) +{
- int i;
- for (i = 0; i < ARRAY_SIZE(dma); i++)
dma_probe(&dma[i]);
+}
looks this function are same for all platforms, can we move it to common part and share it?
Thanks, ~Keyon
diff --git a/src/platform/apollolake/platform.c b/src/platform/apollolake/platform.c index 0b26ae5..589c77e 100644 --- a/src/platform/apollolake/platform.c +++ b/src/platform/apollolake/platform.c @@ -186,7 +186,6 @@ static void platform_memory_windows_init(void)
int platform_init(struct sof *sof) {
- struct dma *dmac; struct dai *ssp; struct dai *dmic0; int i;
@@ -244,25 +243,7 @@ int platform_init(struct sof *sof)
/* init DMACs */ trace_point(TRACE_BOOT_PLATFORM_DMA);
- dmac = dma_get(DMA_GP_LP_DMAC0);
- if (dmac == NULL)
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);
dmac_init();
/* 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..5a0b650 100644 --- a/src/platform/baytrail/dma.c +++ b/src/platform/baytrail/dma.c @@ -186,3 +186,12 @@ struct dma *dma_get(int dmac_id)
return NULL; }
+/* Initialize all platform DMAC's */ +void dmac_init(void) +{
- int i;
- for (i = 0; i < ARRAY_SIZE(dma); i++)
dma_probe(&dma[i]);
+} diff --git a/src/platform/baytrail/platform.c b/src/platform/baytrail/platform.c index 562fabf..50acda9 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;
@@ -356,22 +351,7 @@ int platform_init(struct sof *sof)
/* init DMACs */ trace_point(TRACE_BOOT_PLATFORM_DMA);
- dmac0 = dma_get(DMA_ID_DMAC0);
- if (dmac0 == NULL)
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
dmac_init();
/* 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..9031c17 100644 --- a/src/platform/cannonlake/dma.c +++ b/src/platform/cannonlake/dma.c @@ -182,3 +182,12 @@ struct dma *dma_get(int dmac_id)
return NULL; }
+/* Initialize all platform DMAC's */ +void dmac_init(void) +{
- int i;
- for (i = 0; i < ARRAY_SIZE(dma); i++)
dma_probe(&dma[i]);
+} diff --git a/src/platform/cannonlake/platform.c b/src/platform/cannonlake/platform.c index 2e85088..3ca48e5 100644 --- a/src/platform/cannonlake/platform.c +++ b/src/platform/cannonlake/platform.c @@ -208,7 +208,6 @@ static struct timer platform_ext_timer = {
int platform_init(struct sof *sof) {
- struct dma *dmac; struct dai *ssp; struct dai *dmic0; int i;
@@ -261,25 +260,7 @@ int platform_init(struct sof *sof)
/* init DMACs */ trace_point(TRACE_BOOT_PLATFORM_DMA);
- dmac = dma_get(DMA_GP_LP_DMAC0);
- if (!dmac)
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);
dmac_init();
/* 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..5d1e308 100644 --- a/src/platform/haswell/dma.c +++ b/src/platform/haswell/dma.c @@ -135,3 +135,12 @@ struct dma *dma_get(int dmac_id) return NULL; } }
+/* Initialize all platform DMAC's */ +void dmac_init(void) +{
- int i;
- for (i = 0; i < ARRAY_SIZE(dma); i++)
dma_probe(&dma[i]);
+} diff --git a/src/platform/haswell/platform.c b/src/platform/haswell/platform.c index 81ce67a..8ffb370 100644 --- a/src/platform/haswell/platform.c +++ b/src/platform/haswell/platform.c @@ -240,8 +240,6 @@ static void platform_init_shim(void)
int platform_init(struct sof *sof) {
- struct dma *dmac0;
- struct dma *dmac1; struct dai *ssp0; struct dai *ssp1;
@@ -280,19 +278,7 @@ int platform_init(struct sof *sof)
/* init DMACs */ trace_point(TRACE_BOOT_PLATFORM_DMA);
- dmac0 = dma_get(DMA_ID_DMAC0);
- if (dmac0 == NULL)
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);
dmac_init();
/* clear the masks for dsp of the dmac*/ io_reg_update_bits(SHIM_BASE + SHIM_IMRD,
On Tue, 2018-06-05 at 18:42 +0800, Keyon Jie wrote:
On 2018年06月05日 12:23, Ranjani Sridharan wrote:
This patch proposes to create a DMAC initialization routine in dma.c where it can access the platform DMAC definitions.
Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com
src/include/sof/dma.h | 3 +++ src/platform/apollolake/dma.c | 9 +++++++++ src/platform/apollolake/platform.c | 21 +-------------------- src/platform/baytrail/dma.c | 9 +++++++++ src/platform/baytrail/platform.c | 22 +--------------------- src/platform/cannonlake/dma.c | 9 +++++++++ src/platform/cannonlake/platform.c | 21 +-------------------- src/platform/haswell/dma.c | 9 +++++++++ src/platform/haswell/platform.c | 16 +--------------- 9 files changed, 43 insertions(+), 76 deletions(-)
diff --git a/src/include/sof/dma.h b/src/include/sof/dma.h index 7ba1298..80ca880 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 */ +void 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..001bb67 100644 --- a/src/platform/apollolake/dma.c +++ b/src/platform/apollolake/dma.c @@ -181,3 +181,12 @@ struct dma *dma_get(int dmac_id)
return NULL; }
+/* Initialize all platform DMAC's */ +void dmac_init(void) +{
- int i;
- for (i = 0; i < ARRAY_SIZE(dma); i++)
dma_probe(&dma[i]);
+}
looks this function are same for all platforms, can we move it to common part and share it?
Sure. I'll consolidate both the dmac_init and dma_get() functions in the same file. Thanks!
Thanks, ~Keyon
diff --git a/src/platform/apollolake/platform.c b/src/platform/apollolake/platform.c index 0b26ae5..589c77e 100644 --- a/src/platform/apollolake/platform.c +++ b/src/platform/apollolake/platform.c @@ -186,7 +186,6 @@ static void platform_memory_windows_init(void)
int platform_init(struct sof *sof) {
- struct dma *dmac; struct dai *ssp; struct dai *dmic0; int i;
@@ -244,25 +243,7 @@ int platform_init(struct sof *sof)
/* init DMACs */ trace_point(TRACE_BOOT_PLATFORM_DMA);
- dmac = dma_get(DMA_GP_LP_DMAC0);
- if (dmac == NULL)
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);
dmac_init();
/* 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..5a0b650 100644 --- a/src/platform/baytrail/dma.c +++ b/src/platform/baytrail/dma.c @@ -186,3 +186,12 @@ struct dma *dma_get(int dmac_id)
return NULL; }
+/* Initialize all platform DMAC's */ +void dmac_init(void) +{
- int i;
- for (i = 0; i < ARRAY_SIZE(dma); i++)
dma_probe(&dma[i]);
+} diff --git a/src/platform/baytrail/platform.c b/src/platform/baytrail/platform.c index 562fabf..50acda9 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;
@@ -356,22 +351,7 @@ int platform_init(struct sof *sof)
/* init DMACs */ trace_point(TRACE_BOOT_PLATFORM_DMA);
- dmac0 = dma_get(DMA_ID_DMAC0);
- if (dmac0 == NULL)
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
dmac_init();
/* 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..9031c17 100644 --- a/src/platform/cannonlake/dma.c +++ b/src/platform/cannonlake/dma.c @@ -182,3 +182,12 @@ struct dma *dma_get(int dmac_id)
return NULL; }
+/* Initialize all platform DMAC's */ +void dmac_init(void) +{
- int i;
- for (i = 0; i < ARRAY_SIZE(dma); i++)
dma_probe(&dma[i]);
+} diff --git a/src/platform/cannonlake/platform.c b/src/platform/cannonlake/platform.c index 2e85088..3ca48e5 100644 --- a/src/platform/cannonlake/platform.c +++ b/src/platform/cannonlake/platform.c @@ -208,7 +208,6 @@ static struct timer platform_ext_timer = {
int platform_init(struct sof *sof) {
- struct dma *dmac; struct dai *ssp; struct dai *dmic0; int i;
@@ -261,25 +260,7 @@ int platform_init(struct sof *sof)
/* init DMACs */ trace_point(TRACE_BOOT_PLATFORM_DMA);
- dmac = dma_get(DMA_GP_LP_DMAC0);
- if (!dmac)
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);
dmac_init();
/* 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..5d1e308 100644 --- a/src/platform/haswell/dma.c +++ b/src/platform/haswell/dma.c @@ -135,3 +135,12 @@ struct dma *dma_get(int dmac_id) return NULL; } }
+/* Initialize all platform DMAC's */ +void dmac_init(void) +{
- int i;
- for (i = 0; i < ARRAY_SIZE(dma); i++)
dma_probe(&dma[i]);
+} diff --git a/src/platform/haswell/platform.c b/src/platform/haswell/platform.c index 81ce67a..8ffb370 100644 --- a/src/platform/haswell/platform.c +++ b/src/platform/haswell/platform.c @@ -240,8 +240,6 @@ static void platform_init_shim(void)
int platform_init(struct sof *sof) {
- struct dma *dmac0;
- struct dma *dmac1; struct dai *ssp0; struct dai *ssp1;
@@ -280,19 +278,7 @@ int platform_init(struct sof *sof)
/* init DMACs */ trace_point(TRACE_BOOT_PLATFORM_DMA);
- dmac0 = dma_get(DMA_ID_DMAC0);
- if (dmac0 == NULL)
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);
dmac_init();
/* clear the masks for dsp of the dmac*/ io_reg_update_bits(SHIM_BASE + SHIM_IMRD,
Sound-open-firmware mailing list Sound-open-firmware@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/sound-open-firmware
This patch adds a new dma op for retreiving the number of channels in use in a given DMAC. This will be useful in providing basic and primitive QoS while allocating DMAC for various users.
Signed-off-by: Ranjani Sridharan ranjani.sridharan@linux.intel.com --- src/drivers/dw-dma.c | 19 +++++++++++++++++++ src/drivers/hda-dma.c | 20 ++++++++++++++++++++ src/include/sof/dma.h | 7 +++++++ 3 files changed, 46 insertions(+)
diff --git a/src/drivers/dw-dma.c b/src/drivers/dw-dma.c index c064330..0ed742f 100644 --- a/src/drivers/dw-dma.c +++ b/src/drivers/dw-dma.c @@ -289,6 +289,24 @@ static inline void dw_update_bits(struct dma *dma, uint32_t reg, uint32_t mask, io_reg_update_bits(dma_base(dma) + reg, mask, value); }
+/* get the number of DMA channels in use */ +static int dw_dma_channel_status(struct dma *dma) +{ + struct dma_pdata *p = dma_get_drvdata(dma); + int i, count = 0; + + trace_dma("Dct"); + + for (i = 0; i < DW_MAX_CHAN; i++) { + + /* find channels in use */ + if (p->chan[i].status != COMP_STATE_INIT) + count++; + } + + return count; +} + /* allocate next free DMA channel */ static int dw_dma_channel_get(struct dma *dma, int req_chan) { @@ -1177,6 +1195,7 @@ static int dw_dma_probe(struct dma *dma) const struct dma_ops dw_dma_ops = { .channel_get = dw_dma_channel_get, .channel_put = dw_dma_channel_put, + .channel_status = dw_dma_channel_status, .start = dw_dma_start, .stop = dw_dma_stop, .pause = dw_dma_pause, diff --git a/src/drivers/hda-dma.c b/src/drivers/hda-dma.c index 97ea0ef..0e88a35 100644 --- a/src/drivers/hda-dma.c +++ b/src/drivers/hda-dma.c @@ -131,6 +131,24 @@ static int hda_dma_copy(struct dma *dma, int channel, int bytes) return 0; }
+/* get the number of DMA channels in use */ +static int hda_dma_channel_status(struct dma *dma) +{ + struct dma_pdata *p = dma_get_drvdata(dma); + int i, count = 0; + + trace_host("Dct"); + + for (i = 0; i < HDA_DMA_MAX_CHANS; i++) { + + /* find channels in use */ + if (p->chan[i].status != COMP_STATE_INIT) + count++; + } + + return count; +} + /* acquire the specific DMA channel */ static int hda_dma_channel_get(struct dma *dma, int channel) { @@ -406,6 +424,7 @@ static int hda_dma_probe(struct dma *dma) const struct dma_ops hda_host_dma_ops = { .channel_get = hda_dma_channel_get, .channel_put = hda_dma_channel_put, + .channel_status = hda_dma_channel_status, .start = hda_dma_start, .stop = hda_dma_stop, .copy = hda_dma_copy, @@ -422,6 +441,7 @@ const struct dma_ops hda_host_dma_ops = { const struct dma_ops hda_link_dma_ops = { .channel_get = hda_dma_channel_get, .channel_put = hda_dma_channel_put, + .channel_status = hda_dma_channel_status, .start = hda_dma_start, .stop = hda_dma_stop, .copy = hda_dma_copy, diff --git a/src/include/sof/dma.h b/src/include/sof/dma.h index 80ca880..1de9efc 100644 --- a/src/include/sof/dma.h +++ b/src/include/sof/dma.h @@ -93,6 +93,7 @@ struct dma_ops {
int (*channel_get)(struct dma *dma, int req_channel); void (*channel_put)(struct dma *dma, int channel); + int (*channel_status)(struct dma *dma);
int (*start)(struct dma *dma, int channel); int (*stop)(struct dma *dma, int channel); @@ -178,6 +179,12 @@ static inline void dma_channel_put(struct dma *dma, int channel) dma->ops->channel_put(dma, channel); }
+/* get the number of DMA channels in use */ +static inline int dma_channel_status(struct dma *dma) +{ + return dma->ops->channel_status(dma); +} + static inline int dma_set_cb(struct dma *dma, int channel, int type, void (*cb)(void *data, uint32_t type, struct dma_sg_elem *next), void *data) {
On Mon, 2018-06-04 at 21:23 -0700, Ranjani Sridharan wrote:
This patch adds a new dma op for retreiving the number of channels in use in a given DMAC. This will be useful in providing basic and primitive QoS while allocating DMAC for various users.
Signed-off-by: Ranjani Sridharan ranjani.sridharan@linux.intel.com
src/drivers/dw-dma.c | 19 +++++++++++++++++++ src/drivers/hda-dma.c | 20 ++++++++++++++++++++ src/include/sof/dma.h | 7 +++++++ 3 files changed, 46 insertions(+)
diff --git a/src/drivers/dw-dma.c b/src/drivers/dw-dma.c index c064330..0ed742f 100644 --- a/src/drivers/dw-dma.c +++ b/src/drivers/dw-dma.c @@ -289,6 +289,24 @@ static inline void dw_update_bits(struct dma *dma, uint32_t reg, uint32_t mask, io_reg_update_bits(dma_base(dma) + reg, mask, value); }
+/* get the number of DMA channels in use */ +static int dw_dma_channel_status(struct dma *dma) +{
struct dma_pdata *p = dma_get_drvdata(dma);
int i, count = 0;
trace_dma("Dct");
for (i = 0; i < DW_MAX_CHAN; i++) {
/* find channels in use */
if (p->chan[i].status != COMP_STATE_INIT)
count++;
}
return count;
+}
Easier and quicker just to store this as data and atomically inc/dec via channel get()/put().
Liam
On 2018年06月05日 12:23, Ranjani Sridharan wrote:
This patch adds a new dma op for retreiving the number of channels in use in a given DMAC. This will be useful in providing basic and primitive QoS while allocating DMAC for various users.
Signed-off-by: Ranjani Sridharan ranjani.sridharan@linux.intel.com
src/drivers/dw-dma.c | 19 +++++++++++++++++++ src/drivers/hda-dma.c | 20 ++++++++++++++++++++ src/include/sof/dma.h | 7 +++++++ 3 files changed, 46 insertions(+)
diff --git a/src/drivers/dw-dma.c b/src/drivers/dw-dma.c index c064330..0ed742f 100644 --- a/src/drivers/dw-dma.c +++ b/src/drivers/dw-dma.c @@ -289,6 +289,24 @@ static inline void dw_update_bits(struct dma *dma, uint32_t reg, uint32_t mask, io_reg_update_bits(dma_base(dma) + reg, mask, value); }
+/* get the number of DMA channels in use */ +static int dw_dma_channel_status(struct dma *dma) +{
- struct dma_pdata *p = dma_get_drvdata(dma);
- int i, count = 0;
- trace_dma("Dct");
- for (i = 0; i < DW_MAX_CHAN; i++) {
/* find channels in use */
if (p->chan[i].status != COMP_STATE_INIT)
count++;
- }
- return count;
+}
- /* allocate next free DMA channel */ static int dw_dma_channel_get(struct dma *dma, int req_chan) {
@@ -1177,6 +1195,7 @@ static int dw_dma_probe(struct dma *dma) const struct dma_ops dw_dma_ops = { .channel_get = dw_dma_channel_get, .channel_put = dw_dma_channel_put,
- .channel_status = dw_dma_channel_status, .start = dw_dma_start, .stop = dw_dma_stop, .pause = dw_dma_pause,
diff --git a/src/drivers/hda-dma.c b/src/drivers/hda-dma.c index 97ea0ef..0e88a35 100644 --- a/src/drivers/hda-dma.c +++ b/src/drivers/hda-dma.c @@ -131,6 +131,24 @@ static int hda_dma_copy(struct dma *dma, int channel, int bytes) return 0; }
+/* get the number of DMA channels in use */ +static int hda_dma_channel_status(struct dma *dma) +{
- struct dma_pdata *p = dma_get_drvdata(dma);
- int i, count = 0;
- trace_host("Dct");
- for (i = 0; i < HDA_DMA_MAX_CHANS; i++) {
/* find channels in use */
if (p->chan[i].status != COMP_STATE_INIT)
count++;
- }
- return count;
+}
- /* acquire the specific DMA channel */ static int hda_dma_channel_get(struct dma *dma, int channel) {
@@ -406,6 +424,7 @@ static int hda_dma_probe(struct dma *dma) const struct dma_ops hda_host_dma_ops = { .channel_get = hda_dma_channel_get, .channel_put = hda_dma_channel_put,
- .channel_status = hda_dma_channel_status, .start = hda_dma_start, .stop = hda_dma_stop, .copy = hda_dma_copy,
@@ -422,6 +441,7 @@ const struct dma_ops hda_host_dma_ops = { const struct dma_ops hda_link_dma_ops = { .channel_get = hda_dma_channel_get, .channel_put = hda_dma_channel_put,
- .channel_status = hda_dma_channel_status, .start = hda_dma_start, .stop = hda_dma_stop, .copy = hda_dma_copy,
diff --git a/src/include/sof/dma.h b/src/include/sof/dma.h index 80ca880..1de9efc 100644 --- a/src/include/sof/dma.h +++ b/src/include/sof/dma.h @@ -93,6 +93,7 @@ struct dma_ops {
int (*channel_get)(struct dma *dma, int req_channel); void (*channel_put)(struct dma *dma, int channel);
- int (*channel_status)(struct dma *dma);
get_free_channels()? channel_status() is not explicit enough.
Thanks, ~Keyon
int (*start)(struct dma *dma, int channel); int (*stop)(struct dma *dma, int channel); @@ -178,6 +179,12 @@ static inline void dma_channel_put(struct dma *dma, int channel) dma->ops->channel_put(dma, channel); }
+/* get the number of DMA channels in use */ +static inline int dma_channel_status(struct dma *dma) +{
- return dma->ops->channel_status(dma);
+}
- static inline int dma_set_cb(struct dma *dma, int channel, int type, void (*cb)(void *data, uint32_t type, struct dma_sg_elem *next), void *data) {
This patch introduces a new API for procuring DMAC for various user based on the type of DMAC, copy direction and other flags for share/exclusive access. It defines the necessary DMAC user types, copy direction and the flags to suuport the new API.It also adds two new members to dma_plat_data to differentiate the DMAC based on usage and copy direction.
Finally, it also contains the platform specific implementation of the new dma_get() API.
Signed-off-by: Ranjani Sridharan ranjani.sridharan@linux.intel.com --- src/include/sof/dma.h | 26 ++++++++++++++++- src/platform/apollolake/dma.c | 53 ++++++++++++++++++++++++++++++++--- src/platform/baytrail/dma.c | 41 ++++++++++++++++++++++++--- src/platform/cannonlake/dma.c | 53 ++++++++++++++++++++++++++++++++--- src/platform/haswell/dma.c | 49 ++++++++++++++++++++++++++------ 5 files changed, 201 insertions(+), 21 deletions(-)
diff --git a/src/include/sof/dma.h b/src/include/sof/dma.h index 1de9efc..25581e6 100644 --- a/src/include/sof/dma.h +++ b/src/include/sof/dma.h @@ -48,6 +48,28 @@ enum dma_copy_dir { DMA_DIR_DEV_TO_DEV, };
+/* + * DMAC copy directions + * These are used to specify the copy direction while requesting a DMAC + */ +enum dmac_copy_dir { + DMAC_DIR_READ = 0, + DMAC_DIR_WRITE, + DMAC_DIR_DUPLEX, +}; + +/* DMAC user types */ +enum dmac_user { + DMAC_USER_HOST_DMA = 0, + DMAC_USER_LINK_DMA, + DMAC_USER_GP_LP_DMA, + DMAC_USER_GP_HP_DMA, +}; + +/* DMAC flags */ +#define DMAC_FLAGS_SHARED 0 +#define DMAC_FLAGS_EXCLUSIVE (1 << 0) + /* DMA IRQ types */ #define DMA_IRQ_TYPE_BLOCK (1 << 0) #define DMA_IRQ_TYPE_LLIST (1 << 1) @@ -119,6 +141,8 @@ struct dma_ops { /* DMA platform data */ struct dma_plat_data { uint32_t id; + enum dmac_user type; + enum dmac_copy_dir copy_dir; uint32_t base; uint32_t channels; uint32_t irq; @@ -139,7 +163,7 @@ struct dma_int { uint32_t irq; };
-struct dma *dma_get(int dmac_id); +struct dma *dma_get(enum dmac_user, enum dmac_copy_dir, int flags);
/* initialize all platform DMAC's */ void dmac_init(void); diff --git a/src/platform/apollolake/dma.c b/src/platform/apollolake/dma.c index 001bb67..1ae097e 100644 --- a/src/platform/apollolake/dma.c +++ b/src/platform/apollolake/dma.c @@ -112,6 +112,8 @@ static struct dma dma[] = { { /* Low Power GP DMAC 0 */ .plat_data = { .id = DMA_GP_LP_DMAC0, + .type = DMAC_USER_GP_LP_DMA, + .copy_dir = DMAC_DIR_DUPLEX, .base = LP_GP_DMA_BASE(0), .channels = 8, .irq = IRQ_EXT_LP_GPDMA0_LVL5(0, 0), @@ -122,6 +124,8 @@ static struct dma dma[] = { { /* Low Power GP DMAC 1 */ .plat_data = { .id = DMA_GP_LP_DMAC1, + .type = DMAC_USER_GP_LP_DMA, + .copy_dir = DMAC_DIR_DUPLEX, .base = LP_GP_DMA_BASE(1), .channels = 8, .irq = IRQ_EXT_LP_GPDMA1_LVL5(0, 0), @@ -132,6 +136,8 @@ static struct dma dma[] = { { /* Host In DMAC */ .plat_data = { .id = DMA_HOST_IN_DMAC, + .type = DMAC_USER_HOST_DMA, + .copy_dir = DMAC_DIR_WRITE, .base = GTW_HOST_IN_STREAM_BASE(0), .channels = 7, .irq = IRQ_EXT_HOST_DMA_IN_LVL3(0, 0), @@ -142,6 +148,8 @@ static struct dma dma[] = { { /* Host out DMAC */ .plat_data = { .id = DMA_HOST_OUT_DMAC, + .type = DMAC_USER_HOST_DMA, + .copy_dir = DMAC_DIR_READ, .base = GTW_HOST_OUT_STREAM_BASE(0), .channels = 6, .irq = IRQ_EXT_HOST_DMA_OUT_LVL3(0, 0), @@ -152,6 +160,8 @@ static struct dma dma[] = { { /* Link In DMAC */ .plat_data = { .id = DMA_LINK_IN_DMAC, + .type = DMAC_USER_LINK_DMA, + .copy_dir = DMAC_DIR_WRITE, .base = GTW_LINK_IN_STREAM_BASE(0), .channels = 8, .irq = IRQ_EXT_LINK_DMA_IN_LVL4(0, 0), @@ -162,6 +172,8 @@ static struct dma dma[] = { { /* Link out DMAC */ .plat_data = { .id = DMA_LINK_OUT_DMAC, + .type = DMAC_USER_LINK_DMA, + .copy_dir = DMAC_DIR_READ, .base = GTW_LINK_OUT_STREAM_BASE(0), .channels = 8, .irq = IRQ_EXT_LINK_DMA_OUT_LVL4(0, 0), @@ -170,15 +182,48 @@ static struct dma dma[] = { .ops = &hda_link_dma_ops, },};
-struct dma *dma_get(int dmac_id) +/* + * get DMAC based on user type, copy dir and flags + * "flags" is used to set the type of access requested + * (ex: shared/exclusive access) + */ +struct dma *dma_get(enum dmac_user user, enum dmac_copy_dir dir, int flags) { - int i; + int i, ch_count; + int dma_index = -1; + int min_ch_count = INT32_MAX;
for (i = 0; i < ARRAY_SIZE(dma); i++) { - if (dma[i].plat_data.id == dmac_id) - return &dma[i]; + + /* check DMAC user type */ + if (dma[i].plat_data.type != user) + continue; + + /* check DMAC copy dir */ + if (dma[i].plat_data.copy_dir != dir) + continue; + + /* if exclusive access is requested */ + if (flags & DMAC_FLAGS_EXCLUSIVE) { + + /* ret DMA with no channel in use */ + if (!dma_channel_status(&dma[i])) + return &dma[i]; + } else { + /* get number of channels in use */ + ch_count = dma_channel_status(&dma[i]); + + /* Use this DMAC if its channel count is lower */ + if (ch_count < min_ch_count) { + dma_index = i; + min_ch_count = ch_count; + } + } }
+ if (dma_index >= 0) + return &dma[dma_index]; + return NULL; }
diff --git a/src/platform/baytrail/dma.c b/src/platform/baytrail/dma.c index 5a0b650..71ea241 100644 --- a/src/platform/baytrail/dma.c +++ b/src/platform/baytrail/dma.c @@ -175,15 +175,48 @@ static struct dma dma[] = { #endif };
-struct dma *dma_get(int dmac_id) +/* + * get DMAC based on user type, copy dir and flags + * For BYT/CHT, ignore the dmac_user and copy_dir arguments + * "flags" is used to set the type of access requested + * (ex: shared/exclusive access) + */ +struct dma *dma_get(enum dmac_user user, enum dmac_copy_dir dir, int flags) { - int i; + int i, ch_count; + int min_ch_count = INT32_MAX; + int dma_index = -1;
for (i = 0; i < ARRAY_SIZE(dma); i++) { - if (dma[i].plat_data.id == dmac_id) - return &dma[i]; + + /* if exclusive access is requested */ + if (flags & DMAC_FLAGS_EXCLUSIVE) { + + /* ret DMA with no channel in use */ + if (!dma_channel_status(&dma[i])) + return &dma[i]; + } else { + + /* + * for shared access requests, return DMAC + * with the least number of channels in use + */ + + /* get number of channels in use for this DMAC*/ + ch_count = dma_channel_status(&dma[i]); + + /* Use this DMAC if its channel count is lower */ + if (ch_count < min_ch_count) { + dma_index = i; + min_ch_count = ch_count; + } + } }
+ /* return DMAC */ + if (dma_index >= 0) + return &dma[dma_index]; + return NULL; }
diff --git a/src/platform/cannonlake/dma.c b/src/platform/cannonlake/dma.c index 9031c17..697b9a8 100644 --- a/src/platform/cannonlake/dma.c +++ b/src/platform/cannonlake/dma.c @@ -113,6 +113,8 @@ static struct dma dma[] = { { /* Low Power GP DMAC 0 */ .plat_data = { .id = DMA_GP_LP_DMAC0, + .type = DMAC_USER_GP_LP_DMA, + .copy_dir = DMAC_DIR_DUPLEX, .base = LP_GP_DMA_BASE(0), .channels = 8, .irq = IRQ_EXT_LP_GPDMA0_LVL5(0, 0), @@ -123,6 +125,8 @@ static struct dma dma[] = { { /* Low Power GP DMAC 1 */ .plat_data = { .id = DMA_GP_LP_DMAC1, + .type = DMAC_USER_GP_LP_DMA, + .copy_dir = DMAC_DIR_DUPLEX, .base = LP_GP_DMA_BASE(1), .channels = 8, .irq = IRQ_EXT_LP_GPDMA1_LVL5(0, 0), @@ -133,6 +137,8 @@ static struct dma dma[] = { { /* Host In DMAC */ .plat_data = { .id = DMA_HOST_IN_DMAC, + .type = DMAC_USER_HOST_DMA, + .copy_dir = DMAC_DIR_WRITE, .base = GTW_HOST_IN_STREAM_BASE(0), .channels = 7, .irq = IRQ_EXT_HOST_DMA_IN_LVL3(0, 0), @@ -143,6 +149,8 @@ static struct dma dma[] = { { /* Host out DMAC */ .plat_data = { .id = DMA_HOST_OUT_DMAC, + .type = DMAC_USER_HOST_DMA, + .copy_dir = DMAC_DIR_READ, .base = GTW_HOST_OUT_STREAM_BASE(0), .channels = 9, .irq = IRQ_EXT_HOST_DMA_OUT_LVL3(0, 0), @@ -153,6 +161,8 @@ static struct dma dma[] = { { /* Link In DMAC */ .plat_data = { .id = DMA_LINK_IN_DMAC, + .type = DMAC_USER_LINK_DMA, + .copy_dir = DMAC_DIR_WRITE, .base = GTW_LINK_IN_STREAM_BASE(0), .channels = 9, .irq = IRQ_EXT_LINK_DMA_IN_LVL4(0, 0), @@ -163,6 +173,8 @@ static struct dma dma[] = { { /* Link out DMAC */ .plat_data = { .id = DMA_LINK_OUT_DMAC, + .type = DMAC_USER_LINK_DMA, + .copy_dir = DMAC_DIR_READ, .base = GTW_LINK_OUT_STREAM_BASE(0), .channels = 7, .irq = IRQ_EXT_LINK_DMA_OUT_LVL4(0, 0), @@ -171,15 +183,48 @@ static struct dma dma[] = { .ops = &hda_link_dma_ops, },};
-struct dma *dma_get(int dmac_id) +/* + * get DMAC based on user type, copy dir and flags + * "flags" is used to set the type of access requested + * (ex: shared/exclusive access) + */ +struct dma *dma_get(enum dmac_user user, enum dmac_copy_dir dir, int flags) { - int i; + int i, ch_count; + int dma_index = -1; + int min_ch_count = INT32_MAX;
for (i = 0; i < ARRAY_SIZE(dma); i++) { - if (dma[i].plat_data.id == dmac_id) - return &dma[i]; + + /* check DMAC user type */ + if (dma[i].plat_data.type != user) + continue; + + /* check DMAC copy dir */ + if (dma[i].plat_data.copy_dir != dir) + continue; + + /* if exclusive access is requested */ + if (flags & DMAC_FLAGS_EXCLUSIVE) { + + /* ret DMA with no channel in use */ + if (!dma_channel_status(&dma[i])) + return &dma[i]; + } else { + /* get number of channels in use */ + ch_count = dma_channel_status(&dma[i]); + + /* Use this DMAC if its channel count is lower */ + if (ch_count < min_ch_count) { + dma_index = i; + min_ch_count = ch_count; + } + } }
+ if (dma_index >= 0) + return &dma[dma_index]; + return NULL; }
diff --git a/src/platform/haswell/dma.c b/src/platform/haswell/dma.c index 5d1e308..9138e78 100644 --- a/src/platform/haswell/dma.c +++ b/src/platform/haswell/dma.c @@ -124,16 +124,49 @@ static struct dma dma[] = { .ops = &dw_dma_ops, },};
-struct dma *dma_get(int dmac_id) +/* + * get DMAC based on user type, copy dir and flags + * For BYT/CHT, ignore the dmac_user and copy_dir arguments + * "flags" is used to set the type of access requested + * (ex: shared/exclusive access) + */ +struct dma *dma_get(enum dmac_user user, enum dmac_copy_dir dir, int flags) { - switch (dmac_id) { - case DMA_ID_DMAC0: - return &dma[0]; - case DMA_ID_DMAC1: - return &dma[1]; - default: - return NULL; + int i, ch_count; + int min_ch_count = INT32_MAX; + int dma_index = -1; + + for (i = 0; i < ARRAY_SIZE(dma); i++) { + + /* if exclusive access is requested */ + if (flags & DMAC_FLAGS_EXCLUSIVE) { + + /* ret DMA with no channel in use */ + if (!dma_channel_status(&dma[i])) + return &dma[i]; + } else { + + /* + * for shared access requests, return DMAC + * with the least number of channels in use + */ + + /* get number of channels in use for this DMAC*/ + ch_count = dma_channel_status(&dma[i]); + + /* Use this DMAC if its channel count is lower */ + if (ch_count < min_ch_count) { + dma_index = i; + min_ch_count = ch_count; + } + } } + + /* return DMAC */ + if (dma_index >= 0) + return &dma[dma_index]; + + return NULL; }
/* Initialize all platform DMAC's */
On 6/5/2018 12:23 PM, Ranjani Sridharan wrote:
This patch introduces a new API for procuring DMAC for various user based on the type of DMAC, copy direction and other flags for share/exclusive access. It defines the necessary DMAC user types, copy direction and the flags to suuport the new API.It also adds two new members to dma_plat_data to differentiate the DMAC based on usage and copy direction.
Finally, it also contains the platform specific implementation of the new dma_get() API.
Signed-off-by: Ranjani Sridharan ranjani.sridharan@linux.intel.com
src/include/sof/dma.h | 26 ++++++++++++++++- src/platform/apollolake/dma.c | 53 ++++++++++++++++++++++++++++++++--- src/platform/baytrail/dma.c | 41 ++++++++++++++++++++++++--- src/platform/cannonlake/dma.c | 53 ++++++++++++++++++++++++++++++++--- src/platform/haswell/dma.c | 49 ++++++++++++++++++++++++++------ 5 files changed, 201 insertions(+), 21 deletions(-)
diff --git a/src/include/sof/dma.h b/src/include/sof/dma.h index 1de9efc..25581e6 100644 --- a/src/include/sof/dma.h +++ b/src/include/sof/dma.h @@ -48,6 +48,28 @@ enum dma_copy_dir { DMA_DIR_DEV_TO_DEV, };
+/*
- DMAC copy directions
- These are used to specify the copy direction while requesting a DMAC
- */
+enum dmac_copy_dir {
- DMAC_DIR_READ = 0,
- DMAC_DIR_WRITE,
- DMAC_DIR_DUPLEX,
+};
On HSW and BDW, one difference between two DMA. Both DMA support Memory to memory copy,
but DMA two supports memory <=> device copy. So MEM_TO_DEV, DEV_TO_MEM, HOST_TO_MEM ...
should be added for this case.
+/* DMAC user types */ +enum dmac_user {
- DMAC_USER_HOST_DMA = 0,
- DMAC_USER_LINK_DMA,
- DMAC_USER_GP_LP_DMA,
- DMAC_USER_GP_HP_DMA,
+};
+/* DMAC flags */ +#define DMAC_FLAGS_SHARED 0 +#define DMAC_FLAGS_EXCLUSIVE (1 << 0)
- /* DMA IRQ types */ #define DMA_IRQ_TYPE_BLOCK (1 << 0) #define DMA_IRQ_TYPE_LLIST (1 << 1)
@@ -119,6 +141,8 @@ struct dma_ops { /* DMA platform data */ struct dma_plat_data { uint32_t id;
- enum dmac_user type;
- enum dmac_copy_dir copy_dir; uint32_t base; uint32_t channels; uint32_t irq;
@@ -139,7 +163,7 @@ struct dma_int { uint32_t irq; };
-struct dma *dma_get(int dmac_id); +struct dma *dma_get(enum dmac_user, enum dmac_copy_dir, int flags);
/* initialize all platform DMAC's */ void dmac_init(void); diff --git a/src/platform/apollolake/dma.c b/src/platform/apollolake/dma.c index 001bb67..1ae097e 100644 --- a/src/platform/apollolake/dma.c +++ b/src/platform/apollolake/dma.c @@ -112,6 +112,8 @@ static struct dma dma[] = { { /* Low Power GP DMAC 0 */ .plat_data = { .id = DMA_GP_LP_DMAC0,
.type = DMAC_USER_GP_LP_DMA,
.base = LP_GP_DMA_BASE(0), .channels = 8, .irq = IRQ_EXT_LP_GPDMA0_LVL5(0, 0),.copy_dir = DMAC_DIR_DUPLEX,
@@ -122,6 +124,8 @@ static struct dma dma[] = { { /* Low Power GP DMAC 1 */ .plat_data = { .id = DMA_GP_LP_DMAC1,
.type = DMAC_USER_GP_LP_DMA,
.base = LP_GP_DMA_BASE(1), .channels = 8, .irq = IRQ_EXT_LP_GPDMA1_LVL5(0, 0),.copy_dir = DMAC_DIR_DUPLEX,
@@ -132,6 +136,8 @@ static struct dma dma[] = { { /* Host In DMAC */ .plat_data = { .id = DMA_HOST_IN_DMAC,
.type = DMAC_USER_HOST_DMA,
.base = GTW_HOST_IN_STREAM_BASE(0), .channels = 7, .irq = IRQ_EXT_HOST_DMA_IN_LVL3(0, 0),.copy_dir = DMAC_DIR_WRITE,
@@ -142,6 +148,8 @@ static struct dma dma[] = { { /* Host out DMAC */ .plat_data = { .id = DMA_HOST_OUT_DMAC,
.type = DMAC_USER_HOST_DMA,
.base = GTW_HOST_OUT_STREAM_BASE(0), .channels = 6, .irq = IRQ_EXT_HOST_DMA_OUT_LVL3(0, 0),.copy_dir = DMAC_DIR_READ,
@@ -152,6 +160,8 @@ static struct dma dma[] = { { /* Link In DMAC */ .plat_data = { .id = DMA_LINK_IN_DMAC,
.type = DMAC_USER_LINK_DMA,
.base = GTW_LINK_IN_STREAM_BASE(0), .channels = 8, .irq = IRQ_EXT_LINK_DMA_IN_LVL4(0, 0),.copy_dir = DMAC_DIR_WRITE,
@@ -162,6 +172,8 @@ static struct dma dma[] = { { /* Link out DMAC */ .plat_data = { .id = DMA_LINK_OUT_DMAC,
.type = DMAC_USER_LINK_DMA,
.base = GTW_LINK_OUT_STREAM_BASE(0), .channels = 8, .irq = IRQ_EXT_LINK_DMA_OUT_LVL4(0, 0),.copy_dir = DMAC_DIR_READ,
@@ -170,15 +182,48 @@ static struct dma dma[] = { .ops = &hda_link_dma_ops, },};
-struct dma *dma_get(int dmac_id) +/*
- get DMAC based on user type, copy dir and flags
- "flags" is used to set the type of access requested
- (ex: shared/exclusive access)
- */
+struct dma *dma_get(enum dmac_user user, enum dmac_copy_dir dir, int flags) {
- int i;
int i, ch_count;
int dma_index = -1;
int min_ch_count = INT32_MAX;
for (i = 0; i < ARRAY_SIZE(dma); i++) {
if (dma[i].plat_data.id == dmac_id)
return &dma[i];
/* check DMAC user type */
if (dma[i].plat_data.type != user)
continue;
/* check DMAC copy dir */
if (dma[i].plat_data.copy_dir != dir)
continue;
/* if exclusive access is requested */
if (flags & DMAC_FLAGS_EXCLUSIVE) {
/* ret DMA with no channel in use */
if (!dma_channel_status(&dma[i]))
return &dma[i];
} else {
/* get number of channels in use */
ch_count = dma_channel_status(&dma[i]);
/* Use this DMAC if its channel count is lower */
if (ch_count < min_ch_count) {
dma_index = i;
min_ch_count = ch_count;
}
}
}
if (dma_index >= 0)
return &dma[dma_index];
return NULL; }
diff --git a/src/platform/baytrail/dma.c b/src/platform/baytrail/dma.c index 5a0b650..71ea241 100644 --- a/src/platform/baytrail/dma.c +++ b/src/platform/baytrail/dma.c @@ -175,15 +175,48 @@ static struct dma dma[] = { #endif };
-struct dma *dma_get(int dmac_id) +/*
- get DMAC based on user type, copy dir and flags
- For BYT/CHT, ignore the dmac_user and copy_dir arguments
- "flags" is used to set the type of access requested
- (ex: shared/exclusive access)
- */
+struct dma *dma_get(enum dmac_user user, enum dmac_copy_dir dir, int flags) {
- int i;
int i, ch_count;
int min_ch_count = INT32_MAX;
int dma_index = -1;
for (i = 0; i < ARRAY_SIZE(dma); i++) {
if (dma[i].plat_data.id == dmac_id)
return &dma[i];
/* if exclusive access is requested */
if (flags & DMAC_FLAGS_EXCLUSIVE) {
/* ret DMA with no channel in use */
if (!dma_channel_status(&dma[i]))
return &dma[i];
} else {
/*
* for shared access requests, return DMAC
* with the least number of channels in use
*/
/* get number of channels in use for this DMAC*/
ch_count = dma_channel_status(&dma[i]);
/* Use this DMAC if its channel count is lower */
if (ch_count < min_ch_count) {
dma_index = i;
min_ch_count = ch_count;
}
}
}
/* return DMAC */
if (dma_index >= 0)
return &dma[dma_index];
return NULL; }
diff --git a/src/platform/cannonlake/dma.c b/src/platform/cannonlake/dma.c index 9031c17..697b9a8 100644 --- a/src/platform/cannonlake/dma.c +++ b/src/platform/cannonlake/dma.c @@ -113,6 +113,8 @@ static struct dma dma[] = { { /* Low Power GP DMAC 0 */ .plat_data = { .id = DMA_GP_LP_DMAC0,
.type = DMAC_USER_GP_LP_DMA,
.base = LP_GP_DMA_BASE(0), .channels = 8, .irq = IRQ_EXT_LP_GPDMA0_LVL5(0, 0),.copy_dir = DMAC_DIR_DUPLEX,
@@ -123,6 +125,8 @@ static struct dma dma[] = { { /* Low Power GP DMAC 1 */ .plat_data = { .id = DMA_GP_LP_DMAC1,
.type = DMAC_USER_GP_LP_DMA,
.base = LP_GP_DMA_BASE(1), .channels = 8, .irq = IRQ_EXT_LP_GPDMA1_LVL5(0, 0),.copy_dir = DMAC_DIR_DUPLEX,
@@ -133,6 +137,8 @@ static struct dma dma[] = { { /* Host In DMAC */ .plat_data = { .id = DMA_HOST_IN_DMAC,
.type = DMAC_USER_HOST_DMA,
.base = GTW_HOST_IN_STREAM_BASE(0), .channels = 7, .irq = IRQ_EXT_HOST_DMA_IN_LVL3(0, 0),.copy_dir = DMAC_DIR_WRITE,
@@ -143,6 +149,8 @@ static struct dma dma[] = { { /* Host out DMAC */ .plat_data = { .id = DMA_HOST_OUT_DMAC,
.type = DMAC_USER_HOST_DMA,
.base = GTW_HOST_OUT_STREAM_BASE(0), .channels = 9, .irq = IRQ_EXT_HOST_DMA_OUT_LVL3(0, 0),.copy_dir = DMAC_DIR_READ,
@@ -153,6 +161,8 @@ static struct dma dma[] = { { /* Link In DMAC */ .plat_data = { .id = DMA_LINK_IN_DMAC,
.type = DMAC_USER_LINK_DMA,
.base = GTW_LINK_IN_STREAM_BASE(0), .channels = 9, .irq = IRQ_EXT_LINK_DMA_IN_LVL4(0, 0),.copy_dir = DMAC_DIR_WRITE,
@@ -163,6 +173,8 @@ static struct dma dma[] = { { /* Link out DMAC */ .plat_data = { .id = DMA_LINK_OUT_DMAC,
.type = DMAC_USER_LINK_DMA,
.base = GTW_LINK_OUT_STREAM_BASE(0), .channels = 7, .irq = IRQ_EXT_LINK_DMA_OUT_LVL4(0, 0),.copy_dir = DMAC_DIR_READ,
@@ -171,15 +183,48 @@ static struct dma dma[] = { .ops = &hda_link_dma_ops, },};
-struct dma *dma_get(int dmac_id) +/*
- get DMAC based on user type, copy dir and flags
- "flags" is used to set the type of access requested
- (ex: shared/exclusive access)
- */
+struct dma *dma_get(enum dmac_user user, enum dmac_copy_dir dir, int flags) {
- int i;
int i, ch_count;
int dma_index = -1;
int min_ch_count = INT32_MAX;
for (i = 0; i < ARRAY_SIZE(dma); i++) {
if (dma[i].plat_data.id == dmac_id)
return &dma[i];
/* check DMAC user type */
if (dma[i].plat_data.type != user)
continue;
/* check DMAC copy dir */
if (dma[i].plat_data.copy_dir != dir)
continue;
/* if exclusive access is requested */
if (flags & DMAC_FLAGS_EXCLUSIVE) {
/* ret DMA with no channel in use */
if (!dma_channel_status(&dma[i]))
return &dma[i];
} else {
/* get number of channels in use */
ch_count = dma_channel_status(&dma[i]);
/* Use this DMAC if its channel count is lower */
if (ch_count < min_ch_count) {
dma_index = i;
min_ch_count = ch_count;
}
}
}
if (dma_index >= 0)
return &dma[dma_index];
return NULL; }
diff --git a/src/platform/haswell/dma.c b/src/platform/haswell/dma.c index 5d1e308..9138e78 100644 --- a/src/platform/haswell/dma.c +++ b/src/platform/haswell/dma.c @@ -124,16 +124,49 @@ static struct dma dma[] = { .ops = &dw_dma_ops, },};
-struct dma *dma_get(int dmac_id) +/*
- get DMAC based on user type, copy dir and flags
- For BYT/CHT, ignore the dmac_user and copy_dir arguments
- "flags" is used to set the type of access requested
- (ex: shared/exclusive access)
- */
+struct dma *dma_get(enum dmac_user user, enum dmac_copy_dir dir, int flags) {
- switch (dmac_id) {
- case DMA_ID_DMAC0:
return &dma[0];
- case DMA_ID_DMAC1:
return &dma[1];
- default:
return NULL;
int i, ch_count;
int min_ch_count = INT32_MAX;
int dma_index = -1;
for (i = 0; i < ARRAY_SIZE(dma); i++) {
/* if exclusive access is requested */
if (flags & DMAC_FLAGS_EXCLUSIVE) {
/* ret DMA with no channel in use */
if (!dma_channel_status(&dma[i]))
return &dma[i];
} else {
/*
* for shared access requests, return DMAC
* with the least number of channels in use
*/
/* get number of channels in use for this DMAC*/
ch_count = dma_channel_status(&dma[i]);
/* Use this DMAC if its channel count is lower */
if (ch_count < min_ch_count) {
dma_index = i;
min_ch_count = ch_count;
}
}
}
/* return DMAC */
if (dma_index >= 0)
return &dma[dma_index];
return NULL; }
/* Initialize all platform DMAC's */
On Tue, 2018-06-05 at 16:14 +0800, rander.wang wrote:
On 6/5/2018 12:23 PM, Ranjani Sridharan wrote:
This patch introduces a new API for procuring DMAC for various user based on the type of DMAC, copy direction and other flags for share/exclusive access. It defines the necessary DMAC user types, copy direction and the flags to suuport the new API.It also adds two new members to dma_plat_data to differentiate the DMAC based on usage and copy direction.
Finally, it also contains the platform specific implementation of the new dma_get() API.
Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com
src/include/sof/dma.h | 26 ++++++++++++++++- src/platform/apollolake/dma.c | 53 ++++++++++++++++++++++++++++++++--- src/platform/baytrail/dma.c | 41 ++++++++++++++++++++++++--- src/platform/cannonlake/dma.c | 53 ++++++++++++++++++++++++++++++++--- src/platform/haswell/dma.c | 49 ++++++++++++++++++++++++++-----
5 files changed, 201 insertions(+), 21 deletions(-)
diff --git a/src/include/sof/dma.h b/src/include/sof/dma.h index 1de9efc..25581e6 100644 --- a/src/include/sof/dma.h +++ b/src/include/sof/dma.h @@ -48,6 +48,28 @@ enum dma_copy_dir { DMA_DIR_DEV_TO_DEV, };
+/*
- DMAC copy directions
- These are used to specify the copy direction while requesting a
DMAC
- */
+enum dmac_copy_dir {
- DMAC_DIR_READ = 0,
- DMAC_DIR_WRITE,
- DMAC_DIR_DUPLEX,
+};
On HSW and BDW, one difference between two DMA. Both DMA support Memory to memory copy, but DMA two supports memory <=> device copy. So MEM_TO_DEV, DEV_TO_MEM, HOST_TO_MEM ... should be added for this case.
Rander, there's another enum called dma_copy_dir() which defines those. Are you suggesting we qualify each DMAC with its capabilities in terms of dma_copy_dir as well?
+/* DMAC user types */ +enum dmac_user {
- DMAC_USER_HOST_DMA = 0,
- DMAC_USER_LINK_DMA,
- DMAC_USER_GP_LP_DMA,
- DMAC_USER_GP_HP_DMA,
+};
+/* DMAC flags */ +#define DMAC_FLAGS_SHARED 0 +#define DMAC_FLAGS_EXCLUSIVE (1 << 0)
/* DMA IRQ types */ #define DMA_IRQ_TYPE_BLOCK (1 << 0) #define DMA_IRQ_TYPE_LLIST (1 << 1) @@ -119,6 +141,8 @@ struct dma_ops { /* DMA platform data */ struct dma_plat_data { uint32_t id;
- enum dmac_user type;
- enum dmac_copy_dir copy_dir; uint32_t base; uint32_t channels; uint32_t irq;
@@ -139,7 +163,7 @@ struct dma_int { uint32_t irq; };
-struct dma *dma_get(int dmac_id); +struct dma *dma_get(enum dmac_user, enum dmac_copy_dir, int flags);
/* initialize all platform DMAC's */ void dmac_init(void); diff --git a/src/platform/apollolake/dma.c b/src/platform/apollolake/dma.c index 001bb67..1ae097e 100644 --- a/src/platform/apollolake/dma.c +++ b/src/platform/apollolake/dma.c @@ -112,6 +112,8 @@ static struct dma dma[] = { { /* Low Power GP DMAC 0 */ .plat_data = { .id = DMA_GP_LP_DMAC0,
.type = DMAC_USER_GP_LP_DMA,
.base = LP_GP_DMA_BASE(0), .channels = 8, .irq = IRQ_EXT_LP_GPDMA0_LVL5(0,.copy_dir = DMAC_DIR_DUPLEX,
0), @@ -122,6 +124,8 @@ static struct dma dma[] = { { /* Low Power GP DMAC 1 */ .plat_data = { .id = DMA_GP_LP_DMAC1,
.type = DMAC_USER_GP_LP_DMA,
.base = LP_GP_DMA_BASE(1), .channels = 8, .irq = IRQ_EXT_LP_GPDMA1_LVL5(0,.copy_dir = DMAC_DIR_DUPLEX,
0), @@ -132,6 +136,8 @@ static struct dma dma[] = { { /* Host In DMAC */ .plat_data = { .id = DMA_HOST_IN_DMAC,
.type = DMAC_USER_HOST_DMA,
.base = GTW_HOST_IN_STREAM_BASE(0), .channels = 7, .irq = IRQ_EXT_HOST_DMA_IN_LVL3(0,.copy_dir = DMAC_DIR_WRITE,
0), @@ -142,6 +148,8 @@ static struct dma dma[] = { { /* Host out DMAC */ .plat_data = { .id = DMA_HOST_OUT_DMAC,
.type = DMAC_USER_HOST_DMA,
.base =.copy_dir = DMAC_DIR_READ,
GTW_HOST_OUT_STREAM_BASE(0), .channels = 6, .irq = IRQ_EXT_HOST_DMA_OUT_LVL3(0, 0), @@ -152,6 +160,8 @@ static struct dma dma[] = { { /* Link In DMAC */ .plat_data = { .id = DMA_LINK_IN_DMAC,
.type = DMAC_USER_LINK_DMA,
.base = GTW_LINK_IN_STREAM_BASE(0), .channels = 8, .irq = IRQ_EXT_LINK_DMA_IN_LVL4(0,.copy_dir = DMAC_DIR_WRITE,
0), @@ -162,6 +172,8 @@ static struct dma dma[] = { { /* Link out DMAC */ .plat_data = { .id = DMA_LINK_OUT_DMAC,
.type = DMAC_USER_LINK_DMA,
.base =.copy_dir = DMAC_DIR_READ,
GTW_LINK_OUT_STREAM_BASE(0), .channels = 8, .irq = IRQ_EXT_LINK_DMA_OUT_LVL4(0, 0), @@ -170,15 +182,48 @@ static struct dma dma[] = { .ops = &hda_link_dma_ops, },};
-struct dma *dma_get(int dmac_id) +/*
- get DMAC based on user type, copy dir and flags
- "flags" is used to set the type of access requested
- (ex: shared/exclusive access)
- */
+struct dma *dma_get(enum dmac_user user, enum dmac_copy_dir dir, int flags) {
- int i;
int i, ch_count;
int dma_index = -1;
int min_ch_count = INT32_MAX;
for (i = 0; i < ARRAY_SIZE(dma); i++) {
if (dma[i].plat_data.id == dmac_id)
return &dma[i];
/* check DMAC user type */
if (dma[i].plat_data.type != user)
continue;
/* check DMAC copy dir */
if (dma[i].plat_data.copy_dir != dir)
continue;
/* if exclusive access is requested */
if (flags & DMAC_FLAGS_EXCLUSIVE) {
/* ret DMA with no channel in use */
if (!dma_channel_status(&dma[i]))
return &dma[i];
} else {
/* get number of channels in use */
ch_count = dma_channel_status(&dma[i]);
/* Use this DMAC if its channel count is
lower */
if (ch_count < min_ch_count) {
dma_index = i;
min_ch_count = ch_count;
}
}
}
if (dma_index >= 0)
return &dma[dma_index];
return NULL;
}
diff --git a/src/platform/baytrail/dma.c b/src/platform/baytrail/dma.c index 5a0b650..71ea241 100644 --- a/src/platform/baytrail/dma.c +++ b/src/platform/baytrail/dma.c @@ -175,15 +175,48 @@ static struct dma dma[] = { #endif };
-struct dma *dma_get(int dmac_id) +/*
- get DMAC based on user type, copy dir and flags
- For BYT/CHT, ignore the dmac_user and copy_dir arguments
- "flags" is used to set the type of access requested
- (ex: shared/exclusive access)
- */
+struct dma *dma_get(enum dmac_user user, enum dmac_copy_dir dir, int flags) {
- int i;
int i, ch_count;
int min_ch_count = INT32_MAX;
int dma_index = -1;
for (i = 0; i < ARRAY_SIZE(dma); i++) {
if (dma[i].plat_data.id == dmac_id)
return &dma[i];
/* if exclusive access is requested */
if (flags & DMAC_FLAGS_EXCLUSIVE) {
/* ret DMA with no channel in use */
if (!dma_channel_status(&dma[i]))
return &dma[i];
} else {
/*
* for shared access requests, return DMAC
* with the least number of channels in
use
*/
/* get number of channels in use for this
DMAC*/
ch_count = dma_channel_status(&dma[i]);
/* Use this DMAC if its channel count is
lower */
if (ch_count < min_ch_count) {
dma_index = i;
min_ch_count = ch_count;
}
}
}
/* return DMAC */
if (dma_index >= 0)
return &dma[dma_index];
return NULL;
}
diff --git a/src/platform/cannonlake/dma.c b/src/platform/cannonlake/dma.c index 9031c17..697b9a8 100644 --- a/src/platform/cannonlake/dma.c +++ b/src/platform/cannonlake/dma.c @@ -113,6 +113,8 @@ static struct dma dma[] = { { /* Low Power GP DMAC 0 */ .plat_data = { .id = DMA_GP_LP_DMAC0,
.type = DMAC_USER_GP_LP_DMA,
.base = LP_GP_DMA_BASE(0), .channels = 8, .irq = IRQ_EXT_LP_GPDMA0_LVL5(0, 0),.copy_dir = DMAC_DIR_DUPLEX,
@@ -123,6 +125,8 @@ static struct dma dma[] = { { /* Low Power GP DMAC 1 */ .plat_data = { .id = DMA_GP_LP_DMAC1,
.type = DMAC_USER_GP_LP_DMA,
.base = LP_GP_DMA_BASE(1), .channels = 8, .irq = IRQ_EXT_LP_GPDMA1_LVL5(0, 0),.copy_dir = DMAC_DIR_DUPLEX,
@@ -133,6 +137,8 @@ static struct dma dma[] = { { /* Host In DMAC */ .plat_data = { .id = DMA_HOST_IN_DMAC,
.type = DMAC_USER_HOST_DMA,
.base = GTW_HOST_IN_STREAM_BASE(0), .channels = 7, .irq = IRQ_EXT_HOST_DMA_IN_LVL3(0, 0),.copy_dir = DMAC_DIR_WRITE,
@@ -143,6 +149,8 @@ static struct dma dma[] = { { /* Host out DMAC */ .plat_data = { .id = DMA_HOST_OUT_DMAC,
.type = DMAC_USER_HOST_DMA,
.base =.copy_dir = DMAC_DIR_READ,
GTW_HOST_OUT_STREAM_BASE(0), .channels = 9, .irq = IRQ_EXT_HOST_DMA_OUT_LVL3(0, 0), @@ -153,6 +161,8 @@ static struct dma dma[] = { { /* Link In DMAC */ .plat_data = { .id = DMA_LINK_IN_DMAC,
.type = DMAC_USER_LINK_DMA,
.base = GTW_LINK_IN_STREAM_BASE(0), .channels = 9, .irq = IRQ_EXT_LINK_DMA_IN_LVL4(0, 0),.copy_dir = DMAC_DIR_WRITE,
@@ -163,6 +173,8 @@ static struct dma dma[] = { { /* Link out DMAC */ .plat_data = { .id = DMA_LINK_OUT_DMAC,
.type = DMAC_USER_LINK_DMA,
.base =.copy_dir = DMAC_DIR_READ,
GTW_LINK_OUT_STREAM_BASE(0), .channels = 7, .irq = IRQ_EXT_LINK_DMA_OUT_LVL4(0, 0), @@ -171,15 +183,48 @@ static struct dma dma[] = { .ops = &hda_link_dma_ops, },};
-struct dma *dma_get(int dmac_id) +/*
- get DMAC based on user type, copy dir and flags
- "flags" is used to set the type of access requested
- (ex: shared/exclusive access)
- */
+struct dma *dma_get(enum dmac_user user, enum dmac_copy_dir dir, int flags) {
- int i;
int i, ch_count;
int dma_index = -1;
int min_ch_count = INT32_MAX;
for (i = 0; i < ARRAY_SIZE(dma); i++) {
if (dma[i].plat_data.id == dmac_id)
return &dma[i];
/* check DMAC user type */
if (dma[i].plat_data.type != user)
continue;
/* check DMAC copy dir */
if (dma[i].plat_data.copy_dir != dir)
continue;
/* if exclusive access is requested */
if (flags & DMAC_FLAGS_EXCLUSIVE) {
/* ret DMA with no channel in use */
if (!dma_channel_status(&dma[i]))
return &dma[i];
} else {
/* get number of channels in use */
ch_count = dma_channel_status(&dma[i]);
/* Use this DMAC if its channel count is
lower */
if (ch_count < min_ch_count) {
dma_index = i;
min_ch_count = ch_count;
}
}
}
if (dma_index >= 0)
return &dma[dma_index];
return NULL;
}
diff --git a/src/platform/haswell/dma.c b/src/platform/haswell/dma.c index 5d1e308..9138e78 100644 --- a/src/platform/haswell/dma.c +++ b/src/platform/haswell/dma.c @@ -124,16 +124,49 @@ static struct dma dma[] = { .ops = &dw_dma_ops, },};
-struct dma *dma_get(int dmac_id) +/*
- get DMAC based on user type, copy dir and flags
- For BYT/CHT, ignore the dmac_user and copy_dir arguments
- "flags" is used to set the type of access requested
- (ex: shared/exclusive access)
- */
+struct dma *dma_get(enum dmac_user user, enum dmac_copy_dir dir, int flags) {
- switch (dmac_id) {
- case DMA_ID_DMAC0:
return &dma[0];
- case DMA_ID_DMAC1:
return &dma[1];
- default:
return NULL;
- int i, ch_count;
- int min_ch_count = INT32_MAX;
- int dma_index = -1;
- for (i = 0; i < ARRAY_SIZE(dma); i++) {
/* if exclusive access is requested */
if (flags & DMAC_FLAGS_EXCLUSIVE) {
/* ret DMA with no channel in use */
if (!dma_channel_status(&dma[i]))
return &dma[i];
} else {
/*
* for shared access requests, return DMAC
* with the least number of channels in
use
*/
/* get number of channels in use for this
DMAC*/
ch_count = dma_channel_status(&dma[i]);
/* Use this DMAC if its channel count is
lower */
if (ch_count < min_ch_count) {
dma_index = i;
min_ch_count = ch_count;
}
}}
- /* return DMAC */
- if (dma_index >= 0)
return &dma[dma_index];
- return NULL;
}
/* Initialize all platform DMAC's */
On 6/6/2018 3:12 AM, Ranjani Sridharan wrote:
On Tue, 2018-06-05 at 16:14 +0800, rander.wang wrote:
On 6/5/2018 12:23 PM, Ranjani Sridharan wrote:
This patch introduces a new API for procuring DMAC for various user based on the type of DMAC, copy direction and other flags for share/exclusive access. It defines the necessary DMAC user types, copy direction and the flags to suuport the new API.It also adds two new members to dma_plat_data to differentiate the DMAC based on usage and copy direction.
Finally, it also contains the platform specific implementation of the new dma_get() API.
Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com
src/include/sof/dma.h | 26 ++++++++++++++++- src/platform/apollolake/dma.c | 53 ++++++++++++++++++++++++++++++++--- src/platform/baytrail/dma.c | 41 ++++++++++++++++++++++++--- src/platform/cannonlake/dma.c | 53 ++++++++++++++++++++++++++++++++--- src/platform/haswell/dma.c | 49 ++++++++++++++++++++++++++-----
- 5 files changed, 201 insertions(+), 21 deletions(-)
diff --git a/src/include/sof/dma.h b/src/include/sof/dma.h index 1de9efc..25581e6 100644 --- a/src/include/sof/dma.h +++ b/src/include/sof/dma.h @@ -48,6 +48,28 @@ enum dma_copy_dir { DMA_DIR_DEV_TO_DEV, };
+/*
- DMAC copy directions
- These are used to specify the copy direction while requesting a
DMAC
- */
+enum dmac_copy_dir {
- DMAC_DIR_READ = 0,
- DMAC_DIR_WRITE,
- DMAC_DIR_DUPLEX,
+};
On HSW and BDW, one difference between two DMA. Both DMA support Memory to memory copy, but DMA two supports memory <=> device copy. So MEM_TO_DEV, DEV_TO_MEM, HOST_TO_MEM ... should be added for this case.
Rander, there's another enum called dma_copy_dir() which defines those. Are you suggesting we qualify each DMAC with its capabilities in terms of dma_copy_dir as well?
yes, i find only dam_copy_dir is fit for capabilities. how do you think about it?
+/* DMAC user types */ +enum dmac_user {
- DMAC_USER_HOST_DMA = 0,
- DMAC_USER_LINK_DMA,
- DMAC_USER_GP_LP_DMA,
- DMAC_USER_GP_HP_DMA,
+};
+/* DMAC flags */ +#define DMAC_FLAGS_SHARED 0 +#define DMAC_FLAGS_EXCLUSIVE (1 << 0)
- /* DMA IRQ types */ #define DMA_IRQ_TYPE_BLOCK (1 << 0) #define DMA_IRQ_TYPE_LLIST (1 << 1)
@@ -119,6 +141,8 @@ struct dma_ops { /* DMA platform data */ struct dma_plat_data { uint32_t id;
- enum dmac_user type;
- enum dmac_copy_dir copy_dir; uint32_t base; uint32_t channels; uint32_t irq;
@@ -139,7 +163,7 @@ struct dma_int { uint32_t irq; };
-struct dma *dma_get(int dmac_id); +struct dma *dma_get(enum dmac_user, enum dmac_copy_dir, int flags);
/* initialize all platform DMAC's */ void dmac_init(void); diff --git a/src/platform/apollolake/dma.c b/src/platform/apollolake/dma.c index 001bb67..1ae097e 100644 --- a/src/platform/apollolake/dma.c +++ b/src/platform/apollolake/dma.c @@ -112,6 +112,8 @@ static struct dma dma[] = { { /* Low Power GP DMAC 0 */ .plat_data = { .id = DMA_GP_LP_DMAC0,
.type = DMAC_USER_GP_LP_DMA,
.base = LP_GP_DMA_BASE(0), .channels = 8, .irq = IRQ_EXT_LP_GPDMA0_LVL5(0,.copy_dir = DMAC_DIR_DUPLEX,
0), @@ -122,6 +124,8 @@ static struct dma dma[] = { { /* Low Power GP DMAC 1 */ .plat_data = { .id = DMA_GP_LP_DMAC1,
.type = DMAC_USER_GP_LP_DMA,
.base = LP_GP_DMA_BASE(1), .channels = 8, .irq = IRQ_EXT_LP_GPDMA1_LVL5(0,.copy_dir = DMAC_DIR_DUPLEX,
0), @@ -132,6 +136,8 @@ static struct dma dma[] = { { /* Host In DMAC */ .plat_data = { .id = DMA_HOST_IN_DMAC,
.type = DMAC_USER_HOST_DMA,
.base = GTW_HOST_IN_STREAM_BASE(0), .channels = 7, .irq = IRQ_EXT_HOST_DMA_IN_LVL3(0,.copy_dir = DMAC_DIR_WRITE,
0), @@ -142,6 +148,8 @@ static struct dma dma[] = { { /* Host out DMAC */ .plat_data = { .id = DMA_HOST_OUT_DMAC,
.type = DMAC_USER_HOST_DMA,
.base =.copy_dir = DMAC_DIR_READ,
GTW_HOST_OUT_STREAM_BASE(0), .channels = 6, .irq = IRQ_EXT_HOST_DMA_OUT_LVL3(0, 0), @@ -152,6 +160,8 @@ static struct dma dma[] = { { /* Link In DMAC */ .plat_data = { .id = DMA_LINK_IN_DMAC,
.type = DMAC_USER_LINK_DMA,
.base = GTW_LINK_IN_STREAM_BASE(0), .channels = 8, .irq = IRQ_EXT_LINK_DMA_IN_LVL4(0,.copy_dir = DMAC_DIR_WRITE,
0), @@ -162,6 +172,8 @@ static struct dma dma[] = { { /* Link out DMAC */ .plat_data = { .id = DMA_LINK_OUT_DMAC,
.type = DMAC_USER_LINK_DMA,
.base =.copy_dir = DMAC_DIR_READ,
GTW_LINK_OUT_STREAM_BASE(0), .channels = 8, .irq = IRQ_EXT_LINK_DMA_OUT_LVL4(0, 0), @@ -170,15 +182,48 @@ static struct dma dma[] = { .ops = &hda_link_dma_ops, },};
-struct dma *dma_get(int dmac_id) +/*
- get DMAC based on user type, copy dir and flags
- "flags" is used to set the type of access requested
- (ex: shared/exclusive access)
- */
+struct dma *dma_get(enum dmac_user user, enum dmac_copy_dir dir, int flags) {
- int i;
int i, ch_count;
int dma_index = -1;
int min_ch_count = INT32_MAX;
for (i = 0; i < ARRAY_SIZE(dma); i++) {
if (dma[i].plat_data.id == dmac_id)
return &dma[i];
/* check DMAC user type */
if (dma[i].plat_data.type != user)
continue;
/* check DMAC copy dir */
if (dma[i].plat_data.copy_dir != dir)
continue;
/* if exclusive access is requested */
if (flags & DMAC_FLAGS_EXCLUSIVE) {
/* ret DMA with no channel in use */
if (!dma_channel_status(&dma[i]))
return &dma[i];
} else {
/* get number of channels in use */
ch_count = dma_channel_status(&dma[i]);
/* Use this DMAC if its channel count is
lower */
if (ch_count < min_ch_count) {
dma_index = i;
min_ch_count = ch_count;
}
}
}
if (dma_index >= 0)
return &dma[dma_index];
return NULL; }
diff --git a/src/platform/baytrail/dma.c b/src/platform/baytrail/dma.c index 5a0b650..71ea241 100644 --- a/src/platform/baytrail/dma.c +++ b/src/platform/baytrail/dma.c @@ -175,15 +175,48 @@ static struct dma dma[] = { #endif };
-struct dma *dma_get(int dmac_id) +/*
- get DMAC based on user type, copy dir and flags
- For BYT/CHT, ignore the dmac_user and copy_dir arguments
- "flags" is used to set the type of access requested
- (ex: shared/exclusive access)
- */
+struct dma *dma_get(enum dmac_user user, enum dmac_copy_dir dir, int flags) {
- int i;
int i, ch_count;
int min_ch_count = INT32_MAX;
int dma_index = -1;
for (i = 0; i < ARRAY_SIZE(dma); i++) {
if (dma[i].plat_data.id == dmac_id)
return &dma[i];
/* if exclusive access is requested */
if (flags & DMAC_FLAGS_EXCLUSIVE) {
/* ret DMA with no channel in use */
if (!dma_channel_status(&dma[i]))
return &dma[i];
} else {
/*
* for shared access requests, return DMAC
* with the least number of channels in
use
*/
/* get number of channels in use for this
DMAC*/
ch_count = dma_channel_status(&dma[i]);
/* Use this DMAC if its channel count is
lower */
if (ch_count < min_ch_count) {
dma_index = i;
min_ch_count = ch_count;
}
}
}
/* return DMAC */
if (dma_index >= 0)
return &dma[dma_index];
return NULL; }
diff --git a/src/platform/cannonlake/dma.c b/src/platform/cannonlake/dma.c index 9031c17..697b9a8 100644 --- a/src/platform/cannonlake/dma.c +++ b/src/platform/cannonlake/dma.c @@ -113,6 +113,8 @@ static struct dma dma[] = { { /* Low Power GP DMAC 0 */ .plat_data = { .id = DMA_GP_LP_DMAC0,
.type = DMAC_USER_GP_LP_DMA,
.base = LP_GP_DMA_BASE(0), .channels = 8, .irq = IRQ_EXT_LP_GPDMA0_LVL5(0, 0),.copy_dir = DMAC_DIR_DUPLEX,
@@ -123,6 +125,8 @@ static struct dma dma[] = { { /* Low Power GP DMAC 1 */ .plat_data = { .id = DMA_GP_LP_DMAC1,
.type = DMAC_USER_GP_LP_DMA,
.base = LP_GP_DMA_BASE(1), .channels = 8, .irq = IRQ_EXT_LP_GPDMA1_LVL5(0, 0),.copy_dir = DMAC_DIR_DUPLEX,
@@ -133,6 +137,8 @@ static struct dma dma[] = { { /* Host In DMAC */ .plat_data = { .id = DMA_HOST_IN_DMAC,
.type = DMAC_USER_HOST_DMA,
.base = GTW_HOST_IN_STREAM_BASE(0), .channels = 7, .irq = IRQ_EXT_HOST_DMA_IN_LVL3(0, 0),.copy_dir = DMAC_DIR_WRITE,
@@ -143,6 +149,8 @@ static struct dma dma[] = { { /* Host out DMAC */ .plat_data = { .id = DMA_HOST_OUT_DMAC,
.type = DMAC_USER_HOST_DMA,
.base =.copy_dir = DMAC_DIR_READ,
GTW_HOST_OUT_STREAM_BASE(0), .channels = 9, .irq = IRQ_EXT_HOST_DMA_OUT_LVL3(0, 0), @@ -153,6 +161,8 @@ static struct dma dma[] = { { /* Link In DMAC */ .plat_data = { .id = DMA_LINK_IN_DMAC,
.type = DMAC_USER_LINK_DMA,
.base = GTW_LINK_IN_STREAM_BASE(0), .channels = 9, .irq = IRQ_EXT_LINK_DMA_IN_LVL4(0, 0),.copy_dir = DMAC_DIR_WRITE,
@@ -163,6 +173,8 @@ static struct dma dma[] = { { /* Link out DMAC */ .plat_data = { .id = DMA_LINK_OUT_DMAC,
.type = DMAC_USER_LINK_DMA,
.base =.copy_dir = DMAC_DIR_READ,
GTW_LINK_OUT_STREAM_BASE(0), .channels = 7, .irq = IRQ_EXT_LINK_DMA_OUT_LVL4(0, 0), @@ -171,15 +183,48 @@ static struct dma dma[] = { .ops = &hda_link_dma_ops, },};
-struct dma *dma_get(int dmac_id) +/*
- get DMAC based on user type, copy dir and flags
- "flags" is used to set the type of access requested
- (ex: shared/exclusive access)
- */
+struct dma *dma_get(enum dmac_user user, enum dmac_copy_dir dir, int flags) {
- int i;
int i, ch_count;
int dma_index = -1;
int min_ch_count = INT32_MAX;
for (i = 0; i < ARRAY_SIZE(dma); i++) {
if (dma[i].plat_data.id == dmac_id)
return &dma[i];
/* check DMAC user type */
if (dma[i].plat_data.type != user)
continue;
/* check DMAC copy dir */
if (dma[i].plat_data.copy_dir != dir)
continue;
/* if exclusive access is requested */
if (flags & DMAC_FLAGS_EXCLUSIVE) {
/* ret DMA with no channel in use */
if (!dma_channel_status(&dma[i]))
return &dma[i];
} else {
/* get number of channels in use */
ch_count = dma_channel_status(&dma[i]);
/* Use this DMAC if its channel count is
lower */
if (ch_count < min_ch_count) {
dma_index = i;
min_ch_count = ch_count;
}
}
}
if (dma_index >= 0)
return &dma[dma_index];
return NULL; }
diff --git a/src/platform/haswell/dma.c b/src/platform/haswell/dma.c index 5d1e308..9138e78 100644 --- a/src/platform/haswell/dma.c +++ b/src/platform/haswell/dma.c @@ -124,16 +124,49 @@ static struct dma dma[] = { .ops = &dw_dma_ops, },};
-struct dma *dma_get(int dmac_id) +/*
- get DMAC based on user type, copy dir and flags
- For BYT/CHT, ignore the dmac_user and copy_dir arguments
- "flags" is used to set the type of access requested
- (ex: shared/exclusive access)
- */
+struct dma *dma_get(enum dmac_user user, enum dmac_copy_dir dir, int flags) {
- switch (dmac_id) {
- case DMA_ID_DMAC0:
return &dma[0];
- case DMA_ID_DMAC1:
return &dma[1];
- default:
return NULL;
- int i, ch_count;
- int min_ch_count = INT32_MAX;
- int dma_index = -1;
- for (i = 0; i < ARRAY_SIZE(dma); i++) {
/* if exclusive access is requested */
if (flags & DMAC_FLAGS_EXCLUSIVE) {
/* ret DMA with no channel in use */
if (!dma_channel_status(&dma[i]))
return &dma[i];
} else {
/*
* for shared access requests, return DMAC
* with the least number of channels in
use
*/
/* get number of channels in use for this
DMAC*/
ch_count = dma_channel_status(&dma[i]);
/* Use this DMAC if its channel count is
lower */
if (ch_count < min_ch_count) {
dma_index = i;
min_ch_count = ch_count;
}
}
}
/* return DMAC */
if (dma_index >= 0)
return &dma[dma_index];
return NULL; }
/* Initialize all platform DMAC's */
On Wed, 2018-06-06 at 10:23 +0800, rander.wang wrote:
On 6/6/2018 3:12 AM, Ranjani Sridharan wrote:
On Tue, 2018-06-05 at 16:14 +0800, rander.wang wrote:
On 6/5/2018 12:23 PM, Ranjani Sridharan wrote:
This patch introduces a new API for procuring DMAC for various user based on the type of DMAC, copy direction and other flags for share/exclusive access. It defines the necessary DMAC user types, copy direction and the flags to suuport the new API.It also adds two new members to dma_plat_data to differentiate the DMAC based on usage and copy direction.
Finally, it also contains the platform specific implementation of the new dma_get() API.
Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel .com
src/include/sof/dma.h | 26 ++++++++++++++++- src/platform/apollolake/dma.c | 53 ++++++++++++++++++++++++++++++++--- src/platform/baytrail/dma.c | 41 ++++++++++++++++++++++++
src/platform/cannonlake/dma.c | 53 ++++++++++++++++++++++++++++++++--- src/platform/haswell/dma.c | 49 ++++++++++++++++++++++++++-----
- 5 files changed, 201 insertions(+), 21 deletions(-)
diff --git a/src/include/sof/dma.h b/src/include/sof/dma.h index 1de9efc..25581e6 100644 --- a/src/include/sof/dma.h +++ b/src/include/sof/dma.h @@ -48,6 +48,28 @@ enum dma_copy_dir { DMA_DIR_DEV_TO_DEV, };
+/*
- DMAC copy directions
- These are used to specify the copy direction while
requesting a DMAC
- */
+enum dmac_copy_dir {
- DMAC_DIR_READ = 0,
- DMAC_DIR_WRITE,
- DMAC_DIR_DUPLEX,
+};
On HSW and BDW, one difference between two DMA. Both DMA support Memory to memory copy, but DMA two supports memory <=> device copy. So MEM_TO_DEV, DEV_TO_MEM, HOST_TO_MEM ... should be added for this case.
Rander, there's another enum called dma_copy_dir() which defines those. Are you suggesting we qualify each DMAC with its capabilities in terms of dma_copy_dir as well?
yes, i find only dam_copy_dir is fit for capabilities. how
do you think about it?
OK, keyon has a similar suggestion and I think it makes sense. But he mentioned that for BDW, both DMAC's support all possible caps.
Could you please reply to that and correct if something is wrong? It will be useful for me when I implement. I'll verify with the HAS as well.
+/* DMAC user types */ +enum dmac_user {
- DMAC_USER_HOST_DMA = 0,
- DMAC_USER_LINK_DMA,
- DMAC_USER_GP_LP_DMA,
- DMAC_USER_GP_HP_DMA,
+};
+/* DMAC flags */ +#define DMAC_FLAGS_SHARED 0 +#define DMAC_FLAGS_EXCLUSIVE (1 << 0)
- /* DMA IRQ types */ #define DMA_IRQ_TYPE_BLOCK (1 << 0) #define DMA_IRQ_TYPE_LLIST (1 << 1)
@@ -119,6 +141,8 @@ struct dma_ops { /* DMA platform data */ struct dma_plat_data { uint32_t id;
- enum dmac_user type;
- enum dmac_copy_dir copy_dir; uint32_t base; uint32_t channels; uint32_t irq;
@@ -139,7 +163,7 @@ struct dma_int { uint32_t irq; };
-struct dma *dma_get(int dmac_id); +struct dma *dma_get(enum dmac_user, enum dmac_copy_dir, int flags);
/* initialize all platform DMAC's */ void dmac_init(void); diff --git a/src/platform/apollolake/dma.c b/src/platform/apollolake/dma.c index 001bb67..1ae097e 100644 --- a/src/platform/apollolake/dma.c +++ b/src/platform/apollolake/dma.c @@ -112,6 +112,8 @@ static struct dma dma[] = { { /* Low Power GP DMAC 0 */ .plat_data = { .id = DMA_GP_LP_DMAC0,
.type = DMAC_USER_GP_LP_DMA,
.base = LP_GP_DMA_BASE(0), .channels = 8, .irq =.copy_dir = DMAC_DIR_DUPLEX,
IRQ_EXT_LP_GPDMA0_LVL5(0, 0), @@ -122,6 +124,8 @@ static struct dma dma[] = { { /* Low Power GP DMAC 1 */ .plat_data = { .id = DMA_GP_LP_DMAC1,
.type = DMAC_USER_GP_LP_DMA,
.base = LP_GP_DMA_BASE(1), .channels = 8, .irq =.copy_dir = DMAC_DIR_DUPLEX,
IRQ_EXT_LP_GPDMA1_LVL5(0, 0), @@ -132,6 +136,8 @@ static struct dma dma[] = { { /* Host In DMAC */ .plat_data = { .id = DMA_HOST_IN_DMAC,
.type = DMAC_USER_HOST_DMA,
.base =.copy_dir = DMAC_DIR_WRITE,
GTW_HOST_IN_STREAM_BASE(0), .channels = 7, .irq = IRQ_EXT_HOST_DMA_IN_LVL3(0, 0), @@ -142,6 +148,8 @@ static struct dma dma[] = { { /* Host out DMAC */ .plat_data = { .id = DMA_HOST_OUT_DMAC,
.type = DMAC_USER_HOST_DMA,
.base =.copy_dir = DMAC_DIR_READ,
GTW_HOST_OUT_STREAM_BASE(0), .channels = 6, .irq = IRQ_EXT_HOST_DMA_OUT_LVL3(0, 0), @@ -152,6 +160,8 @@ static struct dma dma[] = { { /* Link In DMAC */ .plat_data = { .id = DMA_LINK_IN_DMAC,
.type = DMAC_USER_LINK_DMA,
.base =.copy_dir = DMAC_DIR_WRITE,
GTW_LINK_IN_STREAM_BASE(0), .channels = 8, .irq = IRQ_EXT_LINK_DMA_IN_LVL4(0, 0), @@ -162,6 +172,8 @@ static struct dma dma[] = { { /* Link out DMAC */ .plat_data = { .id = DMA_LINK_OUT_DMAC,
.type = DMAC_USER_LINK_DMA,
.base =.copy_dir = DMAC_DIR_READ,
GTW_LINK_OUT_STREAM_BASE(0), .channels = 8, .irq = IRQ_EXT_LINK_DMA_OUT_LVL4(0, 0), @@ -170,15 +182,48 @@ static struct dma dma[] = { .ops = &hda_link_dma_ops, },};
-struct dma *dma_get(int dmac_id) +/*
- get DMAC based on user type, copy dir and flags
- "flags" is used to set the type of access requested
- (ex: shared/exclusive access)
- */
+struct dma *dma_get(enum dmac_user user, enum dmac_copy_dir dir, int flags) {
- int i;
int i, ch_count;
int dma_index = -1;
int min_ch_count = INT32_MAX;
for (i = 0; i < ARRAY_SIZE(dma); i++) {
if (dma[i].plat_data.id == dmac_id)
return &dma[i];
/* check DMAC user type */
if (dma[i].plat_data.type != user)
continue;
/* check DMAC copy dir */
if (dma[i].plat_data.copy_dir != dir)
continue;
/* if exclusive access is requested */
if (flags & DMAC_FLAGS_EXCLUSIVE) {
/* ret DMA with no channel in use */
if (!dma_channel_status(&dma[i]))
return &dma[i];
} else {
/* get number of channels in use */
ch_count =
dma_channel_status(&dma[i]);
/* Use this DMAC if its channel count
is lower */
if (ch_count < min_ch_count) {
dma_index = i;
min_ch_count = ch_count;
}
}
}
if (dma_index >= 0)
return &dma[dma_index];
return NULL; }
diff --git a/src/platform/baytrail/dma.c b/src/platform/baytrail/dma.c index 5a0b650..71ea241 100644 --- a/src/platform/baytrail/dma.c +++ b/src/platform/baytrail/dma.c @@ -175,15 +175,48 @@ static struct dma dma[] = { #endif };
-struct dma *dma_get(int dmac_id) +/*
- get DMAC based on user type, copy dir and flags
- For BYT/CHT, ignore the dmac_user and copy_dir arguments
- "flags" is used to set the type of access requested
- (ex: shared/exclusive access)
- */
+struct dma *dma_get(enum dmac_user user, enum dmac_copy_dir dir, int flags) {
- int i;
int i, ch_count;
int min_ch_count = INT32_MAX;
int dma_index = -1;
for (i = 0; i < ARRAY_SIZE(dma); i++) {
if (dma[i].plat_data.id == dmac_id)
return &dma[i];
/* if exclusive access is requested */
if (flags & DMAC_FLAGS_EXCLUSIVE) {
/* ret DMA with no channel in use */
if (!dma_channel_status(&dma[i]))
return &dma[i];
} else {
/*
* for shared access requests, return
DMAC
* with the least number of channels
in use
*/
/* get number of channels in use for
this DMAC*/
ch_count =
dma_channel_status(&dma[i]);
/* Use this DMAC if its channel count
is lower */
if (ch_count < min_ch_count) {
dma_index = i;
min_ch_count = ch_count;
}
}
}
/* return DMAC */
if (dma_index >= 0)
return &dma[dma_index];
return NULL; }
diff --git a/src/platform/cannonlake/dma.c b/src/platform/cannonlake/dma.c index 9031c17..697b9a8 100644 --- a/src/platform/cannonlake/dma.c +++ b/src/platform/cannonlake/dma.c @@ -113,6 +113,8 @@ static struct dma dma[] = { { /* Low Power GP DMAC 0 */ .plat_data = { .id = DMA_GP_LP_DMAC0,
.type = DMAC_USER_GP_LP_DMA,
.base = LP_GP_DMA_BASE(0), .channels = 8, .irq = IRQ_EXT_LP_GPDMA0_LVL5(0, 0),.copy_dir = DMAC_DIR_DUPLEX,
@@ -123,6 +125,8 @@ static struct dma dma[] = { { /* Low Power GP DMAC 1 */ .plat_data = { .id = DMA_GP_LP_DMAC1,
.type = DMAC_USER_GP_LP_DMA,
.base = LP_GP_DMA_BASE(1), .channels = 8, .irq = IRQ_EXT_LP_GPDMA1_LVL5(0, 0),.copy_dir = DMAC_DIR_DUPLEX,
@@ -133,6 +137,8 @@ static struct dma dma[] = { { /* Host In DMAC */ .plat_data = { .id = DMA_HOST_IN_DMAC,
.type = DMAC_USER_HOST_DMA,
.base =.copy_dir = DMAC_DIR_WRITE,
GTW_HOST_IN_STREAM_BASE(0), .channels = 7, .irq = IRQ_EXT_HOST_DMA_IN_LVL3(0, 0), @@ -143,6 +149,8 @@ static struct dma dma[] = { { /* Host out DMAC */ .plat_data = { .id = DMA_HOST_OUT_DMAC,
.type = DMAC_USER_HOST_DMA,
.base =.copy_dir = DMAC_DIR_READ,
GTW_HOST_OUT_STREAM_BASE(0), .channels = 9, .irq = IRQ_EXT_HOST_DMA_OUT_LVL3(0, 0), @@ -153,6 +161,8 @@ static struct dma dma[] = { { /* Link In DMAC */ .plat_data = { .id = DMA_LINK_IN_DMAC,
.type = DMAC_USER_LINK_DMA,
.base =.copy_dir = DMAC_DIR_WRITE,
GTW_LINK_IN_STREAM_BASE(0), .channels = 9, .irq = IRQ_EXT_LINK_DMA_IN_LVL4(0, 0), @@ -163,6 +173,8 @@ static struct dma dma[] = { { /* Link out DMAC */ .plat_data = { .id = DMA_LINK_OUT_DMAC,
.type = DMAC_USER_LINK_DMA,
.base =.copy_dir = DMAC_DIR_READ,
GTW_LINK_OUT_STREAM_BASE(0), .channels = 7, .irq = IRQ_EXT_LINK_DMA_OUT_LVL4(0, 0), @@ -171,15 +183,48 @@ static struct dma dma[] = { .ops = &hda_link_dma_ops, },};
-struct dma *dma_get(int dmac_id) +/*
- get DMAC based on user type, copy dir and flags
- "flags" is used to set the type of access requested
- (ex: shared/exclusive access)
- */
+struct dma *dma_get(enum dmac_user user, enum dmac_copy_dir dir, int flags) {
- int i;
int i, ch_count;
int dma_index = -1;
int min_ch_count = INT32_MAX;
for (i = 0; i < ARRAY_SIZE(dma); i++) {
if (dma[i].plat_data.id == dmac_id)
return &dma[i];
/* check DMAC user type */
if (dma[i].plat_data.type != user)
continue;
/* check DMAC copy dir */
if (dma[i].plat_data.copy_dir != dir)
continue;
/* if exclusive access is requested */
if (flags & DMAC_FLAGS_EXCLUSIVE) {
/* ret DMA with no channel in use */
if (!dma_channel_status(&dma[i]))
return &dma[i];
} else {
/* get number of channels in use */
ch_count =
dma_channel_status(&dma[i]);
/* Use this DMAC if its channel count
is lower */
if (ch_count < min_ch_count) {
dma_index = i;
min_ch_count = ch_count;
}
}
}
if (dma_index >= 0)
return &dma[dma_index];
return NULL; }
diff --git a/src/platform/haswell/dma.c b/src/platform/haswell/dma.c index 5d1e308..9138e78 100644 --- a/src/platform/haswell/dma.c +++ b/src/platform/haswell/dma.c @@ -124,16 +124,49 @@ static struct dma dma[] = { .ops = &dw_dma_ops, },};
-struct dma *dma_get(int dmac_id) +/*
- get DMAC based on user type, copy dir and flags
- For BYT/CHT, ignore the dmac_user and copy_dir arguments
- "flags" is used to set the type of access requested
- (ex: shared/exclusive access)
- */
+struct dma *dma_get(enum dmac_user user, enum dmac_copy_dir dir, int flags) {
- switch (dmac_id) {
- case DMA_ID_DMAC0:
return &dma[0];
- case DMA_ID_DMAC1:
return &dma[1];
- default:
return NULL;
- int i, ch_count;
- int min_ch_count = INT32_MAX;
- int dma_index = -1;
- for (i = 0; i < ARRAY_SIZE(dma); i++) {
/* if exclusive access is requested */
if (flags & DMAC_FLAGS_EXCLUSIVE) {
/* ret DMA with no channel in use */
if (!dma_channel_status(&dma[i]))
return &dma[i];
} else {
/*
* for shared access requests, return
DMAC
* with the least number of channels
in use
*/
/* get number of channels in use for
this DMAC*/
ch_count =
dma_channel_status(&dma[i]);
/* Use this DMAC if its channel count
is lower */
if (ch_count < min_ch_count) {
dma_index = i;
min_ch_count = ch_count;
}
}
}
/* return DMAC */
if (dma_index >= 0)
return &dma[dma_index];
return NULL; }
/* Initialize all platform DMAC's */
Sound-open-firmware mailing list Sound-open-firmware@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/sound-open-firmware
On 6/6/2018 2:06 PM, Ranjani Sridharan wrote:
On Wed, 2018-06-06 at 10:23 +0800, rander.wang wrote:
On 6/6/2018 3:12 AM, Ranjani Sridharan wrote:
On Tue, 2018-06-05 at 16:14 +0800, rander.wang wrote:
On 6/5/2018 12:23 PM, Ranjani Sridharan wrote:
This patch introduces a new API for procuring DMAC for various user based on the type of DMAC, copy direction and other flags for share/exclusive access. It defines the necessary DMAC user types, copy direction and the flags to suuport the new API.It also adds two new members to dma_plat_data to differentiate the DMAC based on usage and copy direction.
Finally, it also contains the platform specific implementation of the new dma_get() API.
Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel .com
src/include/sof/dma.h | 26 ++++++++++++++++- src/platform/apollolake/dma.c | 53 ++++++++++++++++++++++++++++++++--- src/platform/baytrail/dma.c | 41 ++++++++++++++++++++++++
src/platform/cannonlake/dma.c | 53 ++++++++++++++++++++++++++++++++--- src/platform/haswell/dma.c | 49 ++++++++++++++++++++++++++-----
- 5 files changed, 201 insertions(+), 21 deletions(-)
diff --git a/src/include/sof/dma.h b/src/include/sof/dma.h index 1de9efc..25581e6 100644 --- a/src/include/sof/dma.h +++ b/src/include/sof/dma.h @@ -48,6 +48,28 @@ enum dma_copy_dir { DMA_DIR_DEV_TO_DEV, };
+/*
- DMAC copy directions
- These are used to specify the copy direction while
requesting a DMAC
- */
+enum dmac_copy_dir {
- DMAC_DIR_READ = 0,
- DMAC_DIR_WRITE,
- DMAC_DIR_DUPLEX,
+};
On HSW and BDW, one difference between two DMA. Both DMA support Memory to memory copy, but DMA two supports memory <=> device copy. So MEM_TO_DEV, DEV_TO_MEM, HOST_TO_MEM ... should be added for this case.
Rander, there's another enum called dma_copy_dir() which defines those. Are you suggesting we qualify each DMAC with its capabilities in terms of dma_copy_dir as well?
yes, i find only dam_copy_dir is fit for capabilities. how
do you think about it?
OK, keyon has a similar suggestion and I think it makes sense. But he mentioned that for BDW, both DMAC's support all possible caps.
Could you please reply to that and correct if something is wrong? It will be useful for me when I implement. I'll verify with the HAS as well.
Hi, i just talk to keyon, no such conclusion, he just made some examples.
please do as we talked.
thank you!
+/* DMAC user types */ +enum dmac_user {
- DMAC_USER_HOST_DMA = 0,
- DMAC_USER_LINK_DMA,
- DMAC_USER_GP_LP_DMA,
- DMAC_USER_GP_HP_DMA,
+};
+/* DMAC flags */ +#define DMAC_FLAGS_SHARED 0 +#define DMAC_FLAGS_EXCLUSIVE (1 << 0)
- /* DMA IRQ types */ #define DMA_IRQ_TYPE_BLOCK (1 << 0) #define DMA_IRQ_TYPE_LLIST (1 << 1)
@@ -119,6 +141,8 @@ struct dma_ops { /* DMA platform data */ struct dma_plat_data { uint32_t id;
- enum dmac_user type;
- enum dmac_copy_dir copy_dir; uint32_t base; uint32_t channels; uint32_t irq;
@@ -139,7 +163,7 @@ struct dma_int { uint32_t irq; };
-struct dma *dma_get(int dmac_id); +struct dma *dma_get(enum dmac_user, enum dmac_copy_dir, int flags);
/* initialize all platform DMAC's */ void dmac_init(void); diff --git a/src/platform/apollolake/dma.c b/src/platform/apollolake/dma.c index 001bb67..1ae097e 100644 --- a/src/platform/apollolake/dma.c +++ b/src/platform/apollolake/dma.c @@ -112,6 +112,8 @@ static struct dma dma[] = { { /* Low Power GP DMAC 0 */ .plat_data = { .id = DMA_GP_LP_DMAC0,
.type = DMAC_USER_GP_LP_DMA,
.copy_dir = DMAC_DIR_DUPLEX, .base = LP_GP_DMA_BASE(0), .channels = 8, .irq =
IRQ_EXT_LP_GPDMA0_LVL5(0, 0), @@ -122,6 +124,8 @@ static struct dma dma[] = { { /* Low Power GP DMAC 1 */ .plat_data = { .id = DMA_GP_LP_DMAC1,
.type = DMAC_USER_GP_LP_DMA,
.copy_dir = DMAC_DIR_DUPLEX, .base = LP_GP_DMA_BASE(1), .channels = 8, .irq =
IRQ_EXT_LP_GPDMA1_LVL5(0, 0), @@ -132,6 +136,8 @@ static struct dma dma[] = { { /* Host In DMAC */ .plat_data = { .id = DMA_HOST_IN_DMAC,
.type = DMAC_USER_HOST_DMA,
.copy_dir = DMAC_DIR_WRITE, .base =
GTW_HOST_IN_STREAM_BASE(0), .channels = 7, .irq = IRQ_EXT_HOST_DMA_IN_LVL3(0, 0), @@ -142,6 +148,8 @@ static struct dma dma[] = { { /* Host out DMAC */ .plat_data = { .id = DMA_HOST_OUT_DMAC,
.type = DMAC_USER_HOST_DMA,
.copy_dir = DMAC_DIR_READ, .base =
GTW_HOST_OUT_STREAM_BASE(0), .channels = 6, .irq = IRQ_EXT_HOST_DMA_OUT_LVL3(0, 0), @@ -152,6 +160,8 @@ static struct dma dma[] = { { /* Link In DMAC */ .plat_data = { .id = DMA_LINK_IN_DMAC,
.type = DMAC_USER_LINK_DMA,
.copy_dir = DMAC_DIR_WRITE, .base =
GTW_LINK_IN_STREAM_BASE(0), .channels = 8, .irq = IRQ_EXT_LINK_DMA_IN_LVL4(0, 0), @@ -162,6 +172,8 @@ static struct dma dma[] = { { /* Link out DMAC */ .plat_data = { .id = DMA_LINK_OUT_DMAC,
.type = DMAC_USER_LINK_DMA,
.copy_dir = DMAC_DIR_READ, .base =
GTW_LINK_OUT_STREAM_BASE(0), .channels = 8, .irq = IRQ_EXT_LINK_DMA_OUT_LVL4(0, 0), @@ -170,15 +182,48 @@ static struct dma dma[] = { .ops = &hda_link_dma_ops, },};
-struct dma *dma_get(int dmac_id) +/*
- get DMAC based on user type, copy dir and flags
- "flags" is used to set the type of access requested
- (ex: shared/exclusive access)
- */
+struct dma *dma_get(enum dmac_user user, enum dmac_copy_dir dir, int flags) {
- int i;
int i, ch_count;
int dma_index = -1;
int min_ch_count = INT32_MAX;
for (i = 0; i < ARRAY_SIZE(dma); i++) {
if (dma[i].plat_data.id == dmac_id)
return &dma[i];
/* check DMAC user type */
if (dma[i].plat_data.type != user)
continue;
/* check DMAC copy dir */
if (dma[i].plat_data.copy_dir != dir)
continue;
/* if exclusive access is requested */
if (flags & DMAC_FLAGS_EXCLUSIVE) {
/* ret DMA with no channel in use */
if (!dma_channel_status(&dma[i]))
return &dma[i];
} else {
/* get number of channels in use */
ch_count =
dma_channel_status(&dma[i]);
/* Use this DMAC if its channel count
is lower */
if (ch_count < min_ch_count) {
dma_index = i;
min_ch_count = ch_count;
}
}
}
if (dma_index >= 0)
return &dma[dma_index];
return NULL; }
diff --git a/src/platform/baytrail/dma.c b/src/platform/baytrail/dma.c index 5a0b650..71ea241 100644 --- a/src/platform/baytrail/dma.c +++ b/src/platform/baytrail/dma.c @@ -175,15 +175,48 @@ static struct dma dma[] = { #endif };
-struct dma *dma_get(int dmac_id) +/*
- get DMAC based on user type, copy dir and flags
- For BYT/CHT, ignore the dmac_user and copy_dir arguments
- "flags" is used to set the type of access requested
- (ex: shared/exclusive access)
- */
+struct dma *dma_get(enum dmac_user user, enum dmac_copy_dir dir, int flags) {
- int i;
int i, ch_count;
int min_ch_count = INT32_MAX;
int dma_index = -1;
for (i = 0; i < ARRAY_SIZE(dma); i++) {
if (dma[i].plat_data.id == dmac_id)
return &dma[i];
/* if exclusive access is requested */
if (flags & DMAC_FLAGS_EXCLUSIVE) {
/* ret DMA with no channel in use */
if (!dma_channel_status(&dma[i]))
return &dma[i];
} else {
/*
* for shared access requests, return
DMAC
* with the least number of channels
in use
*/
/* get number of channels in use for
this DMAC*/
ch_count =
dma_channel_status(&dma[i]);
/* Use this DMAC if its channel count
is lower */
if (ch_count < min_ch_count) {
dma_index = i;
min_ch_count = ch_count;
}
}
}
/* return DMAC */
if (dma_index >= 0)
return &dma[dma_index];
return NULL; }
diff --git a/src/platform/cannonlake/dma.c b/src/platform/cannonlake/dma.c index 9031c17..697b9a8 100644 --- a/src/platform/cannonlake/dma.c +++ b/src/platform/cannonlake/dma.c @@ -113,6 +113,8 @@ static struct dma dma[] = { { /* Low Power GP DMAC 0 */ .plat_data = { .id = DMA_GP_LP_DMAC0,
.type = DMAC_USER_GP_LP_DMA,
.copy_dir = DMAC_DIR_DUPLEX, .base = LP_GP_DMA_BASE(0), .channels = 8, .irq = IRQ_EXT_LP_GPDMA0_LVL5(0, 0),
@@ -123,6 +125,8 @@ static struct dma dma[] = { { /* Low Power GP DMAC 1 */ .plat_data = { .id = DMA_GP_LP_DMAC1,
.type = DMAC_USER_GP_LP_DMA,
.copy_dir = DMAC_DIR_DUPLEX, .base = LP_GP_DMA_BASE(1), .channels = 8, .irq = IRQ_EXT_LP_GPDMA1_LVL5(0, 0),
@@ -133,6 +137,8 @@ static struct dma dma[] = { { /* Host In DMAC */ .plat_data = { .id = DMA_HOST_IN_DMAC,
.type = DMAC_USER_HOST_DMA,
.copy_dir = DMAC_DIR_WRITE, .base =
GTW_HOST_IN_STREAM_BASE(0), .channels = 7, .irq = IRQ_EXT_HOST_DMA_IN_LVL3(0, 0), @@ -143,6 +149,8 @@ static struct dma dma[] = { { /* Host out DMAC */ .plat_data = { .id = DMA_HOST_OUT_DMAC,
.type = DMAC_USER_HOST_DMA,
.copy_dir = DMAC_DIR_READ, .base =
GTW_HOST_OUT_STREAM_BASE(0), .channels = 9, .irq = IRQ_EXT_HOST_DMA_OUT_LVL3(0, 0), @@ -153,6 +161,8 @@ static struct dma dma[] = { { /* Link In DMAC */ .plat_data = { .id = DMA_LINK_IN_DMAC,
.type = DMAC_USER_LINK_DMA,
.copy_dir = DMAC_DIR_WRITE, .base =
GTW_LINK_IN_STREAM_BASE(0), .channels = 9, .irq = IRQ_EXT_LINK_DMA_IN_LVL4(0, 0), @@ -163,6 +173,8 @@ static struct dma dma[] = { { /* Link out DMAC */ .plat_data = { .id = DMA_LINK_OUT_DMAC,
.type = DMAC_USER_LINK_DMA,
.copy_dir = DMAC_DIR_READ, .base =
GTW_LINK_OUT_STREAM_BASE(0), .channels = 7, .irq = IRQ_EXT_LINK_DMA_OUT_LVL4(0, 0), @@ -171,15 +183,48 @@ static struct dma dma[] = { .ops = &hda_link_dma_ops, },};
-struct dma *dma_get(int dmac_id) +/*
- get DMAC based on user type, copy dir and flags
- "flags" is used to set the type of access requested
- (ex: shared/exclusive access)
- */
+struct dma *dma_get(enum dmac_user user, enum dmac_copy_dir dir, int flags) {
- int i;
int i, ch_count;
int dma_index = -1;
int min_ch_count = INT32_MAX;
for (i = 0; i < ARRAY_SIZE(dma); i++) {
if (dma[i].plat_data.id == dmac_id)
return &dma[i];
/* check DMAC user type */
if (dma[i].plat_data.type != user)
continue;
/* check DMAC copy dir */
if (dma[i].plat_data.copy_dir != dir)
continue;
/* if exclusive access is requested */
if (flags & DMAC_FLAGS_EXCLUSIVE) {
/* ret DMA with no channel in use */
if (!dma_channel_status(&dma[i]))
return &dma[i];
} else {
/* get number of channels in use */
ch_count =
dma_channel_status(&dma[i]);
/* Use this DMAC if its channel count
is lower */
if (ch_count < min_ch_count) {
dma_index = i;
min_ch_count = ch_count;
}
}
}
if (dma_index >= 0)
return &dma[dma_index];
return NULL; }
diff --git a/src/platform/haswell/dma.c b/src/platform/haswell/dma.c index 5d1e308..9138e78 100644 --- a/src/platform/haswell/dma.c +++ b/src/platform/haswell/dma.c @@ -124,16 +124,49 @@ static struct dma dma[] = { .ops = &dw_dma_ops, },};
-struct dma *dma_get(int dmac_id) +/*
- get DMAC based on user type, copy dir and flags
- For BYT/CHT, ignore the dmac_user and copy_dir arguments
- "flags" is used to set the type of access requested
- (ex: shared/exclusive access)
- */
+struct dma *dma_get(enum dmac_user user, enum dmac_copy_dir dir, int flags) {
- switch (dmac_id) {
- case DMA_ID_DMAC0:
return &dma[0];
- case DMA_ID_DMAC1:
return &dma[1];
- default:
return NULL;
- int i, ch_count;
- int min_ch_count = INT32_MAX;
- int dma_index = -1;
- for (i = 0; i < ARRAY_SIZE(dma); i++) {
/* if exclusive access is requested */
if (flags & DMAC_FLAGS_EXCLUSIVE) {
/* ret DMA with no channel in use */
if (!dma_channel_status(&dma[i]))
return &dma[i];
} else {
/*
* for shared access requests, return
DMAC
* with the least number of channels
in use
*/
/* get number of channels in use for
this DMAC*/
ch_count =
dma_channel_status(&dma[i]);
/* Use this DMAC if its channel count
is lower */
if (ch_count < min_ch_count) {
dma_index = i;
min_ch_count = ch_count;
}
}
}
/* return DMAC */
if (dma_index >= 0)
return &dma[dma_index];
return NULL; }
/* Initialize all platform DMAC's */
Sound-open-firmware mailing list Sound-open-firmware@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/sound-open-firmware
On 6/5/2018 12:23 PM, Ranjani Sridharan wrote:
This patch introduces a new API for procuring DMAC for various user based on the type of DMAC, copy direction and other flags for share/exclusive access. It defines the necessary DMAC user types, copy direction and the flags to suuport the new API.It also adds two new members to dma_plat_data to differentiate the DMAC based on usage and copy direction.
Finally, it also contains the platform specific implementation of the new dma_get() API.
Signed-off-by: Ranjani Sridharan ranjani.sridharan@linux.intel.com
src/include/sof/dma.h | 26 ++++++++++++++++- src/platform/apollolake/dma.c | 53 ++++++++++++++++++++++++++++++++--- src/platform/baytrail/dma.c | 41 ++++++++++++++++++++++++--- src/platform/cannonlake/dma.c | 53 ++++++++++++++++++++++++++++++++--- src/platform/haswell/dma.c | 49 ++++++++++++++++++++++++++------ 5 files changed, 201 insertions(+), 21 deletions(-)
diff --git a/src/include/sof/dma.h b/src/include/sof/dma.h index 1de9efc..25581e6 100644 --- a/src/include/sof/dma.h +++ b/src/include/sof/dma.h @@ -48,6 +48,28 @@ enum dma_copy_dir { DMA_DIR_DEV_TO_DEV, };
+/*
- DMAC copy directions
- These are used to specify the copy direction while requesting a DMAC
- */
+enum dmac_copy_dir {
- DMAC_DIR_READ = 0,
- DMAC_DIR_WRITE,
- DMAC_DIR_DUPLEX,
+};
+/* DMAC user types */ +enum dmac_user {
- DMAC_USER_HOST_DMA = 0,
- DMAC_USER_LINK_DMA,
- DMAC_USER_GP_LP_DMA,
- DMAC_USER_GP_HP_DMA,
+};
+/* DMAC flags */ +#define DMAC_FLAGS_SHARED 0 +#define DMAC_FLAGS_EXCLUSIVE (1 << 0)
- /* DMA IRQ types */ #define DMA_IRQ_TYPE_BLOCK (1 << 0) #define DMA_IRQ_TYPE_LLIST (1 << 1)
@@ -119,6 +141,8 @@ struct dma_ops { /* DMA platform data */ struct dma_plat_data { uint32_t id;
- enum dmac_user type;
- enum dmac_copy_dir copy_dir; uint32_t base; uint32_t channels; uint32_t irq;
@@ -139,7 +163,7 @@ struct dma_int { uint32_t irq; };
-struct dma *dma_get(int dmac_id); +struct dma *dma_get(enum dmac_user, enum dmac_copy_dir, int flags);
/* initialize all platform DMAC's */ void dmac_init(void); diff --git a/src/platform/apollolake/dma.c b/src/platform/apollolake/dma.c index 001bb67..1ae097e 100644 --- a/src/platform/apollolake/dma.c +++ b/src/platform/apollolake/dma.c @@ -112,6 +112,8 @@ static struct dma dma[] = { { /* Low Power GP DMAC 0 */ .plat_data = { .id = DMA_GP_LP_DMAC0,
.type = DMAC_USER_GP_LP_DMA,
.base = LP_GP_DMA_BASE(0), .channels = 8, .irq = IRQ_EXT_LP_GPDMA0_LVL5(0, 0),.copy_dir = DMAC_DIR_DUPLEX,
@@ -122,6 +124,8 @@ static struct dma dma[] = { { /* Low Power GP DMAC 1 */ .plat_data = { .id = DMA_GP_LP_DMAC1,
.type = DMAC_USER_GP_LP_DMA,
.base = LP_GP_DMA_BASE(1), .channels = 8, .irq = IRQ_EXT_LP_GPDMA1_LVL5(0, 0),.copy_dir = DMAC_DIR_DUPLEX,
@@ -132,6 +136,8 @@ static struct dma dma[] = { { /* Host In DMAC */ .plat_data = { .id = DMA_HOST_IN_DMAC,
.type = DMAC_USER_HOST_DMA,
.base = GTW_HOST_IN_STREAM_BASE(0), .channels = 7, .irq = IRQ_EXT_HOST_DMA_IN_LVL3(0, 0),.copy_dir = DMAC_DIR_WRITE,
@@ -142,6 +148,8 @@ static struct dma dma[] = { { /* Host out DMAC */ .plat_data = { .id = DMA_HOST_OUT_DMAC,
.type = DMAC_USER_HOST_DMA,
.base = GTW_HOST_OUT_STREAM_BASE(0), .channels = 6, .irq = IRQ_EXT_HOST_DMA_OUT_LVL3(0, 0),.copy_dir = DMAC_DIR_READ,
@@ -152,6 +160,8 @@ static struct dma dma[] = { { /* Link In DMAC */ .plat_data = { .id = DMA_LINK_IN_DMAC,
.type = DMAC_USER_LINK_DMA,
.base = GTW_LINK_IN_STREAM_BASE(0), .channels = 8, .irq = IRQ_EXT_LINK_DMA_IN_LVL4(0, 0),.copy_dir = DMAC_DIR_WRITE,
@@ -162,6 +172,8 @@ static struct dma dma[] = { { /* Link out DMAC */ .plat_data = { .id = DMA_LINK_OUT_DMAC,
.type = DMAC_USER_LINK_DMA,
.base = GTW_LINK_OUT_STREAM_BASE(0), .channels = 8, .irq = IRQ_EXT_LINK_DMA_OUT_LVL4(0, 0),.copy_dir = DMAC_DIR_READ,
@@ -170,15 +182,48 @@ static struct dma dma[] = { .ops = &hda_link_dma_ops, },};
-struct dma *dma_get(int dmac_id) +/*
- get DMAC based on user type, copy dir and flags
- "flags" is used to set the type of access requested
- (ex: shared/exclusive access)
- */
+struct dma *dma_get(enum dmac_user user, enum dmac_copy_dir dir, int flags) {
- int i;
int i, ch_count;
int dma_index = -1;
int min_ch_count = INT32_MAX;
for (i = 0; i < ARRAY_SIZE(dma); i++) {
if (dma[i].plat_data.id == dmac_id)
return &dma[i];
/* check DMAC user type */
if (dma[i].plat_data.type != user)
continue;
/* check DMAC copy dir */
if (dma[i].plat_data.copy_dir != dir)
continue;
/* if exclusive access is requested */
if (flags & DMAC_FLAGS_EXCLUSIVE) {
/* ret DMA with no channel in use */
if (!dma_channel_status(&dma[i]))
return &dma[i];
} else {
/* get number of channels in use */
ch_count = dma_channel_status(&dma[i]);
/* Use this DMAC if its channel count is lower */
if (ch_count < min_ch_count) {
dma_index = i;
min_ch_count = ch_count;
}
}
}
if (dma_index >= 0)
return &dma[dma_index];
return NULL; }
diff --git a/src/platform/baytrail/dma.c b/src/platform/baytrail/dma.c index 5a0b650..71ea241 100644 --- a/src/platform/baytrail/dma.c +++ b/src/platform/baytrail/dma.c @@ -175,15 +175,48 @@ static struct dma dma[] = { #endif };
-struct dma *dma_get(int dmac_id) +/*
- get DMAC based on user type, copy dir and flags
- For BYT/CHT, ignore the dmac_user and copy_dir arguments
- "flags" is used to set the type of access requested
- (ex: shared/exclusive access)
- */
+struct dma *dma_get(enum dmac_user user, enum dmac_copy_dir dir, int flags) {
- int i;
int i, ch_count;
int min_ch_count = INT32_MAX;
int dma_index = -1;
for (i = 0; i < ARRAY_SIZE(dma); i++) {
if (dma[i].plat_data.id == dmac_id)
return &dma[i];
/* if exclusive access is requested */
if (flags & DMAC_FLAGS_EXCLUSIVE) {
/* ret DMA with no channel in use */
if (!dma_channel_status(&dma[i]))
return &dma[i];
} else {
/*
* for shared access requests, return DMAC
* with the least number of channels in use
*/
/* get number of channels in use for this DMAC*/
ch_count = dma_channel_status(&dma[i]);
/* Use this DMAC if its channel count is lower */
if (ch_count < min_ch_count) {
dma_index = i;
min_ch_count = ch_count;
}
}
}
/* return DMAC */
if (dma_index >= 0)
return &dma[dma_index];
return NULL; }
diff --git a/src/platform/cannonlake/dma.c b/src/platform/cannonlake/dma.c index 9031c17..697b9a8 100644 --- a/src/platform/cannonlake/dma.c +++ b/src/platform/cannonlake/dma.c @@ -113,6 +113,8 @@ static struct dma dma[] = { { /* Low Power GP DMAC 0 */ .plat_data = { .id = DMA_GP_LP_DMAC0,
.type = DMAC_USER_GP_LP_DMA,
.base = LP_GP_DMA_BASE(0), .channels = 8, .irq = IRQ_EXT_LP_GPDMA0_LVL5(0, 0),.copy_dir = DMAC_DIR_DUPLEX,
@@ -123,6 +125,8 @@ static struct dma dma[] = { { /* Low Power GP DMAC 1 */ .plat_data = { .id = DMA_GP_LP_DMAC1,
.type = DMAC_USER_GP_LP_DMA,
.base = LP_GP_DMA_BASE(1), .channels = 8, .irq = IRQ_EXT_LP_GPDMA1_LVL5(0, 0),.copy_dir = DMAC_DIR_DUPLEX,
as we discussed, there are 3 DMACs on CNL, can you help to add it ?
@@ -133,6 +137,8 @@ static struct dma dma[] = { { /* Host In DMAC */ .plat_data = { .id = DMA_HOST_IN_DMAC,
.type = DMAC_USER_HOST_DMA,
.base = GTW_HOST_IN_STREAM_BASE(0), .channels = 7, .irq = IRQ_EXT_HOST_DMA_IN_LVL3(0, 0),.copy_dir = DMAC_DIR_WRITE,
@@ -143,6 +149,8 @@ static struct dma dma[] = { { /* Host out DMAC */ .plat_data = { .id = DMA_HOST_OUT_DMAC,
.type = DMAC_USER_HOST_DMA,
.base = GTW_HOST_OUT_STREAM_BASE(0), .channels = 9, .irq = IRQ_EXT_HOST_DMA_OUT_LVL3(0, 0),.copy_dir = DMAC_DIR_READ,
@@ -153,6 +161,8 @@ static struct dma dma[] = { { /* Link In DMAC */ .plat_data = { .id = DMA_LINK_IN_DMAC,
.type = DMAC_USER_LINK_DMA,
.base = GTW_LINK_IN_STREAM_BASE(0), .channels = 9, .irq = IRQ_EXT_LINK_DMA_IN_LVL4(0, 0),.copy_dir = DMAC_DIR_WRITE,
@@ -163,6 +173,8 @@ static struct dma dma[] = { { /* Link out DMAC */ .plat_data = { .id = DMA_LINK_OUT_DMAC,
.type = DMAC_USER_LINK_DMA,
.base = GTW_LINK_OUT_STREAM_BASE(0), .channels = 7, .irq = IRQ_EXT_LINK_DMA_OUT_LVL4(0, 0),.copy_dir = DMAC_DIR_READ,
@@ -171,15 +183,48 @@ static struct dma dma[] = { .ops = &hda_link_dma_ops, },};
-struct dma *dma_get(int dmac_id) +/*
- get DMAC based on user type, copy dir and flags
- "flags" is used to set the type of access requested
- (ex: shared/exclusive access)
- */
+struct dma *dma_get(enum dmac_user user, enum dmac_copy_dir dir, int flags) {
- int i;
int i, ch_count;
int dma_index = -1;
int min_ch_count = INT32_MAX;
for (i = 0; i < ARRAY_SIZE(dma); i++) {
if (dma[i].plat_data.id == dmac_id)
return &dma[i];
/* check DMAC user type */
if (dma[i].plat_data.type != user)
continue;
/* check DMAC copy dir */
if (dma[i].plat_data.copy_dir != dir)
continue;
/* if exclusive access is requested */
if (flags & DMAC_FLAGS_EXCLUSIVE) {
/* ret DMA with no channel in use */
if (!dma_channel_status(&dma[i]))
return &dma[i];
} else {
/* get number of channels in use */
ch_count = dma_channel_status(&dma[i]);
/* Use this DMAC if its channel count is lower */
if (ch_count < min_ch_count) {
dma_index = i;
min_ch_count = ch_count;
}
}
}
if (dma_index >= 0)
return &dma[dma_index];
return NULL; }
diff --git a/src/platform/haswell/dma.c b/src/platform/haswell/dma.c index 5d1e308..9138e78 100644 --- a/src/platform/haswell/dma.c +++ b/src/platform/haswell/dma.c @@ -124,16 +124,49 @@ static struct dma dma[] = { .ops = &dw_dma_ops, },};
-struct dma *dma_get(int dmac_id) +/*
- get DMAC based on user type, copy dir and flags
- For BYT/CHT, ignore the dmac_user and copy_dir arguments
- "flags" is used to set the type of access requested
- (ex: shared/exclusive access)
- */
+struct dma *dma_get(enum dmac_user user, enum dmac_copy_dir dir, int flags) {
- switch (dmac_id) {
- case DMA_ID_DMAC0:
return &dma[0];
- case DMA_ID_DMAC1:
return &dma[1];
- default:
return NULL;
int i, ch_count;
int min_ch_count = INT32_MAX;
int dma_index = -1;
for (i = 0; i < ARRAY_SIZE(dma); i++) {
/* if exclusive access is requested */
if (flags & DMAC_FLAGS_EXCLUSIVE) {
/* ret DMA with no channel in use */
if (!dma_channel_status(&dma[i]))
return &dma[i];
} else {
/*
* for shared access requests, return DMAC
* with the least number of channels in use
*/
/* get number of channels in use for this DMAC*/
ch_count = dma_channel_status(&dma[i]);
/* Use this DMAC if its channel count is lower */
if (ch_count < min_ch_count) {
dma_index = i;
min_ch_count = ch_count;
}
}
}
/* return DMAC */
if (dma_index >= 0)
return &dma[dma_index];
return NULL; }
/* Initialize all platform DMAC's */
On Mon, 2018-06-04 at 21:23 -0700, Ranjani Sridharan wrote:
This patch introduces a new API for procuring DMAC for various user based on the type of DMAC, copy direction and other flags for share/exclusive access. It defines the necessary DMAC user types, copy direction and the flags to suuport the new API.It also adds two new members to dma_plat_data to differentiate the DMAC based on usage and copy direction.
Finally, it also contains the platform specific implementation of the new dma_get() API.
Signed-off-by: Ranjani Sridharan ranjani.sridharan@linux.intel.com
src/include/sof/dma.h | 26 ++++++++++++++++- src/platform/apollolake/dma.c | 53 ++++++++++++++++++++++++++++++++--- src/platform/baytrail/dma.c | 41 ++++++++++++++++++++++++--- src/platform/cannonlake/dma.c | 53 ++++++++++++++++++++++++++++++++--- src/platform/haswell/dma.c | 49 ++++++++++++++++++++++++++------ 5 files changed, 201 insertions(+), 21 deletions(-)
Lets consolidate the dma_get() into a common dma file.
Liam
diff --git a/src/include/sof/dma.h b/src/include/sof/dma.h index 1de9efc..25581e6 100644 --- a/src/include/sof/dma.h +++ b/src/include/sof/dma.h @@ -48,6 +48,28 @@ enum dma_copy_dir { DMA_DIR_DEV_TO_DEV, };
+/*
- DMAC copy directions
- These are used to specify the copy direction while requesting a DMAC
- */
+enum dmac_copy_dir {
- DMAC_DIR_READ = 0,
- DMAC_DIR_WRITE,
- DMAC_DIR_DUPLEX,
+};
+/* DMAC user types */ +enum dmac_user {
- DMAC_USER_HOST_DMA = 0,
- DMAC_USER_LINK_DMA,
- DMAC_USER_GP_LP_DMA,
- DMAC_USER_GP_HP_DMA,
+};
+/* DMAC flags */ +#define DMAC_FLAGS_SHARED 0 +#define DMAC_FLAGS_EXCLUSIVE (1 << 0)
/* DMA IRQ types */ #define DMA_IRQ_TYPE_BLOCK (1 << 0) #define DMA_IRQ_TYPE_LLIST (1 << 1) @@ -119,6 +141,8 @@ struct dma_ops { /* DMA platform data */ struct dma_plat_data { uint32_t id;
- enum dmac_user type;
- enum dmac_copy_dir copy_dir; uint32_t base; uint32_t channels; uint32_t irq;
@@ -139,7 +163,7 @@ struct dma_int { uint32_t irq; };
-struct dma *dma_get(int dmac_id); +struct dma *dma_get(enum dmac_user, enum dmac_copy_dir, int flags);
/* initialize all platform DMAC's */ void dmac_init(void); diff --git a/src/platform/apollolake/dma.c b/src/platform/apollolake/dma.c index 001bb67..1ae097e 100644 --- a/src/platform/apollolake/dma.c +++ b/src/platform/apollolake/dma.c @@ -112,6 +112,8 @@ static struct dma dma[] = { { /* Low Power GP DMAC 0 */ .plat_data = { .id = DMA_GP_LP_DMAC0,
.type = DMAC_USER_GP_LP_DMA,
.base = LP_GP_DMA_BASE(0), .channels = 8, .irq = IRQ_EXT_LP_GPDMA0_LVL5(0, 0),.copy_dir = DMAC_DIR_DUPLEX,
@@ -122,6 +124,8 @@ static struct dma dma[] = { { /* Low Power GP DMAC 1 */ .plat_data = { .id = DMA_GP_LP_DMAC1,
.type = DMAC_USER_GP_LP_DMA,
.base = LP_GP_DMA_BASE(1), .channels = 8, .irq = IRQ_EXT_LP_GPDMA1_LVL5(0, 0),.copy_dir = DMAC_DIR_DUPLEX,
@@ -132,6 +136,8 @@ static struct dma dma[] = { { /* Host In DMAC */ .plat_data = { .id = DMA_HOST_IN_DMAC,
.type = DMAC_USER_HOST_DMA,
.base = GTW_HOST_IN_STREAM_BASE(0), .channels = 7, .irq = IRQ_EXT_HOST_DMA_IN_LVL3(0, 0),.copy_dir = DMAC_DIR_WRITE,
@@ -142,6 +148,8 @@ static struct dma dma[] = { { /* Host out DMAC */ .plat_data = { .id = DMA_HOST_OUT_DMAC,
.type = DMAC_USER_HOST_DMA,
.base = GTW_HOST_OUT_STREAM_BASE(0), .channels = 6, .irq = IRQ_EXT_HOST_DMA_OUT_LVL3(0, 0),.copy_dir = DMAC_DIR_READ,
@@ -152,6 +160,8 @@ static struct dma dma[] = { { /* Link In DMAC */ .plat_data = { .id = DMA_LINK_IN_DMAC,
.type = DMAC_USER_LINK_DMA,
.base = GTW_LINK_IN_STREAM_BASE(0), .channels = 8, .irq = IRQ_EXT_LINK_DMA_IN_LVL4(0, 0),.copy_dir = DMAC_DIR_WRITE,
@@ -162,6 +172,8 @@ static struct dma dma[] = { { /* Link out DMAC */ .plat_data = { .id = DMA_LINK_OUT_DMAC,
.type = DMAC_USER_LINK_DMA,
.base = GTW_LINK_OUT_STREAM_BASE(0), .channels = 8, .irq = IRQ_EXT_LINK_DMA_OUT_LVL4(0, 0),.copy_dir = DMAC_DIR_READ,
@@ -170,15 +182,48 @@ static struct dma dma[] = { .ops = &hda_link_dma_ops, },};
-struct dma *dma_get(int dmac_id) +/*
- get DMAC based on user type, copy dir and flags
- "flags" is used to set the type of access requested
- (ex: shared/exclusive access)
- */
+struct dma *dma_get(enum dmac_user user, enum dmac_copy_dir dir, int flags) {
- int i;
int i, ch_count;
int dma_index = -1;
int min_ch_count = INT32_MAX;
for (i = 0; i < ARRAY_SIZE(dma); i++) {
if (dma[i].plat_data.id == dmac_id)
return &dma[i];
/* check DMAC user type */
if (dma[i].plat_data.type != user)
continue;
/* check DMAC copy dir */
if (dma[i].plat_data.copy_dir != dir)
continue;
/* if exclusive access is requested */
if (flags & DMAC_FLAGS_EXCLUSIVE) {
/* ret DMA with no channel in use */
if (!dma_channel_status(&dma[i]))
return &dma[i];
} else {
/* get number of channels in use */
ch_count = dma_channel_status(&dma[i]);
/* Use this DMAC if its channel count is lower */
if (ch_count < min_ch_count) {
dma_index = i;
min_ch_count = ch_count;
}
}
}
if (dma_index >= 0)
return &dma[dma_index];
return NULL;
}
diff --git a/src/platform/baytrail/dma.c b/src/platform/baytrail/dma.c index 5a0b650..71ea241 100644 --- a/src/platform/baytrail/dma.c +++ b/src/platform/baytrail/dma.c @@ -175,15 +175,48 @@ static struct dma dma[] = { #endif };
-struct dma *dma_get(int dmac_id) +/*
- get DMAC based on user type, copy dir and flags
- For BYT/CHT, ignore the dmac_user and copy_dir arguments
- "flags" is used to set the type of access requested
- (ex: shared/exclusive access)
- */
+struct dma *dma_get(enum dmac_user user, enum dmac_copy_dir dir, int flags) {
- int i;
int i, ch_count;
int min_ch_count = INT32_MAX;
int dma_index = -1;
for (i = 0; i < ARRAY_SIZE(dma); i++) {
if (dma[i].plat_data.id == dmac_id)
return &dma[i];
/* if exclusive access is requested */
if (flags & DMAC_FLAGS_EXCLUSIVE) {
/* ret DMA with no channel in use */
if (!dma_channel_status(&dma[i]))
return &dma[i];
} else {
/*
* for shared access requests, return DMAC
* with the least number of channels in use
*/
/* get number of channels in use for this DMAC*/
ch_count = dma_channel_status(&dma[i]);
/* Use this DMAC if its channel count is lower */
if (ch_count < min_ch_count) {
dma_index = i;
min_ch_count = ch_count;
}
}
}
/* return DMAC */
if (dma_index >= 0)
return &dma[dma_index];
return NULL;
}
diff --git a/src/platform/cannonlake/dma.c b/src/platform/cannonlake/dma.c index 9031c17..697b9a8 100644 --- a/src/platform/cannonlake/dma.c +++ b/src/platform/cannonlake/dma.c @@ -113,6 +113,8 @@ static struct dma dma[] = { { /* Low Power GP DMAC 0 */ .plat_data = { .id = DMA_GP_LP_DMAC0,
.type = DMAC_USER_GP_LP_DMA,
.base = LP_GP_DMA_BASE(0), .channels = 8, .irq = IRQ_EXT_LP_GPDMA0_LVL5(0, 0),.copy_dir = DMAC_DIR_DUPLEX,
@@ -123,6 +125,8 @@ static struct dma dma[] = { { /* Low Power GP DMAC 1 */ .plat_data = { .id = DMA_GP_LP_DMAC1,
.type = DMAC_USER_GP_LP_DMA,
.base = LP_GP_DMA_BASE(1), .channels = 8, .irq = IRQ_EXT_LP_GPDMA1_LVL5(0, 0),.copy_dir = DMAC_DIR_DUPLEX,
@@ -133,6 +137,8 @@ static struct dma dma[] = { { /* Host In DMAC */ .plat_data = { .id = DMA_HOST_IN_DMAC,
.type = DMAC_USER_HOST_DMA,
.base = GTW_HOST_IN_STREAM_BASE(0), .channels = 7, .irq = IRQ_EXT_HOST_DMA_IN_LVL3(0, 0),.copy_dir = DMAC_DIR_WRITE,
@@ -143,6 +149,8 @@ static struct dma dma[] = { { /* Host out DMAC */ .plat_data = { .id = DMA_HOST_OUT_DMAC,
.type = DMAC_USER_HOST_DMA,
.base = GTW_HOST_OUT_STREAM_BASE(0), .channels = 9, .irq = IRQ_EXT_HOST_DMA_OUT_LVL3(0, 0),.copy_dir = DMAC_DIR_READ,
@@ -153,6 +161,8 @@ static struct dma dma[] = { { /* Link In DMAC */ .plat_data = { .id = DMA_LINK_IN_DMAC,
.type = DMAC_USER_LINK_DMA,
.base = GTW_LINK_IN_STREAM_BASE(0), .channels = 9, .irq = IRQ_EXT_LINK_DMA_IN_LVL4(0, 0),.copy_dir = DMAC_DIR_WRITE,
@@ -163,6 +173,8 @@ static struct dma dma[] = { { /* Link out DMAC */ .plat_data = { .id = DMA_LINK_OUT_DMAC,
.type = DMAC_USER_LINK_DMA,
.base = GTW_LINK_OUT_STREAM_BASE(0), .channels = 7, .irq = IRQ_EXT_LINK_DMA_OUT_LVL4(0, 0),.copy_dir = DMAC_DIR_READ,
@@ -171,15 +183,48 @@ static struct dma dma[] = { .ops = &hda_link_dma_ops, },};
-struct dma *dma_get(int dmac_id) +/*
- get DMAC based on user type, copy dir and flags
- "flags" is used to set the type of access requested
- (ex: shared/exclusive access)
- */
+struct dma *dma_get(enum dmac_user user, enum dmac_copy_dir dir, int flags) {
- int i;
int i, ch_count;
int dma_index = -1;
int min_ch_count = INT32_MAX;
for (i = 0; i < ARRAY_SIZE(dma); i++) {
if (dma[i].plat_data.id == dmac_id)
return &dma[i];
/* check DMAC user type */
if (dma[i].plat_data.type != user)
continue;
/* check DMAC copy dir */
if (dma[i].plat_data.copy_dir != dir)
continue;
/* if exclusive access is requested */
if (flags & DMAC_FLAGS_EXCLUSIVE) {
/* ret DMA with no channel in use */
if (!dma_channel_status(&dma[i]))
return &dma[i];
} else {
/* get number of channels in use */
ch_count = dma_channel_status(&dma[i]);
/* Use this DMAC if its channel count is lower */
if (ch_count < min_ch_count) {
dma_index = i;
min_ch_count = ch_count;
}
}
}
if (dma_index >= 0)
return &dma[dma_index];
return NULL;
}
diff --git a/src/platform/haswell/dma.c b/src/platform/haswell/dma.c index 5d1e308..9138e78 100644 --- a/src/platform/haswell/dma.c +++ b/src/platform/haswell/dma.c @@ -124,16 +124,49 @@ static struct dma dma[] = { .ops = &dw_dma_ops, },};
-struct dma *dma_get(int dmac_id) +/*
- get DMAC based on user type, copy dir and flags
- For BYT/CHT, ignore the dmac_user and copy_dir arguments
- "flags" is used to set the type of access requested
- (ex: shared/exclusive access)
- */
+struct dma *dma_get(enum dmac_user user, enum dmac_copy_dir dir, int flags) {
- switch (dmac_id) {
- case DMA_ID_DMAC0:
return &dma[0];
- case DMA_ID_DMAC1:
return &dma[1];
- default:
return NULL;
- int i, ch_count;
- int min_ch_count = INT32_MAX;
- int dma_index = -1;
- for (i = 0; i < ARRAY_SIZE(dma); i++) {
/* if exclusive access is requested */
if (flags & DMAC_FLAGS_EXCLUSIVE) {
/* ret DMA with no channel in use */
if (!dma_channel_status(&dma[i]))
return &dma[i];
} else {
/*
* for shared access requests, return DMAC
* with the least number of channels in use
*/
/* get number of channels in use for this DMAC*/
ch_count = dma_channel_status(&dma[i]);
/* Use this DMAC if its channel count is lower */
if (ch_count < min_ch_count) {
dma_index = i;
min_ch_count = ch_count;
}
}}
- /* return DMAC */
- if (dma_index >= 0)
return &dma[dma_index];
- return NULL;
}
/* Initialize all platform DMAC's */
On 6/5/2018 5:19 PM, Liam Girdwood wrote:
On Mon, 2018-06-04 at 21:23 -0700, Ranjani Sridharan wrote:
This patch introduces a new API for procuring DMAC for various user based on the type of DMAC, copy direction and other flags for share/exclusive access. It defines the necessary DMAC user types, copy direction and the flags to suuport the new API.It also adds two new members to dma_plat_data to differentiate the DMAC based on usage and copy direction.
Finally, it also contains the platform specific implementation of the new dma_get() API.
Signed-off-by: Ranjani Sridharan ranjani.sridharan@linux.intel.com
src/include/sof/dma.h | 26 ++++++++++++++++- src/platform/apollolake/dma.c | 53 ++++++++++++++++++++++++++++++++--- src/platform/baytrail/dma.c | 41 ++++++++++++++++++++++++--- src/platform/cannonlake/dma.c | 53 ++++++++++++++++++++++++++++++++--- src/platform/haswell/dma.c | 49 ++++++++++++++++++++++++++------ 5 files changed, 201 insertions(+), 21 deletions(-)
Lets consolidate the dma_get() into a common dma file.
Liam
but different platform may use different algorithm for choosing
diff --git a/src/include/sof/dma.h b/src/include/sof/dma.h index 1de9efc..25581e6 100644 --- a/src/include/sof/dma.h +++ b/src/include/sof/dma.h @@ -48,6 +48,28 @@ enum dma_copy_dir { DMA_DIR_DEV_TO_DEV, };
+/*
- DMAC copy directions
- These are used to specify the copy direction while requesting a DMAC
- */
+enum dmac_copy_dir {
- DMAC_DIR_READ = 0,
- DMAC_DIR_WRITE,
- DMAC_DIR_DUPLEX,
+};
+/* DMAC user types */ +enum dmac_user {
- DMAC_USER_HOST_DMA = 0,
- DMAC_USER_LINK_DMA,
- DMAC_USER_GP_LP_DMA,
- DMAC_USER_GP_HP_DMA,
+};
+/* DMAC flags */ +#define DMAC_FLAGS_SHARED 0 +#define DMAC_FLAGS_EXCLUSIVE (1 << 0)
- /* DMA IRQ types */ #define DMA_IRQ_TYPE_BLOCK (1 << 0) #define DMA_IRQ_TYPE_LLIST (1 << 1)
@@ -119,6 +141,8 @@ struct dma_ops { /* DMA platform data */ struct dma_plat_data { uint32_t id;
- enum dmac_user type;
- enum dmac_copy_dir copy_dir; uint32_t base; uint32_t channels; uint32_t irq;
@@ -139,7 +163,7 @@ struct dma_int { uint32_t irq; };
-struct dma *dma_get(int dmac_id); +struct dma *dma_get(enum dmac_user, enum dmac_copy_dir, int flags);
/* initialize all platform DMAC's */ void dmac_init(void); diff --git a/src/platform/apollolake/dma.c b/src/platform/apollolake/dma.c index 001bb67..1ae097e 100644 --- a/src/platform/apollolake/dma.c +++ b/src/platform/apollolake/dma.c @@ -112,6 +112,8 @@ static struct dma dma[] = { { /* Low Power GP DMAC 0 */ .plat_data = { .id = DMA_GP_LP_DMAC0,
.type = DMAC_USER_GP_LP_DMA,
.base = LP_GP_DMA_BASE(0), .channels = 8, .irq = IRQ_EXT_LP_GPDMA0_LVL5(0, 0),.copy_dir = DMAC_DIR_DUPLEX,
@@ -122,6 +124,8 @@ static struct dma dma[] = { { /* Low Power GP DMAC 1 */ .plat_data = { .id = DMA_GP_LP_DMAC1,
.type = DMAC_USER_GP_LP_DMA,
.base = LP_GP_DMA_BASE(1), .channels = 8, .irq = IRQ_EXT_LP_GPDMA1_LVL5(0, 0),.copy_dir = DMAC_DIR_DUPLEX,
@@ -132,6 +136,8 @@ static struct dma dma[] = { { /* Host In DMAC */ .plat_data = { .id = DMA_HOST_IN_DMAC,
.type = DMAC_USER_HOST_DMA,
.base = GTW_HOST_IN_STREAM_BASE(0), .channels = 7, .irq = IRQ_EXT_HOST_DMA_IN_LVL3(0, 0),.copy_dir = DMAC_DIR_WRITE,
@@ -142,6 +148,8 @@ static struct dma dma[] = { { /* Host out DMAC */ .plat_data = { .id = DMA_HOST_OUT_DMAC,
.type = DMAC_USER_HOST_DMA,
.base = GTW_HOST_OUT_STREAM_BASE(0), .channels = 6, .irq = IRQ_EXT_HOST_DMA_OUT_LVL3(0, 0),.copy_dir = DMAC_DIR_READ,
@@ -152,6 +160,8 @@ static struct dma dma[] = { { /* Link In DMAC */ .plat_data = { .id = DMA_LINK_IN_DMAC,
.type = DMAC_USER_LINK_DMA,
.base = GTW_LINK_IN_STREAM_BASE(0), .channels = 8, .irq = IRQ_EXT_LINK_DMA_IN_LVL4(0, 0),.copy_dir = DMAC_DIR_WRITE,
@@ -162,6 +172,8 @@ static struct dma dma[] = { { /* Link out DMAC */ .plat_data = { .id = DMA_LINK_OUT_DMAC,
.type = DMAC_USER_LINK_DMA,
.base = GTW_LINK_OUT_STREAM_BASE(0), .channels = 8, .irq = IRQ_EXT_LINK_DMA_OUT_LVL4(0, 0),.copy_dir = DMAC_DIR_READ,
@@ -170,15 +182,48 @@ static struct dma dma[] = { .ops = &hda_link_dma_ops, },};
-struct dma *dma_get(int dmac_id) +/*
- get DMAC based on user type, copy dir and flags
- "flags" is used to set the type of access requested
- (ex: shared/exclusive access)
- */
+struct dma *dma_get(enum dmac_user user, enum dmac_copy_dir dir, int flags) {
- int i;
int i, ch_count;
int dma_index = -1;
int min_ch_count = INT32_MAX;
for (i = 0; i < ARRAY_SIZE(dma); i++) {
if (dma[i].plat_data.id == dmac_id)
return &dma[i];
/* check DMAC user type */
if (dma[i].plat_data.type != user)
continue;
/* check DMAC copy dir */
if (dma[i].plat_data.copy_dir != dir)
continue;
/* if exclusive access is requested */
if (flags & DMAC_FLAGS_EXCLUSIVE) {
/* ret DMA with no channel in use */
if (!dma_channel_status(&dma[i]))
return &dma[i];
} else {
/* get number of channels in use */
ch_count = dma_channel_status(&dma[i]);
/* Use this DMAC if its channel count is lower */
if (ch_count < min_ch_count) {
dma_index = i;
min_ch_count = ch_count;
}
}
}
if (dma_index >= 0)
return &dma[dma_index];
return NULL; }
diff --git a/src/platform/baytrail/dma.c b/src/platform/baytrail/dma.c index 5a0b650..71ea241 100644 --- a/src/platform/baytrail/dma.c +++ b/src/platform/baytrail/dma.c @@ -175,15 +175,48 @@ static struct dma dma[] = { #endif };
-struct dma *dma_get(int dmac_id) +/*
- get DMAC based on user type, copy dir and flags
- For BYT/CHT, ignore the dmac_user and copy_dir arguments
- "flags" is used to set the type of access requested
- (ex: shared/exclusive access)
- */
+struct dma *dma_get(enum dmac_user user, enum dmac_copy_dir dir, int flags) {
- int i;
int i, ch_count;
int min_ch_count = INT32_MAX;
int dma_index = -1;
for (i = 0; i < ARRAY_SIZE(dma); i++) {
if (dma[i].plat_data.id == dmac_id)
return &dma[i];
/* if exclusive access is requested */
if (flags & DMAC_FLAGS_EXCLUSIVE) {
/* ret DMA with no channel in use */
if (!dma_channel_status(&dma[i]))
return &dma[i];
} else {
/*
* for shared access requests, return DMAC
* with the least number of channels in use
*/
/* get number of channels in use for this DMAC*/
ch_count = dma_channel_status(&dma[i]);
/* Use this DMAC if its channel count is lower */
if (ch_count < min_ch_count) {
dma_index = i;
min_ch_count = ch_count;
}
}
}
/* return DMAC */
if (dma_index >= 0)
return &dma[dma_index];
return NULL; }
diff --git a/src/platform/cannonlake/dma.c b/src/platform/cannonlake/dma.c index 9031c17..697b9a8 100644 --- a/src/platform/cannonlake/dma.c +++ b/src/platform/cannonlake/dma.c @@ -113,6 +113,8 @@ static struct dma dma[] = { { /* Low Power GP DMAC 0 */ .plat_data = { .id = DMA_GP_LP_DMAC0,
.type = DMAC_USER_GP_LP_DMA,
.base = LP_GP_DMA_BASE(0), .channels = 8, .irq = IRQ_EXT_LP_GPDMA0_LVL5(0, 0),.copy_dir = DMAC_DIR_DUPLEX,
@@ -123,6 +125,8 @@ static struct dma dma[] = { { /* Low Power GP DMAC 1 */ .plat_data = { .id = DMA_GP_LP_DMAC1,
.type = DMAC_USER_GP_LP_DMA,
.base = LP_GP_DMA_BASE(1), .channels = 8, .irq = IRQ_EXT_LP_GPDMA1_LVL5(0, 0),.copy_dir = DMAC_DIR_DUPLEX,
@@ -133,6 +137,8 @@ static struct dma dma[] = { { /* Host In DMAC */ .plat_data = { .id = DMA_HOST_IN_DMAC,
.type = DMAC_USER_HOST_DMA,
.base = GTW_HOST_IN_STREAM_BASE(0), .channels = 7, .irq = IRQ_EXT_HOST_DMA_IN_LVL3(0, 0),.copy_dir = DMAC_DIR_WRITE,
@@ -143,6 +149,8 @@ static struct dma dma[] = { { /* Host out DMAC */ .plat_data = { .id = DMA_HOST_OUT_DMAC,
.type = DMAC_USER_HOST_DMA,
.base = GTW_HOST_OUT_STREAM_BASE(0), .channels = 9, .irq = IRQ_EXT_HOST_DMA_OUT_LVL3(0, 0),.copy_dir = DMAC_DIR_READ,
@@ -153,6 +161,8 @@ static struct dma dma[] = { { /* Link In DMAC */ .plat_data = { .id = DMA_LINK_IN_DMAC,
.type = DMAC_USER_LINK_DMA,
.base = GTW_LINK_IN_STREAM_BASE(0), .channels = 9, .irq = IRQ_EXT_LINK_DMA_IN_LVL4(0, 0),.copy_dir = DMAC_DIR_WRITE,
@@ -163,6 +173,8 @@ static struct dma dma[] = { { /* Link out DMAC */ .plat_data = { .id = DMA_LINK_OUT_DMAC,
.type = DMAC_USER_LINK_DMA,
.base = GTW_LINK_OUT_STREAM_BASE(0), .channels = 7, .irq = IRQ_EXT_LINK_DMA_OUT_LVL4(0, 0),.copy_dir = DMAC_DIR_READ,
@@ -171,15 +183,48 @@ static struct dma dma[] = { .ops = &hda_link_dma_ops, },};
-struct dma *dma_get(int dmac_id) +/*
- get DMAC based on user type, copy dir and flags
- "flags" is used to set the type of access requested
- (ex: shared/exclusive access)
- */
+struct dma *dma_get(enum dmac_user user, enum dmac_copy_dir dir, int flags) {
- int i;
int i, ch_count;
int dma_index = -1;
int min_ch_count = INT32_MAX;
for (i = 0; i < ARRAY_SIZE(dma); i++) {
if (dma[i].plat_data.id == dmac_id)
return &dma[i];
/* check DMAC user type */
if (dma[i].plat_data.type != user)
continue;
/* check DMAC copy dir */
if (dma[i].plat_data.copy_dir != dir)
continue;
/* if exclusive access is requested */
if (flags & DMAC_FLAGS_EXCLUSIVE) {
/* ret DMA with no channel in use */
if (!dma_channel_status(&dma[i]))
return &dma[i];
} else {
/* get number of channels in use */
ch_count = dma_channel_status(&dma[i]);
/* Use this DMAC if its channel count is lower */
if (ch_count < min_ch_count) {
dma_index = i;
min_ch_count = ch_count;
}
}
}
if (dma_index >= 0)
return &dma[dma_index];
return NULL; }
diff --git a/src/platform/haswell/dma.c b/src/platform/haswell/dma.c index 5d1e308..9138e78 100644 --- a/src/platform/haswell/dma.c +++ b/src/platform/haswell/dma.c @@ -124,16 +124,49 @@ static struct dma dma[] = { .ops = &dw_dma_ops, },};
-struct dma *dma_get(int dmac_id) +/*
- get DMAC based on user type, copy dir and flags
- For BYT/CHT, ignore the dmac_user and copy_dir arguments
- "flags" is used to set the type of access requested
- (ex: shared/exclusive access)
- */
+struct dma *dma_get(enum dmac_user user, enum dmac_copy_dir dir, int flags) {
- switch (dmac_id) {
- case DMA_ID_DMAC0:
return &dma[0];
- case DMA_ID_DMAC1:
return &dma[1];
- default:
return NULL;
int i, ch_count;
int min_ch_count = INT32_MAX;
int dma_index = -1;
for (i = 0; i < ARRAY_SIZE(dma); i++) {
/* if exclusive access is requested */
if (flags & DMAC_FLAGS_EXCLUSIVE) {
/* ret DMA with no channel in use */
if (!dma_channel_status(&dma[i]))
return &dma[i];
} else {
/*
* for shared access requests, return DMAC
* with the least number of channels in use
*/
/* get number of channels in use for this DMAC*/
ch_count = dma_channel_status(&dma[i]);
/* Use this DMAC if its channel count is lower */
if (ch_count < min_ch_count) {
dma_index = i;
min_ch_count = ch_count;
}
}
}
/* return DMAC */
if (dma_index >= 0)
return &dma[dma_index];
return NULL; }
/* Initialize all platform DMAC's */
Sound-open-firmware mailing list Sound-open-firmware@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/sound-open-firmware
On Tue, 2018-06-05 at 18:00 +0800, rander.wang wrote:
src/include/sof/dma.h | 26 ++++++++++++++++- src/platform/apollolake/dma.c | 53 ++++++++++++++++++++++++++++++++--- src/platform/baytrail/dma.c | 41 ++++++++++++++++++++++++--- src/platform/cannonlake/dma.c | 53 ++++++++++++++++++++++++++++++++--- src/platform/haswell/dma.c | 49 ++++++++++++++++++++++++++------ 5 files changed, 201 insertions(+), 21 deletions(-)
Lets consolidate the dma_get() into a common dma file.
Liam
but different platform may use different algorithm for choosing
Algo should be the same, but array of platform DMACs will be different and chosen based on flags, type etc.
Liam
On 2018年06月05日 12:23, Ranjani Sridharan wrote:
This patch introduces a new API for procuring DMAC for various user based on the type of DMAC, copy direction and other flags for share/exclusive access. It defines the necessary DMAC user types, copy direction and the flags to suuport the new API.It also adds two new members to dma_plat_data to differentiate the DMAC based on usage and copy direction.
Finally, it also contains the platform specific implementation of the new dma_get() API.
Signed-off-by: Ranjani Sridharan ranjani.sridharan@linux.intel.com
src/include/sof/dma.h | 26 ++++++++++++++++- src/platform/apollolake/dma.c | 53 ++++++++++++++++++++++++++++++++--- src/platform/baytrail/dma.c | 41 ++++++++++++++++++++++++--- src/platform/cannonlake/dma.c | 53 ++++++++++++++++++++++++++++++++--- src/platform/haswell/dma.c | 49 ++++++++++++++++++++++++++------ 5 files changed, 201 insertions(+), 21 deletions(-)
diff --git a/src/include/sof/dma.h b/src/include/sof/dma.h index 1de9efc..25581e6 100644 --- a/src/include/sof/dma.h +++ b/src/include/sof/dma.h @@ -48,6 +48,28 @@ enum dma_copy_dir { DMA_DIR_DEV_TO_DEV, };
+/*
- DMAC copy directions
- These are used to specify the copy direction while requesting a DMAC
- */
+enum dmac_copy_dir {
- DMAC_DIR_READ = 0,
- DMAC_DIR_WRITE,
- DMAC_DIR_DUPLEX,
+};
I can't understand this, what is read and what is write? For DMA, it always read from some buffer and write them to another buffer.
[edit] after reading the patch, I got your point. maybe naming it with
+enum dmac_dir_cap { + DMAC_CAP_READ = 0, + DMAC_CAP_WRITE, + DMAC_CAP_DUPLEX, +};
or we can use bit mask for that, which can be reused with user type below also, e.g.
bit 0: cap_read bit 1: cap_write bit 2: host/link bit 3: lp/hp. bit 4: share/exclusive ...
+/* DMAC user types */ +enum dmac_user {
- DMAC_USER_HOST_DMA = 0,
- DMAC_USER_LINK_DMA,
do we need split into output and input for these?
- DMAC_USER_GP_LP_DMA,
- DMAC_USER_GP_HP_DMA,
+};
+/* DMAC flags */ +#define DMAC_FLAGS_SHARED 0 +#define DMAC_FLAGS_EXCLUSIVE (1 << 0)
Can you explain what is shared and how channels are shared? Are you meaning channel reservation for specific user with exclusive? I can't image the use case for this.
- /* DMA IRQ types */ #define DMA_IRQ_TYPE_BLOCK (1 << 0) #define DMA_IRQ_TYPE_LLIST (1 << 1)
@@ -119,6 +141,8 @@ struct dma_ops { /* DMA platform data */ struct dma_plat_data { uint32_t id;
- enum dmac_user type;
- enum dmac_copy_dir copy_dir; uint32_t base; uint32_t channels; uint32_t irq;
@@ -139,7 +163,7 @@ struct dma_int { uint32_t irq; };
-struct dma *dma_get(int dmac_id); +struct dma *dma_get(enum dmac_user, enum dmac_copy_dir, int flags);
/* initialize all platform DMAC's */ void dmac_init(void); diff --git a/src/platform/apollolake/dma.c b/src/platform/apollolake/dma.c index 001bb67..1ae097e 100644 --- a/src/platform/apollolake/dma.c +++ b/src/platform/apollolake/dma.c @@ -112,6 +112,8 @@ static struct dma dma[] = { { /* Low Power GP DMAC 0 */ .plat_data = { .id = DMA_GP_LP_DMAC0,
.type = DMAC_USER_GP_LP_DMA,
.base = LP_GP_DMA_BASE(0), .channels = 8, .irq = IRQ_EXT_LP_GPDMA0_LVL5(0, 0),.copy_dir = DMAC_DIR_DUPLEX,
@@ -122,6 +124,8 @@ static struct dma dma[] = { { /* Low Power GP DMAC 1 */ .plat_data = { .id = DMA_GP_LP_DMAC1,
.type = DMAC_USER_GP_LP_DMA,
.base = LP_GP_DMA_BASE(1), .channels = 8, .irq = IRQ_EXT_LP_GPDMA1_LVL5(0, 0),.copy_dir = DMAC_DIR_DUPLEX,
@@ -132,6 +136,8 @@ static struct dma dma[] = { { /* Host In DMAC */ .plat_data = { .id = DMA_HOST_IN_DMAC,
.type = DMAC_USER_HOST_DMA,
.base = GTW_HOST_IN_STREAM_BASE(0), .channels = 7, .irq = IRQ_EXT_HOST_DMA_IN_LVL3(0, 0),.copy_dir = DMAC_DIR_WRITE,
@@ -142,6 +148,8 @@ static struct dma dma[] = { { /* Host out DMAC */ .plat_data = { .id = DMA_HOST_OUT_DMAC,
.type = DMAC_USER_HOST_DMA,
.base = GTW_HOST_OUT_STREAM_BASE(0), .channels = 6, .irq = IRQ_EXT_HOST_DMA_OUT_LVL3(0, 0),.copy_dir = DMAC_DIR_READ,
@@ -152,6 +160,8 @@ static struct dma dma[] = { { /* Link In DMAC */ .plat_data = { .id = DMA_LINK_IN_DMAC,
.type = DMAC_USER_LINK_DMA,
.base = GTW_LINK_IN_STREAM_BASE(0), .channels = 8, .irq = IRQ_EXT_LINK_DMA_IN_LVL4(0, 0),.copy_dir = DMAC_DIR_WRITE,
@@ -162,6 +172,8 @@ static struct dma dma[] = { { /* Link out DMAC */ .plat_data = { .id = DMA_LINK_OUT_DMAC,
.type = DMAC_USER_LINK_DMA,
.base = GTW_LINK_OUT_STREAM_BASE(0), .channels = 8, .irq = IRQ_EXT_LINK_DMA_OUT_LVL4(0, 0),.copy_dir = DMAC_DIR_READ,
@@ -170,15 +182,48 @@ static struct dma dma[] = { .ops = &hda_link_dma_ops, },};
-struct dma *dma_get(int dmac_id) +/*
- get DMAC based on user type, copy dir and flags
- "flags" is used to set the type of access requested
- (ex: shared/exclusive access)
- */
+struct dma *dma_get(enum dmac_user user, enum dmac_copy_dir dir, int flags) {
- int i;
int i, ch_count;
int dma_index = -1;
int min_ch_count = INT32_MAX;
for (i = 0; i < ARRAY_SIZE(dma); i++) {
if (dma[i].plat_data.id == dmac_id)
return &dma[i];
/* check DMAC user type */
if (dma[i].plat_data.type != user)
continue;
/* check DMAC copy dir */
if (dma[i].plat_data.copy_dir != dir)
continue;
/* if exclusive access is requested */
if (flags & DMAC_FLAGS_EXCLUSIVE) {
/* ret DMA with no channel in use */
if (!dma_channel_status(&dma[i]))
return &dma[i];
} else {
/* get number of channels in use */
ch_count = dma_channel_status(&dma[i]);
/* Use this DMAC if its channel count is lower */
if (ch_count < min_ch_count) {
dma_index = i;
min_ch_count = ch_count;
}
}
}
if (dma_index >= 0)
return &dma[dma_index];
return NULL; }
diff --git a/src/platform/baytrail/dma.c b/src/platform/baytrail/dma.c index 5a0b650..71ea241 100644 --- a/src/platform/baytrail/dma.c +++ b/src/platform/baytrail/dma.c @@ -175,15 +175,48 @@ static struct dma dma[] = { #endif };
-struct dma *dma_get(int dmac_id) +/*
- get DMAC based on user type, copy dir and flags
- For BYT/CHT, ignore the dmac_user and copy_dir arguments
- "flags" is used to set the type of access requested
- (ex: shared/exclusive access)
- */
+struct dma *dma_get(enum dmac_user user, enum dmac_copy_dir dir, int flags) {
- int i;
int i, ch_count;
int min_ch_count = INT32_MAX;
int dma_index = -1;
for (i = 0; i < ARRAY_SIZE(dma); i++) {
if (dma[i].plat_data.id == dmac_id)
return &dma[i];
/* if exclusive access is requested */
if (flags & DMAC_FLAGS_EXCLUSIVE) {
/* ret DMA with no channel in use */
if (!dma_channel_status(&dma[i]))
return &dma[i];
} else {
/*
* for shared access requests, return DMAC
* with the least number of channels in use
*/
/* get number of channels in use for this DMAC*/
ch_count = dma_channel_status(&dma[i]);
/* Use this DMAC if its channel count is lower */
if (ch_count < min_ch_count) {
dma_index = i;
min_ch_count = ch_count;
}
}
}
/* return DMAC */
if (dma_index >= 0)
return &dma[dma_index];
return NULL; }
again, this function can be shared also?
Thanks, ~Keyon
diff --git a/src/platform/cannonlake/dma.c b/src/platform/cannonlake/dma.c index 9031c17..697b9a8 100644 --- a/src/platform/cannonlake/dma.c +++ b/src/platform/cannonlake/dma.c @@ -113,6 +113,8 @@ static struct dma dma[] = { { /* Low Power GP DMAC 0 */ .plat_data = { .id = DMA_GP_LP_DMAC0,
.type = DMAC_USER_GP_LP_DMA,
.base = LP_GP_DMA_BASE(0), .channels = 8, .irq = IRQ_EXT_LP_GPDMA0_LVL5(0, 0),.copy_dir = DMAC_DIR_DUPLEX,
@@ -123,6 +125,8 @@ static struct dma dma[] = { { /* Low Power GP DMAC 1 */ .plat_data = { .id = DMA_GP_LP_DMAC1,
.type = DMAC_USER_GP_LP_DMA,
.base = LP_GP_DMA_BASE(1), .channels = 8, .irq = IRQ_EXT_LP_GPDMA1_LVL5(0, 0),.copy_dir = DMAC_DIR_DUPLEX,
@@ -133,6 +137,8 @@ static struct dma dma[] = { { /* Host In DMAC */ .plat_data = { .id = DMA_HOST_IN_DMAC,
.type = DMAC_USER_HOST_DMA,
.base = GTW_HOST_IN_STREAM_BASE(0), .channels = 7, .irq = IRQ_EXT_HOST_DMA_IN_LVL3(0, 0),.copy_dir = DMAC_DIR_WRITE,
@@ -143,6 +149,8 @@ static struct dma dma[] = { { /* Host out DMAC */ .plat_data = { .id = DMA_HOST_OUT_DMAC,
.type = DMAC_USER_HOST_DMA,
.base = GTW_HOST_OUT_STREAM_BASE(0), .channels = 9, .irq = IRQ_EXT_HOST_DMA_OUT_LVL3(0, 0),.copy_dir = DMAC_DIR_READ,
@@ -153,6 +161,8 @@ static struct dma dma[] = { { /* Link In DMAC */ .plat_data = { .id = DMA_LINK_IN_DMAC,
.type = DMAC_USER_LINK_DMA,
.base = GTW_LINK_IN_STREAM_BASE(0), .channels = 9, .irq = IRQ_EXT_LINK_DMA_IN_LVL4(0, 0),.copy_dir = DMAC_DIR_WRITE,
@@ -163,6 +173,8 @@ static struct dma dma[] = { { /* Link out DMAC */ .plat_data = { .id = DMA_LINK_OUT_DMAC,
.type = DMAC_USER_LINK_DMA,
.base = GTW_LINK_OUT_STREAM_BASE(0), .channels = 7, .irq = IRQ_EXT_LINK_DMA_OUT_LVL4(0, 0),.copy_dir = DMAC_DIR_READ,
@@ -171,15 +183,48 @@ static struct dma dma[] = { .ops = &hda_link_dma_ops, },};
-struct dma *dma_get(int dmac_id) +/*
- get DMAC based on user type, copy dir and flags
- "flags" is used to set the type of access requested
- (ex: shared/exclusive access)
- */
+struct dma *dma_get(enum dmac_user user, enum dmac_copy_dir dir, int flags) {
- int i;
int i, ch_count;
int dma_index = -1;
int min_ch_count = INT32_MAX;
for (i = 0; i < ARRAY_SIZE(dma); i++) {
if (dma[i].plat_data.id == dmac_id)
return &dma[i];
/* check DMAC user type */
if (dma[i].plat_data.type != user)
continue;
/* check DMAC copy dir */
if (dma[i].plat_data.copy_dir != dir)
continue;
/* if exclusive access is requested */
if (flags & DMAC_FLAGS_EXCLUSIVE) {
/* ret DMA with no channel in use */
if (!dma_channel_status(&dma[i]))
return &dma[i];
} else {
/* get number of channels in use */
ch_count = dma_channel_status(&dma[i]);
/* Use this DMAC if its channel count is lower */
if (ch_count < min_ch_count) {
dma_index = i;
min_ch_count = ch_count;
}
}
}
if (dma_index >= 0)
return &dma[dma_index];
return NULL; }
diff --git a/src/platform/haswell/dma.c b/src/platform/haswell/dma.c index 5d1e308..9138e78 100644 --- a/src/platform/haswell/dma.c +++ b/src/platform/haswell/dma.c @@ -124,16 +124,49 @@ static struct dma dma[] = { .ops = &dw_dma_ops, },};
-struct dma *dma_get(int dmac_id) +/*
- get DMAC based on user type, copy dir and flags
- For BYT/CHT, ignore the dmac_user and copy_dir arguments
- "flags" is used to set the type of access requested
- (ex: shared/exclusive access)
- */
+struct dma *dma_get(enum dmac_user user, enum dmac_copy_dir dir, int flags) {
- switch (dmac_id) {
- case DMA_ID_DMAC0:
return &dma[0];
- case DMA_ID_DMAC1:
return &dma[1];
- default:
return NULL;
int i, ch_count;
int min_ch_count = INT32_MAX;
int dma_index = -1;
for (i = 0; i < ARRAY_SIZE(dma); i++) {
/* if exclusive access is requested */
if (flags & DMAC_FLAGS_EXCLUSIVE) {
/* ret DMA with no channel in use */
if (!dma_channel_status(&dma[i]))
return &dma[i];
} else {
/*
* for shared access requests, return DMAC
* with the least number of channels in use
*/
/* get number of channels in use for this DMAC*/
ch_count = dma_channel_status(&dma[i]);
/* Use this DMAC if its channel count is lower */
if (ch_count < min_ch_count) {
dma_index = i;
min_ch_count = ch_count;
}
}
}
/* return DMAC */
if (dma_index >= 0)
return &dma[dma_index];
return NULL; }
/* Initialize all platform DMAC's */
On Tue, 2018-06-05 at 19:05 +0800, Keyon Jie wrote:
On 2018年06月05日 12:23, Ranjani Sridharan wrote:
This patch introduces a new API for procuring DMAC for various user based on the type of DMAC, copy direction and other flags for share/exclusive access. It defines the necessary DMAC user types, copy direction and the flags to suuport the new API.It also adds two new members to dma_plat_data to differentiate the DMAC based on usage and copy direction.
Finally, it also contains the platform specific implementation of the new dma_get() API.
Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com
src/include/sof/dma.h | 26 ++++++++++++++++- src/platform/apollolake/dma.c | 53 ++++++++++++++++++++++++++++++++--- src/platform/baytrail/dma.c | 41 ++++++++++++++++++++++++--- src/platform/cannonlake/dma.c | 53 ++++++++++++++++++++++++++++++++--- src/platform/haswell/dma.c | 49 ++++++++++++++++++++++++++--
5 files changed, 201 insertions(+), 21 deletions(-)
diff --git a/src/include/sof/dma.h b/src/include/sof/dma.h index 1de9efc..25581e6 100644 --- a/src/include/sof/dma.h +++ b/src/include/sof/dma.h @@ -48,6 +48,28 @@ enum dma_copy_dir { DMA_DIR_DEV_TO_DEV, };
+/*
- DMAC copy directions
- These are used to specify the copy direction while requesting a
DMAC
- */
+enum dmac_copy_dir {
- DMAC_DIR_READ = 0,
- DMAC_DIR_WRITE,
- DMAC_DIR_DUPLEX,
+};
I can't understand this, what is read and what is write? For DMA, it always read from some buffer and write them to another buffer.
[edit] after reading the patch, I got your point. maybe naming it with
+enum dmac_dir_cap {
- DMAC_CAP_READ = 0,
- DMAC_CAP_WRITE,
- DMAC_CAP_DUPLEX,
+};
or we can use bit mask for that, which can be reused with user type below also, e.g.
bit 0: cap_read bit 1: cap_write bit 2: host/link bit 3: lp/hp. bit 4: share/exclusive
I can rename the enum but I'd like to stick with the arguments for the dma_get API. It is really only 3 arguments and it makes deciphering code much easier than applying bitmasks.
Unless, you have a compelling reason for me not to use separate arguments?
...
+/* DMAC user types */ +enum dmac_user {
- DMAC_USER_HOST_DMA = 0,
- DMAC_USER_LINK_DMA,
do we need split into output and input for these?
- DMAC_USER_GP_LP_DMA,
- DMAC_USER_GP_HP_DMA,
+};
+/* DMAC flags */ +#define DMAC_FLAGS_SHARED 0 +#define DMAC_FLAGS_EXCLUSIVE (1 << 0)
Can you explain what is shared and how channels are shared? Are you meaning channel reservation for specific user with exclusive? I can't image the use case for this.
Shared is the most common usage, where we share DMAC between users.
Exclusive as Liam explained will be fore critical usages that require that only one user will use the DMAC at any time. ie there will only be one channel draining at any time.
I havent seen the need for exclusive access so far. But we might need it in the future.
- /* DMA IRQ types */ #define DMA_IRQ_TYPE_BLOCK (1 << 0) #define DMA_IRQ_TYPE_LLIST (1 << 1)
@@ -119,6 +141,8 @@ struct dma_ops { /* DMA platform data */ struct dma_plat_data { uint32_t id;
- enum dmac_user type;
- enum dmac_copy_dir copy_dir; uint32_t base; uint32_t channels; uint32_t irq;
@@ -139,7 +163,7 @@ struct dma_int { uint32_t irq; };
-struct dma *dma_get(int dmac_id); +struct dma *dma_get(enum dmac_user, enum dmac_copy_dir, int flags);
/* initialize all platform DMAC's */ void dmac_init(void); diff --git a/src/platform/apollolake/dma.c b/src/platform/apollolake/dma.c index 001bb67..1ae097e 100644 --- a/src/platform/apollolake/dma.c +++ b/src/platform/apollolake/dma.c @@ -112,6 +112,8 @@ static struct dma dma[] = { { /* Low Power GP DMAC 0 */ .plat_data = { .id = DMA_GP_LP_DMAC0,
.type = DMAC_USER_GP_LP_DMA,
.base = LP_GP_DMA_BASE(0), .channels = 8, .irq = IRQ_EXT_LP_GPDMA0_LVL5(0,.copy_dir = DMAC_DIR_DUPLEX,
0), @@ -122,6 +124,8 @@ static struct dma dma[] = { { /* Low Power GP DMAC 1 */ .plat_data = { .id = DMA_GP_LP_DMAC1,
.type = DMAC_USER_GP_LP_DMA,
.base = LP_GP_DMA_BASE(1), .channels = 8, .irq = IRQ_EXT_LP_GPDMA1_LVL5(0,.copy_dir = DMAC_DIR_DUPLEX,
0), @@ -132,6 +136,8 @@ static struct dma dma[] = { { /* Host In DMAC */ .plat_data = { .id = DMA_HOST_IN_DMAC,
.type = DMAC_USER_HOST_DMA,
.base =.copy_dir = DMAC_DIR_WRITE,
GTW_HOST_IN_STREAM_BASE(0), .channels = 7, .irq = IRQ_EXT_HOST_DMA_IN_LVL3(0, 0), @@ -142,6 +148,8 @@ static struct dma dma[] = { { /* Host out DMAC */ .plat_data = { .id = DMA_HOST_OUT_DMAC,
.type = DMAC_USER_HOST_DMA,
.base =.copy_dir = DMAC_DIR_READ,
GTW_HOST_OUT_STREAM_BASE(0), .channels = 6, .irq = IRQ_EXT_HOST_DMA_OUT_LVL3(0, 0), @@ -152,6 +160,8 @@ static struct dma dma[] = { { /* Link In DMAC */ .plat_data = { .id = DMA_LINK_IN_DMAC,
.type = DMAC_USER_LINK_DMA,
.base =.copy_dir = DMAC_DIR_WRITE,
GTW_LINK_IN_STREAM_BASE(0), .channels = 8, .irq = IRQ_EXT_LINK_DMA_IN_LVL4(0, 0), @@ -162,6 +172,8 @@ static struct dma dma[] = { { /* Link out DMAC */ .plat_data = { .id = DMA_LINK_OUT_DMAC,
.type = DMAC_USER_LINK_DMA,
.base =.copy_dir = DMAC_DIR_READ,
GTW_LINK_OUT_STREAM_BASE(0), .channels = 8, .irq = IRQ_EXT_LINK_DMA_OUT_LVL4(0, 0), @@ -170,15 +182,48 @@ static struct dma dma[] = { .ops = &hda_link_dma_ops, },};
-struct dma *dma_get(int dmac_id) +/*
- get DMAC based on user type, copy dir and flags
- "flags" is used to set the type of access requested
- (ex: shared/exclusive access)
- */
+struct dma *dma_get(enum dmac_user user, enum dmac_copy_dir dir, int flags) {
- int i;
int i, ch_count;
int dma_index = -1;
int min_ch_count = INT32_MAX;
for (i = 0; i < ARRAY_SIZE(dma); i++) {
if (dma[i].plat_data.id == dmac_id)
return &dma[i];
/* check DMAC user type */
if (dma[i].plat_data.type != user)
continue;
/* check DMAC copy dir */
if (dma[i].plat_data.copy_dir != dir)
continue;
/* if exclusive access is requested */
if (flags & DMAC_FLAGS_EXCLUSIVE) {
/* ret DMA with no channel in use */
if (!dma_channel_status(&dma[i]))
return &dma[i];
} else {
/* get number of channels in use */
ch_count = dma_channel_status(&dma[i]);
/* Use this DMAC if its channel count is
lower */
if (ch_count < min_ch_count) {
dma_index = i;
min_ch_count = ch_count;
}
}
}
if (dma_index >= 0)
return &dma[dma_index];
return NULL; }
diff --git a/src/platform/baytrail/dma.c b/src/platform/baytrail/dma.c index 5a0b650..71ea241 100644 --- a/src/platform/baytrail/dma.c +++ b/src/platform/baytrail/dma.c @@ -175,15 +175,48 @@ static struct dma dma[] = { #endif };
-struct dma *dma_get(int dmac_id) +/*
- get DMAC based on user type, copy dir and flags
- For BYT/CHT, ignore the dmac_user and copy_dir arguments
- "flags" is used to set the type of access requested
- (ex: shared/exclusive access)
- */
+struct dma *dma_get(enum dmac_user user, enum dmac_copy_dir dir, int flags) {
- int i;
int i, ch_count;
int min_ch_count = INT32_MAX;
int dma_index = -1;
for (i = 0; i < ARRAY_SIZE(dma); i++) {
if (dma[i].plat_data.id == dmac_id)
return &dma[i];
/* if exclusive access is requested */
if (flags & DMAC_FLAGS_EXCLUSIVE) {
/* ret DMA with no channel in use */
if (!dma_channel_status(&dma[i]))
return &dma[i];
} else {
/*
* for shared access requests, return DMAC
* with the least number of channels in
use
*/
/* get number of channels in use for this
DMAC*/
ch_count = dma_channel_status(&dma[i]);
/* Use this DMAC if its channel count is
lower */
if (ch_count < min_ch_count) {
dma_index = i;
min_ch_count = ch_count;
}
}
}
/* return DMAC */
if (dma_index >= 0)
return &dma[dma_index];
return NULL; }
again, this function can be shared also?
Thanks, ~Keyon
diff --git a/src/platform/cannonlake/dma.c b/src/platform/cannonlake/dma.c index 9031c17..697b9a8 100644 --- a/src/platform/cannonlake/dma.c +++ b/src/platform/cannonlake/dma.c @@ -113,6 +113,8 @@ static struct dma dma[] = { { /* Low Power GP DMAC 0 */ .plat_data = { .id = DMA_GP_LP_DMAC0,
.type = DMAC_USER_GP_LP_DMA,
.base = LP_GP_DMA_BASE(0), .channels = 8, .irq = IRQ_EXT_LP_GPDMA0_LVL5(0, 0),.copy_dir = DMAC_DIR_DUPLEX,
@@ -123,6 +125,8 @@ static struct dma dma[] = { { /* Low Power GP DMAC 1 */ .plat_data = { .id = DMA_GP_LP_DMAC1,
.type = DMAC_USER_GP_LP_DMA,
.base = LP_GP_DMA_BASE(1), .channels = 8, .irq = IRQ_EXT_LP_GPDMA1_LVL5(0, 0),.copy_dir = DMAC_DIR_DUPLEX,
@@ -133,6 +137,8 @@ static struct dma dma[] = { { /* Host In DMAC */ .plat_data = { .id = DMA_HOST_IN_DMAC,
.type = DMAC_USER_HOST_DMA,
.base =.copy_dir = DMAC_DIR_WRITE,
GTW_HOST_IN_STREAM_BASE(0), .channels = 7, .irq = IRQ_EXT_HOST_DMA_IN_LVL3(0, 0), @@ -143,6 +149,8 @@ static struct dma dma[] = { { /* Host out DMAC */ .plat_data = { .id = DMA_HOST_OUT_DMAC,
.type = DMAC_USER_HOST_DMA,
.base =.copy_dir = DMAC_DIR_READ,
GTW_HOST_OUT_STREAM_BASE(0), .channels = 9, .irq = IRQ_EXT_HOST_DMA_OUT_LVL3(0, 0), @@ -153,6 +161,8 @@ static struct dma dma[] = { { /* Link In DMAC */ .plat_data = { .id = DMA_LINK_IN_DMAC,
.type = DMAC_USER_LINK_DMA,
.base =.copy_dir = DMAC_DIR_WRITE,
GTW_LINK_IN_STREAM_BASE(0), .channels = 9, .irq = IRQ_EXT_LINK_DMA_IN_LVL4(0, 0), @@ -163,6 +173,8 @@ static struct dma dma[] = { { /* Link out DMAC */ .plat_data = { .id = DMA_LINK_OUT_DMAC,
.type = DMAC_USER_LINK_DMA,
.base =.copy_dir = DMAC_DIR_READ,
GTW_LINK_OUT_STREAM_BASE(0), .channels = 7, .irq = IRQ_EXT_LINK_DMA_OUT_LVL4(0, 0), @@ -171,15 +183,48 @@ static struct dma dma[] = { .ops = &hda_link_dma_ops, },};
-struct dma *dma_get(int dmac_id) +/*
- get DMAC based on user type, copy dir and flags
- "flags" is used to set the type of access requested
- (ex: shared/exclusive access)
- */
+struct dma *dma_get(enum dmac_user user, enum dmac_copy_dir dir, int flags) {
- int i;
int i, ch_count;
int dma_index = -1;
int min_ch_count = INT32_MAX;
for (i = 0; i < ARRAY_SIZE(dma); i++) {
if (dma[i].plat_data.id == dmac_id)
return &dma[i];
/* check DMAC user type */
if (dma[i].plat_data.type != user)
continue;
/* check DMAC copy dir */
if (dma[i].plat_data.copy_dir != dir)
continue;
/* if exclusive access is requested */
if (flags & DMAC_FLAGS_EXCLUSIVE) {
/* ret DMA with no channel in use */
if (!dma_channel_status(&dma[i]))
return &dma[i];
} else {
/* get number of channels in use */
ch_count = dma_channel_status(&dma[i]);
/* Use this DMAC if its channel count is
lower */
if (ch_count < min_ch_count) {
dma_index = i;
min_ch_count = ch_count;
}
}
}
if (dma_index >= 0)
return &dma[dma_index];
return NULL; }
diff --git a/src/platform/haswell/dma.c b/src/platform/haswell/dma.c index 5d1e308..9138e78 100644 --- a/src/platform/haswell/dma.c +++ b/src/platform/haswell/dma.c @@ -124,16 +124,49 @@ static struct dma dma[] = { .ops = &dw_dma_ops, },};
-struct dma *dma_get(int dmac_id) +/*
- get DMAC based on user type, copy dir and flags
- For BYT/CHT, ignore the dmac_user and copy_dir arguments
- "flags" is used to set the type of access requested
- (ex: shared/exclusive access)
- */
+struct dma *dma_get(enum dmac_user user, enum dmac_copy_dir dir, int flags) {
- switch (dmac_id) {
- case DMA_ID_DMAC0:
return &dma[0];
- case DMA_ID_DMAC1:
return &dma[1];
- default:
return NULL;
- int i, ch_count;
- int min_ch_count = INT32_MAX;
- int dma_index = -1;
- for (i = 0; i < ARRAY_SIZE(dma); i++) {
/* if exclusive access is requested */
if (flags & DMAC_FLAGS_EXCLUSIVE) {
/* ret DMA with no channel in use */
if (!dma_channel_status(&dma[i]))
return &dma[i];
} else {
/*
* for shared access requests, return DMAC
* with the least number of channels in
use
*/
/* get number of channels in use for this
DMAC*/
ch_count = dma_channel_status(&dma[i]);
/* Use this DMAC if its channel count is
lower */
if (ch_count < min_ch_count) {
dma_index = i;
min_ch_count = ch_count;
}
}
}
/* return DMAC */
if (dma_index >= 0)
return &dma[dma_index];
return NULL; }
/* Initialize all platform DMAC's */
Sound-open-firmware mailing list Sound-open-firmware@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/sound-open-firmware
On 2018年06月06日 03:18, Ranjani Sridharan wrote:
On Tue, 2018-06-05 at 19:05 +0800, Keyon Jie wrote:
On 2018年06月05日 12:23, Ranjani Sridharan wrote:
This patch introduces a new API for procuring DMAC for various user based on the type of DMAC, copy direction and other flags for share/exclusive access. It defines the necessary DMAC user types, copy direction and the flags to suuport the new API.It also adds two new members to dma_plat_data to differentiate the DMAC based on usage and copy direction.
Finally, it also contains the platform specific implementation of the new dma_get() API.
Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com
src/include/sof/dma.h | 26 ++++++++++++++++- src/platform/apollolake/dma.c | 53 ++++++++++++++++++++++++++++++++--- src/platform/baytrail/dma.c | 41 ++++++++++++++++++++++++--- src/platform/cannonlake/dma.c | 53 ++++++++++++++++++++++++++++++++--- src/platform/haswell/dma.c | 49 ++++++++++++++++++++++++++--
5 files changed, 201 insertions(+), 21 deletions(-)
diff --git a/src/include/sof/dma.h b/src/include/sof/dma.h index 1de9efc..25581e6 100644 --- a/src/include/sof/dma.h +++ b/src/include/sof/dma.h @@ -48,6 +48,28 @@ enum dma_copy_dir { DMA_DIR_DEV_TO_DEV, };
+/*
- DMAC copy directions
- These are used to specify the copy direction while requesting a
DMAC
- */
+enum dmac_copy_dir {
- DMAC_DIR_READ = 0,
- DMAC_DIR_WRITE,
- DMAC_DIR_DUPLEX,
+};
I can't understand this, what is read and what is write? For DMA, it always read from some buffer and write them to another buffer.
[edit] after reading the patch, I got your point. maybe naming it with
+enum dmac_dir_cap {
- DMAC_CAP_READ = 0,
- DMAC_CAP_WRITE,
- DMAC_CAP_DUPLEX,
+};
or we can use bit mask for that, which can be reused with user type below also, e.g.
bit 0: cap_read bit 1: cap_write bit 2: host/link bit 3: lp/hp. bit 4: share/exclusive
I can rename the enum but I'd like to stick with the arguments for the dma_get API. It is really only 3 arguments and it makes deciphering code much easier than applying bitmasks.
Unless, you have a compelling reason for me not to use separate arguments?
I think using the bitmasks is more object oriented, e.g. for direction, what directions does your dmac supported? host_mem_to_mem(1)? mem_to_mem(2)? mem_to_dev(3)? dev_to_dev(4)? mem_to_link(5)? or the opposite? The combination of these can be up to 10.
for byt/bdw, we can support (1)(2)(3)(4)(6)(7)(8)(9); for apl/cnl, host_dmac_output can support (1) only, host_dmac_input can support (6) only, gpdma can support (2)(3)(4)(7)(8)(9), link_dmac_output can support (5), link_dmac_input can support (10) only.
if you tell these clear enough, you will be able to use unify logic in a common dma_get(): /* check DMAC copy dir */ if (dma[i].plat_data.caps & require_cap == require_cap) retrun dma[i]; // very simple, isn't it?
for the user: byt/bdw: playback, host: dma_get(host_mem_to_mem); dai: dma_get(mem_to_dev); capture, host: dma_get(mem_to_hostmem); dai: dma_get(dev_to_mem_); page_table_parsing, dma_get(host_mem_to_mem); dma_trace, dma_get(mem_to_host_mem). apl/cnl: playback, host: dma_get(host_mem_to_mem); dai: dma_get(mem_to_dev); capture, host: dma_get(mem_to_hostmem); dai: dma_get(dev_to_mem_); page_table_parsing, dma_get(host_mem_to_mem); dma_trace, dma_get(mem_to_host_mem).
can you see what? with this, you can make the code very clean/unified in host/dai/dma_trace...
...
+/* DMAC user types */ +enum dmac_user {
- DMAC_USER_HOST_DMA = 0,
- DMAC_USER_LINK_DMA,
do we need split into output and input for these?
- DMAC_USER_GP_LP_DMA,
- DMAC_USER_GP_HP_DMA,
+};
+/* DMAC flags */ +#define DMAC_FLAGS_SHARED 0 +#define DMAC_FLAGS_EXCLUSIVE (1 << 0)
Can you explain what is shared and how channels are shared? Are you meaning channel reservation for specific user with exclusive? I can't image the use case for this.
Shared is the most common usage, where we share DMAC between users.
Exclusive as Liam explained will be fore critical usages that require that only one user will use the DMAC at any time. ie there will only be one channel draining at any time.
Hi Liam, can you explain more about this? Where is the limitation about only one channel draining at the same time, from DMAC or the user? Per my understanding, channels of the same DMAC are quite independent, they can in draining at the same time from the point of DMAC. And, we event don't use the DMA draining feature yet.
Thanks, ~Keyon
I havent seen the need for exclusive access so far. But we might need it in the future.
- /* DMA IRQ types */ #define DMA_IRQ_TYPE_BLOCK (1 << 0) #define DMA_IRQ_TYPE_LLIST (1 << 1)
@@ -119,6 +141,8 @@ struct dma_ops { /* DMA platform data */ struct dma_plat_data { uint32_t id;
- enum dmac_user type;
- enum dmac_copy_dir copy_dir; uint32_t base; uint32_t channels; uint32_t irq;
@@ -139,7 +163,7 @@ struct dma_int { uint32_t irq; };
-struct dma *dma_get(int dmac_id); +struct dma *dma_get(enum dmac_user, enum dmac_copy_dir, int flags);
/* initialize all platform DMAC's */ void dmac_init(void); diff --git a/src/platform/apollolake/dma.c b/src/platform/apollolake/dma.c index 001bb67..1ae097e 100644 --- a/src/platform/apollolake/dma.c +++ b/src/platform/apollolake/dma.c @@ -112,6 +112,8 @@ static struct dma dma[] = { { /* Low Power GP DMAC 0 */ .plat_data = { .id = DMA_GP_LP_DMAC0,
.type = DMAC_USER_GP_LP_DMA,
.copy_dir = DMAC_DIR_DUPLEX, .base = LP_GP_DMA_BASE(0), .channels = 8, .irq = IRQ_EXT_LP_GPDMA0_LVL5(0,
0), @@ -122,6 +124,8 @@ static struct dma dma[] = { { /* Low Power GP DMAC 1 */ .plat_data = { .id = DMA_GP_LP_DMAC1,
.type = DMAC_USER_GP_LP_DMA,
.copy_dir = DMAC_DIR_DUPLEX, .base = LP_GP_DMA_BASE(1), .channels = 8, .irq = IRQ_EXT_LP_GPDMA1_LVL5(0,
0), @@ -132,6 +136,8 @@ static struct dma dma[] = { { /* Host In DMAC */ .plat_data = { .id = DMA_HOST_IN_DMAC,
.type = DMAC_USER_HOST_DMA,
.copy_dir = DMAC_DIR_WRITE, .base =
GTW_HOST_IN_STREAM_BASE(0), .channels = 7, .irq = IRQ_EXT_HOST_DMA_IN_LVL3(0, 0), @@ -142,6 +148,8 @@ static struct dma dma[] = { { /* Host out DMAC */ .plat_data = { .id = DMA_HOST_OUT_DMAC,
.type = DMAC_USER_HOST_DMA,
.copy_dir = DMAC_DIR_READ, .base =
GTW_HOST_OUT_STREAM_BASE(0), .channels = 6, .irq = IRQ_EXT_HOST_DMA_OUT_LVL3(0, 0), @@ -152,6 +160,8 @@ static struct dma dma[] = { { /* Link In DMAC */ .plat_data = { .id = DMA_LINK_IN_DMAC,
.type = DMAC_USER_LINK_DMA,
.copy_dir = DMAC_DIR_WRITE, .base =
GTW_LINK_IN_STREAM_BASE(0), .channels = 8, .irq = IRQ_EXT_LINK_DMA_IN_LVL4(0, 0), @@ -162,6 +172,8 @@ static struct dma dma[] = { { /* Link out DMAC */ .plat_data = { .id = DMA_LINK_OUT_DMAC,
.type = DMAC_USER_LINK_DMA,
.copy_dir = DMAC_DIR_READ, .base =
GTW_LINK_OUT_STREAM_BASE(0), .channels = 8, .irq = IRQ_EXT_LINK_DMA_OUT_LVL4(0, 0), @@ -170,15 +182,48 @@ static struct dma dma[] = { .ops = &hda_link_dma_ops, },};
-struct dma *dma_get(int dmac_id) +/*
- get DMAC based on user type, copy dir and flags
- "flags" is used to set the type of access requested
- (ex: shared/exclusive access)
- */
+struct dma *dma_get(enum dmac_user user, enum dmac_copy_dir dir, int flags) {
- int i;
int i, ch_count;
int dma_index = -1;
int min_ch_count = INT32_MAX;
for (i = 0; i < ARRAY_SIZE(dma); i++) {
if (dma[i].plat_data.id == dmac_id)
return &dma[i];
/* check DMAC user type */
if (dma[i].plat_data.type != user)
continue;
/* check DMAC copy dir */
if (dma[i].plat_data.copy_dir != dir)
continue;
/* if exclusive access is requested */
if (flags & DMAC_FLAGS_EXCLUSIVE) {
/* ret DMA with no channel in use */
if (!dma_channel_status(&dma[i]))
return &dma[i];
} else {
/* get number of channels in use */
ch_count = dma_channel_status(&dma[i]);
/* Use this DMAC if its channel count is
lower */
if (ch_count < min_ch_count) {
dma_index = i;
min_ch_count = ch_count;
}
}
}
if (dma_index >= 0)
return &dma[dma_index];
return NULL; }
diff --git a/src/platform/baytrail/dma.c b/src/platform/baytrail/dma.c index 5a0b650..71ea241 100644 --- a/src/platform/baytrail/dma.c +++ b/src/platform/baytrail/dma.c @@ -175,15 +175,48 @@ static struct dma dma[] = { #endif };
-struct dma *dma_get(int dmac_id) +/*
- get DMAC based on user type, copy dir and flags
- For BYT/CHT, ignore the dmac_user and copy_dir arguments
- "flags" is used to set the type of access requested
- (ex: shared/exclusive access)
- */
+struct dma *dma_get(enum dmac_user user, enum dmac_copy_dir dir, int flags) {
- int i;
int i, ch_count;
int min_ch_count = INT32_MAX;
int dma_index = -1;
for (i = 0; i < ARRAY_SIZE(dma); i++) {
if (dma[i].plat_data.id == dmac_id)
return &dma[i];
/* if exclusive access is requested */
if (flags & DMAC_FLAGS_EXCLUSIVE) {
/* ret DMA with no channel in use */
if (!dma_channel_status(&dma[i]))
return &dma[i];
} else {
/*
* for shared access requests, return DMAC
* with the least number of channels in
use
*/
/* get number of channels in use for this
DMAC*/
ch_count = dma_channel_status(&dma[i]);
/* Use this DMAC if its channel count is
lower */
if (ch_count < min_ch_count) {
dma_index = i;
min_ch_count = ch_count;
}
}
}
/* return DMAC */
if (dma_index >= 0)
return &dma[dma_index];
return NULL; }
again, this function can be shared also?
Thanks, ~Keyon
diff --git a/src/platform/cannonlake/dma.c b/src/platform/cannonlake/dma.c index 9031c17..697b9a8 100644 --- a/src/platform/cannonlake/dma.c +++ b/src/platform/cannonlake/dma.c @@ -113,6 +113,8 @@ static struct dma dma[] = { { /* Low Power GP DMAC 0 */ .plat_data = { .id = DMA_GP_LP_DMAC0,
.type = DMAC_USER_GP_LP_DMA,
.copy_dir = DMAC_DIR_DUPLEX, .base = LP_GP_DMA_BASE(0), .channels = 8, .irq = IRQ_EXT_LP_GPDMA0_LVL5(0, 0),
@@ -123,6 +125,8 @@ static struct dma dma[] = { { /* Low Power GP DMAC 1 */ .plat_data = { .id = DMA_GP_LP_DMAC1,
.type = DMAC_USER_GP_LP_DMA,
.copy_dir = DMAC_DIR_DUPLEX, .base = LP_GP_DMA_BASE(1), .channels = 8, .irq = IRQ_EXT_LP_GPDMA1_LVL5(0, 0),
@@ -133,6 +137,8 @@ static struct dma dma[] = { { /* Host In DMAC */ .plat_data = { .id = DMA_HOST_IN_DMAC,
.type = DMAC_USER_HOST_DMA,
.copy_dir = DMAC_DIR_WRITE, .base =
GTW_HOST_IN_STREAM_BASE(0), .channels = 7, .irq = IRQ_EXT_HOST_DMA_IN_LVL3(0, 0), @@ -143,6 +149,8 @@ static struct dma dma[] = { { /* Host out DMAC */ .plat_data = { .id = DMA_HOST_OUT_DMAC,
.type = DMAC_USER_HOST_DMA,
.copy_dir = DMAC_DIR_READ, .base =
GTW_HOST_OUT_STREAM_BASE(0), .channels = 9, .irq = IRQ_EXT_HOST_DMA_OUT_LVL3(0, 0), @@ -153,6 +161,8 @@ static struct dma dma[] = { { /* Link In DMAC */ .plat_data = { .id = DMA_LINK_IN_DMAC,
.type = DMAC_USER_LINK_DMA,
.copy_dir = DMAC_DIR_WRITE, .base =
GTW_LINK_IN_STREAM_BASE(0), .channels = 9, .irq = IRQ_EXT_LINK_DMA_IN_LVL4(0, 0), @@ -163,6 +173,8 @@ static struct dma dma[] = { { /* Link out DMAC */ .plat_data = { .id = DMA_LINK_OUT_DMAC,
.type = DMAC_USER_LINK_DMA,
.copy_dir = DMAC_DIR_READ, .base =
GTW_LINK_OUT_STREAM_BASE(0), .channels = 7, .irq = IRQ_EXT_LINK_DMA_OUT_LVL4(0, 0), @@ -171,15 +183,48 @@ static struct dma dma[] = { .ops = &hda_link_dma_ops, },};
-struct dma *dma_get(int dmac_id) +/*
- get DMAC based on user type, copy dir and flags
- "flags" is used to set the type of access requested
- (ex: shared/exclusive access)
- */
+struct dma *dma_get(enum dmac_user user, enum dmac_copy_dir dir, int flags) {
- int i;
int i, ch_count;
int dma_index = -1;
int min_ch_count = INT32_MAX;
for (i = 0; i < ARRAY_SIZE(dma); i++) {
if (dma[i].plat_data.id == dmac_id)
return &dma[i];
/* check DMAC user type */
if (dma[i].plat_data.type != user)
continue;
/* check DMAC copy dir */
if (dma[i].plat_data.copy_dir != dir)
continue;
/* if exclusive access is requested */
if (flags & DMAC_FLAGS_EXCLUSIVE) {
/* ret DMA with no channel in use */
if (!dma_channel_status(&dma[i]))
return &dma[i];
} else {
/* get number of channels in use */
ch_count = dma_channel_status(&dma[i]);
/* Use this DMAC if its channel count is
lower */
if (ch_count < min_ch_count) {
dma_index = i;
min_ch_count = ch_count;
}
}
}
if (dma_index >= 0)
return &dma[dma_index];
return NULL; }
diff --git a/src/platform/haswell/dma.c b/src/platform/haswell/dma.c index 5d1e308..9138e78 100644 --- a/src/platform/haswell/dma.c +++ b/src/platform/haswell/dma.c @@ -124,16 +124,49 @@ static struct dma dma[] = { .ops = &dw_dma_ops, },};
-struct dma *dma_get(int dmac_id) +/*
- get DMAC based on user type, copy dir and flags
- For BYT/CHT, ignore the dmac_user and copy_dir arguments
- "flags" is used to set the type of access requested
- (ex: shared/exclusive access)
- */
+struct dma *dma_get(enum dmac_user user, enum dmac_copy_dir dir, int flags) {
- switch (dmac_id) {
- case DMA_ID_DMAC0:
return &dma[0];
- case DMA_ID_DMAC1:
return &dma[1];
- default:
return NULL;
- int i, ch_count;
- int min_ch_count = INT32_MAX;
- int dma_index = -1;
- for (i = 0; i < ARRAY_SIZE(dma); i++) {
/* if exclusive access is requested */
if (flags & DMAC_FLAGS_EXCLUSIVE) {
/* ret DMA with no channel in use */
if (!dma_channel_status(&dma[i]))
return &dma[i];
} else {
/*
* for shared access requests, return DMAC
* with the least number of channels in
use
*/
/* get number of channels in use for this
DMAC*/
ch_count = dma_channel_status(&dma[i]);
/* Use this DMAC if its channel count is
lower */
if (ch_count < min_ch_count) {
dma_index = i;
min_ch_count = ch_count;
}
}
}
/* return DMAC */
if (dma_index >= 0)
return &dma[dma_index];
return NULL; }
/* Initialize all platform DMAC's */
Sound-open-firmware mailing list Sound-open-firmware@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/sound-open-firmware
On Wed, 2018-06-06 at 11:20 +0800, Keyon Jie wrote:
On 2018年06月06日 03:18, Ranjani Sridharan wrote:
On Tue, 2018-06-05 at 19:05 +0800, Keyon Jie wrote:
On 2018年06月05日 12:23, Ranjani Sridharan wrote:
This patch introduces a new API for procuring DMAC for various user based on the type of DMAC, copy direction and other flags for share/exclusive access. It defines the necessary DMAC user types, copy direction and the flags to suuport the new API.It also adds two new members to dma_plat_data to differentiate the DMAC based on usage and copy direction.
Finally, it also contains the platform specific implementation of the new dma_get() API.
Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel .com
src/include/sof/dma.h | 26 ++++++++++++++++- src/platform/apollolake/dma.c | 53 ++++++++++++++++++++++++++++++++--- src/platform/baytrail/dma.c | 41 ++++++++++++++++++++++++- -- src/platform/cannonlake/dma.c | 53 ++++++++++++++++++++++++++++++++--- src/platform/haswell/dma.c | 49
++++++++++++++++++++++++++--
5 files changed, 201 insertions(+), 21 deletions(-)
diff --git a/src/include/sof/dma.h b/src/include/sof/dma.h index 1de9efc..25581e6 100644 --- a/src/include/sof/dma.h +++ b/src/include/sof/dma.h @@ -48,6 +48,28 @@ enum dma_copy_dir { DMA_DIR_DEV_TO_DEV, };
+/*
- DMAC copy directions
- These are used to specify the copy direction while
requesting a DMAC
- */
+enum dmac_copy_dir {
- DMAC_DIR_READ = 0,
- DMAC_DIR_WRITE,
- DMAC_DIR_DUPLEX,
+};
I can't understand this, what is read and what is write? For DMA, it always read from some buffer and write them to another buffer.
[edit] after reading the patch, I got your point. maybe naming it with
+enum dmac_dir_cap {
- DMAC_CAP_READ = 0,
- DMAC_CAP_WRITE,
- DMAC_CAP_DUPLEX,
+};
or we can use bit mask for that, which can be reused with user type below also, e.g.
bit 0: cap_read bit 1: cap_write bit 2: host/link bit 3: lp/hp. bit 4: share/exclusive
I can rename the enum but I'd like to stick with the arguments for the dma_get API. It is really only 3 arguments and it makes deciphering code much easier than applying bitmasks.
Unless, you have a compelling reason for me not to use separate arguments?
I think using the bitmasks is more object oriented, e.g. for direction, what directions does your dmac supported? host_mem_to_mem(1)? mem_to_mem(2)? mem_to_dev(3)? dev_to_dev(4)? mem_to_link(5)? or the opposite? The combination of these can be up to 10.
Is it only 8 or 10? mem_to hostmem (6), dev_to_mem(7) and link_to_mem(8). What am I missing?
for byt/bdw, we can support (1)(2)(3)(4)(6)(7)(8)(9); for apl/cnl, host_dmac_output can support (1) only, host_dmac_input can support (6) only, gpdma can support (2)(3)(4)(7)(8)(9), link_dmac_output can support (5), link_dmac_input can support (10) only.
if you tell these clear enough, you will be able to use unify logic in a
With the above definitions, I can unify the type/dir arguments but I'd still need the access flags.
Thanks for this. I can incorporate this change in v2.
common dma_get(): /* check DMAC copy dir */ if (dma[i].plat_data.caps & require_cap == require_cap) retrun dma[i]; // very simple, isn't it?
for the user: byt/bdw: playback, host: dma_get(host_mem_to_mem); dai: dma_get(mem_to_dev); capture, host: dma_get(mem_to_hostmem); dai: dma_get(dev_to_mem_); page_table_parsing, dma_get(host_mem_to_mem); dma_trace, dma_get(mem_to_host_mem). apl/cnl: playback, host: dma_get(host_mem_to_mem); dai: dma_get(mem_to_dev); capture, host: dma_get(mem_to_hostmem); dai: dma_get(dev_to_mem_); page_table_parsing, dma_get(host_mem_to_mem); dma_trace, dma_get(mem_to_host_mem).
can you see what? with this, you can make the code very clean/unified in host/dai/dma_trace...
...
+/* DMAC user types */ +enum dmac_user {
- DMAC_USER_HOST_DMA = 0,
- DMAC_USER_LINK_DMA,
do we need split into output and input for these?
- DMAC_USER_GP_LP_DMA,
- DMAC_USER_GP_HP_DMA,
+};
+/* DMAC flags */ +#define DMAC_FLAGS_SHARED 0 +#define DMAC_FLAGS_EXCLUSIVE (1 << 0)
Can you explain what is shared and how channels are shared? Are you meaning channel reservation for specific user with exclusive? I can't image the use case for this.
Shared is the most common usage, where we share DMAC between users.
Exclusive as Liam explained will be fore critical usages that require that only one user will use the DMAC at any time. ie there will only be one channel draining at any time.
Hi Liam, can you explain more about this? Where is the limitation about only one channel draining at the same time, from DMAC or the user? Per my understanding, channels of the same DMAC are quite independent, they can in draining at the same time from the point of DMAC. And, we event don't use the DMA draining feature yet.
Thanks, ~Keyon
I havent seen the need for exclusive access so far. But we might need it in the future.
- /* DMA IRQ types */ #define DMA_IRQ_TYPE_BLOCK (1 << 0) #define DMA_IRQ_TYPE_LLIST (1 << 1)
@@ -119,6 +141,8 @@ struct dma_ops { /* DMA platform data */ struct dma_plat_data { uint32_t id;
- enum dmac_user type;
- enum dmac_copy_dir copy_dir; uint32_t base; uint32_t channels; uint32_t irq;
@@ -139,7 +163,7 @@ struct dma_int { uint32_t irq; };
-struct dma *dma_get(int dmac_id); +struct dma *dma_get(enum dmac_user, enum dmac_copy_dir, int flags);
/* initialize all platform DMAC's */ void dmac_init(void); diff --git a/src/platform/apollolake/dma.c b/src/platform/apollolake/dma.c index 001bb67..1ae097e 100644 --- a/src/platform/apollolake/dma.c +++ b/src/platform/apollolake/dma.c @@ -112,6 +112,8 @@ static struct dma dma[] = { { /* Low Power GP DMAC 0 */ .plat_data = { .id = DMA_GP_LP_DMAC0,
.type = DMAC_USER_GP_LP_DMA,
.copy_dir = DMAC_DIR_DUPLEX, .base = LP_GP_DMA_BASE(0), .channels = 8, .irq =
IRQ_EXT_LP_GPDMA0_LVL5(0, 0), @@ -122,6 +124,8 @@ static struct dma dma[] = { { /* Low Power GP DMAC 1 */ .plat_data = { .id = DMA_GP_LP_DMAC1,
.type = DMAC_USER_GP_LP_DMA,
.copy_dir = DMAC_DIR_DUPLEX, .base = LP_GP_DMA_BASE(1), .channels = 8, .irq =
IRQ_EXT_LP_GPDMA1_LVL5(0, 0), @@ -132,6 +136,8 @@ static struct dma dma[] = { { /* Host In DMAC */ .plat_data = { .id = DMA_HOST_IN_DMAC,
.type = DMAC_USER_HOST_DMA,
.copy_dir = DMAC_DIR_WRITE, .base =
GTW_HOST_IN_STREAM_BASE(0), .channels = 7, .irq = IRQ_EXT_HOST_DMA_IN_LVL3(0, 0), @@ -142,6 +148,8 @@ static struct dma dma[] = { { /* Host out DMAC */ .plat_data = { .id = DMA_HOST_OUT_DMAC,
.type = DMAC_USER_HOST_DMA,
.copy_dir = DMAC_DIR_READ, .base =
GTW_HOST_OUT_STREAM_BASE(0), .channels = 6, .irq = IRQ_EXT_HOST_DMA_OUT_LVL3(0, 0), @@ -152,6 +160,8 @@ static struct dma dma[] = { { /* Link In DMAC */ .plat_data = { .id = DMA_LINK_IN_DMAC,
.type = DMAC_USER_LINK_DMA,
.copy_dir = DMAC_DIR_WRITE, .base =
GTW_LINK_IN_STREAM_BASE(0), .channels = 8, .irq = IRQ_EXT_LINK_DMA_IN_LVL4(0, 0), @@ -162,6 +172,8 @@ static struct dma dma[] = { { /* Link out DMAC */ .plat_data = { .id = DMA_LINK_OUT_DMAC,
.type = DMAC_USER_LINK_DMA,
.copy_dir = DMAC_DIR_READ, .base =
GTW_LINK_OUT_STREAM_BASE(0), .channels = 8, .irq = IRQ_EXT_LINK_DMA_OUT_LVL4(0, 0), @@ -170,15 +182,48 @@ static struct dma dma[] = { .ops = &hda_link_dma_ops, },};
-struct dma *dma_get(int dmac_id) +/*
- get DMAC based on user type, copy dir and flags
- "flags" is used to set the type of access requested
- (ex: shared/exclusive access)
- */
+struct dma *dma_get(enum dmac_user user, enum dmac_copy_dir dir, int flags) {
- int i;
int i, ch_count;
int dma_index = -1;
int min_ch_count = INT32_MAX;
for (i = 0; i < ARRAY_SIZE(dma); i++) {
if (dma[i].plat_data.id == dmac_id)
return &dma[i];
/* check DMAC user type */
if (dma[i].plat_data.type != user)
continue;
/* check DMAC copy dir */
if (dma[i].plat_data.copy_dir != dir)
continue;
/* if exclusive access is requested */
if (flags & DMAC_FLAGS_EXCLUSIVE) {
/* ret DMA with no channel in use */
if (!dma_channel_status(&dma[i]))
return &dma[i];
} else {
/* get number of channels in use */
ch_count =
dma_channel_status(&dma[i]);
/* Use this DMAC if its channel count
is lower */
if (ch_count < min_ch_count) {
dma_index = i;
min_ch_count = ch_count;
}
}
}
if (dma_index >= 0)
return &dma[dma_index];
return NULL; }
diff --git a/src/platform/baytrail/dma.c b/src/platform/baytrail/dma.c index 5a0b650..71ea241 100644 --- a/src/platform/baytrail/dma.c +++ b/src/platform/baytrail/dma.c @@ -175,15 +175,48 @@ static struct dma dma[] = { #endif };
-struct dma *dma_get(int dmac_id) +/*
- get DMAC based on user type, copy dir and flags
- For BYT/CHT, ignore the dmac_user and copy_dir arguments
- "flags" is used to set the type of access requested
- (ex: shared/exclusive access)
- */
+struct dma *dma_get(enum dmac_user user, enum dmac_copy_dir dir, int flags) {
- int i;
int i, ch_count;
int min_ch_count = INT32_MAX;
int dma_index = -1;
for (i = 0; i < ARRAY_SIZE(dma); i++) {
if (dma[i].plat_data.id == dmac_id)
return &dma[i];
/* if exclusive access is requested */
if (flags & DMAC_FLAGS_EXCLUSIVE) {
/* ret DMA with no channel in use */
if (!dma_channel_status(&dma[i]))
return &dma[i];
} else {
/*
* for shared access requests, return
DMAC
* with the least number of channels
in use
*/
/* get number of channels in use for
this DMAC*/
ch_count =
dma_channel_status(&dma[i]);
/* Use this DMAC if its channel count
is lower */
if (ch_count < min_ch_count) {
dma_index = i;
min_ch_count = ch_count;
}
}
}
/* return DMAC */
if (dma_index >= 0)
return &dma[dma_index];
return NULL; }
again, this function can be shared also?
Thanks, ~Keyon
diff --git a/src/platform/cannonlake/dma.c b/src/platform/cannonlake/dma.c index 9031c17..697b9a8 100644 --- a/src/platform/cannonlake/dma.c +++ b/src/platform/cannonlake/dma.c @@ -113,6 +113,8 @@ static struct dma dma[] = { { /* Low Power GP DMAC 0 */ .plat_data = { .id = DMA_GP_LP_DMAC0,
.type = DMAC_USER_GP_LP_DMA,
.copy_dir = DMAC_DIR_DUPLEX, .base = LP_GP_DMA_BASE(0), .channels = 8, .irq = IRQ_EXT_LP_GPDMA0_LVL5(0, 0),
@@ -123,6 +125,8 @@ static struct dma dma[] = { { /* Low Power GP DMAC 1 */ .plat_data = { .id = DMA_GP_LP_DMAC1,
.type = DMAC_USER_GP_LP_DMA,
.copy_dir = DMAC_DIR_DUPLEX, .base = LP_GP_DMA_BASE(1), .channels = 8, .irq = IRQ_EXT_LP_GPDMA1_LVL5(0, 0),
@@ -133,6 +137,8 @@ static struct dma dma[] = { { /* Host In DMAC */ .plat_data = { .id = DMA_HOST_IN_DMAC,
.type = DMAC_USER_HOST_DMA,
.copy_dir = DMAC_DIR_WRITE, .base =
GTW_HOST_IN_STREAM_BASE(0), .channels = 7, .irq = IRQ_EXT_HOST_DMA_IN_LVL3(0, 0), @@ -143,6 +149,8 @@ static struct dma dma[] = { { /* Host out DMAC */ .plat_data = { .id = DMA_HOST_OUT_DMAC,
.type = DMAC_USER_HOST_DMA,
.copy_dir = DMAC_DIR_READ, .base =
GTW_HOST_OUT_STREAM_BASE(0), .channels = 9, .irq = IRQ_EXT_HOST_DMA_OUT_LVL3(0, 0), @@ -153,6 +161,8 @@ static struct dma dma[] = { { /* Link In DMAC */ .plat_data = { .id = DMA_LINK_IN_DMAC,
.type = DMAC_USER_LINK_DMA,
.copy_dir = DMAC_DIR_WRITE, .base =
GTW_LINK_IN_STREAM_BASE(0), .channels = 9, .irq = IRQ_EXT_LINK_DMA_IN_LVL4(0, 0), @@ -163,6 +173,8 @@ static struct dma dma[] = { { /* Link out DMAC */ .plat_data = { .id = DMA_LINK_OUT_DMAC,
.type = DMAC_USER_LINK_DMA,
.copy_dir = DMAC_DIR_READ, .base =
GTW_LINK_OUT_STREAM_BASE(0), .channels = 7, .irq = IRQ_EXT_LINK_DMA_OUT_LVL4(0, 0), @@ -171,15 +183,48 @@ static struct dma dma[] = { .ops = &hda_link_dma_ops, },};
-struct dma *dma_get(int dmac_id) +/*
- get DMAC based on user type, copy dir and flags
- "flags" is used to set the type of access requested
- (ex: shared/exclusive access)
- */
+struct dma *dma_get(enum dmac_user user, enum dmac_copy_dir dir, int flags) {
- int i;
int i, ch_count;
int dma_index = -1;
int min_ch_count = INT32_MAX;
for (i = 0; i < ARRAY_SIZE(dma); i++) {
if (dma[i].plat_data.id == dmac_id)
return &dma[i];
/* check DMAC user type */
if (dma[i].plat_data.type != user)
continue;
/* check DMAC copy dir */
if (dma[i].plat_data.copy_dir != dir)
continue;
/* if exclusive access is requested */
if (flags & DMAC_FLAGS_EXCLUSIVE) {
/* ret DMA with no channel in use */
if (!dma_channel_status(&dma[i]))
return &dma[i];
} else {
/* get number of channels in use */
ch_count =
dma_channel_status(&dma[i]);
/* Use this DMAC if its channel count
is lower */
if (ch_count < min_ch_count) {
dma_index = i;
min_ch_count = ch_count;
}
}
}
if (dma_index >= 0)
return &dma[dma_index];
return NULL; }
diff --git a/src/platform/haswell/dma.c b/src/platform/haswell/dma.c index 5d1e308..9138e78 100644 --- a/src/platform/haswell/dma.c +++ b/src/platform/haswell/dma.c @@ -124,16 +124,49 @@ static struct dma dma[] = { .ops = &dw_dma_ops, },};
-struct dma *dma_get(int dmac_id) +/*
- get DMAC based on user type, copy dir and flags
- For BYT/CHT, ignore the dmac_user and copy_dir arguments
- "flags" is used to set the type of access requested
- (ex: shared/exclusive access)
- */
+struct dma *dma_get(enum dmac_user user, enum dmac_copy_dir dir, int flags) {
- switch (dmac_id) {
- case DMA_ID_DMAC0:
return &dma[0];
- case DMA_ID_DMAC1:
return &dma[1];
- default:
return NULL;
- int i, ch_count;
- int min_ch_count = INT32_MAX;
- int dma_index = -1;
- for (i = 0; i < ARRAY_SIZE(dma); i++) {
/* if exclusive access is requested */
if (flags & DMAC_FLAGS_EXCLUSIVE) {
/* ret DMA with no channel in use */
if (!dma_channel_status(&dma[i]))
return &dma[i];
} else {
/*
* for shared access requests, return
DMAC
* with the least number of channels
in use
*/
/* get number of channels in use for
this DMAC*/
ch_count =
dma_channel_status(&dma[i]);
/* Use this DMAC if its channel count
is lower */
if (ch_count < min_ch_count) {
dma_index = i;
min_ch_count = ch_count;
}
}
}
/* return DMAC */
if (dma_index >= 0)
return &dma[dma_index];
return NULL; }
/* Initialize all platform DMAC's */
Sound-open-firmware mailing list Sound-open-firmware@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/sound-open-firmw are
Sound-open-firmware mailing list Sound-open-firmware@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/sound-open-firmware
On 2018年06月06日 14:00, Ranjani Sridharan wrote:
On Wed, 2018-06-06 at 11:20 +0800, Keyon Jie wrote:
On 2018年06月06日 03:18, Ranjani Sridharan wrote:
On Tue, 2018-06-05 at 19:05 +0800, Keyon Jie wrote:
On 2018年06月05日 12:23, Ranjani Sridharan wrote:
This patch introduces a new API for procuring DMAC for various user based on the type of DMAC, copy direction and other flags for share/exclusive access. It defines the necessary DMAC user types, copy direction and the flags to suuport the new API.It also adds two new members to dma_plat_data to differentiate the DMAC based on usage and copy direction.
Finally, it also contains the platform specific implementation of the new dma_get() API.
Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel .com
src/include/sof/dma.h | 26 ++++++++++++++++- src/platform/apollolake/dma.c | 53
++++++++++++++++++++++++++++++++--- src/platform/baytrail/dma.c | 41 ++++++++++++++++++++++++- -- src/platform/cannonlake/dma.c | 53 ++++++++++++++++++++++++++++++++--- src/platform/haswell/dma.c | 49
++++++++++++++++++++++++++--
5 files changed, 201 insertions(+), 21 deletions(-)
diff --git a/src/include/sof/dma.h b/src/include/sof/dma.h index 1de9efc..25581e6 100644 --- a/src/include/sof/dma.h +++ b/src/include/sof/dma.h @@ -48,6 +48,28 @@ enum dma_copy_dir { DMA_DIR_DEV_TO_DEV, };
+/*
- DMAC copy directions
- These are used to specify the copy direction while
requesting a DMAC
- */
+enum dmac_copy_dir {
- DMAC_DIR_READ = 0,
- DMAC_DIR_WRITE,
- DMAC_DIR_DUPLEX,
+};
I can't understand this, what is read and what is write? For DMA, it always read from some buffer and write them to another buffer.
[edit] after reading the patch, I got your point. maybe naming it with
+enum dmac_dir_cap {
- DMAC_CAP_READ = 0,
- DMAC_CAP_WRITE,
- DMAC_CAP_DUPLEX,
+};
or we can use bit mask for that, which can be reused with user type below also, e.g.
bit 0: cap_read bit 1: cap_write bit 2: host/link bit 3: lp/hp. bit 4: share/exclusive
I can rename the enum but I'd like to stick with the arguments for the dma_get API. It is really only 3 arguments and it makes deciphering code much easier than applying bitmasks.
Unless, you have a compelling reason for me not to use separate arguments?
I think using the bitmasks is more object oriented, e.g. for direction, what directions does your dmac supported? host_mem_to_mem(1)? mem_to_mem(2)? mem_to_dev(3)? dev_to_dev(4)? mem_to_link(5)? or the opposite? The combination of these can be up to 10.
Is it only 8 or 10? mem_to hostmem (6), dev_to_mem(7) and link_to_mem(8). What am I missing?
right, it should be 8 as mem2mem and dev2dev are duplicated.
for byt/bdw, we can support (1)(2)(3)(4)(6)(7)(8)(9);
please also be noticed here that as Rander experimented, on bdw, gpdmac0 and gpdmac1 may have different caps, and all those gpdma can't support (5) and (8) we noted above.
Thanks, ~Keyon
for apl/cnl, host_dmac_output can support (1) only, host_dmac_input can support (6) only, gpdma can support (2)(3)(4)(7)(8)(9), link_dmac_output can support (5), link_dmac_input can support (10) only.
if you tell these clear enough, you will be able to use unify logic in a
With the above definitions, I can unify the type/dir arguments but I'd still need the access flags.
Thanks for this. I can incorporate this change in v2.
common dma_get(): /* check DMAC copy dir */ if (dma[i].plat_data.caps & require_cap == require_cap) retrun dma[i]; // very simple, isn't it?
for the user: byt/bdw: playback, host: dma_get(host_mem_to_mem); dai: dma_get(mem_to_dev); capture, host: dma_get(mem_to_hostmem); dai: dma_get(dev_to_mem_); page_table_parsing, dma_get(host_mem_to_mem); dma_trace, dma_get(mem_to_host_mem). apl/cnl: playback, host: dma_get(host_mem_to_mem); dai: dma_get(mem_to_dev); capture, host: dma_get(mem_to_hostmem); dai: dma_get(dev_to_mem_); page_table_parsing, dma_get(host_mem_to_mem); dma_trace, dma_get(mem_to_host_mem).
can you see what? with this, you can make the code very clean/unified in host/dai/dma_trace...
...
+/* DMAC user types */ +enum dmac_user {
- DMAC_USER_HOST_DMA = 0,
- DMAC_USER_LINK_DMA,
do we need split into output and input for these?
- DMAC_USER_GP_LP_DMA,
- DMAC_USER_GP_HP_DMA,
+};
+/* DMAC flags */ +#define DMAC_FLAGS_SHARED 0 +#define DMAC_FLAGS_EXCLUSIVE (1 << 0)
Can you explain what is shared and how channels are shared? Are you meaning channel reservation for specific user with exclusive? I can't image the use case for this.
Shared is the most common usage, where we share DMAC between users.
Exclusive as Liam explained will be fore critical usages that require that only one user will use the DMAC at any time. ie there will only be one channel draining at any time.
Hi Liam, can you explain more about this? Where is the limitation about only one channel draining at the same time, from DMAC or the user? Per my understanding, channels of the same DMAC are quite independent, they can in draining at the same time from the point of DMAC. And, we event don't use the DMA draining feature yet.
Thanks, ~Keyon
I havent seen the need for exclusive access so far. But we might need it in the future.
- /* DMA IRQ types */ #define DMA_IRQ_TYPE_BLOCK (1 << 0) #define DMA_IRQ_TYPE_LLIST (1 << 1)
@@ -119,6 +141,8 @@ struct dma_ops { /* DMA platform data */ struct dma_plat_data { uint32_t id;
- enum dmac_user type;
- enum dmac_copy_dir copy_dir; uint32_t base; uint32_t channels; uint32_t irq;
@@ -139,7 +163,7 @@ struct dma_int { uint32_t irq; };
-struct dma *dma_get(int dmac_id); +struct dma *dma_get(enum dmac_user, enum dmac_copy_dir, int flags);
/* initialize all platform DMAC's */ void dmac_init(void);
diff --git a/src/platform/apollolake/dma.c b/src/platform/apollolake/dma.c index 001bb67..1ae097e 100644 --- a/src/platform/apollolake/dma.c +++ b/src/platform/apollolake/dma.c @@ -112,6 +112,8 @@ static struct dma dma[] = { { /* Low Power GP DMAC 0 */ .plat_data = { .id = DMA_GP_LP_DMAC0,
.type = DMAC_USER_GP_LP_DMA,
.copy_dir = DMAC_DIR_DUPLEX, .base = LP_GP_DMA_BASE(0), .channels = 8, .irq =
IRQ_EXT_LP_GPDMA0_LVL5(0, 0), @@ -122,6 +124,8 @@ static struct dma dma[] = { { /* Low Power GP DMAC 1 */ .plat_data = { .id = DMA_GP_LP_DMAC1,
.type = DMAC_USER_GP_LP_DMA,
.copy_dir = DMAC_DIR_DUPLEX, .base = LP_GP_DMA_BASE(1), .channels = 8, .irq =
IRQ_EXT_LP_GPDMA1_LVL5(0, 0), @@ -132,6 +136,8 @@ static struct dma dma[] = { { /* Host In DMAC */ .plat_data = { .id = DMA_HOST_IN_DMAC,
.type = DMAC_USER_HOST_DMA,
.copy_dir = DMAC_DIR_WRITE, .base =
GTW_HOST_IN_STREAM_BASE(0), .channels = 7, .irq = IRQ_EXT_HOST_DMA_IN_LVL3(0, 0), @@ -142,6 +148,8 @@ static struct dma dma[] = { { /* Host out DMAC */ .plat_data = { .id = DMA_HOST_OUT_DMAC,
.type = DMAC_USER_HOST_DMA,
.copy_dir = DMAC_DIR_READ, .base =
GTW_HOST_OUT_STREAM_BASE(0), .channels = 6, .irq = IRQ_EXT_HOST_DMA_OUT_LVL3(0, 0), @@ -152,6 +160,8 @@ static struct dma dma[] = { { /* Link In DMAC */ .plat_data = { .id = DMA_LINK_IN_DMAC,
.type = DMAC_USER_LINK_DMA,
.copy_dir = DMAC_DIR_WRITE, .base =
GTW_LINK_IN_STREAM_BASE(0), .channels = 8, .irq = IRQ_EXT_LINK_DMA_IN_LVL4(0, 0), @@ -162,6 +172,8 @@ static struct dma dma[] = { { /* Link out DMAC */ .plat_data = { .id = DMA_LINK_OUT_DMAC,
.type = DMAC_USER_LINK_DMA,
.copy_dir = DMAC_DIR_READ, .base =
GTW_LINK_OUT_STREAM_BASE(0), .channels = 8, .irq = IRQ_EXT_LINK_DMA_OUT_LVL4(0, 0), @@ -170,15 +182,48 @@ static struct dma dma[] = { .ops = &hda_link_dma_ops, },};
-struct dma *dma_get(int dmac_id) +/*
- get DMAC based on user type, copy dir and flags
- "flags" is used to set the type of access requested
- (ex: shared/exclusive access)
- */
+struct dma *dma_get(enum dmac_user user, enum dmac_copy_dir dir, int flags) {
- int i;
int i, ch_count;
int dma_index = -1;
int min_ch_count = INT32_MAX;
for (i = 0; i < ARRAY_SIZE(dma); i++) {
if (dma[i].plat_data.id == dmac_id)
return &dma[i];
/* check DMAC user type */
if (dma[i].plat_data.type != user)
continue;
/* check DMAC copy dir */
if (dma[i].plat_data.copy_dir != dir)
continue;
/* if exclusive access is requested */
if (flags & DMAC_FLAGS_EXCLUSIVE) {
/* ret DMA with no channel in use */
if (!dma_channel_status(&dma[i]))
return &dma[i];
} else {
/* get number of channels in use */
ch_count =
dma_channel_status(&dma[i]);
/* Use this DMAC if its channel count
is lower */
if (ch_count < min_ch_count) {
dma_index = i;
min_ch_count = ch_count;
}
} }
if (dma_index >= 0)
return &dma[dma_index];
return NULL;
}
diff --git a/src/platform/baytrail/dma.c b/src/platform/baytrail/dma.c index 5a0b650..71ea241 100644 --- a/src/platform/baytrail/dma.c +++ b/src/platform/baytrail/dma.c @@ -175,15 +175,48 @@ static struct dma dma[] = { #endif };
-struct dma *dma_get(int dmac_id) +/*
- get DMAC based on user type, copy dir and flags
- For BYT/CHT, ignore the dmac_user and copy_dir arguments
- "flags" is used to set the type of access requested
- (ex: shared/exclusive access)
- */
+struct dma *dma_get(enum dmac_user user, enum dmac_copy_dir dir, int flags) {
- int i;
int i, ch_count;
int min_ch_count = INT32_MAX;
int dma_index = -1;
for (i = 0; i < ARRAY_SIZE(dma); i++) {
if (dma[i].plat_data.id == dmac_id)
return &dma[i];
/* if exclusive access is requested */
if (flags & DMAC_FLAGS_EXCLUSIVE) {
/* ret DMA with no channel in use */
if (!dma_channel_status(&dma[i]))
return &dma[i];
} else {
/*
* for shared access requests, return
DMAC
* with the least number of channels
in use
*/
/* get number of channels in use for
this DMAC*/
ch_count =
dma_channel_status(&dma[i]);
/* Use this DMAC if its channel count
is lower */
if (ch_count < min_ch_count) {
dma_index = i;
min_ch_count = ch_count;
}
} }
/* return DMAC */
if (dma_index >= 0)
return &dma[dma_index];
return NULL;
}
again, this function can be shared also?
Thanks, ~Keyon
diff --git a/src/platform/cannonlake/dma.c b/src/platform/cannonlake/dma.c index 9031c17..697b9a8 100644 --- a/src/platform/cannonlake/dma.c +++ b/src/platform/cannonlake/dma.c @@ -113,6 +113,8 @@ static struct dma dma[] = { { /* Low Power GP DMAC 0 */ .plat_data = { .id = DMA_GP_LP_DMAC0,
.type = DMAC_USER_GP_LP_DMA,
.copy_dir = DMAC_DIR_DUPLEX, .base = LP_GP_DMA_BASE(0), .channels = 8, .irq = IRQ_EXT_LP_GPDMA0_LVL5(0, 0),
@@ -123,6 +125,8 @@ static struct dma dma[] = { { /* Low Power GP DMAC 1 */ .plat_data = { .id = DMA_GP_LP_DMAC1,
.type = DMAC_USER_GP_LP_DMA,
.copy_dir = DMAC_DIR_DUPLEX, .base = LP_GP_DMA_BASE(1), .channels = 8, .irq = IRQ_EXT_LP_GPDMA1_LVL5(0, 0),
@@ -133,6 +137,8 @@ static struct dma dma[] = { { /* Host In DMAC */ .plat_data = { .id = DMA_HOST_IN_DMAC,
.type = DMAC_USER_HOST_DMA,
.copy_dir = DMAC_DIR_WRITE, .base =
GTW_HOST_IN_STREAM_BASE(0), .channels = 7, .irq = IRQ_EXT_HOST_DMA_IN_LVL3(0, 0), @@ -143,6 +149,8 @@ static struct dma dma[] = { { /* Host out DMAC */ .plat_data = { .id = DMA_HOST_OUT_DMAC,
.type = DMAC_USER_HOST_DMA,
.copy_dir = DMAC_DIR_READ, .base =
GTW_HOST_OUT_STREAM_BASE(0), .channels = 9, .irq = IRQ_EXT_HOST_DMA_OUT_LVL3(0, 0), @@ -153,6 +161,8 @@ static struct dma dma[] = { { /* Link In DMAC */ .plat_data = { .id = DMA_LINK_IN_DMAC,
.type = DMAC_USER_LINK_DMA,
.copy_dir = DMAC_DIR_WRITE, .base =
GTW_LINK_IN_STREAM_BASE(0), .channels = 9, .irq = IRQ_EXT_LINK_DMA_IN_LVL4(0, 0), @@ -163,6 +173,8 @@ static struct dma dma[] = { { /* Link out DMAC */ .plat_data = { .id = DMA_LINK_OUT_DMAC,
.type = DMAC_USER_LINK_DMA,
.copy_dir = DMAC_DIR_READ, .base =
GTW_LINK_OUT_STREAM_BASE(0), .channels = 7, .irq = IRQ_EXT_LINK_DMA_OUT_LVL4(0, 0), @@ -171,15 +183,48 @@ static struct dma dma[] = { .ops = &hda_link_dma_ops, },};
-struct dma *dma_get(int dmac_id) +/*
- get DMAC based on user type, copy dir and flags
- "flags" is used to set the type of access requested
- (ex: shared/exclusive access)
- */
+struct dma *dma_get(enum dmac_user user, enum dmac_copy_dir dir, int flags) {
- int i;
int i, ch_count;
int dma_index = -1;
int min_ch_count = INT32_MAX;
for (i = 0; i < ARRAY_SIZE(dma); i++) {
if (dma[i].plat_data.id == dmac_id)
return &dma[i];
/* check DMAC user type */
if (dma[i].plat_data.type != user)
continue;
/* check DMAC copy dir */
if (dma[i].plat_data.copy_dir != dir)
continue;
/* if exclusive access is requested */
if (flags & DMAC_FLAGS_EXCLUSIVE) {
/* ret DMA with no channel in use */
if (!dma_channel_status(&dma[i]))
return &dma[i];
} else {
/* get number of channels in use */
ch_count =
dma_channel_status(&dma[i]);
/* Use this DMAC if its channel count
is lower */
if (ch_count < min_ch_count) {
dma_index = i;
min_ch_count = ch_count;
}
} }
if (dma_index >= 0)
return &dma[dma_index];
return NULL;
}
diff --git a/src/platform/haswell/dma.c b/src/platform/haswell/dma.c index 5d1e308..9138e78 100644 --- a/src/platform/haswell/dma.c +++ b/src/platform/haswell/dma.c @@ -124,16 +124,49 @@ static struct dma dma[] = { .ops = &dw_dma_ops, },};
-struct dma *dma_get(int dmac_id) +/*
- get DMAC based on user type, copy dir and flags
- For BYT/CHT, ignore the dmac_user and copy_dir arguments
- "flags" is used to set the type of access requested
- (ex: shared/exclusive access)
- */
+struct dma *dma_get(enum dmac_user user, enum dmac_copy_dir dir, int flags) {
- switch (dmac_id) {
- case DMA_ID_DMAC0:
return &dma[0];
- case DMA_ID_DMAC1:
return &dma[1];
- default:
return NULL;
- int i, ch_count;
- int min_ch_count = INT32_MAX;
- int dma_index = -1;
- for (i = 0; i < ARRAY_SIZE(dma); i++) {
/* if exclusive access is requested */
if (flags & DMAC_FLAGS_EXCLUSIVE) {
/* ret DMA with no channel in use */
if (!dma_channel_status(&dma[i]))
return &dma[i];
} else {
/*
* for shared access requests, return
DMAC
* with the least number of channels
in use
*/
/* get number of channels in use for
this DMAC*/
ch_count =
dma_channel_status(&dma[i]);
/* Use this DMAC if its channel count
is lower */
if (ch_count < min_ch_count) {
dma_index = i;
min_ch_count = ch_count;
}
} }
/* return DMAC */
if (dma_index >= 0)
return &dma[dma_index];
return NULL; }
/* Initialize all platform DMAC's */
Sound-open-firmware mailing list Sound-open-firmware@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/sound-open-firmw are
Sound-open-firmware mailing list Sound-open-firmware@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/sound-open-firmware
On Wed, 2018-06-06 at 11:20 +0800, Keyon Jie wrote:
On 2018年06月06日 03:18, Ranjani Sridharan wrote:
On Tue, 2018-06-05 at 19:05 +0800, Keyon Jie wrote:
On 2018年06月05日 12:23, Ranjani Sridharan wrote:
This patch introduces a new API for procuring DMAC for various user based on the type of DMAC, copy direction and other flags for share/exclusive access. It defines the necessary DMAC user types, copy direction and the flags to suuport the new API.It also adds two new members to dma_plat_data to differentiate the DMAC based on usage and copy direction.
Finally, it also contains the platform specific implementation of the new dma_get() API.
Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel .com
src/include/sof/dma.h | 26 ++++++++++++++++- src/platform/apollolake/dma.c | 53 ++++++++++++++++++++++++++++++++--- src/platform/baytrail/dma.c | 41 ++++++++++++++++++++++++- -- src/platform/cannonlake/dma.c | 53 ++++++++++++++++++++++++++++++++--- src/platform/haswell/dma.c | 49
++++++++++++++++++++++++++--
5 files changed, 201 insertions(+), 21 deletions(-)
diff --git a/src/include/sof/dma.h b/src/include/sof/dma.h index 1de9efc..25581e6 100644 --- a/src/include/sof/dma.h +++ b/src/include/sof/dma.h @@ -48,6 +48,28 @@ enum dma_copy_dir { DMA_DIR_DEV_TO_DEV, };
+/*
- DMAC copy directions
- These are used to specify the copy direction while
requesting a DMAC
- */
+enum dmac_copy_dir {
- DMAC_DIR_READ = 0,
- DMAC_DIR_WRITE,
- DMAC_DIR_DUPLEX,
+};
I can't understand this, what is read and what is write? For DMA, it always read from some buffer and write them to another buffer.
[edit] after reading the patch, I got your point. maybe naming it with
+enum dmac_dir_cap {
- DMAC_CAP_READ = 0,
- DMAC_CAP_WRITE,
- DMAC_CAP_DUPLEX,
+};
or we can use bit mask for that, which can be reused with user type below also, e.g.
bit 0: cap_read bit 1: cap_write bit 2: host/link bit 3: lp/hp. bit 4: share/exclusive
I can rename the enum but I'd like to stick with the arguments for the dma_get API. It is really only 3 arguments and it makes deciphering code much easier than applying bitmasks.
Unless, you have a compelling reason for me not to use separate arguments?
I think using the bitmasks is more object oriented, e.g. for direction, what directions does your dmac supported? host_mem_to_mem(1)? mem_to_mem(2)? mem_to_dev(3)? dev_to_dev(4)? mem_to_link(5)? or the opposite? The combination of these can be up to 10.
for byt/bdw, we can support (1)(2)(3)(4)(6)(7)(8)(9); for apl/cnl, host_dmac_output can support (1) only, host_dmac_input can support (6) only, gpdma can support (2)(3)(4)(7)(8)(9), link_dmac_output can support (5), link_dmac_input can support (10) only.
if you tell these clear enough, you will be able to use unify logic in a common dma_get(): /* check DMAC copy dir */ if (dma[i].plat_data.caps & require_cap == require_cap) retrun dma[i]; // very simple, isn't it?
for the user: byt/bdw: playback, host: dma_get(host_mem_to_mem); dai: dma_get(mem_to_dev); capture, host: dma_get(mem_to_hostmem); dai: dma_get(dev_to_mem_); page_table_parsing, dma_get(host_mem_to_mem); dma_trace, dma_get(mem_to_host_mem). apl/cnl: playback, host: dma_get(host_mem_to_mem); dai: dma_get(mem_to_dev); capture, host: dma_get(mem_to_hostmem); dai: dma_get(dev_to_mem_); page_table_parsing, dma_get(host_mem_to_mem); dma_trace, dma_get(mem_to_host_mem).Keyon/Rander,
Keyon/Rander,
I did some experiments with the new API suggested and ran into issues with the APL platform. And the problem was with the ipc DMAC. What type would I use for ipc? We've been using the GP LP DMA for ipc but with this API, there's no way for me to request a GPLP DMA and requesting a capability of mem_to_mem or mem_dev/dev_to_mem, just to get a GP_LP DMA , would be misleading. So I think I am leaning back to the original solution proposed by Liam.
We will have to qualify DMAC with a type and copy cap like like these:
DMAC_TYPE would be one of: GP_LP_DMA, GP_HP_DMA, Host_DMA or Link DMA
DMAC_COPY_CAP would be one of: REDA, WRITE or DUPLEX
With this it is easy for me to choose the dma like this:
host: dma_get(Host_DMA, READ/WRITE, FLAGS) dai: dma_get(GP_LP_DMA, READ/WRITE, FLAGS) page table: dma_get(HOST_DMA, READ, FLAGS) ipc: dma_get(GP_LP_DMA, DUPLEX)
Let me know your thoughts.
Thanks, Ranjani
can you see what? with this, you can make the code very clean/unified in host/dai/dma_trace...
...
+/* DMAC user types */ +enum dmac_user {
- DMAC_USER_HOST_DMA = 0,
- DMAC_USER_LINK_DMA,
do we need split into output and input for these?
- DMAC_USER_GP_LP_DMA,
- DMAC_USER_GP_HP_DMA,
+};
+/* DMAC flags */ +#define DMAC_FLAGS_SHARED 0 +#define DMAC_FLAGS_EXCLUSIVE (1 << 0)
Can you explain what is shared and how channels are shared? Are you meaning channel reservation for specific user with exclusive? I can't image the use case for this.
Shared is the most common usage, where we share DMAC between users.
Exclusive as Liam explained will be fore critical usages that require that only one user will use the DMAC at any time. ie there will only be one channel draining at any time.
Hi Liam, can you explain more about this? Where is the limitation about only one channel draining at the same time, from DMAC or the user? Per my understanding, channels of the same DMAC are quite independent, they can in draining at the same time from the point of DMAC. And, we event don't use the DMA draining feature yet.
Thanks, ~Keyon
I havent seen the need for exclusive access so far. But we might need it in the future.
- /* DMA IRQ types */ #define DMA_IRQ_TYPE_BLOCK (1 << 0) #define DMA_IRQ_TYPE_LLIST (1 << 1)
@@ -119,6 +141,8 @@ struct dma_ops { /* DMA platform data */ struct dma_plat_data { uint32_t id;
- enum dmac_user type;
- enum dmac_copy_dir copy_dir; uint32_t base; uint32_t channels; uint32_t irq;
@@ -139,7 +163,7 @@ struct dma_int { uint32_t irq; };
-struct dma *dma_get(int dmac_id); +struct dma *dma_get(enum dmac_user, enum dmac_copy_dir, int flags);
/* initialize all platform DMAC's */ void dmac_init(void); diff --git a/src/platform/apollolake/dma.c b/src/platform/apollolake/dma.c index 001bb67..1ae097e 100644 --- a/src/platform/apollolake/dma.c +++ b/src/platform/apollolake/dma.c @@ -112,6 +112,8 @@ static struct dma dma[] = { { /* Low Power GP DMAC 0 */ .plat_data = { .id = DMA_GP_LP_DMAC0,
.type = DMAC_USER_GP_LP_DMA,
.copy_dir = DMAC_DIR_DUPLEX, .base = LP_GP_DMA_BASE(0), .channels = 8, .irq =
IRQ_EXT_LP_GPDMA0_LVL5(0, 0), @@ -122,6 +124,8 @@ static struct dma dma[] = { { /* Low Power GP DMAC 1 */ .plat_data = { .id = DMA_GP_LP_DMAC1,
.type = DMAC_USER_GP_LP_DMA,
.copy_dir = DMAC_DIR_DUPLEX, .base = LP_GP_DMA_BASE(1), .channels = 8, .irq =
IRQ_EXT_LP_GPDMA1_LVL5(0, 0), @@ -132,6 +136,8 @@ static struct dma dma[] = { { /* Host In DMAC */ .plat_data = { .id = DMA_HOST_IN_DMAC,
.type = DMAC_USER_HOST_DMA,
.copy_dir = DMAC_DIR_WRITE, .base =
GTW_HOST_IN_STREAM_BASE(0), .channels = 7, .irq = IRQ_EXT_HOST_DMA_IN_LVL3(0, 0), @@ -142,6 +148,8 @@ static struct dma dma[] = { { /* Host out DMAC */ .plat_data = { .id = DMA_HOST_OUT_DMAC,
.type = DMAC_USER_HOST_DMA,
.copy_dir = DMAC_DIR_READ, .base =
GTW_HOST_OUT_STREAM_BASE(0), .channels = 6, .irq = IRQ_EXT_HOST_DMA_OUT_LVL3(0, 0), @@ -152,6 +160,8 @@ static struct dma dma[] = { { /* Link In DMAC */ .plat_data = { .id = DMA_LINK_IN_DMAC,
.type = DMAC_USER_LINK_DMA,
.copy_dir = DMAC_DIR_WRITE, .base =
GTW_LINK_IN_STREAM_BASE(0), .channels = 8, .irq = IRQ_EXT_LINK_DMA_IN_LVL4(0, 0), @@ -162,6 +172,8 @@ static struct dma dma[] = { { /* Link out DMAC */ .plat_data = { .id = DMA_LINK_OUT_DMAC,
.type = DMAC_USER_LINK_DMA,
.copy_dir = DMAC_DIR_READ, .base =
GTW_LINK_OUT_STREAM_BASE(0), .channels = 8, .irq = IRQ_EXT_LINK_DMA_OUT_LVL4(0, 0), @@ -170,15 +182,48 @@ static struct dma dma[] = { .ops = &hda_link_dma_ops, },};
-struct dma *dma_get(int dmac_id) +/*
- get DMAC based on user type, copy dir and flags
- "flags" is used to set the type of access requested
- (ex: shared/exclusive access)
- */
+struct dma *dma_get(enum dmac_user user, enum dmac_copy_dir dir, int flags) {
- int i;
int i, ch_count;
int dma_index = -1;
int min_ch_count = INT32_MAX;
for (i = 0; i < ARRAY_SIZE(dma); i++) {
if (dma[i].plat_data.id == dmac_id)
return &dma[i];
/* check DMAC user type */
if (dma[i].plat_data.type != user)
continue;
/* check DMAC copy dir */
if (dma[i].plat_data.copy_dir != dir)
continue;
/* if exclusive access is requested */
if (flags & DMAC_FLAGS_EXCLUSIVE) {
/* ret DMA with no channel in use */
if (!dma_channel_status(&dma[i]))
return &dma[i];
} else {
/* get number of channels in use */
ch_count =
dma_channel_status(&dma[i]);
/* Use this DMAC if its channel count
is lower */
if (ch_count < min_ch_count) {
dma_index = i;
min_ch_count = ch_count;
}
}
}
if (dma_index >= 0)
return &dma[dma_index];
return NULL; }
diff --git a/src/platform/baytrail/dma.c b/src/platform/baytrail/dma.c index 5a0b650..71ea241 100644 --- a/src/platform/baytrail/dma.c +++ b/src/platform/baytrail/dma.c @@ -175,15 +175,48 @@ static struct dma dma[] = { #endif };
-struct dma *dma_get(int dmac_id) +/*
- get DMAC based on user type, copy dir and flags
- For BYT/CHT, ignore the dmac_user and copy_dir arguments
- "flags" is used to set the type of access requested
- (ex: shared/exclusive access)
- */
+struct dma *dma_get(enum dmac_user user, enum dmac_copy_dir dir, int flags) {
- int i;
int i, ch_count;
int min_ch_count = INT32_MAX;
int dma_index = -1;
for (i = 0; i < ARRAY_SIZE(dma); i++) {
if (dma[i].plat_data.id == dmac_id)
return &dma[i];
/* if exclusive access is requested */
if (flags & DMAC_FLAGS_EXCLUSIVE) {
/* ret DMA with no channel in use */
if (!dma_channel_status(&dma[i]))
return &dma[i];
} else {
/*
* for shared access requests, return
DMAC
* with the least number of channels
in use
*/
/* get number of channels in use for
this DMAC*/
ch_count =
dma_channel_status(&dma[i]);
/* Use this DMAC if its channel count
is lower */
if (ch_count < min_ch_count) {
dma_index = i;
min_ch_count = ch_count;
}
}
}
/* return DMAC */
if (dma_index >= 0)
return &dma[dma_index];
return NULL; }
again, this function can be shared also?
Thanks, ~Keyon
diff --git a/src/platform/cannonlake/dma.c b/src/platform/cannonlake/dma.c index 9031c17..697b9a8 100644 --- a/src/platform/cannonlake/dma.c +++ b/src/platform/cannonlake/dma.c @@ -113,6 +113,8 @@ static struct dma dma[] = { { /* Low Power GP DMAC 0 */ .plat_data = { .id = DMA_GP_LP_DMAC0,
.type = DMAC_USER_GP_LP_DMA,
.copy_dir = DMAC_DIR_DUPLEX, .base = LP_GP_DMA_BASE(0), .channels = 8, .irq = IRQ_EXT_LP_GPDMA0_LVL5(0, 0),
@@ -123,6 +125,8 @@ static struct dma dma[] = { { /* Low Power GP DMAC 1 */ .plat_data = { .id = DMA_GP_LP_DMAC1,
.type = DMAC_USER_GP_LP_DMA,
.copy_dir = DMAC_DIR_DUPLEX, .base = LP_GP_DMA_BASE(1), .channels = 8, .irq = IRQ_EXT_LP_GPDMA1_LVL5(0, 0),
@@ -133,6 +137,8 @@ static struct dma dma[] = { { /* Host In DMAC */ .plat_data = { .id = DMA_HOST_IN_DMAC,
.type = DMAC_USER_HOST_DMA,
.copy_dir = DMAC_DIR_WRITE, .base =
GTW_HOST_IN_STREAM_BASE(0), .channels = 7, .irq = IRQ_EXT_HOST_DMA_IN_LVL3(0, 0), @@ -143,6 +149,8 @@ static struct dma dma[] = { { /* Host out DMAC */ .plat_data = { .id = DMA_HOST_OUT_DMAC,
.type = DMAC_USER_HOST_DMA,
.copy_dir = DMAC_DIR_READ, .base =
GTW_HOST_OUT_STREAM_BASE(0), .channels = 9, .irq = IRQ_EXT_HOST_DMA_OUT_LVL3(0, 0), @@ -153,6 +161,8 @@ static struct dma dma[] = { { /* Link In DMAC */ .plat_data = { .id = DMA_LINK_IN_DMAC,
.type = DMAC_USER_LINK_DMA,
.copy_dir = DMAC_DIR_WRITE, .base =
GTW_LINK_IN_STREAM_BASE(0), .channels = 9, .irq = IRQ_EXT_LINK_DMA_IN_LVL4(0, 0), @@ -163,6 +173,8 @@ static struct dma dma[] = { { /* Link out DMAC */ .plat_data = { .id = DMA_LINK_OUT_DMAC,
.type = DMAC_USER_LINK_DMA,
.copy_dir = DMAC_DIR_READ, .base =
GTW_LINK_OUT_STREAM_BASE(0), .channels = 7, .irq = IRQ_EXT_LINK_DMA_OUT_LVL4(0, 0), @@ -171,15 +183,48 @@ static struct dma dma[] = { .ops = &hda_link_dma_ops, },};
-struct dma *dma_get(int dmac_id) +/*
- get DMAC based on user type, copy dir and flags
- "flags" is used to set the type of access requested
- (ex: shared/exclusive access)
- */
+struct dma *dma_get(enum dmac_user user, enum dmac_copy_dir dir, int flags) {
- int i;
int i, ch_count;
int dma_index = -1;
int min_ch_count = INT32_MAX;
for (i = 0; i < ARRAY_SIZE(dma); i++) {
if (dma[i].plat_data.id == dmac_id)
return &dma[i];
/* check DMAC user type */
if (dma[i].plat_data.type != user)
continue;
/* check DMAC copy dir */
if (dma[i].plat_data.copy_dir != dir)
continue;
/* if exclusive access is requested */
if (flags & DMAC_FLAGS_EXCLUSIVE) {
/* ret DMA with no channel in use */
if (!dma_channel_status(&dma[i]))
return &dma[i];
} else {
/* get number of channels in use */
ch_count =
dma_channel_status(&dma[i]);
/* Use this DMAC if its channel count
is lower */
if (ch_count < min_ch_count) {
dma_index = i;
min_ch_count = ch_count;
}
}
}
if (dma_index >= 0)
return &dma[dma_index];
return NULL; }
diff --git a/src/platform/haswell/dma.c b/src/platform/haswell/dma.c index 5d1e308..9138e78 100644 --- a/src/platform/haswell/dma.c +++ b/src/platform/haswell/dma.c @@ -124,16 +124,49 @@ static struct dma dma[] = { .ops = &dw_dma_ops, },};
-struct dma *dma_get(int dmac_id) +/*
- get DMAC based on user type, copy dir and flags
- For BYT/CHT, ignore the dmac_user and copy_dir arguments
- "flags" is used to set the type of access requested
- (ex: shared/exclusive access)
- */
+struct dma *dma_get(enum dmac_user user, enum dmac_copy_dir dir, int flags) {
- switch (dmac_id) {
- case DMA_ID_DMAC0:
return &dma[0];
- case DMA_ID_DMAC1:
return &dma[1];
- default:
return NULL;
- int i, ch_count;
- int min_ch_count = INT32_MAX;
- int dma_index = -1;
- for (i = 0; i < ARRAY_SIZE(dma); i++) {
/* if exclusive access is requested */
if (flags & DMAC_FLAGS_EXCLUSIVE) {
/* ret DMA with no channel in use */
if (!dma_channel_status(&dma[i]))
return &dma[i];
} else {
/*
* for shared access requests, return
DMAC
* with the least number of channels
in use
*/
/* get number of channels in use for
this DMAC*/
ch_count =
dma_channel_status(&dma[i]);
/* Use this DMAC if its channel count
is lower */
if (ch_count < min_ch_count) {
dma_index = i;
min_ch_count = ch_count;
}
}
}
/* return DMAC */
if (dma_index >= 0)
return &dma[dma_index];
return NULL; }
/* Initialize all platform DMAC's */
Sound-open-firmware mailing list Sound-open-firmware@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/sound-open-firmw are
On Thu, 2018-06-07 at 10:26 -0700, Ranjani Sridharan wrote:
I did some experiments with the new API suggested and ran into issues with the APL platform. And the problem was with the ipc DMAC. What type would I use for ipc? We've been using the GP LP DMA for ipc but with this API, there's no way for me to request a GPLP DMA and requesting a capability of mem_to_mem or mem_dev/dev_to_mem, just to get a GP_LP DMA , would be misleading. So I think I am leaning back to the original solution proposed by Liam.
We will have to qualify DMAC with a type and copy cap like like these:
DMAC_TYPE would be one of: GP_LP_DMA, GP_HP_DMA, Host_DMA or Link DMA
DMAC_COPY_CAP would be one of: REDA, WRITE or DUPLEX
With this it is easy for me to choose the dma like this:
host: dma_get(Host_DMA, READ/WRITE, FLAGS) dai: dma_get(GP_LP_DMA, READ/WRITE, FLAGS) page table: dma_get(HOST_DMA, READ, FLAGS) ipc: dma_get(GP_LP_DMA, DUPLEX)
ipc is host DMA.
Before doing v3, maybe best to reply with proposed flags and types ?
Thanks
Liam
Let me know your thoughts.
On Thu, 2018-06-07 at 20:45 +0100, Liam Girdwood wrote:
On Thu, 2018-06-07 at 10:26 -0700, Ranjani Sridharan wrote:
I did some experiments with the new API suggested and ran into issues with the APL platform. And the problem was with the ipc DMAC. What type would I use for ipc? We've been using the GP LP DMA for ipc but with this API, there's no way for me to request a GPLP DMA and requesting a capability of mem_to_mem or mem_dev/dev_to_mem, just to get a GP_LP DMA , would be misleading. So I think I am leaning back to the original solution proposed by Liam.
We will have to qualify DMAC with a type and copy cap like like these:
DMAC_TYPE would be one of: GP_LP_DMA, GP_HP_DMA, Host_DMA or Link DMA
DMAC_COPY_CAP would be one of: REDA, WRITE or DUPLEX
With this it is easy for me to choose the dma like this:
host: dma_get(Host_DMA, READ/WRITE, FLAGS) dai: dma_get(GP_LP_DMA, READ/WRITE, FLAGS) page table: dma_get(HOST_DMA, READ, FLAGS) ipc: dma_get(GP_LP_DMA, DUPLEX)
ipc is host DMA.
This is what is breaking for me atm on APL. In the current implementation, we are using GP_LP_DMA for ipc.
Before doing v3, maybe best to reply with proposed flags and types ?
Thanks
Liam
Let me know your thoughts.
Sound-open-firmware mailing list Sound-open-firmware@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/sound-open-firmware
-----Original Message----- From: sound-open-firmware-bounces@alsa-project.org [mailto:sound-open- firmware-bounces@alsa-project.org] On Behalf Of Ranjani Sridharan Sent: Friday, June 8, 2018 8:25 AM To: Liam Girdwood liam.r.girdwood@linux.intel.com; Keyon Jie yang.jie@linux.intel.com; sound-open-firmware@alsa-project.org Cc: rander.wang rander.wang@linux.intel.com Subject: Re: [Sound-open-firmware] [RFC PATCH 3/6] dma: introduce new API for requesting DMAC
On Thu, 2018-06-07 at 20:45 +0100, Liam Girdwood wrote:
On Thu, 2018-06-07 at 10:26 -0700, Ranjani Sridharan wrote:
I did some experiments with the new API suggested and ran into issues with the APL platform. And the problem was with the ipc DMAC. What type would I use for ipc? We've been using the GP LP DMA for ipc but with this API, there's no way for me to request a GPLP DMA and requesting a capability of mem_to_mem or mem_dev/dev_to_mem, just to get a GP_LP DMA , would be misleading. So I think I am leaning back to the original solution proposed by Liam.
We will have to qualify DMAC with a type and copy cap like like these:
DMAC_TYPE would be one of: GP_LP_DMA, GP_HP_DMA, Host_DMA or Link DMA
DMAC_COPY_CAP would be one of: REDA, WRITE or DUPLEX
With this it is easy for me to choose the dma like this:
host: dma_get(Host_DMA, READ/WRITE, FLAGS) dai: dma_get(GP_LP_DMA, READ/WRITE, FLAGS) page table: dma_get(HOST_DMA, READ, FLAGS) ipc: dma_get(GP_LP_DMA, DUPLEX)
ipc is host DMA.
This is what is breaking for me atm on APL. In the current implementation, we are using GP_LP_DMA for ipc.
Are you meaning DMA trace with "ipc"? if so, you should use host input DMA.
Thanks, ~Keyon
Before doing v3, maybe best to reply with proposed flags and types ?
Thanks
Liam
Let me know your thoughts.
Sound-open-firmware mailing list Sound-open-firmware@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/sound-open-firmware
Sound-open-firmware mailing list Sound-open-firmware@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/sound-open-firmware
Use the new dma_get() API to procure DMAC's for all the users.
Signed-off-by: Ranjani Sridharan ranjani.sridharan@linux.intel.com --- src/audio/dai.c | 7 ++++++- src/audio/host.c | 28 +++++++++++++++++++++++----- src/host/common_test.c | 2 +- src/ipc/apl-ipc.c | 3 ++- src/ipc/byt-ipc.c | 4 ++-- src/ipc/cnl-ipc.c | 4 ++-- src/ipc/dma-copy.c | 7 ++++++- src/ipc/hsw-ipc.c | 4 ++-- 8 files changed, 44 insertions(+), 15 deletions(-)
diff --git a/src/audio/dai.c b/src/audio/dai.c index 1eeecd2..715e4c6 100644 --- a/src/audio/dai.c +++ b/src/audio/dai.c @@ -201,7 +201,12 @@ static struct comp_dev *dai_new(struct sof_ipc_comp *comp) goto error; }
- dd->dma = dma_get(ipc_dai->dmac_id); + /* + * request DMAC with DAI_DMA user type, DUPLEX copy direction + * shared access flag + */ + dd->dma = dma_get(DMAC_USER_GP_LP_DMA, DMAC_DIR_DUPLEX, + DMAC_FLAGS_SHARED); if (dd->dma == NULL) { trace_dai_error("eDd"); goto error; diff --git a/src/audio/host.c b/src/audio/host.c index c0f4e1b..6c5076b 100644 --- a/src/audio/host.c +++ b/src/audio/host.c @@ -530,12 +530,30 @@ 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); + /* + * request DMAC with HOST_DMA user type, duplex copy direction + * and shared access flag + */ + hd->dma = dma_get(DMAC_USER_HOST_DMA, DMAC_DIR_DUPLEX, + DMAC_FLAGS_SHARED); #else - if (ipc_host->direction == SOF_IPC_STREAM_PLAYBACK) - hd->dma = dma_get(DMA_HOST_OUT_DMAC); - else - hd->dma = dma_get(DMA_HOST_IN_DMAC); + if (ipc_host->direction == SOF_IPC_STREAM_PLAYBACK) { + + /* + * request DMAC with HOST_DMA user type, READ copy direction + * and shared access flag + */ + hd->dma = dma_get(DMAC_USER_HOST_DMA, DMAC_DIR_READ, + DMAC_FLAGS_SHARED); + } else { + + /* + * request DMAC with HOST_DMA user type, WRITE copy direction + * and shared access flag + */ + hd->dma = dma_get(DMAC_USER_HOST_DMA, DMAC_DIR_WRITE, + DMAC_FLAGS_SHARED); + } #endif if (hd->dma == NULL) { trace_host_error("eDM"); diff --git a/src/host/common_test.c b/src/host/common_test.c index e286883..155c81b 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(enum dmac_user, enum dmac_copy_dir, int flags) { return NULL; } diff --git a/src/ipc/apl-ipc.c b/src/ipc/apl-ipc.c index 78291d0..c7d7305 100644 --- a/src/ipc/apl-ipc.c +++ b/src/ipc/apl-ipc.c @@ -199,7 +199,8 @@ int platform_ipc_init(struct ipc *ipc) bzero(iipc->page_table, HOST_PAGE_SIZE);
/* dma */ - iipc->dmac = dma_get(DMA_GP_LP_DMAC0); + iipc->dmac = dma_get(DMAC_USER_GP_LP_DMA, DMAC_DIR_DUPLEX, + DMAC_FLAGS_SHARED);
/* PM */ iipc->pm_prepare_D3 = 0; diff --git a/src/ipc/byt-ipc.c b/src/ipc/byt-ipc.c index 87e7949..7c9feba 100644 --- a/src/ipc/byt-ipc.c +++ b/src/ipc/byt-ipc.c @@ -225,8 +225,8 @@ 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 DMAC with shared access flag */ + iipc->dmac = dma_get(0, 0, DMAC_FLAGS_SHARED);
/* PM */ iipc->pm_prepare_D3 = 0; diff --git a/src/ipc/cnl-ipc.c b/src/ipc/cnl-ipc.c index ba65164..fa71aa3 100644 --- a/src/ipc/cnl-ipc.c +++ b/src/ipc/cnl-ipc.c @@ -199,8 +199,8 @@ int platform_ipc_init(struct ipc *ipc) bzero(iipc->page_table, HOST_PAGE_SIZE);
/* dma */ - iipc->dmac = dma_get(DMA_GP_LP_DMAC0); - + iipc->dmac = dma_get(DMAC_USER_GP_LP_DMA, DMAC_DIR_DUPLEX, + DMAC_FLAGS_SHARED); /* PM */ iipc->pm_prepare_D3 = 0;
diff --git a/src/ipc/dma-copy.c b/src/ipc/dma-copy.c index be72eb8..7fd8449 100644 --- a/src/ipc/dma-copy.c +++ b/src/ipc/dma-copy.c @@ -375,7 +375,12 @@ 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); + /* + * request DMAC with HOST_DMA user type, WRITE copy direction + * with shared access and high perf flags + */ + dc->dmac = dma_get(DMAC_USER_HOST_DMA, DMAC_DIR_WRITE, + DMAC_FLAGS_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..bbfc10b 100644 --- a/src/ipc/hsw-ipc.c +++ b/src/ipc/hsw-ipc.c @@ -221,8 +221,8 @@ 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 DMAC with shared access flag */ + iipc->dmac = dma_get(0, 0, DMAC_FLAGS_SHARED);
/* PM */ iipc->pm_prepare_D3 = 0;
On Mon, 2018-06-04 at 21:23 -0700, Ranjani Sridharan wrote:
/* dma */
iipc->dmac = dma_get(DMA_ID_DMAC0);
/* request DMAC with shared access flag */
iipc->dmac = dma_get(0, 0, DMAC_FLAGS_SHARED);
Missing user and direction here.
Liam
On 2018年06月05日 12:23, Ranjani Sridharan wrote:
Use the new dma_get() API to procure DMAC's for all the users.
Signed-off-by: Ranjani Sridharan ranjani.sridharan@linux.intel.com
src/audio/dai.c | 7 ++++++- src/audio/host.c | 28 +++++++++++++++++++++++----- src/host/common_test.c | 2 +- src/ipc/apl-ipc.c | 3 ++- src/ipc/byt-ipc.c | 4 ++-- src/ipc/cnl-ipc.c | 4 ++-- src/ipc/dma-copy.c | 7 ++++++- src/ipc/hsw-ipc.c | 4 ++-- 8 files changed, 44 insertions(+), 15 deletions(-)
diff --git a/src/audio/dai.c b/src/audio/dai.c index 1eeecd2..715e4c6 100644 --- a/src/audio/dai.c +++ b/src/audio/dai.c @@ -201,7 +201,12 @@ static struct comp_dev *dai_new(struct sof_ipc_comp *comp) goto error; }
- dd->dma = dma_get(ipc_dai->dmac_id);
- /*
* request DMAC with DAI_DMA user type, DUPLEX copy direction
* shared access flag
*/
- dd->dma = dma_get(DMAC_USER_GP_LP_DMA, DMAC_DIR_DUPLEX,
DMAC_FLAGS_SHARED);
I still thinking that you are introducing too much params for it, the problem we need solve is only manage the channel resource for 2/3 GPDMAC together.
Thanks, ~Keyon
if (dd->dma == NULL) { trace_dai_error("eDd"); goto error; diff --git a/src/audio/host.c b/src/audio/host.c index c0f4e1b..6c5076b 100644 --- a/src/audio/host.c +++ b/src/audio/host.c @@ -530,12 +530,30 @@ 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);
- /*
* request DMAC with HOST_DMA user type, duplex copy direction
* and shared access flag
*/
- hd->dma = dma_get(DMAC_USER_HOST_DMA, DMAC_DIR_DUPLEX,
#elseDMAC_FLAGS_SHARED);
- if (ipc_host->direction == SOF_IPC_STREAM_PLAYBACK)
hd->dma = dma_get(DMA_HOST_OUT_DMAC);
- else
hd->dma = dma_get(DMA_HOST_IN_DMAC);
- if (ipc_host->direction == SOF_IPC_STREAM_PLAYBACK) {
/*
* request DMAC with HOST_DMA user type, READ copy direction
* and shared access flag
*/
hd->dma = dma_get(DMAC_USER_HOST_DMA, DMAC_DIR_READ,
DMAC_FLAGS_SHARED);
- } else {
/*
* request DMAC with HOST_DMA user type, WRITE copy direction
* and shared access flag
*/
hd->dma = dma_get(DMAC_USER_HOST_DMA, DMAC_DIR_WRITE,
DMAC_FLAGS_SHARED);
- } #endif if (hd->dma == NULL) { trace_host_error("eDM");
diff --git a/src/host/common_test.c b/src/host/common_test.c index e286883..155c81b 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(enum dmac_user, enum dmac_copy_dir, int flags) { return NULL; } diff --git a/src/ipc/apl-ipc.c b/src/ipc/apl-ipc.c index 78291d0..c7d7305 100644 --- a/src/ipc/apl-ipc.c +++ b/src/ipc/apl-ipc.c @@ -199,7 +199,8 @@ int platform_ipc_init(struct ipc *ipc) bzero(iipc->page_table, HOST_PAGE_SIZE);
/* dma */
- iipc->dmac = dma_get(DMA_GP_LP_DMAC0);
iipc->dmac = dma_get(DMAC_USER_GP_LP_DMA, DMAC_DIR_DUPLEX,
DMAC_FLAGS_SHARED);
/* PM */ iipc->pm_prepare_D3 = 0;
diff --git a/src/ipc/byt-ipc.c b/src/ipc/byt-ipc.c index 87e7949..7c9feba 100644 --- a/src/ipc/byt-ipc.c +++ b/src/ipc/byt-ipc.c @@ -225,8 +225,8 @@ 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 DMAC with shared access flag */
iipc->dmac = dma_get(0, 0, DMAC_FLAGS_SHARED);
/* PM */ iipc->pm_prepare_D3 = 0;
diff --git a/src/ipc/cnl-ipc.c b/src/ipc/cnl-ipc.c index ba65164..fa71aa3 100644 --- a/src/ipc/cnl-ipc.c +++ b/src/ipc/cnl-ipc.c @@ -199,8 +199,8 @@ int platform_ipc_init(struct ipc *ipc) bzero(iipc->page_table, HOST_PAGE_SIZE);
/* dma */
- iipc->dmac = dma_get(DMA_GP_LP_DMAC0);
- iipc->dmac = dma_get(DMAC_USER_GP_LP_DMA, DMAC_DIR_DUPLEX,
/* PM */ iipc->pm_prepare_D3 = 0;DMAC_FLAGS_SHARED);
diff --git a/src/ipc/dma-copy.c b/src/ipc/dma-copy.c index be72eb8..7fd8449 100644 --- a/src/ipc/dma-copy.c +++ b/src/ipc/dma-copy.c @@ -375,7 +375,12 @@ 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);
- /*
* request DMAC with HOST_DMA user type, WRITE copy direction
* with shared access and high perf flags
*/
- dc->dmac = dma_get(DMAC_USER_HOST_DMA, DMAC_DIR_WRITE,
if (dc->dmac == NULL) { trace_dma_error("ec0"); return -ENODEV;DMAC_FLAGS_SHARED);
diff --git a/src/ipc/hsw-ipc.c b/src/ipc/hsw-ipc.c index aa4d9e1..bbfc10b 100644 --- a/src/ipc/hsw-ipc.c +++ b/src/ipc/hsw-ipc.c @@ -221,8 +221,8 @@ 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 DMAC with shared access flag */
iipc->dmac = dma_get(0, 0, DMAC_FLAGS_SHARED);
/* PM */ iipc->pm_prepare_D3 = 0;
On 2018年06月05日 12:23, Ranjani Sridharan wrote:
Use the new dma_get() API to procure DMAC's for all the users.
Signed-off-by: Ranjani Sridharan ranjani.sridharan@linux.intel.com
src/audio/dai.c | 7 ++++++- src/audio/host.c | 28 +++++++++++++++++++++++----- src/host/common_test.c | 2 +- src/ipc/apl-ipc.c | 3 ++- src/ipc/byt-ipc.c | 4 ++-- src/ipc/cnl-ipc.c | 4 ++-- src/ipc/dma-copy.c | 7 ++++++- src/ipc/hsw-ipc.c | 4 ++-- 8 files changed, 44 insertions(+), 15 deletions(-)
diff --git a/src/audio/dai.c b/src/audio/dai.c index 1eeecd2..715e4c6 100644 --- a/src/audio/dai.c +++ b/src/audio/dai.c @@ -201,7 +201,12 @@ static struct comp_dev *dai_new(struct sof_ipc_comp *comp) goto error; }
- dd->dma = dma_get(ipc_dai->dmac_id);
- /*
* request DMAC with DAI_DMA user type, DUPLEX copy direction
* shared access flag
*/
- dd->dma = dma_get(DMAC_USER_GP_LP_DMA, DMAC_DIR_DUPLEX,
if (dd->dma == NULL) { trace_dai_error("eDd"); goto error;DMAC_FLAGS_SHARED);
diff --git a/src/audio/host.c b/src/audio/host.c index c0f4e1b..6c5076b 100644 --- a/src/audio/host.c +++ b/src/audio/host.c @@ -530,12 +530,30 @@ 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);
- /*
* request DMAC with HOST_DMA user type, duplex copy direction
* and shared access flag
*/
- hd->dma = dma_get(DMAC_USER_HOST_DMA, DMAC_DIR_DUPLEX,
#elseDMAC_FLAGS_SHARED);
- if (ipc_host->direction == SOF_IPC_STREAM_PLAYBACK)
hd->dma = dma_get(DMA_HOST_OUT_DMAC);
- else
hd->dma = dma_get(DMA_HOST_IN_DMAC);
- if (ipc_host->direction == SOF_IPC_STREAM_PLAYBACK) {
/*
* request DMAC with HOST_DMA user type, READ copy direction
* and shared access flag
*/
hd->dma = dma_get(DMAC_USER_HOST_DMA, DMAC_DIR_READ,
DMAC_FLAGS_SHARED);
- } else {
/*
* request DMAC with HOST_DMA user type, WRITE copy direction
* and shared access flag
*/
hd->dma = dma_get(DMAC_USER_HOST_DMA, DMAC_DIR_WRITE,
DMAC_FLAGS_SHARED);
- } #endif if (hd->dma == NULL) { trace_host_error("eDM");
diff --git a/src/host/common_test.c b/src/host/common_test.c index e286883..155c81b 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(enum dmac_user, enum dmac_copy_dir, int flags) { return NULL; } diff --git a/src/ipc/apl-ipc.c b/src/ipc/apl-ipc.c index 78291d0..c7d7305 100644 --- a/src/ipc/apl-ipc.c +++ b/src/ipc/apl-ipc.c @@ -199,7 +199,8 @@ int platform_ipc_init(struct ipc *ipc) bzero(iipc->page_table, HOST_PAGE_SIZE);
/* dma */
- iipc->dmac = dma_get(DMA_GP_LP_DMAC0);
iipc->dmac = dma_get(DMAC_USER_GP_LP_DMA, DMAC_DIR_DUPLEX,
DMAC_FLAGS_SHARED);
/* PM */ iipc->pm_prepare_D3 = 0;
diff --git a/src/ipc/byt-ipc.c b/src/ipc/byt-ipc.c index 87e7949..7c9feba 100644 --- a/src/ipc/byt-ipc.c +++ b/src/ipc/byt-ipc.c @@ -225,8 +225,8 @@ 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 DMAC with shared access flag */
iipc->dmac = dma_get(0, 0, DMAC_FLAGS_SHARED);
/* PM */ iipc->pm_prepare_D3 = 0;
diff --git a/src/ipc/cnl-ipc.c b/src/ipc/cnl-ipc.c index ba65164..fa71aa3 100644 --- a/src/ipc/cnl-ipc.c +++ b/src/ipc/cnl-ipc.c @@ -199,8 +199,8 @@ int platform_ipc_init(struct ipc *ipc) bzero(iipc->page_table, HOST_PAGE_SIZE);
/* dma */
- iipc->dmac = dma_get(DMA_GP_LP_DMAC0);
- iipc->dmac = dma_get(DMAC_USER_GP_LP_DMA, DMAC_DIR_DUPLEX,
/* PM */ iipc->pm_prepare_D3 = 0;DMAC_FLAGS_SHARED);
diff --git a/src/ipc/dma-copy.c b/src/ipc/dma-copy.c index be72eb8..7fd8449 100644 --- a/src/ipc/dma-copy.c +++ b/src/ipc/dma-copy.c @@ -375,7 +375,12 @@ 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);
- /*
* request DMAC with HOST_DMA user type, WRITE copy direction
* with shared access and high perf flags
*/
- dc->dmac = dma_get(DMAC_USER_HOST_DMA, DMAC_DIR_WRITE,
DMAC_FLAGS_SHARED);
be careful about this, for platform older than skl, we don't have host dma, so I assume your patch will break dma trace on byt.
Thanks, ~Keyon
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..bbfc10b 100644 --- a/src/ipc/hsw-ipc.c +++ b/src/ipc/hsw-ipc.c @@ -221,8 +221,8 @@ 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 DMAC with shared access flag */
iipc->dmac = dma_get(0, 0, DMAC_FLAGS_SHARED);
/* PM */ iipc->pm_prepare_D3 = 0;
On Tue, 2018-06-05 at 19:14 +0800, Keyon Jie wrote:
On 2018年06月05日 12:23, Ranjani Sridharan wrote:
Use the new dma_get() API to procure DMAC's for all the users.
Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com
src/audio/dai.c | 7 ++++++- src/audio/host.c | 28 +++++++++++++++++++++++----- src/host/common_test.c | 2 +- src/ipc/apl-ipc.c | 3 ++- src/ipc/byt-ipc.c | 4 ++-- src/ipc/cnl-ipc.c | 4 ++-- src/ipc/dma-copy.c | 7 ++++++- src/ipc/hsw-ipc.c | 4 ++-- 8 files changed, 44 insertions(+), 15 deletions(-)
diff --git a/src/audio/dai.c b/src/audio/dai.c index 1eeecd2..715e4c6 100644 --- a/src/audio/dai.c +++ b/src/audio/dai.c @@ -201,7 +201,12 @@ static struct comp_dev *dai_new(struct sof_ipc_comp *comp) goto error; }
- dd->dma = dma_get(ipc_dai->dmac_id);
- /*
* request DMAC with DAI_DMA user type, DUPLEX copy
direction
* shared access flag
*/
- dd->dma = dma_get(DMAC_USER_GP_LP_DMA, DMAC_DIR_DUPLEX,
if (dd->dma == NULL) { trace_dai_error("eDd"); goto error;DMAC_FLAGS_SHARED);
diff --git a/src/audio/host.c b/src/audio/host.c index c0f4e1b..6c5076b 100644 --- a/src/audio/host.c +++ b/src/audio/host.c @@ -530,12 +530,30 @@ 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);
- /*
* request DMAC with HOST_DMA user type, duplex copy
direction
* and shared access flag
*/
- hd->dma = dma_get(DMAC_USER_HOST_DMA, DMAC_DIR_DUPLEX,
#elseDMAC_FLAGS_SHARED);
- if (ipc_host->direction == SOF_IPC_STREAM_PLAYBACK)
hd->dma = dma_get(DMA_HOST_OUT_DMAC);
- else
hd->dma = dma_get(DMA_HOST_IN_DMAC);
- if (ipc_host->direction == SOF_IPC_STREAM_PLAYBACK) {
/*
* request DMAC with HOST_DMA user type, READ copy
direction
* and shared access flag
*/
hd->dma = dma_get(DMAC_USER_HOST_DMA,
DMAC_DIR_READ,
DMAC_FLAGS_SHARED);
- } else {
/*
* request DMAC with HOST_DMA user type, WRITE
copy direction
* and shared access flag
*/
hd->dma = dma_get(DMAC_USER_HOST_DMA,
DMAC_DIR_WRITE,
DMAC_FLAGS_SHARED);
- } #endif if (hd->dma == NULL) { trace_host_error("eDM");
diff --git a/src/host/common_test.c b/src/host/common_test.c index e286883..155c81b 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(enum dmac_user, enum dmac_copy_dir, int flags) { return NULL; } diff --git a/src/ipc/apl-ipc.c b/src/ipc/apl-ipc.c index 78291d0..c7d7305 100644 --- a/src/ipc/apl-ipc.c +++ b/src/ipc/apl-ipc.c @@ -199,7 +199,8 @@ int platform_ipc_init(struct ipc *ipc) bzero(iipc->page_table, HOST_PAGE_SIZE);
/* dma */
- iipc->dmac = dma_get(DMA_GP_LP_DMAC0);
iipc->dmac = dma_get(DMAC_USER_GP_LP_DMA, DMAC_DIR_DUPLEX,
DMAC_FLAGS_SHARED);
/* PM */ iipc->pm_prepare_D3 = 0;
diff --git a/src/ipc/byt-ipc.c b/src/ipc/byt-ipc.c index 87e7949..7c9feba 100644 --- a/src/ipc/byt-ipc.c +++ b/src/ipc/byt-ipc.c @@ -225,8 +225,8 @@ 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 DMAC with shared access flag */
iipc->dmac = dma_get(0, 0, DMAC_FLAGS_SHARED);
/* PM */ iipc->pm_prepare_D3 = 0;
diff --git a/src/ipc/cnl-ipc.c b/src/ipc/cnl-ipc.c index ba65164..fa71aa3 100644 --- a/src/ipc/cnl-ipc.c +++ b/src/ipc/cnl-ipc.c @@ -199,8 +199,8 @@ int platform_ipc_init(struct ipc *ipc) bzero(iipc->page_table, HOST_PAGE_SIZE);
/* dma */
- iipc->dmac = dma_get(DMA_GP_LP_DMAC0);
- iipc->dmac = dma_get(DMAC_USER_GP_LP_DMA, DMAC_DIR_DUPLEX,
/* PM */ iipc->pm_prepare_D3 = 0;DMAC_FLAGS_SHARED);
diff --git a/src/ipc/dma-copy.c b/src/ipc/dma-copy.c index be72eb8..7fd8449 100644 --- a/src/ipc/dma-copy.c +++ b/src/ipc/dma-copy.c @@ -375,7 +375,12 @@ 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);
- /*
* request DMAC with HOST_DMA user type, WRITE copy
direction
* with shared access and high perf flags
*/
- dc->dmac = dma_get(DMAC_USER_HOST_DMA, DMAC_DIR_WRITE,
DMAC_FLAGS_SHARED);
be careful about this, for platform older than skl, we don't have host dma, so I assume your patch will break dma trace on byt.
The first 2 arguments are ignored for BYT/CHT/HSW so no issues there. BYT is the only platform I've tested this set of patches to work on.
Thanks, ~Keyon
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..bbfc10b 100644 --- a/src/ipc/hsw-ipc.c +++ b/src/ipc/hsw-ipc.c @@ -221,8 +221,8 @@ 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 DMAC with shared access flag */
iipc->dmac = dma_get(0, 0, DMAC_FLAGS_SHARED);
/* PM */ iipc->pm_prepare_D3 = 0;
Sound-open-firmware mailing list Sound-open-firmware@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/sound-open-firmware
On 2018年06月06日 03:20, Ranjani Sridharan wrote:
On Tue, 2018-06-05 at 19:14 +0800, Keyon Jie wrote:
On 2018年06月05日 12:23, Ranjani Sridharan wrote:
Use the new dma_get() API to procure DMAC's for all the users.
Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com
src/audio/dai.c | 7 ++++++- src/audio/host.c | 28 +++++++++++++++++++++++----- src/host/common_test.c | 2 +- src/ipc/apl-ipc.c | 3 ++- src/ipc/byt-ipc.c | 4 ++-- src/ipc/cnl-ipc.c | 4 ++-- src/ipc/dma-copy.c | 7 ++++++- src/ipc/hsw-ipc.c | 4 ++-- 8 files changed, 44 insertions(+), 15 deletions(-)
diff --git a/src/audio/dai.c b/src/audio/dai.c index 1eeecd2..715e4c6 100644 --- a/src/audio/dai.c +++ b/src/audio/dai.c @@ -201,7 +201,12 @@ static struct comp_dev *dai_new(struct sof_ipc_comp *comp) goto error; }
- dd->dma = dma_get(ipc_dai->dmac_id);
- /*
* request DMAC with DAI_DMA user type, DUPLEX copy
direction
* shared access flag
*/
- dd->dma = dma_get(DMAC_USER_GP_LP_DMA, DMAC_DIR_DUPLEX,
if (dd->dma == NULL) { trace_dai_error("eDd"); goto error;DMAC_FLAGS_SHARED);
diff --git a/src/audio/host.c b/src/audio/host.c index c0f4e1b..6c5076b 100644 --- a/src/audio/host.c +++ b/src/audio/host.c @@ -530,12 +530,30 @@ 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);
- /*
* request DMAC with HOST_DMA user type, duplex copy
direction
* and shared access flag
*/
- hd->dma = dma_get(DMAC_USER_HOST_DMA, DMAC_DIR_DUPLEX,
#elseDMAC_FLAGS_SHARED);
- if (ipc_host->direction == SOF_IPC_STREAM_PLAYBACK)
hd->dma = dma_get(DMA_HOST_OUT_DMAC);
- else
hd->dma = dma_get(DMA_HOST_IN_DMAC);
- if (ipc_host->direction == SOF_IPC_STREAM_PLAYBACK) {
/*
* request DMAC with HOST_DMA user type, READ copy
direction
* and shared access flag
*/
hd->dma = dma_get(DMAC_USER_HOST_DMA,
DMAC_DIR_READ,
DMAC_FLAGS_SHARED);
- } else {
/*
* request DMAC with HOST_DMA user type, WRITE
copy direction
* and shared access flag
*/
hd->dma = dma_get(DMAC_USER_HOST_DMA,
DMAC_DIR_WRITE,
DMAC_FLAGS_SHARED);
- } #endif if (hd->dma == NULL) { trace_host_error("eDM");
diff --git a/src/host/common_test.c b/src/host/common_test.c index e286883..155c81b 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(enum dmac_user, enum dmac_copy_dir, int flags) { return NULL; } diff --git a/src/ipc/apl-ipc.c b/src/ipc/apl-ipc.c index 78291d0..c7d7305 100644 --- a/src/ipc/apl-ipc.c +++ b/src/ipc/apl-ipc.c @@ -199,7 +199,8 @@ int platform_ipc_init(struct ipc *ipc) bzero(iipc->page_table, HOST_PAGE_SIZE);
/* dma */
- iipc->dmac = dma_get(DMA_GP_LP_DMAC0);
iipc->dmac = dma_get(DMAC_USER_GP_LP_DMA, DMAC_DIR_DUPLEX,
DMAC_FLAGS_SHARED);
/* PM */ iipc->pm_prepare_D3 = 0;
diff --git a/src/ipc/byt-ipc.c b/src/ipc/byt-ipc.c index 87e7949..7c9feba 100644 --- a/src/ipc/byt-ipc.c +++ b/src/ipc/byt-ipc.c @@ -225,8 +225,8 @@ 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 DMAC with shared access flag */
iipc->dmac = dma_get(0, 0, DMAC_FLAGS_SHARED);
/* PM */ iipc->pm_prepare_D3 = 0;
diff --git a/src/ipc/cnl-ipc.c b/src/ipc/cnl-ipc.c index ba65164..fa71aa3 100644 --- a/src/ipc/cnl-ipc.c +++ b/src/ipc/cnl-ipc.c @@ -199,8 +199,8 @@ int platform_ipc_init(struct ipc *ipc) bzero(iipc->page_table, HOST_PAGE_SIZE);
/* dma */
- iipc->dmac = dma_get(DMA_GP_LP_DMAC0);
- iipc->dmac = dma_get(DMAC_USER_GP_LP_DMA, DMAC_DIR_DUPLEX,
/* PM */ iipc->pm_prepare_D3 = 0;DMAC_FLAGS_SHARED);
diff --git a/src/ipc/dma-copy.c b/src/ipc/dma-copy.c index be72eb8..7fd8449 100644 --- a/src/ipc/dma-copy.c +++ b/src/ipc/dma-copy.c @@ -375,7 +375,12 @@ 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);
- /*
* request DMAC with HOST_DMA user type, WRITE copy
direction
* with shared access and high perf flags
*/
- dc->dmac = dma_get(DMAC_USER_HOST_DMA, DMAC_DIR_WRITE,
DMAC_FLAGS_SHARED);
be careful about this, for platform older than skl, we don't have host dma, so I assume your patch will break dma trace on byt.
The first 2 arguments are ignored for BYT/CHT/HSW so no issues there.
OK, that's fine then.
Thanks, ~Keyon
BYT is the only platform I've tested this set of patches to work on.
Thanks, ~Keyon
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..bbfc10b 100644 --- a/src/ipc/hsw-ipc.c +++ b/src/ipc/hsw-ipc.c @@ -221,8 +221,8 @@ 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 DMAC with shared access flag */
iipc->dmac = dma_get(0, 0, DMAC_FLAGS_SHARED);
/* PM */ iipc->pm_prepare_D3 = 0;
Sound-open-firmware mailing list Sound-open-firmware@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/sound-open-firmware
Sound-open-firmware mailing list Sound-open-firmware@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/sound-open-firmware
On 6/5/2018 6:23 AM, Ranjani Sridharan wrote:
#if !defined CONFIG_DMA_GW
- hd->dma = dma_get(ipc_host->dmac_id);
- /*
* request DMAC with HOST_DMA user type, duplex copy direction
* and shared access flag
*/
- hd->dma = dma_get(DMAC_USER_HOST_DMA, DMAC_DIR_DUPLEX,
DMAC_FLAGS_SHARED);
#else
- if (ipc_host->direction == SOF_IPC_STREAM_PLAYBACK)
hd->dma = dma_get(DMA_HOST_OUT_DMAC);
- else
hd->dma = dma_get(DMA_HOST_IN_DMAC);
- if (ipc_host->direction == SOF_IPC_STREAM_PLAYBACK) {
/*
* request DMAC with HOST_DMA user type, READ copy direction
* and shared access flag
*/
hd->dma = dma_get(DMAC_USER_HOST_DMA, DMAC_DIR_READ,
DMAC_FLAGS_SHARED);
- } else {
/*
* request DMAC with HOST_DMA user type, WRITE copy direction
* and shared access flag
*/
hd->dma = dma_get(DMAC_USER_HOST_DMA, DMAC_DIR_WRITE,
DMAC_FLAGS_SHARED);
- }
#endif
Is it possible to have a single implementation, the one inside #else that would call any dma_ops with either DMAC_DIR_READ or DMAC_DIR_WRITE depending on the direction? And remove #if-else-endif then.
Marcin
On Tue, 2018-06-05 at 19:37 +0200, Marcin Maka wrote:
On 6/5/2018 6:23 AM, Ranjani Sridharan wrote:
#if !defined CONFIG_DMA_GW
- hd->dma = dma_get(ipc_host->dmac_id);
- /*
* request DMAC with HOST_DMA user type, duplex copy
direction
* and shared access flag
*/
- hd->dma = dma_get(DMAC_USER_HOST_DMA, DMAC_DIR_DUPLEX,
DMAC_FLAGS_SHARED);
#else
- if (ipc_host->direction == SOF_IPC_STREAM_PLAYBACK)
hd->dma = dma_get(DMA_HOST_OUT_DMAC);
- else
hd->dma = dma_get(DMA_HOST_IN_DMAC);
- if (ipc_host->direction == SOF_IPC_STREAM_PLAYBACK) {
/*
* request DMAC with HOST_DMA user type, READ copy
direction
* and shared access flag
*/
hd->dma = dma_get(DMAC_USER_HOST_DMA,
DMAC_DIR_READ,
DMAC_FLAGS_SHARED);
- } else {
/*
* request DMAC with HOST_DMA user type, WRITE
copy direction
* and shared access flag
*/
hd->dma = dma_get(DMAC_USER_HOST_DMA,
DMAC_DIR_WRITE,
DMAC_FLAGS_SHARED);
- }
#endif
Is it possible to have a single implementation, the one inside #else that would call any dma_ops with either DMAC_DIR_READ or DMAC_DIR_WRITE depending on the direction? And remove #if-else-endif then.
Yes, Marcin. I just realized this #if-else-endif might not be needed with the new changes. Thanks!
Marcin _______________________________________________ Sound-open-firmware mailing list Sound-open-firmware@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/sound-open-firmware
dma_copy_context() does not need DMAC ID argument anymore.
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 +- 3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/include/sof/dma.h b/src/include/sof/dma.h index 25581e6..d825590 100644 --- a/src/include/sof/dma.h +++ b/src/include/sof/dma.h @@ -292,7 +292,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 7fd8449..bb4d4e4 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) { /* * request DMAC with HOST_DMA user type, WRITE copy direction 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);
The new dma_get() API procures a DMAC based on user, copy direction and other flags. So no need to define the DMAC ID for trace DMA anymore.
Signed-off-by: Ranjani Sridharan ranjani.sridharan@linux.intel.com --- 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 --- 4 files changed, 12 deletions(-)
diff --git a/src/platform/apollolake/include/platform/platform.h b/src/platform/apollolake/include/platform/platform.h index aefa9b2..e77bf6f 100644 --- a/src/platform/apollolake/include/platform/platform.h +++ b/src/platform/apollolake/include/platform/platform.h @@ -103,9 +103,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 6a7ebc9..8a7d0a3 100644 --- a/src/platform/baytrail/include/platform/platform.h +++ b/src/platform/baytrail/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_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 35219d7..91c1f71 100644 --- a/src/platform/cannonlake/include/platform/platform.h +++ b/src/platform/cannonlake/include/platform/platform.h @@ -109,9 +109,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 d30f329..768a63c 100644 --- a/src/platform/haswell/include/platform/platform.h +++ b/src/platform/haswell/include/platform/platform.h @@ -94,9 +94,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
On 2018年06月05日 12:23, Ranjani Sridharan wrote:
The new dma_get() API procures a DMAC based on user, copy direction and other flags. So no need to define the DMAC ID for trace DMA anymore.
Signed-off-by: Ranjani Sridharan ranjani.sridharan@linux.intel.com
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 --- 4 files changed, 12 deletions(-)
diff --git a/src/platform/apollolake/include/platform/platform.h b/src/platform/apollolake/include/platform/platform.h index aefa9b2..e77bf6f 100644 --- a/src/platform/apollolake/include/platform/platform.h +++ b/src/platform/apollolake/include/platform/platform.h @@ -103,9 +103,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 6a7ebc9..8a7d0a3 100644 --- a/src/platform/baytrail/include/platform/platform.h +++ b/src/platform/baytrail/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_DMAC0
as commented in 4/6, you need to make sure the correct dmac is used for DMA trace on byt.
thanks, ~Keyon
- /* 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 35219d7..91c1f71 100644 --- a/src/platform/cannonlake/include/platform/platform.h +++ b/src/platform/cannonlake/include/platform/platform.h @@ -109,9 +109,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 d30f329..768a63c 100644 --- a/src/platform/haswell/include/platform/platform.h +++ b/src/platform/haswell/include/platform/platform.h @@ -94,9 +94,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
On Tue, 2018-06-05 at 19:15 +0800, Keyon Jie wrote:
On 2018年06月05日 12:23, Ranjani Sridharan wrote:
The new dma_get() API procures a DMAC based on user, copy direction and other flags. So no need to define the DMAC ID for trace DMA anymore.
Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com
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 --- 4 files changed, 12 deletions(-)
diff --git a/src/platform/apollolake/include/platform/platform.h b/src/platform/apollolake/include/platform/platform.h index aefa9b2..e77bf6f 100644 --- a/src/platform/apollolake/include/platform/platform.h +++ b/src/platform/apollolake/include/platform/platform.h @@ -103,9 +103,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 6a7ebc9..8a7d0a3 100644 --- a/src/platform/baytrail/include/platform/platform.h +++ b/src/platform/baytrail/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_DMAC0
as commented in 4/6, you need to make sure the correct dmac is used for DMA trace on byt.
Keyon, are you saying we cannot use DMAC1 for trace dma on BYT? Because the way the new API works on BYT is: it ignores the first 2 arguments and picks the DMAC with the least number of busy channels. I've tested it on BYT and tracw works fine.
But, if I cannot DMAC1 for trace on BYT like you;re saying. then I'd have to change the logic accordingly. So could you please confirm?
thanks, ~Keyon
- /* 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 35219d7..91c1f71 100644 --- a/src/platform/cannonlake/include/platform/platform.h +++ b/src/platform/cannonlake/include/platform/platform.h @@ -109,9 +109,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 d30f329..768a63c 100644 --- a/src/platform/haswell/include/platform/platform.h +++ b/src/platform/haswell/include/platform/platform.h @@ -94,9 +94,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
Sound-open-firmware mailing list Sound-open-firmware@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/sound-open-firmware
participants (6)
-
Jie, Yang
-
Keyon Jie
-
Liam Girdwood
-
Marcin Maka
-
rander.wang
-
Ranjani Sridharan