mmp audio support
Subsystems (4)
cover mmp audio support
v0->v1:
dmaengine -> soc-dmaengine.
update according to Mark's suggestion
These patches provide mmp audio support under alsa via dmaengine Support platfrom pxa688 and pxa910mmp_tdma.c and mmp-pcm.c is shared for pxa688 and pxa910 pxa688 (mmp2) use mmp2-sspa.c
pxa910 directly use pxa-ssp.cmmp_tdma.c is under dmaengine framework
Verified on brownstone (pxa688) and ttc-dkb
Qiao Zhou (1):
ASoC: add ttc-dkb machine support
Zhangfei Gao (4):
dmaengine: mmp_tdma: add mmp tdma support
ASoC: mmp: add audio dma support
ASOC: mmp: add sspa support
ASoC: add mmp brownstone support
drivers/dma/Kconfig | 10 + drivers/dma/Makefile | 1 + drivers/dma/mmp_tdma.c | 649 +++++++++++++++++++++++++++++++ include/linux/platform_data/mmp_audio.h | 22 + include/linux/platform_data/mmp_dma.h | 20 + sound/soc/pxa/Kconfig | 42 ++ sound/soc/pxa/Makefile | 8 + sound/soc/pxa/brownstone.c | 178 +++++++++ sound/soc/pxa/mmp-pcm.c | 317 +++++++++++++++ sound/soc/pxa/mmp-sspa.c | 496 +++++++++++++++++++++++ sound/soc/pxa/mmp-sspa.h | 92 +++++ sound/soc/pxa/ttc-dkb.c | 173 ++++++++ 12 files changed, 2008 insertions(+), 0 deletions(-) create mode 100644 drivers/dma/mmp_tdma.c create mode 100644 include/linux/platform_data/mmp_audio.h create mode 100644 include/linux/platform_data/mmp_dma.h create mode 100644 sound/soc/pxa/brownstone.c create mode 100644 sound/soc/pxa/mmp-pcm.c create mode 100644 sound/soc/pxa/mmp-sspa.c create mode 100644 sound/soc/pxa/mmp-sspa.h create mode 100644 sound/soc/pxa/ttc-dkb.c
PATCH 1/5 dmaengine: mmp_tdma: add mmp tdma support
Add support for two-channel dma under dmaengine
support: mmp-adma and pxa910-squ
--- drivers/dma/Kconfig | 10 + drivers/dma/Makefile | 1 + drivers/dma/mmp_tdma.c | 649 +++++++++++++++++++++++++++++++++ include/linux/platform_data/mmp_dma.h | 20 + 4 files changed, 680 insertions(+), 0 deletions(-) create mode 100644 drivers/dma/mmp_tdma.c create mode 100644 include/linux/platform_data/mmp_dma.h
drivers/dma/Kconfig +10 -0
@@ -259,6 +259,16 @@ config DMA_SA11X0 SA-1110 SoCs. This DMA engine can only be used with on-chip devices. +config MMP_TDMA + bool "MMP Two-Channel DMA support" + default ARCH_MMP + select DMA_ENGINE + help + Support the MMP Two-Channel DMA engine. + This engine used for MMP Audio DMA and pxa910 SQU. + + Say Y here if you enabled MMP ADMA, otherwise say N. + config DMA_ENGINE bool
drivers/dma/Makefile +1 -0
@@ -28,3 +28,4 @@ obj-$(CONFIG_PCH_DMA) += pch_dma.o obj-$(CONFIG_AMBA_PL08X) += amba-pl08x.o obj-$(CONFIG_EP93XX_DMA) += ep93xx_dma.o obj-$(CONFIG_DMA_SA11X0) += sa11x0-dma.o +obj-$(CONFIG_MMP_TDMA) += mmp_tdma.o
drivers/dma/mmp_tdma.c new file +649 -0
649 lines not on this page · raw message
include/linux/platform_data/mmp_dma.h new file +20 -0
@@ -0,0 +1,20 @@ +/* +* MMP Platform DMA Management +* +* Copyright (c) 2011 Marvell Semiconductors Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +*/ + +#ifndef MMP_DMA_H +#define MMP_DMA_H + +struct mmp_tdma_data { +u32 bus_size; +u32 pack_mod; +}; + +#endif /* MMP_DMA_H */
Signature · 1 line
1.7.1
Re: [PATCH v1 1/5] dmaengine: mmp_tdma: add mmp tdma support
Quoted 9 lines · Zhangfei Gao
Add support for two-channel dma under dmaengine
support: mmp-adma and pxa910-squSigned-off-by Zhangfei Gao <[email protected]>Signed-off-by Leo Yan <[email protected]>Signed-off-by Qiao Zhou <[email protected]>drivers/dma/mmp_tdma.c new file +1
-0+
drivers/dma/mmp_tdma.c line 259
Quoted 10 lines
drivers/dma/mmp_tdma.c new file +10
-0+static int mmp_tdma_clear_chan_irq (struct mmp_tdma_chan *tdmac) +{ +u32 reg =readl (tdmac->reg_base +TDISR ); + +if (reg &TDISR_COMP ) { +/* clear irq */ + reg &= ~TDISR_COMP ; +writel (reg, tdmac->reg_base +TDISR ); + +return 1 ;
hrmm.?
Quoted 54 lines
drivers/dma/mmp_tdma.c new file +54
-0+ } +return 0 ; +} + +static irqreturn_t mmp_tdma_chan_handler (int irq,void *dev_id) +{ +struct mmp_tdma_chan *tdmac = dev_id; + +if (mmp_tdma_clear_chan_irq (tdmac)) { + tdmac->pos = (tdmac->pos + tdmac->period_len) % tdmac->buf_len; +tasklet_schedule (&tdmac->tasklet); +return IRQ_HANDLED ; + }else +return IRQ_NONE ; +} + +static irqreturn_t mmp_tdma_int_handler (int irq,void *dev_id) +{ +struct mmp_tdma_device *tdev = dev_id; +int i, ret; +int irq_num =0 ; + +for (i =0 ; i <TDMA_CHANNEL_NUM ; i++) { +struct mmp_tdma_chan *tdmac = tdev->tdmac[i]; + + ret =mmp_tdma_chan_handler (irq, tdmac); +if (ret ==IRQ_HANDLED ) + irq_num++; + } + +if (irq_num) +return IRQ_HANDLED ; +else +return IRQ_NONE ; +} + +static void dma_do_tasklet (unsigned long data) +{ +struct mmp_tdma_chan *tdmac = (struct mmp_tdma_chan *)data; + +if (tdmac->desc.callback) + tdmac->desc.callback (tdmac->desc.callback_param); + +} + +static void mmp_tdma_free_descriptor (struct mmp_tdma_chan *tdmac) +{ +struct gen_pool *gpool; +int size = tdmac->desc_num *sizeof (struct mmp_tdma_desc ); + + gpool =sram_get_gpool ("asram" ); +if (tdmac->desc_arr) +gen_pool_free (gpool, (unsigned long )tdmac->desc_arr, + size);
drivers/dma/mmp_tdma.c line 323
Quoted 10 lines
drivers/dma/mmp_tdma.c new file +10
-0+ tdmac->desc_arr =NULL ; + +return ; +} + +static dma_cookie_t mmp_tdma_tx_submit (struct dma_async_tx_descriptor *tx) +{ +struct mmp_tdma_chan *tdmac =to_mmp_tdma_chan (tx->chan); + +mmp_tdma_chan_set_desc (tdmac, tdmac->desc_arr_phys);
This seems odd. In submit you are supposed to move this to your pending list. Btw where is the .issue_pending handler?
Quoted 12 lines
drivers/dma/mmp_tdma.c new file +12
-0+ +return 0 ; +} + +static int mmp_tdma_alloc_chan_resources (struct dma_chan *chan) +{ +struct mmp_tdma_chan *tdmac =to_mmp_tdma_chan (chan); +int ret; + +dev_dbg (tdmac->dev,"%s: enter\n" , __func__); + +dma_async_tx_descriptor_init (&tdmac->desc, chan);
drivers/dma/mmp_tdma.c line 345
Quoted 10 lines
drivers/dma/mmp_tdma.c new file +10
-0+ tdmac->desc.tx_submit = mmp_tdma_tx_submit; + +if (tdmac->irq) { + ret =devm_request_irq (tdmac->dev, tdmac->irq, + mmp_tdma_chan_handler,IRQF_DISABLED ,"tdma" , tdmac); +if (ret) + goto err_request_irq; + } + +return 0 ;
NO. This is supposed to return the number of descriptors allocated.
Quoted 5 lines
drivers/dma/mmp_tdma.c new file +5
-0+ +err_request_irq: +mmp_tdma_free_descriptor (tdmac); +return ret; +}
drivers/dma/mmp_tdma.c line 360
Quoted 10 lines
drivers/dma/mmp_tdma.c new file +10
-0+ +static void mmp_tdma_free_chan_resources (struct dma_chan *chan) +{ +struct mmp_tdma_chan *tdmac =to_mmp_tdma_chan (chan); + +dev_dbg (tdmac->dev,"%s: enter\n" , __func__); + +if (tdmac->irq) +devm_free_irq (tdmac->dev, tdmac->irq, tdmac); +mmp_tdma_disable_chan (tdmac);
channel should be already disabled, why do you need this here?
Quoted 8 lines
drivers/dma/mmp_tdma.c new file +8
-0+mmp_tdma_free_descriptor (tdmac); +return ; +} + + +static struct dma_async_tx_descriptor *mmp_tdma_prep_slave_sg( + struct dma_chan *chan, struct scatterlist *sgl, + unsigned int sg_len, enum dma_transfer_direction direction,
drivers/dma/mmp_tdma.c line 378
Quoted 10 lines
drivers/dma/mmp_tdma.c new file +10
-0+ unsigned long flags, void *context) +{ +/* +* This operation is not supported on the TDMA controller +* +* However, we need to provide the function pointer to allow the +* device_control() method to work. +*/ +return NULL ; +}
Pls remove if not supported
Quoted 10 lines
drivers/dma/mmp_tdma.c new file +10
-0+ +static int mmp_tdma_alloc_descriptor (struct mmp_tdma_chan *tdmac) +{ +struct gen_pool *gpool; +int size = tdmac->desc_num *sizeof (struct mmp_tdma_desc ); + +dev_dbg (tdmac->dev,"%s: enter\n" , __func__); + + gpool =sram_get_gpool ("asram" ); +if (!gpool)
drivers/dma/mmp_tdma.c line 398
Quoted 10 lines
drivers/dma/mmp_tdma.c new file +10
-0+return -ENOMEM ; + + tdmac->desc_arr = (void *)gen_pool_alloc (gpool, size); +if (!tdmac->desc_arr) +return -ENOMEM ; + + tdmac->desc_arr_phys =gen_pool_virt_to_phys (gpool, + (unsigned long )tdmac->desc_arr); + +return 0 ;
this needs fix
Quoted 13 lines
drivers/dma/mmp_tdma.c new file +13
-0+} + +static struct dma_async_tx_descriptor *mmp_tdma_prep_dma_cyclic ( +struct dma_chan *chan,dma_addr_t dma_addr,size_t buf_len, +size_t period_len,enum dma_transfer_direction direction, +void *context) +{ +struct mmp_tdma_chan *tdmac =to_mmp_tdma_chan (chan); +int num_periods = buf_len / period_len; +int i =0 , buf =0 ; +int ret; + +if (tdmac->status !=DMA_SUCCESS )
drivers/dma/mmp_tdma.c line 421
Quoted 10 lines
drivers/dma/mmp_tdma.c new file +10
-0+return NULL ; + +if (period_len >TDMA_MAX_XFER_BYTES ) { +dev_err (tdmac->dev, +"maximum period size exceeded: %d > %d\n" , + period_len,TDMA_MAX_XFER_BYTES ); + goto err_out; + } + + tdmac->status =DMA_IN_PROGRESS ;
???
drivers/dma/mmp_tdma.c line 428
Quoted 7 lines
drivers/dma/mmp_tdma.c new file +7
-0+ tdmac->desc_num = num_periods; + ret =mmp_tdma_alloc_descriptor (tdmac); +if (ret <0 ) + goto err_out; + +while (buf < buf_len) { +struct mmp_tdma_desc *desc = &tdmac->desc_arr[i];
what if i call prepare twice on the same channel?
Better way would to manage a descriptor list, see other drivers for examples.
drivers/dma/mmp_tdma.c line 434
Quoted 6 lines
drivers/dma/mmp_tdma.c new file +6
-0+ +if (i +1 == num_periods) + desc->nxt_desc = tdmac->desc_arr_phys; +else + desc->nxt_desc = tdmac->desc_arr_phys + +sizeof (*desc) * (i +1 );
pls use kernel link list, it is provided to you so that you dont have to do above.
Quoted 64 lines
drivers/dma/mmp_tdma.c new file +64
-0+ +if (direction ==DMA_MEM_TO_DEV ) { + desc->src_addr = dma_addr; + desc->dst_addr = tdmac->dev_addr; + }else { + desc->src_addr = tdmac->dev_addr; + desc->dst_addr = dma_addr; + } + desc->byte_cnt = period_len; + dma_addr += period_len; + buf += period_len; + i++; + } + + tdmac->buf_len = buf_len; + tdmac->period_len = period_len; + tdmac->pos =0 ; + +return &tdmac->desc; + +err_out: + tdmac->status =DMA_ERROR ; +return NULL ; +} + +static int mmp_tdma_control (struct dma_chan *chan,enum dma_ctrl_cmd cmd, +unsigned long arg) +{ +struct mmp_tdma_chan *tdmac =to_mmp_tdma_chan (chan); +struct dma_slave_config *dmaengine_cfg = (void *)arg; +int ret =0 ; + +switch (cmd) { +case DMA_TERMINATE_ALL : +mmp_tdma_disable_chan (tdmac); +break ; +case DMA_PAUSE : +mmp_tdma_pause_chan (tdmac); +break ; +case DMA_RESUME : +mmp_tdma_resume_chan (tdmac); +break ; +case DMA_SLAVE_CONFIG : +if (dmaengine_cfg->direction ==DMA_DEV_TO_MEM ) { + tdmac->dev_addr = dmaengine_cfg->src_addr; + tdmac->burst_sz = dmaengine_cfg->src_maxburst; + }else { + tdmac->dev_addr = dmaengine_cfg->dst_addr; + tdmac->burst_sz = dmaengine_cfg->dst_maxburst; + } + tdmac->dir = dmaengine_cfg->direction; +return mmp_tdma_config_chan (tdmac); +default : + ret = -ENOSYS ; + } + +return ret; +} + +static enum dma_status mmp_tdma_tx_status (struct dma_chan *chan, +dma_cookie_t cookie,struct dma_tx_state *txstate) +{ +struct mmp_tdma_chan *tdmac =to_mmp_tdma_chan (chan); +
drivers/dma/mmp_tdma.c line 508
Quoted 10 lines
drivers/dma/mmp_tdma.c new file +10
-0+dma_set_residue (txstate, tdmac->buf_len - tdmac->pos); + +return tdmac->status; +} + +static void mmp_tdma_issue_pending (struct dma_chan *chan) +{ +struct mmp_tdma_chan *tdmac =to_mmp_tdma_chan (chan); + +mmp_tdma_enable_chan (tdmac);
can you queue the descriptors here? That was purpose to have separate issue pending and submit.
Quoted 131 lines
drivers/dma/mmp_tdma.c new file +131
-0+} + +static int __devexit mmp_tdma_remove(struct platform_device *pdev) +{ +struct mmp_tdma_device *tdev =platform_get_drvdata (pdev); + +dma_async_device_unregister (&tdev->device); +return 0 ; +} + +static int __devinit mmp_tdma_chan_init (struct mmp_tdma_device *tdev, +int idx,int irq,int type) +{ +struct mmp_tdma_chan *tdmac; + +if (idx >=TDMA_CHANNEL_NUM ) { +dev_err (tdev->dev,"too many channels for device!\n" ); +return -EINVAL ; + } + +/* alloc channel */ + tdmac =devm_kzalloc (tdev->dev,sizeof (*tdmac),GFP_KERNEL ); +if (!tdmac) { +dev_err (tdev->dev,"no free memory for DMA channels!\n" ); +return -ENOMEM ; + } +if (irq) + tdmac->irq = irq + idx; + tdmac->dev = tdev->dev; + tdmac->chan.device = &tdev->device; + tdmac->idx = idx; + tdmac->type = type; + tdmac->reg_base = (unsigned long )tdev->base + idx *4 ; + tdmac->status =DMA_SUCCESS ; + tdev->tdmac[tdmac->idx] = tdmac; +tasklet_init (&tdmac->tasklet, dma_do_tasklet, (unsigned long )tdmac); + +/* add the channel to tdma_chan list */ +list_add_tail (&tdmac->chan.device_node, + &tdev->device.channels); + +return 0 ; +} + +static int __devinit mmp_tdma_probe (struct platform_device *pdev) +{ +const struct platform_device_id *id =platform_get_device_id (pdev); +enum mmp_tdma_type type = id->driver_data; +struct mmp_tdma_device *tdev; +struct resource *iores; +int i, ret; +int irq =0 ; +int chan_num =TDMA_CHANNEL_NUM ; + +/* always have couple channels */ + tdev =devm_kzalloc (&pdev->dev,sizeof (*tdev),GFP_KERNEL ); +if (!tdev) +return -ENOMEM ; + + tdev->dev = &pdev->dev; + iores =platform_get_resource (pdev,IORESOURCE_IRQ ,0 ); +if (!iores) +return -EINVAL ; + +if (resource_size (iores) != chan_num) + tdev->irq = iores->start; +else + irq = iores->start; + + iores =platform_get_resource (pdev,IORESOURCE_MEM ,0 ); +if (!iores) +return -EINVAL ; + + tdev->base =devm_request_and_ioremap (&pdev->dev, iores); +if (!tdev->base) +return -EADDRNOTAVAIL ; + +if (tdev->irq) { + ret =devm_request_irq (&pdev->dev, tdev->irq, + mmp_tdma_int_handler,IRQF_DISABLED ,"tdma" , tdev); +if (ret) +return ret; + } + +dma_cap_set (DMA_SLAVE , tdev->device.cap_mask); +dma_cap_set (DMA_CYCLIC , tdev->device.cap_mask); + +INIT_LIST_HEAD (&tdev->device.channels); + +/* initialize channel parameters */ +for (i =0 ; i < chan_num; i++) { + ret =mmp_tdma_chan_init (tdev, i, irq, type); +if (ret) +return ret; + } + + tdev->device.dev = &pdev->dev; + tdev->device.device_alloc_chan_resources = + mmp_tdma_alloc_chan_resources; + tdev->device.device_free_chan_resources = + mmp_tdma_free_chan_resources; + tdev->device.device_prep_slave_sg = mmp_tdma_prep_slave_sg; + tdev->device.device_prep_dma_cyclic = mmp_tdma_prep_dma_cyclic; + tdev->device.device_tx_status = mmp_tdma_tx_status; + tdev->device.device_issue_pending = mmp_tdma_issue_pending; + tdev->device.device_control = mmp_tdma_control; + tdev->device.copy_align =TDMA_ALIGNMENT ; + +dma_set_mask (&pdev->dev,DMA_BIT_MASK (64 )); +platform_set_drvdata (pdev, tdev); + + ret =dma_async_device_register (&tdev->device); +if (ret) { +dev_err (tdev->device.dev,"unable to register\n" ); +return ret; + } + +dev_info (tdev->device.dev,"initialized\n" ); +return 0 ; +} + +static const struct platform_device_id mmp_tdma_id_table[] = { + {"mmp-adma" ,MMP_AUD_TDMA }, + {"pxa910-squ" ,PXA910_SQU }, + { }, +}; + +static struct platform_driver mmp_tdma_driver = { + .driver = { + .name ="mmp-tdma" , + .owner =THIS_MODULE ,
drivers/dma/mmp_tdma.c line 649
Quoted 10 lines
drivers/dma/mmp_tdma.c new file +10
-0+ }, + .id_table = mmp_tdma_id_table, + .probe = mmp_tdma_probe, + .remove = __devexit_p(mmp_tdma_remove), +}; + +module_platform_driver (mmp_tdma_driver); + +MODULE_DESCRIPTION ("MMP Two-Channel DMA Driver" ); +MODULE_LICENSE ("GPL" );
AUTHOR, ALIAS too pls
Quoted 16 lines
include/linux/platform_data/mmp_dma.h new file +10
-0@@ -0,0 +1,20 @@ +/* +* MMP Platform DMA Management +* +* Copyright (c) 2011 Marvell Semiconductors Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +*/
include/linux/platform_data/mmp_dma.h line 20
Quoted 10 lines
include/linux/platform_data/mmp_dma.h new file +10
-0+ +#ifndef MMP_DMA_H +#define MMP_DMA_H + +struct mmp_tdma_data { +u32 bus_size; +u32 pack_mod; +}; + +#endif /* MMP_DMA_H */
why do you need separate header for this?
Signature · 1 line
~Vinod
Re: [PATCH v1 1/5] dmaengine: mmp_tdma: add mmp tdma support
Quoted 9 lines · Vinod Koul
Quoted 6 lines · Zhangfei Gao
Add support for two-channel dma under dmaengine
support: mmp-adma and pxa910-squSigned-off-by Zhangfei Gao <[email protected]>Signed-off-by Leo Yan <[email protected]>Signed-off-by Qiao Zhou <[email protected]>
Quoted 12 lines
Review
Quoted 11 lines
(quoted diff) +11
-0+ +static int mmp_tdma_clear_chan_irq(struct mmp_tdma_chan *tdmac) +{ + ? ? u32 reg = readl(tdmac->reg_base + TDISR); + + ? ? if (reg & TDISR_COMP) { + ? ? ? ? ? ? /* clear irq */ + ? ? ? ? ? ? reg &= ~TDISR_COMP; + ? ? ? ? ? ? writel(reg, tdmac->reg_base + TDISR); + + ? ? ? ? ? ? return 1;hrmm.?
This is local function used to check whether this channel has irq then return 1. Used by chan_handler.
Quoted 58 lines
Quoted 58 lines
+ ? ? }
+ ? ? return 0;(quoted diff) +56
-0+} + +static irqreturn_t mmp_tdma_chan_handler(int irq, void *dev_id) +{ + ? ? struct mmp_tdma_chan *tdmac = dev_id; + + ? ? if (mmp_tdma_clear_chan_irq(tdmac)) { + ? ? ? ? ? ? tdmac->pos = (tdmac->pos + tdmac->period_len) % tdmac->buf_len; + ? ? ? ? ? ? tasklet_schedule(&tdmac->tasklet); + ? ? ? ? ? ? return IRQ_HANDLED; + ? ? } else + ? ? ? ? ? ? return IRQ_NONE; +} + +static irqreturn_t mmp_tdma_int_handler(int irq, void *dev_id) +{ + ? ? struct mmp_tdma_device *tdev = dev_id; + ? ? int i, ret; + ? ? int irq_num = 0; + + ? ? for (i = 0; i < TDMA_CHANNEL_NUM; i++) { + ? ? ? ? ? ? struct mmp_tdma_chan *tdmac = tdev->tdmac[i]; + + ? ? ? ? ? ? ret = mmp_tdma_chan_handler(irq, tdmac); + ? ? ? ? ? ? if (ret == IRQ_HANDLED) + ? ? ? ? ? ? ? ? ? ? irq_num++; + ? ? } + + ? ? if (irq_num) + ? ? ? ? ? ? return IRQ_HANDLED; + ? ? else + ? ? ? ? ? ? return IRQ_NONE; +} + +static void dma_do_tasklet(unsigned long data) +{ + ? ? struct mmp_tdma_chan *tdmac = (struct mmp_tdma_chan *)data; + + ? ? if (tdmac->desc.callback) + ? ? ? ? ? ? tdmac->desc.callback(tdmac->desc.callback_param); + +} + +static void mmp_tdma_free_descriptor(struct mmp_tdma_chan *tdmac) +{ + ? ? struct gen_pool *gpool; + ? ? int size = tdmac->desc_num * sizeof(struct mmp_tdma_desc); + + ? ? gpool = sram_get_gpool("asram"); + ? ? if (tdmac->desc_arr) + ? ? ? ? ? ? gen_pool_free(gpool, (unsigned long)tdmac->desc_arr, + ? ? ? ? ? ? ? ? ? ? ? ? ? ? size); + ? ? tdmac->desc_arr = NULL; + + ? ? return; +}
Quoted 8 lines
drivers/dma/mmp_tdma.c
Quoted 6 lines
drivers/dma/mmp_tdma.c new file +6
-0+ +static dma_cookie_t mmp_tdma_tx_submit (struct dma_async_tx_descriptor *tx) +{ + ? ? struct mmp_tdma_chan *tdmac = to_mmp_tdma_chan(tx->chan); + + ? ? mmp_tdma_chan_set_desc(tdmac, tdmac->desc_arr_phys);This seems odd. In submit you are supposed to move this to your pending list. Btw where is the .issue_pending handler?
The driver is specifically for audio.
So we make it simple, only support cylic method and no pending list at all. Only support sync mode.tx_submit will directly write dma address with single descriptor chain. .issue_pending will directly start the dma.
When dma started, it will keep process data from/to user.
Quoted 15 lines
Quoted 15 lines
drivers/dma/mmp_tdma.c new file +15
-0+ + ? ? return 0; +} + +static int mmp_tdma_alloc_chan_resources (struct dma_chan *chan) +{ + ? ? struct mmp_tdma_chan *tdmac = to_mmp_tdma_chan(chan); + ? ? int ret; + + ? ? dev_dbg(tdmac->dev, "%s: enter\n", __func__); + + ? ? dma_async_tx_descriptor_init(&tdmac->desc, chan); + ? ? tdmac->desc.tx_submit = mmp_tdma_tx_submit; + + ? ? if (tdmac->irq) {
Quoted 8 lines
Quoted 7 lines
+ ? ? ? ? ? ? ret = devm_request_irq(tdmac->dev,
tdmac->irq,
+ ? ? ? ? ? ? ? ? ? ?mmp_tdma_chan_handler,IRQF_DISABLED, "tdma", tdmac);
+ ? ? ? ? ? ? if (ret)
+ ? ? ? ? ? ? ? ? ? ? gotoerr_request_irq;
+ ? ? }
+
+ ? ? return 0;NO. This is supposed to return the number of descriptors allocated.
Thanks for remainder.
Quoted 10 lines
Review
Quoted 9 lines
(quoted diff) +9
-0+static void mmp_tdma_free_chan_resources(struct dma_chan *chan) +{ + ? ? struct mmp_tdma_chan *tdmac = to_mmp_tdma_chan(chan); + + ? ? dev_dbg(tdmac->dev, "%s: enter\n", __func__); + + ? ? if (tdmac->irq) + ? ? ? ? ? ? devm_free_irq(tdmac->dev, tdmac->irq, tdmac); + ? ? mmp_tdma_disable_chan(tdmac);channel should be already disabled, why do you need this here?
Is there case directly call dma_put_channel without DMA_TERMINATE_ALL?
Quoted 11 lines
Quoted 11 lines
+ ? ?
mmp_tdma_free_descriptor(tdmac);
+ ? ? return;drivers/dma/mmp_tdma.c new file +9
-0+} + + +static struct dma_async_tx_descriptor *mmp_tdma_prep_slave_sg ( + ? ? ? ? ? ? struct dma_chan *chan, struct scatterlist *sgl, + ? ? ? ? ? ? unsigned int sg_len, enum dma_transfer_direction direction, + ? ? ? ? ? ? unsigned long flags, void *context) +{ + ? ? /*
Quoted 8 lines
Quoted 7 lines
+ ? ? ?* This operation is not supported on the TDMA controller
+ ? ? ?*
+ ? ? ?* However, we need to provide the function pointer to allow the
+ ? ? ?*device_control()method to work.
+ ? ? ?*/
+ ? ? return NULL;
+}Pls remove if not supported
Got it, my mistake,
confused by
BUG_ON(dma_has_cap(DMA_SLAVE, device->cap_mask) &&
!device->device_control);
Quoted 13 lines
Quoted 13 lines
(quoted diff) +13
-0+ +static int mmp_tdma_alloc_descriptor(struct mmp_tdma_chan *tdmac) +{ + ? ? struct gen_pool *gpool; + ? ? int size = tdmac->desc_num * sizeof(struct mmp_tdma_desc); + + ? ? dev_dbg(tdmac->dev, "%s: enter\n", __func__); + + ? ? gpool = sram_get_gpool("asram"); + ? ? if (!gpool) + ? ? ? ? ? ? return -ENOMEM; + + ? ? tdmac->desc_arr = (void *)gen_pool_alloc(gpool, size);
Quoted 8 lines
Review
Quoted 7 lines
+ ? ? if (!tdmac->desc_arr)
+ ? ? ? ? ? ? return-ENOMEM;(quoted diff) +5
-0+ + ? ? tdmac->desc_arr_phys = gen_pool_virt_to_phys(gpool, + ? ? ? ? ? ? ? ? ? ? (unsigned long)tdmac->desc_arr); + + ? ? return 0;this needs fix
Could you give more hints?
Quoted 24 lines
Quoted 13 lines
(quoted diff) +13
-0+} + +static struct dma_async_tx_descriptor *mmp_tdma_prep_dma_cyclic( + ? ? ? ? ? ? struct dma_chan *chan, dma_addr_t dma_addr, size_t buf_len, + ? ? ? ? ? ? size_t period_len, enum dma_transfer_direction direction, + ? ? ? ? ? ? void *context) +{ + ? ? struct mmp_tdma_chan *tdmac = to_mmp_tdma_chan(chan); + ? ? int num_periods = buf_len / period_len; + ? ? int i = 0, buf = 0; + ? ? int ret; + + ? ? if (tdmac->status != DMA_SUCCESS)Review
Quoted 10 lines
(quoted diff) +10
-0+ ? ? ? ? ? ? return NULL; + + ? ? if (period_len > TDMA_MAX_XFER_BYTES) { + ? ? ? ? ? ? dev_err(tdmac->dev, + ? ? ? ? ? ? ? ? ? ? ? ? ? ? "maximum period size exceeded: %d > %d\n", + ? ? ? ? ? ? ? ? ? ? ? ? ? ? period_len, TDMA_MAX_XFER_BYTES); + ? ? ? ? ? ? goto err_out; + ? ? } + + ? ? tdmac->status = DMA_IN_PROGRESS;???
Quoted 8 lines
Quoted 7 lines
+ ? ?
tdmac->desc_num=num_periods;
+ ? ? ret =mmp_tdma_alloc_descriptor(tdmac);
+ ? ? if (ret < 0)
+ ? ? ? ? ? ? gotoerr_out;
+
+ ? ? while (buf <buf_len) {
+ ? ? ? ? ? ? structmmp_tdma_desc*desc = &tdmac->desc_arr[i];what if i call prepare twice on the same channel?
We use tdmac->status to prevent calling again during transfering except the resource is freed.
Usually once cyclic dma is build, only data comming and out, without rebuild dma chain.
Here dma chain is simple, does not support asyn mode.
Quoted 10 lines
Better way would to manage a descriptor list, see other drivers for examples.
Quoted 6 lines
+
+ ? ? ? ? ? ? if (i + 1 ==num_periods)
+ ? ? ? ? ? ? ? ? ? ?desc->nxt_desc=tdmac->desc_arr_phys;
+ ? ? ? ? ? ? else
+ ? ? ? ? ? ? ? ? ? ?desc->nxt_desc=tdmac->desc_arr_phys+
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ?sizeof(*desc)* (i + 1);pls use kernel link list, it is provided to you so that you dont have to do above.
We have limitation for hardware.
SRAM has to be used for both dma buffer and dma descriptor. While SRAM is very very limited on some platform, as a result link node may not able to be allocated. So we simply organize descriptor physically one by one.
Quoted 8 lines
drivers/dma/mmp_tdma.c
Quoted 6 lines
drivers/dma/mmp_tdma.c new file +6
-0+ +static void mmp_tdma_issue_pending (struct dma_chan *chan) +{ + ? ? struct mmp_tdma_chan *tdmac = to_mmp_tdma_chan(chan); + + ? ? mmp_tdma_enable_chan(tdmac);can you queue the descriptors here? That was purpose to have separate issue pending and submit.
Since the SRAM is limited, I am afraid it can not allocate memory for queue. And to make it simple, we just arrange descriptor one by one.
Quoted 6 lines
drivers/dma/mmp_tdma.c line 649
Quoted 5 lines
drivers/dma/mmp_tdma.c new file +5
-0+ +module_platform_driver (mmp_tdma_driver); + +MODULE_DESCRIPTION ("MMP Two-Channel DMA Driver" ); +MODULE_LICENSE ("GPL" );AUTHOR, ALIAS too pls
Thanks, got it.
Quoted 20 lines
Quoted 20 lines
include/linux/platform_data/mmp_dma.h new file +13
-0@@ -0,0 +1,20 @@ +/* +* ?MMP Platform DMA Management +* +* ?Copyright (c) 2011 Marvell Semiconductors Inc. +* +* ?This program is free software; you can redistribute it and/or modify +* ?it under the terms of the GNU General Public License version 2 as +* ?published by the Free Software Foundation. +* +*/ + +#ifndef MMP_DMA_H +#define MMP_DMA_H
Quoted 8 lines
include/linux/platform_data/mmp_dma.h line 20
Quoted 7 lines
include/linux/platform_data/mmp_dma.h new file +7
-0+ +struct mmp_tdma_data { + ? ? u32 bus_size; + ? ? u32 pack_mod; +}; + +#endif /* MMP_DMA_H */ why do you need separate header for this?
The structure is sharing private config between dma driver and pcm driver under sound.
The header file will be expanded for other dma driver.
Quoted 5 lines
--
~Vinod
Re: [PATCH v1 1/5] dmaengine: mmp_tdma: add mmp tdma support
Quoted 11 lines · zhangfei gao
Quoted 11 lines
drivers/dma/mmp_tdma.c line 259
Quoted 10 lines
drivers/dma/mmp_tdma.c new file +10
-0+static int mmp_tdma_clear_chan_irq (struct mmp_tdma_chan *tdmac) +{ +u32 reg =readl (tdmac->reg_base +TDISR ); + +if (reg &TDISR_COMP ) { +/* clear irq */ + reg &= ~TDISR_COMP ; +writel (reg, tdmac->reg_base +TDISR ); + +return 1 ;hrmm.?
Quoted 2 lines
This is local function used to check whether this channel has irq then return 1. Used by
chan_handler.
quite linux unlike.
Quoted 9 lines
Quoted 8 lines
drivers/dma/mmp_tdma.c line 323
Quoted 6 lines
drivers/dma/mmp_tdma.c new file +6
-0+ +static dma_cookie_t mmp_tdma_tx_submit (struct dma_async_tx_descriptor *tx) +{ +struct mmp_tdma_chan *tdmac =to_mmp_tdma_chan (tx->chan); + +mmp_tdma_chan_set_desc (tdmac, tdmac->desc_arr_phys);This seems odd. In submit you are supposed to move this to your pending list. Btw where is the .issue_pending handler?
Quoted 6 lines
The driver is specifically for audio.
So we make it simple, only support cylic method and no pending list at all. Only support sync mode.tx_submitwill directly write dma address with single descriptor chain. .issue_pending will directly start the dma.
When dma started, it will keep process data from/to user.
But then you are putting unnecessary limitation on its use. Limiation should be based on h/w caps
Quoted 38 lines
Quoted 16 lines
Quoted 16 lines
drivers/dma/mmp_tdma.c new file +15
-0+ +return 0 ; +} + +static int mmp_tdma_alloc_chan_resources (struct dma_chan *chan) +{ +struct mmp_tdma_chan *tdmac =to_mmp_tdma_chan (chan); +int ret; + +dev_dbg (tdmac->dev,"%s: enter\n" , __func__); + +dma_async_tx_descriptor_init (&tdmac->desc, chan); + tdmac->desc.tx_submit = mmp_tdma_tx_submit; + +if (tdmac->irq) {Quoted 8 lines
drivers/dma/mmp_tdma.c line 345
Quoted 7 lines
drivers/dma/mmp_tdma.c new file +7
-0+ ret =devm_request_irq (tdmac->dev, tdmac->irq, + mmp_tdma_chan_handler,IRQF_DISABLED ,"tdma" , tdmac); +if (ret) + goto err_request_irq; + } + +return 0 ;NO. This is supposed to return the number of descriptors allocated.
Thanks for remainder.
Quoted 10 lines
drivers/dma/mmp_tdma.c line 360
Quoted 9 lines
drivers/dma/mmp_tdma.c new file +9
-0+static void mmp_tdma_free_chan_resources (struct dma_chan *chan) +{ +struct mmp_tdma_chan *tdmac =to_mmp_tdma_chan (chan); + +dev_dbg (tdmac->dev,"%s: enter\n" , __func__); + +if (tdmac->irq) +devm_free_irq (tdmac->dev, tdmac->irq, tdmac); +mmp_tdma_disable_chan (tdmac);channel should be already disabled, why do you need this here?
Quoted 1 line
Is there case directly call
dma_put_channelwithoutDMA_TERMINATE_ALL?
in cyclic no, otherwise yes.
Quoted 47 lines
Quoted 12 lines
Quoted 12 lines
drivers/dma/mmp_tdma.c new file +11
-0+mmp_tdma_free_descriptor (tdmac); +return ; +} + + +static struct dma_async_tx_descriptor *mmp_tdma_prep_slave_sg ( +struct dma_chan *chan,struct scatterlist *sgl, +unsigned int sg_len,enum dma_transfer_direction direction, +unsigned long flags,void *context) +{ +/* Quoted 8 lines
drivers/dma/mmp_tdma.c line 378
Quoted 7 lines
drivers/dma/mmp_tdma.c new file +7
-0+* This operation is not supported on the TDMA controller +* +* However, we need to provide the function pointer to allow the +* device_control() method to work. +*/ +return NULL ; +}Pls remove if not supported
Got it, my mistake,
confused by
BUG_ON(dma_has_cap(DMA_SLAVE,device->cap_mask) &&!device->device_control);Quoted 13 lines
Quoted 13 lines
drivers/dma/mmp_tdma.c new file +13
-0+ +static int mmp_tdma_alloc_descriptor (struct mmp_tdma_chan *tdmac) +{ +struct gen_pool *gpool; +int size = tdmac->desc_num *sizeof (struct mmp_tdma_desc ); + +dev_dbg (tdmac->dev,"%s: enter\n" , __func__); + + gpool =sram_get_gpool ("asram" ); +if (!gpool) +return -ENOMEM ; + + tdmac->desc_arr = (void *)gen_pool_alloc (gpool, size);Quoted 8 lines
drivers/dma/mmp_tdma.c line 398
Quoted 7 lines
drivers/dma/mmp_tdma.c new file +7
-0+if (!tdmac->desc_arr) +return -ENOMEM ; + + tdmac->desc_arr_phys =gen_pool_virt_to_phys (gpool, + (unsigned long )tdmac->desc_arr); + +return 0 ;this needs fix
Quoted 1 line
Could you give more hints?
return the descriptors allocated
Quoted 48 lines
Quoted 25 lines
Quoted 14 lines
drivers/dma/mmp_tdma.c new file +13
-0+} + +static struct dma_async_tx_descriptor *mmp_tdma_prep_dma_cyclic ( +struct dma_chan *chan,dma_addr_t dma_addr,size_t buf_len, +size_t period_len,enum dma_transfer_direction direction, +void *context) +{ +struct mmp_tdma_chan *tdmac =to_mmp_tdma_chan (chan); +int num_periods = buf_len / period_len; +int i =0 , buf =0 ; +int ret; + +if (tdmac->status !=DMA_SUCCESS )drivers/dma/mmp_tdma.c line 421
Quoted 10 lines
drivers/dma/mmp_tdma.c new file +10
-0+return NULL ; + +if (period_len >TDMA_MAX_XFER_BYTES ) { +dev_err (tdmac->dev, +"maximum period size exceeded: %d > %d\n" , + period_len,TDMA_MAX_XFER_BYTES ); + goto err_out; + } + + tdmac->status =DMA_IN_PROGRESS ;???
Quoted 8 lines
drivers/dma/mmp_tdma.c line 428
Quoted 7 lines
drivers/dma/mmp_tdma.c new file +7
-0+ tdmac->desc_num = num_periods; + ret =mmp_tdma_alloc_descriptor (tdmac); +if (ret <0 ) + goto err_out; + +while (buf < buf_len) { +struct mmp_tdma_desc *desc = &tdmac->desc_arr[i];what if i call prepare twice on the same channel?
We use
tdmac->statusto prevent calling again during transfering except the resource is freed.
Usually once cyclic dma is build, only data comming and out, without rebuild dma chain.
Here dma chain is simple, does not support asyn mode.Quoted 8 lines
Better way would to manage a descriptor list, see other drivers for examples.
Quoted 6 lines
drivers/dma/mmp_tdma.c new file +6
-0+ +if (i +1 == num_periods) + desc->nxt_desc = tdmac->desc_arr_phys; +else + desc->nxt_desc = tdmac->desc_arr_phys + +sizeof (*desc) * (i +1 );
Quoted 8 lines
Quoted 2 lines
pls use kernel link list, it is provided to you so that you dont have to do above.
We have limitation for hardware.
SRAM has to be used for both dma buffer and dma descriptor. While SRAM is very very limited on some platform, as a result link node may not able to be allocated. So we simply organize descriptor physically one by one.
You can embed your h/w descriptor in your list structure, managing them becomes easy.
Quoted 52 lines
Quoted 10 lines
drivers/dma/mmp_tdma.c line 508
Quoted 8 lines
drivers/dma/mmp_tdma.c new file +6
-0+ +static void mmp_tdma_issue_pending (struct dma_chan *chan) +{ +struct mmp_tdma_chan *tdmac =to_mmp_tdma_chan (chan); + +mmp_tdma_enable_chan (tdmac);can you queue the descriptors here? That was purpose to have separate issue pending and submit.
Since the SRAM is limited, I am afraid it can not allocate memory for queue. And to make it simple, we just arrange descriptor one by one.
Quoted 6 lines
drivers/dma/mmp_tdma.c line 649
Quoted 5 lines
drivers/dma/mmp_tdma.c new file +5
-0+ +module_platform_driver (mmp_tdma_driver); + +MODULE_DESCRIPTION ("MMP Two-Channel DMA Driver" ); +MODULE_LICENSE ("GPL" );AUTHOR, ALIAS too pls
Thanks, got it.
Quoted 20 lines
Quoted 20 lines
include/linux/platform_data/mmp_dma.h new file +13
-0@@ -0,0 +1,20 @@ +/* +* MMP Platform DMA Management +* +* Copyright (c) 2011 Marvell Semiconductors Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +*/ + +#ifndef MMP_DMA_H +#define MMP_DMA_H Quoted 8 lines
include/linux/platform_data/mmp_dma.h line 20
Quoted 7 lines
include/linux/platform_data/mmp_dma.h new file +7
-0+ +struct mmp_tdma_data { +u32 bus_size; +u32 pack_mod; +}; + +#endif /* MMP_DMA_H */ why do you need separate header for this?
Quoted 3 lines
The structure is sharing private config between dma driver and pcm driver under sound.
The header file will be expanded for other dma driver.
Other?
Signature · 1 line
~Vinod
Re: [PATCH v1 1/5] dmaengine: mmp_tdma: add mmp tdma support
Quoted 173 lines · Vinod Koul
Quoted 11 lines · zhangfei gao
Quoted 11 lines
drivers/dma/mmp_tdma.c line 259
Quoted 10 lines
drivers/dma/mmp_tdma.c new file +10
-0+static int mmp_tdma_clear_chan_irq (struct mmp_tdma_chan *tdmac) +{ + u32 reg = readl(tdmac->reg_base + TDISR); + + if (reg & TDISR_COMP) { + /* clear irq */ + reg &= ~TDISR_COMP; + writel(reg, tdmac->reg_base + TDISR); + + return 1;hrmm.?
Quoted 2 lines
This is local function used to check whether this channel has irq then return 1. Used by
chan_handler.quite linux unlike.
Quoted 9 lines
Quoted 8 lines
drivers/dma/mmp_tdma.c line 323
Quoted 6 lines
drivers/dma/mmp_tdma.c new file +6
-0+ +static dma_cookie_t mmp_tdma_tx_submit (struct dma_async_tx_descriptor *tx) +{ + struct mmp_tdma_chan *tdmac = to_mmp_tdma_chan(tx->chan); + + mmp_tdma_chan_set_desc(tdmac, tdmac->desc_arr_phys);This seems odd. In submit you are supposed to move this to your pending list. Btw where is the .issue_pending handler?
Quoted 6 lines
The driver is specifically for audio.
So we make it simple, only support cylic method and no pending list at all. Only support sync mode.tx_submitwill directly write dma address with single descriptor chain. .issue_pending will directly start the dma.
When dma started, it will keep process data from/to user.But then you are putting unnecessary limitation on its use. Limiation should be based on h/w caps
Quoted 38 lines
Quoted 16 lines
Quoted 16 lines
drivers/dma/mmp_tdma.c new file +15
-0+ + return 0; +} + +static int mmp_tdma_alloc_chan_resources (struct dma_chan *chan) +{ + struct mmp_tdma_chan *tdmac = to_mmp_tdma_chan(chan); + int ret; + + dev_dbg(tdmac->dev, "%s: enter\n", __func__); + + dma_async_tx_descriptor_init(&tdmac->desc, chan); + tdmac->desc.tx_submit = mmp_tdma_tx_submit; + + if (tdmac->irq) {Quoted 8 lines
Quoted 7 lines
+ ret = devm_request_irq(tdmac->dev,
tdmac->irq,
+mmp_tdma_chan_handler,IRQF_DISABLED, "tdma", tdmac);
+ if (ret)
+ gotoerr_request_irq;
+ }
+
+ return 0;NO. This is supposed to return the number of descriptors allocated.
Thanks for remainder.
Quoted 10 lines
drivers/dma/mmp_tdma.c line 360
Quoted 9 lines
drivers/dma/mmp_tdma.c new file +9
-0+static void mmp_tdma_free_chan_resources (struct dma_chan *chan) +{ + struct mmp_tdma_chan *tdmac = to_mmp_tdma_chan(chan); + + dev_dbg(tdmac->dev, "%s: enter\n", __func__); + + if (tdmac->irq) + devm_free_irq(tdmac->dev, tdmac->irq, tdmac); + mmp_tdma_disable_chan(tdmac);channel should be already disabled, why do you need this here?
Quoted 1 line
Is there case directly call
dma_put_channelwithoutDMA_TERMINATE_ALL?in cyclic no, otherwise yes.
Quoted 47 lines
Quoted 12 lines
Quoted 12 lines
+
mmp_tdma_free_descriptor(tdmac);
+ return;drivers/dma/mmp_tdma.c new file +9
-0+} + + +static struct dma_async_tx_descriptor *mmp_tdma_prep_slave_sg ( + struct dma_chan *chan, struct scatterlist *sgl, + unsigned int sg_len, enum dma_transfer_direction direction, + unsigned long flags, void *context) +{ + /*Quoted 8 lines
Quoted 7 lines
+ * This operation is not supported on the TDMA controller
+ *
+ * However, we need to provide the function pointer to allow the
+ *device_control()method to work.
+ */
+ return NULL;
+}Pls remove if not supported
Got it, my mistake,
confused byBUG_ON(dma_has_cap(DMA_SLAVE, device->cap_mask) && !device->device_control);Quoted 13 lines
Quoted 13 lines
drivers/dma/mmp_tdma.c new file +13
-0+ +static int mmp_tdma_alloc_descriptor (struct mmp_tdma_chan *tdmac) +{ + struct gen_pool *gpool; + int size = tdmac->desc_num * sizeof(struct mmp_tdma_desc); + + dev_dbg(tdmac->dev, "%s: enter\n", __func__); + + gpool = sram_get_gpool("asram"); + if (!gpool) + return -ENOMEM; + + tdmac->desc_arr = (void *)gen_pool_alloc(gpool, size);Quoted 8 lines
drivers/dma/mmp_tdma.c line 398
Quoted 7 lines
+ if (!tdmac->desc_arr)
+ return-ENOMEM;drivers/dma/mmp_tdma.c new file +5
-0+ + tdmac->desc_arr_phys = gen_pool_virt_to_phys(gpool, + (unsigned long)tdmac->desc_arr); + + return 0;this needs fix
Quoted 1 line
Could you give more hints?
return the descriptors allocated
Quoted 51 lines
Quoted 25 lines
Quoted 14 lines
drivers/dma/mmp_tdma.c new file +13
-0+} + +static struct dma_async_tx_descriptor *mmp_tdma_prep_dma_cyclic ( + struct dma_chan *chan, dma_addr_t dma_addr, size_t buf_len, + size_t period_len, enum dma_transfer_direction direction, + void *context) +{ + struct mmp_tdma_chan *tdmac = to_mmp_tdma_chan(chan); + int num_periods = buf_len / period_len; + int i = 0, buf = 0; + int ret; + + if (tdmac->status != DMA_SUCCESS)drivers/dma/mmp_tdma.c line 421
Quoted 10 lines
drivers/dma/mmp_tdma.c new file +10
-0+ return NULL; + + if (period_len > TDMA_MAX_XFER_BYTES) { + dev_err(tdmac->dev, + "maximum period size exceeded: %d > %d\n", + period_len, TDMA_MAX_XFER_BYTES); + goto err_out; + } + + tdmac->status = DMA_IN_PROGRESS;???
Quoted 8 lines
Quoted 7 lines
+
tdmac->desc_num=num_periods;
+ ret =mmp_tdma_alloc_descriptor(tdmac);
+ if (ret < 0)
+ gotoerr_out;
+
+ while (buf <buf_len) {
+ structmmp_tdma_desc*desc = &tdmac->desc_arr[i];what if i call prepare twice on the same channel?
We use tdmac->status to prevent calling again during transfering except the resource is freed.
Usually once cyclic dma is build, only data comming and out, without rebuild dma chain.
Here dma chain is simple, does not support asyn mode.Quoted 10 lines
Better way would to manage a descriptor list, see other drivers for examples.
Quoted 6 lines
+
+ if (i + 1 ==num_periods)
+desc->nxt_desc=tdmac->desc_arr_phys;
+ else
+desc->nxt_desc=tdmac->desc_arr_phys+
+sizeof(*desc)* (i + 1);pls use kernel link list, it is provided to you so that you dont have to do above.
Quoted 7 lines
Quoted 5 lines
We have limitation for hardware.
SRAM has to be used for both dma buffer and dma descriptor. While SRAM is very very limited on some platform, as a result link node may not able to be allocated. So we simply organize descriptor physically one by one.You can embed your h/w descriptor in your list structure, managing them becomes easy.
Thanks Vinod.
Our plan is keep this audio dma driver as simple as possible Only support cyclic & sync mode,
And dma descriptor chain only build once, have no chance to re-organize. Then cyclic dma keep running and consuming/generating data.
SRAM have to be used, which is limited, but SRAM can work at low power mode. So maybe it is easier to organize statically.
We still have peripheral dma working on ddr, with different register and free usage.
It support async mode and have to use pending list, etc.
Quoted 60 lines
Quoted 52 lines
Quoted 10 lines
drivers/dma/mmp_tdma.c line 508
Quoted 8 lines
drivers/dma/mmp_tdma.c new file +6
-0+ +static void mmp_tdma_issue_pending (struct dma_chan *chan) +{ + struct mmp_tdma_chan *tdmac = to_mmp_tdma_chan(chan); + + mmp_tdma_enable_chan(tdmac);can you queue the descriptors here? That was purpose to have separate issue pending and submit.
Since the SRAM is limited, I am afraid it can not allocate memory for queue. And to make it simple, we just arrange descriptor one by one.
Quoted 6 lines
drivers/dma/mmp_tdma.c line 649
Quoted 5 lines
drivers/dma/mmp_tdma.c new file +5
-0+ +module_platform_driver (mmp_tdma_driver); + +MODULE_DESCRIPTION ("MMP Two-Channel DMA Driver" ); +MODULE_LICENSE ("GPL" );AUTHOR, ALIAS too pls
Thanks, got it.
Quoted 20 lines
Quoted 20 lines
include/linux/platform_data/mmp_dma.h new file +13
-0@@ -0,0 +1,20 @@ +/* +* MMP Platform DMA Management +* +* Copyright (c) 2011 Marvell Semiconductors Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +*/ + +#ifndef MMP_DMA_H +#define MMP_DMA_H Quoted 8 lines
include/linux/platform_data/mmp_dma.h line 20
Quoted 7 lines
include/linux/platform_data/mmp_dma.h new file +7
-0+ +struct mmp_tdma_data { + u32 bus_size; + u32 pack_mod; +}; + +#endif /* MMP_DMA_H */ why do you need separate header for this?
Quoted 3 lines
The structure is sharing private config between dma driver and pcm driver under sound.
The header file will be expanded for other dma driver.Other?
--
~Vinod
PATCH 2/5 ASoC: mmp: add audio dma support
In reply to Zhangfei Gaommp-pcm handle audio dma based on soc-dmaengine
Support mmp and pxa910
--- include/linux/platform_data/mmp_audio.h | 22 ++ sound/soc/pxa/Kconfig | 9 + sound/soc/pxa/Makefile | 2 + sound/soc/pxa/mmp-pcm.c | 317 +++++++++++++++++++++++++++++++ 4 files changed, 350 insertions(+), 0 deletions(-) create mode 100644 include/linux/platform_data/mmp_audio.h create mode 100644 sound/soc/pxa/mmp-pcm.c
include/linux/platform_data/mmp_audio.h new file +22 -0
@@ -0,0 +1,22 @@ +/* +* MMP Platform AUDIO Management +* +* Copyright (c) 2011 Marvell Semiconductors Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +*/ + +#ifndef MMP_AUDIO_H +#define MMP_AUDIO_H + +struct mmp_audio_platdata { +u32 period_max_capture; +u32 buffer_max_capture; +u32 period_max_playback; +u32 buffer_max_playback; +}; + +#endif /* MMP_AUDIO_H */
sound/soc/pxa/Kconfig +9 -0
@@ -8,6 +8,15 @@ config SND_PXA2XX_SOC the PXA2xx AC97, I2S or SSP interface. You will also need to select the audio interfaces to support below. +config SND_MMP_SOC + bool "Soc Audio for Marvell MMP chips" + depends on ARCH_MMP + select SND_SOC_DMAENGINE_PCM + select SND_ARM + help + Say Y if you want to add support for codecs attached to + the MMP SSPA interface. + config SND_PXA2XX_AC97 tristate select SND_AC97_CODEC
sound/soc/pxa/Makefile +2 -0
@@ -3,11 +3,13 @@ snd-soc-pxa2xx-objs := pxa2xx-pcm.o snd-soc-pxa2xx-ac97-objs := pxa2xx-ac97.o snd-soc-pxa2xx-i2s-objs := pxa2xx-i2s.o snd-soc-pxa-ssp-objs := pxa-ssp.o +snd-soc-mmp-objs := mmp-pcm.o obj-$(CONFIG_SND_PXA2XX_SOC) += snd-soc-pxa2xx.o obj-$(CONFIG_SND_PXA2XX_SOC_AC97) += snd-soc-pxa2xx-ac97.o obj-$(CONFIG_SND_PXA2XX_SOC_I2S) += snd-soc-pxa2xx-i2s.o obj-$(CONFIG_SND_PXA_SOC_SSP) += snd-soc-pxa-ssp.o +obj-$(CONFIG_SND_MMP_SOC) += snd-soc-mmp.o # PXA Machine Support snd-soc-corgi-objs := corgi.o
sound/soc/pxa/mmp-pcm.c new file +317 -0
317 lines not on this page · raw message
Signature · 1 line
1.7.1
Re: [PATCH v1 2/5] ASoC: mmp: add audio dma support
Quoted 2 lines · Zhangfei Gao
mmp-pcm handle audio dma based on soc-dmaengine
Support mmp and pxa910
See soc-dmaengine.c. You sneed to use the library to use dmaengine.
Quoted 402 lines
Signed-off-by Zhangfei Gao <[email protected]>Signed-off-by Leo Yan <[email protected]>Signed-off-by Qiao Zhou <[email protected]>--- include/linux/platform_data/mmp_audio.h | 22 ++ sound/soc/pxa/Kconfig | 9 + sound/soc/pxa/Makefile | 2 + sound/soc/pxa/mmp-pcm.c | 317 +++++++++++++++++++++++++++++++ 4 files changed, 350 insertions(+), 0 deletions(-) create mode 100644 include/linux/platform_data/mmp_audio.h create mode 100644 sound/soc/pxa/mmp-pcm.cinclude/linux/platform_data/mmp_audio.h new file +22
-0@@ -0,0 +1,22 @@ +/* +* MMP Platform AUDIO Management +* +* Copyright (c) 2011 Marvell Semiconductors Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +*/ + +#ifndef MMP_AUDIO_H +#define MMP_AUDIO_H + +struct mmp_audio_platdata { +u32 period_max_capture; +u32 buffer_max_capture; +u32 period_max_playback; +u32 buffer_max_playback; +}; + +#endif /* MMP_AUDIO_H */ sound/soc/pxa/Kconfig +9
-0@@ -8,6 +8,15 @@ config SND_PXA2XX_SOC the PXA2xx AC97, I2S or SSP interface. You will also need to select the audio interfaces to support below. +config SND_MMP_SOC + bool "Soc Audio for Marvell MMP chips" + depends on ARCH_MMP + select SND_SOC_DMAENGINE_PCM + select SND_ARM + help + Say Y if you want to add support for codecs attached to + the MMP SSPA interface. + config SND_PXA2XX_AC97 tristate select SND_AC97_CODECsound/soc/pxa/Makefile +2
-0@@ -3,11 +3,13 @@ snd-soc-pxa2xx-objs := pxa2xx-pcm.o snd-soc-pxa2xx-ac97-objs := pxa2xx-ac97.o snd-soc-pxa2xx-i2s-objs := pxa2xx-i2s.o snd-soc-pxa-ssp-objs := pxa-ssp.o +snd-soc-mmp-objs := mmp-pcm.o obj-$(CONFIG_SND_PXA2XX_SOC) += snd-soc-pxa2xx.o obj-$(CONFIG_SND_PXA2XX_SOC_AC97) += snd-soc-pxa2xx-ac97.o obj-$(CONFIG_SND_PXA2XX_SOC_I2S) += snd-soc-pxa2xx-i2s.o obj-$(CONFIG_SND_PXA_SOC_SSP) += snd-soc-pxa-ssp.o +obj-$(CONFIG_SND_MMP_SOC) += snd-soc-mmp.o # PXA Machine Support snd-soc-corgi-objs := corgi.osound/soc/pxa/mmp-pcm.c new file +317
-0@@ -0,0 +1,317 @@ +/* +* linux/sound/soc/pxa/mmp-pcm.c +* +* Copyright (C) 2011 Marvell International Ltd. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +*/ +#include <linux/module.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/slab.h> +#include <linux/dma-mapping.h> +#include <linux/dmaengine.h> +#include <linux/platform_data/mmp_dma.h> +#include <linux/platform_data/mmp_audio.h> +#include <sound/pxa2xx-lib.h> +#include <sound/core.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/soc.h> +#include <mach/sram.h> +#include <sound/dmaengine_pcm.h> + +struct mmp_dma_data { +int ssp_id; +struct resource *dma_res; +struct mmp_tdma_data tdma_data; +}; + +#define MMP_PCM_INFO (SNDRV_PCM_INFO_MMAP | \ + SNDRV_PCM_INFO_MMAP_VALID | \ + SNDRV_PCM_INFO_INTERLEAVED | \ + SNDRV_PCM_INFO_PAUSE | \ + SNDRV_PCM_INFO_RESUME) + +#define MMP_PCM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S24_LE | \ + SNDRV_PCM_FMTBIT_S32_LE) + +static struct snd_pcm_hardware mmp_pcm_hardware[] = { + { + .info =MMP_PCM_INFO , + .formats =MMP_PCM_FORMATS , + .period_bytes_min =1024 , + .period_bytes_max =2048 , + .periods_min =2 , + .periods_max =32 , + .buffer_bytes_max =4096 , + .fifo_size =32 , + }, + { + .info =MMP_PCM_INFO , + .formats =MMP_PCM_FORMATS , + .period_bytes_min =1024 , + .period_bytes_max =2048 , + .periods_min =2 , + .periods_max =32 , + .buffer_bytes_max =4096 , + .fifo_size =32 , + }, +}; + +static int mmp_pcm_hw_params (struct snd_pcm_substream *substream, +struct snd_pcm_hw_params *params) +{ +struct mmp_dma_data *dma_data =snd_dmaengine_pcm_get_data (substream); +struct dma_chan *chan =snd_dmaengine_pcm_get_chan (substream); +struct snd_soc_pcm_runtime *rtd = substream->private_data; +struct pxa2xx_pcm_dma_params *dma_params; +int ret; +struct dma_slave_config slave_config; + + dma_params =snd_soc_dai_get_dma_data (rtd->cpu_dai, substream); +if (!dma_params) +return 0 ; + +switch (params_format (params)) { +case SNDRV_PCM_FORMAT_S8 : + dma_data->tdma_data.bus_size =8 ; +break ; +case SNDRV_PCM_FORMAT_S16_LE : + dma_data->tdma_data.bus_size =16 ; +break ; +case SNDRV_PCM_FORMAT_S24_LE : + dma_data->tdma_data.bus_size =24 ; +break ; +case SNDRV_PCM_FORMAT_S32_LE : + dma_data->tdma_data.bus_size =32 ; +break ; +default : +return -EINVAL ; + } + dma_data->tdma_data.pack_mod = true; + +if (substream->stream ==SNDRV_PCM_STREAM_PLAYBACK ) { + slave_config.direction =DMA_TO_DEVICE ; + slave_config.dst_addr = dma_params->dev_addr; + slave_config.dst_maxburst =4 ; + }else { + slave_config.direction =DMA_FROM_DEVICE ; + slave_config.src_addr = dma_params->dev_addr; + slave_config.src_maxburst =4 ; + } + + ret =dmaengine_slave_config (chan, &slave_config); +if (ret) +return ret; + +snd_pcm_set_runtime_buffer (substream, &substream->dma_buffer); + +return 0 ; +} + +static bool filter (struct dma_chan *chan,void *param) +{ +struct mmp_dma_data *dma_data = param; +bool found = false; +char *devname; + + devname =kasprintf (GFP_KERNEL ,"%s.%d" , dma_data->dma_res->name, + dma_data->ssp_id); +if ((strcmp (dev_name (chan->device->dev), devname) ==0 ) && + (chan->chan_id == dma_data->dma_res->start)) { + chan->private = &dma_data->tdma_data; + found = true; + } + +kfree (devname); +return found; +} + +static int mmp_pcm_open (struct snd_pcm_substream *substream) +{ +struct snd_soc_pcm_runtime *rtd = substream->private_data; +struct platform_device *pdev =to_platform_device (rtd->platform->dev); +struct snd_soc_dai *cpu_dai = rtd->cpu_dai; +struct mmp_dma_data *dma_data; +struct resource *r; +int ret; + + r =platform_get_resource (pdev,IORESOURCE_DMA , substream->stream); +if (!r) +return -EBUSY ; + +snd_soc_set_runtime_hwparams (substream, + &mmp_pcm_hardware[substream->stream]); + dma_data =devm_kzalloc (&pdev->dev, +sizeof (struct mmp_dma_data ),GFP_KERNEL ); +if (dma_data ==NULL ) +return -ENOMEM ; + + dma_data->dma_res = r; + dma_data->ssp_id = cpu_dai->id; + + ret =snd_dmaengine_pcm_open (substream, filter, dma_data); +if (ret) { +devm_kfree (&pdev->dev, dma_data); +return ret; + } + +snd_dmaengine_pcm_set_data (substream, dma_data); +return 0 ; +} + +static int mmp_pcm_close (struct snd_pcm_substream *substream) +{ +struct mmp_dma_data *dma_data =snd_dmaengine_pcm_get_data (substream); +struct snd_soc_pcm_runtime *rtd = substream->private_data; +struct platform_device *pdev =to_platform_device (rtd->platform->dev); + +snd_dmaengine_pcm_close (substream); +devm_kfree (&pdev->dev, dma_data); +return 0 ; +} + +static int mmp_pcm_mmap (struct snd_pcm_substream *substream, +struct vm_area_struct *vma) +{ +struct snd_pcm_runtime *runtime = substream->runtime; +unsigned long off = vma->vm_pgoff; + + vma->vm_page_prot =pgprot_noncached (vma->vm_page_prot); +return remap_pfn_range (vma, vma->vm_start, +__phys_to_pfn (runtime->dma_addr) + off, + vma->vm_end - vma->vm_start, vma->vm_page_prot); +} + +struct snd_pcm_ops mmp_pcm_ops = { + .open = mmp_pcm_open, + .close = mmp_pcm_close, + .ioctl = snd_pcm_lib_ioctl, + .hw_params = mmp_pcm_hw_params, + .trigger = snd_dmaengine_pcm_trigger, + .pointer = snd_dmaengine_pcm_pointer, + .mmap = mmp_pcm_mmap, +}; + +static void mmp_pcm_free_dma_buffers (struct snd_pcm *pcm) +{ +struct snd_pcm_substream *substream; +struct snd_dma_buffer *buf; +int stream; +struct gen_pool *gpool; + + gpool =sram_get_gpool ("asram" ); +if (!gpool) +return ; + +for (stream =0 ; stream <2 ; stream++) { +size_t size = mmp_pcm_hardware[stream].buffer_bytes_max; + + substream = pcm->streams[stream].substream; +if (!substream) +continue ; + + buf = &substream->dma_buffer; +if (!buf->area) +continue ; +gen_pool_free (gpool, (unsigned long )buf->area, size); + buf->area =NULL ; + } + +return ; +} + +static int mmp_pcm_preallocate_dma_buffer (struct snd_pcm_substream *substream, +int stream) +{ +struct snd_dma_buffer *buf = &substream->dma_buffer; +size_t size = mmp_pcm_hardware[stream].buffer_bytes_max; +struct gen_pool *gpool; + + buf->dev.type =SNDRV_DMA_TYPE_DEV ; + buf->dev.dev = substream->pcm->card->dev; + buf->private_data =NULL ; + + gpool =sram_get_gpool ("asram" ); +if (!gpool) +return -ENOMEM ; + + buf->area = (unsigned char *)gen_pool_alloc (gpool, size); +if (!buf->area) +return -ENOMEM ; + buf->addr =gen_pool_virt_to_phys (gpool, (unsigned long )buf->area); + buf->bytes = size; +return 0 ; +} + +int mmp_pcm_new (struct snd_soc_pcm_runtime *rtd) +{ +struct snd_pcm_substream *substream; +struct snd_pcm *pcm = rtd->pcm; +int ret =0 , stream; + +for (stream =0 ; stream <2 ; stream++) { + substream = pcm->streams[stream].substream; + + ret =mmp_pcm_preallocate_dma_buffer (substream, stream); +if (ret) + goto err; + } + +return 0 ; + +err: +mmp_pcm_free_dma_buffers (pcm); +return ret; +} + +struct snd_soc_platform_driver mmp_soc_platform = { + .ops = &mmp_pcm_ops, + .pcm_new = mmp_pcm_new, + .pcm_free = mmp_pcm_free_dma_buffers, +}; + +static __devinit int mmp_pcm_probe (struct platform_device *pdev) +{ +struct mmp_audio_platdata *pdata = pdev->dev.platform_data; + +if (pdata) { + mmp_pcm_hardware[SNDRV_PCM_STREAM_PLAYBACK ].buffer_bytes_max = + pdata->buffer_max_playback; + mmp_pcm_hardware[SNDRV_PCM_STREAM_PLAYBACK ].period_bytes_max = + pdata->period_max_playback; + mmp_pcm_hardware[SNDRV_PCM_STREAM_CAPTURE ].buffer_bytes_max = + pdata->buffer_max_capture; + mmp_pcm_hardware[SNDRV_PCM_STREAM_CAPTURE ].period_bytes_max = + pdata->period_max_capture; + } +return snd_soc_register_platform (&pdev->dev, &mmp_soc_platform); +} + +static int __devexit mmp_pcm_remove(struct platform_device *pdev) +{ +snd_soc_unregister_platform (&pdev->dev); +return 0 ; +} + +static struct platform_driver mmp_pcm_driver = { + .driver = { + .name ="mmp-pcm-audio" , + .owner =THIS_MODULE , + }, + + .probe = mmp_pcm_probe, + .remove =__devexit_p (mmp_pcm_remove), +}; + +module_platform_driver (mmp_pcm_driver); + +MODULE_AUTHOR ("Leo Yan <[email protected]>" ); +MODULE_DESCRIPTION ("MMP Soc Audio DMA module" ); +MODULE_LICENSE ("GPL" );
Signature · 1 line
~Vinod
Re: [PATCH v1 2/5] ASoC: mmp: add audio dma support
Quoted 5 lines · Vinod Koul
Quoted 2 lines · Zhangfei Gao
mmp-pcm handle audio dma based on soc-dmaengine
Support mmp and pxa910See
soc-dmaengine.c. You sneed to use the library to use dmaengine.
Thanks Vinod for kind review.
Some confusion, only find sound/soc/soc-dmaengine-pcm.c. So the driver base on the library, snd_dmaengine_pcm_open/close etc. Replacing dma_request_channel etc.
Is it right direction?
Re: [PATCH v1 2/5] ASoC: mmp: add audio dma support
Quoted 7 lines · zhangfei gao
Quoted 5 lines · Vinod Koul
Quoted 2 lines · Zhangfei Gao
mmp-pcm handle audio dma based on soc-dmaengine
Support mmp and pxa910See
soc-dmaengine.c. You sneed to use the library to use dmaengine.
Quoted 7 lines
Thanks Vinod for kind review.
Some confusion, only find
sound/soc/soc-dmaengine-pcm.c. So the driver base on the library, snd_dmaengine_pcm_open/close etc. Replacingdma_request_channeletc.Is it right direction?
Yes your driver should use it. See examples in other soc drivers
Signature · 1 line
~Vinod
Re: [PATCH v1 2/5] ASoC: mmp: add audio dma support
Quoted 8 lines · Vinod Koul
Quoted 7 lines · zhangfei gao
Quoted 5 lines · Vinod Koul
Quoted 2 lines · Zhangfei Gao
mmp-pcm handle audio dma based on soc-dmaengine
Support mmp and pxa910See
soc-dmaengine.c. You sneed to use the library to use dmaengine.
Quoted 8 lines
Quoted 7 lines
Thanks Vinod for kind review.
Some confusion, only find
sound/soc/soc-dmaengine-pcm.c. So the driver base on the library, snd_dmaengine_pcm_open/close etc. Replacingdma_request_channeletc.Is it right direction?
Yes your driver should use it. See examples in other soc drivers
This driver already been ported to soc-dmaengine-pcm.c, refer mxs-pcm.c and imx-pcm-dma-mx2.c.
Using snd_dmaengine_pcm_open, snd_dmaengine_pcm_close, etc.
Only exception is dmaengine_slave_config, since we have some specific config.
Quoted 5 lines
--
~Vinod
Re: [PATCH v1 2/5] ASoC: mmp: add audio dma support
Quoted 1 line · zhangfei gao
Only exception is
dmaengine_slave_config, since we have some specific config.
And why?
sound/soc/pxa/mmp-pcm.c line 128
Quoted 11 lines
sound/soc/pxa/mmp-pcm.c new file +11
-0+static bool filter (struct dma_chan *chan,void *param) +{ +struct mmp_dma_data *dma_data = param; +bool found = false; +char *devname; + + devname =kasprintf (GFP_KERNEL ,"%s.%d" , dma_data->dma_res->name, + dma_data->ssp_id); +if ((strcmp (dev_name (chan->device->dev), devname) ==0 ) && + (chan->chan_id == dma_data->dma_res->start)) { + chan->private = &dma_data->tdma_data;
chan->private is deprecated and should not be used
Quoted 6 lines
sound/soc/pxa/mmp-pcm.c new file +6
-0+ found = true; + } + +kfree (devname); +return found; +}
Signature · 1 line
~Vinod
Re: [PATCH v1 2/5] ASoC: mmp: add audio dma support
Quoted 4 lines · Vinod Koul
Quoted 1 line · zhangfei gao
Only exception is
dmaengine_slave_config, since we have some specific config.And why?
Quoted 12 lines
sound/soc/pxa/mmp-pcm.c line 128
Quoted 11 lines
sound/soc/pxa/mmp-pcm.c new file +11
-0+static bool filter (struct dma_chan *chan,void *param) +{ + struct mmp_dma_data *dma_data = param; + bool found = false; + char *devname; + + devname = kasprintf(GFP_KERNEL, "%s.%d", dma_data->dma_res->name, + dma_data->ssp_id); + if ((strcmp(dev_name(chan->device->dev), devname) == 0) && + (chan->chan_id == dma_data->dma_res->start)) { + chan->private = &dma_data->tdma_data;
chan->privateis deprecated and should not be used
Thanks for the info, will update accordingly.
The concern is DMA_SLAVE_BUSWIDTH_4_BYTES is used for S20, S24, S32. And our controller handles differently, though they not seen much.
Besides, dmaengine_slave_config still have to be used for src/dst_addr and src/dst_maxburst.
Quoted 11 lines
sound/soc/pxa/mmp-pcm.c line 134
Quoted 6 lines
+ found = true;
+ }sound/soc/pxa/mmp-pcm.c new file +4
-0+ + kfree(devname); + return found; +}--
~Vinod
PATCH 3/5 ASOC: mmp: add sspa support
In reply to Zhangfei GaoThe SSPA is a configurable multi-channel audio serial (TDM) interface. It's configurable at runtime to support up to 128 channels and the number of bits per sample: 8, 12, 16, 20, 24 and 32 bits. It also support stereo format: I2S, left-justified or right-justified.
--- sound/soc/pxa/Kconfig | 3 + sound/soc/pxa/Makefile | 2 + sound/soc/pxa/mmp-sspa.c | 496 ++++++++++++++++++++++++++++++++++++++++++++++ sound/soc/pxa/mmp-sspa.h | 92 +++++++++ 4 files changed, 593 insertions(+), 0 deletions(-) create mode 100644 sound/soc/pxa/mmp-sspa.c create mode 100644 sound/soc/pxa/mmp-sspa.h
sound/soc/pxa/Kconfig +3 -0
@@ -35,6 +35,9 @@ config SND_PXA_SOC_SSP tristate select PXA_SSP +config SND_MMP_SOC_SSPA + tristate + config SND_PXA2XX_SOC_CORGI tristate "SoC Audio support for Sharp Zaurus SL-C7x0" depends on SND_PXA2XX_SOC && PXA_SHARP_C7xx
sound/soc/pxa/Makefile +2 -0
@@ -4,12 +4,14 @@ snd-soc-pxa2xx-ac97-objs := pxa2xx-ac97.o snd-soc-pxa2xx-i2s-objs := pxa2xx-i2s.o snd-soc-pxa-ssp-objs := pxa-ssp.o snd-soc-mmp-objs := mmp-pcm.o +snd-soc-mmp-sspa-objs := mmp-sspa.o obj-$(CONFIG_SND_PXA2XX_SOC) += snd-soc-pxa2xx.o obj-$(CONFIG_SND_PXA2XX_SOC_AC97) += snd-soc-pxa2xx-ac97.o obj-$(CONFIG_SND_PXA2XX_SOC_I2S) += snd-soc-pxa2xx-i2s.o obj-$(CONFIG_SND_PXA_SOC_SSP) += snd-soc-pxa-ssp.o obj-$(CONFIG_SND_MMP_SOC) += snd-soc-mmp.o +obj-$(CONFIG_SND_MMP_SOC_SSPA) += snd-soc-mmp-sspa.o # PXA Machine Support snd-soc-corgi-objs := corgi.o
sound/soc/pxa/mmp-sspa.c new file +496 -0
496 lines not on this page · raw message
sound/soc/pxa/mmp-sspa.h new file +92 -0
92 lines not on this page · raw message
Signature · 1 line
1.7.1
PATCH 3/5 ASOC: mmp: add sspa support
Quoted 4 lines · Zhangfei Gao
The SSPA is a configurable multi-channel audio serial (TDM) interface. It's configurable at runtime to support up to 128 channels and the number of bits per sample: 8, 12, 16, 20, 24 and 32 bits. It also support stereo format: I2S, left-justified or right-justified.
This looks mostly good (though you want to check your indentation a bit) but...
sound/soc/pxa/mmp-sspa.c line 480
Quoted 10 lines
sound/soc/pxa/mmp-sspa.c new file +10
-0+static int __init mmp_sspa_modinit (void ) +{ + audio_clk =clk_get (NULL ,"mmp-audio" ); +if (IS_ERR (audio_clk)) +return PTR_ERR (audio_clk); + + sysclk =clk_get (NULL ,"mmp-sysclk" ); +if (IS_ERR (sysclk)) +return PTR_ERR (sysclk); +clk_enable (audio_clk);
You should be doing this stuff from the driver, not from the module init
(and ideally you'd be managing the audio clock dynamically). Even if
it's the same clock every time in current silicon it's still a good idea
to do this from a quality of implementation point of view.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20120608/7c7f2870/attachment-0001.sig>
Re: [PATCH v1 3/5] ASOC: mmp: add sspa support
Quoted 9 lines · Mark Brown
Quoted 4 lines · Zhangfei Gao
The SSPA is a configurable multi-channel audio serial (TDM) interface. It's configurable at runtime to support up to 128 channels and the number of bits per sample: 8, 12, 16, 20, 24 and 32 bits. It also support stereo format: I2S, left-justified or right-justified.
This looks mostly good (though you want to check your indentation a bit) but...
Quoted 15 lines
sound/soc/pxa/mmp-sspa.c line 480
Quoted 10 lines
sound/soc/pxa/mmp-sspa.c new file +10
-0+static int __init mmp_sspa_modinit (void ) +{ + audio_clk = clk_get(NULL, "mmp-audio"); + if (IS_ERR(audio_clk)) + return PTR_ERR(audio_clk); + + sysclk = clk_get(NULL, "mmp-sysclk"); + if (IS_ERR(sysclk)) + return PTR_ERR(sysclk); + clk_enable(audio_clk);You should be doing this stuff from the driver, not from the module init (and ideally you'd be managing the audio clock dynamically). Even if it's the same clock every time in current silicon it's still a good idea to do this from a quality of implementation point of view.
Thanks, will remove the module init, and move clk staff to probe. However, dynamically control audio_clk make audio subsystem works abnormally.
Re: [PATCH v1 3/5] ASOC: mmp: add sspa support
In reply to Zhangfei GaoQuoted 4 lines · Zhangfei Gao
The SSPA is a configurable multi-channel audio serial (TDM) interface. It's configurable at runtime to support up to 128 channels and the number of bits per sample: 8, 12, 16, 20, 24 and 32 bits. It also support stereo format: I2S, left-justified or right-justified.
This looks mostly good (though you want to check your indentation a bit) but...
sound/soc/pxa/mmp-sspa.c line 480
Quoted 10 lines
sound/soc/pxa/mmp-sspa.c new file +10
-0+static int __init mmp_sspa_modinit (void ) +{ + audio_clk =clk_get (NULL ,"mmp-audio" ); +if (IS_ERR (audio_clk)) +return PTR_ERR (audio_clk); + + sysclk =clk_get (NULL ,"mmp-sysclk" ); +if (IS_ERR (sysclk)) +return PTR_ERR (sysclk); +clk_enable (audio_clk);
You should be doing this stuff from the driver, not from the module init (and ideally you'd be managing the audio clock dynamically). Even if it's the same clock every time in current silicon it's still a good idea to do this from a quality of implementation point of view.
PATCH 4/5 ASoC: add mmp brownstone support
In reply to Zhangfei GaoAdds Alsa audio platform driver for mmp brownstone machine
--- sound/soc/pxa/Kconfig | 10 +++ sound/soc/pxa/Makefile | 2 + sound/soc/pxa/brownstone.c | 178 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 190 insertions(+), 0 deletions(-) create mode 100644 sound/soc/pxa/brownstone.c
sound/soc/pxa/Kconfig +10 -0
@@ -206,3 +206,13 @@ config SND_PXA2XX_SOC_IMOTE2 help Say Y if you want to add support for SoC audio on the IMote 2. + +config SND_MMP_SOC_BROWNSTONE + tristate "SoC Audio support for Marvell Brownstone" + depends on SND_MMP_SOC && MACH_BROWNSTONE + select SND_MMP_SOC_SSPA + select MFD_WM8994 + select SND_SOC_WM8994 + help + Say Y if you want to add support for SoC audio on the + Marvell Brownstone reference platform.
sound/soc/pxa/Makefile +2 -0
@@ -32,6 +32,7 @@ snd-soc-mioa701-objs := mioa701_wm9713.o snd-soc-z2-objs := z2.o snd-soc-imote2-objs := imote2.o snd-soc-raumfeld-objs := raumfeld.o +snd-soc-brownstone-objs := brownstone.o obj-$(CONFIG_SND_PXA2XX_SOC_CORGI) += snd-soc-corgi.o obj-$(CONFIG_SND_PXA2XX_SOC_POODLE) += snd-soc-poodle.o
@@ -51,3 +52,4 @@ obj-$(CONFIG_SND_SOC_TAVOREVB3) += snd-soc-tavorevb3.o obj-$(CONFIG_SND_SOC_ZYLONITE) += snd-soc-zylonite.o obj-$(CONFIG_SND_PXA2XX_SOC_IMOTE2) += snd-soc-imote2.o obj-$(CONFIG_SND_SOC_RAUMFELD) += snd-soc-raumfeld.o +obj-$(CONFIG_SND_MMP_SOC_BROWNSTONE) += snd-soc-brownstone.o
sound/soc/pxa/brownstone.c new file +178 -0
178 lines not on this page · raw message
Signature · 1 line
1.7.1
Re: [PATCH v1 4/5] ASoC: add mmp brownstone support
On Mon, Jun 04, 2012 at 02:37:30PM +0800, Zhangfei Gao wrote:
One small thing here...
sound/soc/pxa/brownstone.c line 57
Quoted 4 lines
sound/soc/pxa/brownstone.c new file +4
-0+ ret =snd_soc_add_card_controls (dapm->card, brownstone_dapm_control, +ARRAY_SIZE (brownstone_dapm_control)); +if (ret <0 ) +return ret;
You can just set these up with the controls member of the card struct.
Re: [PATCH v1 4/5] ASoC: add mmp brownstone support
Quoted 10 lines · Mark Brown
On Mon, Jun 04, 2012 at 02:37:30PM +0800, Zhangfei Gao wrote:
One small thing here...
Quoted 4 lines
+ ? ? ret = snd_soc_add_card_controls(dapm->card,
brownstone_dapm_control,
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?ARRAY_SIZE(brownstone_dapm_control));
+ ? ? if (ret < 0)
+ ? ? ? ? ? ? return ret;You can just set these up with the controls member of the card struct.
Great, it will make it easier, thanks.
Quoted 6 lines
_______________________________________________
Alsa-devel mailing list
Alsa-devel at alsa-project.org
http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
PATCH 5/5 ASoC: add ttc-dkb machine support
In reply to Zhangfei GaoFrom: Qiao Zhou <[email protected]>
add ttc-dkb machine support for pxa910. It uses 88pm8607 as codec dai, mmp-pcm as platform and pxa-ssp as cpu dai.
--- sound/soc/pxa/Kconfig | 20 ++++++ sound/soc/pxa/Makefile | 2 + sound/soc/pxa/ttc-dkb.c | 173 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 195 insertions(+), 0 deletions(-) create mode 100644 sound/soc/pxa/ttc-dkb.c
sound/soc/pxa/Kconfig +20 -0
@@ -150,6 +150,26 @@ config SND_SOC_TAVOREVB3 Say Y if you want to add support for SoC audio on the Marvell Saarb reference platform. +config SND_PXA910_SOC + tristate "SoC Audio for Marvell PXA910 chip" + depends on ARCH_MMP && SND + select SND_PCM + help + Say Y if you want to add support for SoC audio on the + Marvell PXA910 reference platform. + +config SND_SOC_TTC_DKB + bool "SoC Audio support for TTC DKB" + depends on SND_PXA910_SOC && MACH_TTC_DKB + select PXA_SSP + select SND_PXA_SOC_SSP + select SND_MMP_SOC + select MFD_88PM860X + select SND_SOC_88PM860X + help + Say Y if you want to add support for SoC audio on TTC DKB + + config SND_SOC_ZYLONITE tristate "SoC Audio support for Marvell Zylonite" depends on SND_PXA2XX_SOC && MACH_ZYLONITE
sound/soc/pxa/Makefile +2 -0
@@ -33,6 +33,7 @@ snd-soc-z2-objs := z2.o snd-soc-imote2-objs := imote2.o snd-soc-raumfeld-objs := raumfeld.o snd-soc-brownstone-objs := brownstone.o +snd-soc-ttc-dkb-objs := ttc-dkb.o obj-$(CONFIG_SND_PXA2XX_SOC_CORGI) += snd-soc-corgi.o obj-$(CONFIG_SND_PXA2XX_SOC_POODLE) += snd-soc-poodle.o
@@ -53,3 +54,4 @@ obj-$(CONFIG_SND_SOC_ZYLONITE) += snd-soc-zylonite.o obj-$(CONFIG_SND_PXA2XX_SOC_IMOTE2) += snd-soc-imote2.o obj-$(CONFIG_SND_SOC_RAUMFELD) += snd-soc-raumfeld.o obj-$(CONFIG_SND_MMP_SOC_BROWNSTONE) += snd-soc-brownstone.o +obj-$(CONFIG_SND_SOC_TTC_DKB) += snd-soc-ttc-dkb.o
sound/soc/pxa/ttc-dkb.c new file +173 -0
173 lines not on this page · raw message
Signature · 1 line
1.7.1