[Sound-open-firmware] [RFC PATCH 3/6] dma: introduce new API for requesting DMAC
rander.wang
rander.wang at linux.intel.com
Tue Jun 5 12:00:40 CEST 2018
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 at 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,
>> + .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 at alsa-project.org
> http://mailman.alsa-project.org/mailman/listinfo/sound-open-firmware
More information about the Sound-open-firmware
mailing list