Message ID | 20220317082818.503143-11-s.hauer@pengutronix.de (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | ASoC: fsl_micfil: Driver updates | expand |
On Thu, Mar 17, 2022 at 05:08:55PM +0800, Shengjiu Wang wrote: > On Thu, Mar 17, 2022 at 4:28 PM Sascha Hauer <[1]s.hauer@pengutronix.de> > wrote: > > +struct sdma_peripheral_config { > + int n_fifos_src; > + int n_fifos_dst; > + bool sw_done; > +}; > + > #endif > > Hi Sascha > This is our internal definition for this sdma_peripheral_config. > Could you please adopt this? This structure is completely internal to the kernel and can be adjusted when we need it. I don't see a reason to add unused fields to it just to be compatible with a downstream kernel. Sascha > /** > * struct sdma_audio_config - special sdma config for audio case > * @src_fifo_num: source fifo number for mcu_2_sai/sai_2_mcu script > * For example, if there are 4 fifos, sdma will fetch > * fifos one by one and roll back to the first fifo after > * the 4th fifo fetch. > * @dst_fifo_num: similar as src_fifo_num, but dest fifo instead. > * @src_fifo_off: source fifo offset, 0 means all fifos are continuous, 1 > * means 1 word offset between fifos. All offset between > * fifos should be same. > * @dst_fifo_off: dst fifo offset, similar as @src_fifo_off. > * @words_per_fifo: numbers of words per fifo fetch/fill, 0 means > * one channel per fifo, 1 means 2 channels per fifo.. > * If 'src_fifo_num = 4' and 'chans_per_fifo = 1', it > * means the first two words(channels) fetch from fifo1 > * and then jump to fifo2 for next two words, and so on > * after the last fifo4 fetched, roll back to fifo1. > * @sw_done_sel: software done selector, PDM need enable software done > feature > * in mcu_2_sai/sai_2_mcu script. > * Bit31: sw_done eanbled or not > * Bit16~Bit0: selector > * For example: 0x80000000 means sw_done enabled for done0 > * sector which is for PDM on i.mx8mm. > */ > struct sdma_audio_config { > u8 src_fifo_num; > u8 dst_fifo_num; > u8 src_fifo_off; > u8 dst_fifo_off; > u8 words_per_fifo; > u32 sw_done_sel; > }; > best regards > wang shengjiu > > > References > > Visible links > 1. mailto:s.hauer@pengutronix.de > 2. mailto:s.hauer@pengutronix.de
On Thu, Mar 17, 2022 at 08:20:22PM +0800, Shengjiu Wang wrote: > Hi > On Thu, Mar 17, 2022 at 6:19 PM Sascha Hauer <[1]s.hauer@pengutronix.de> > wrote: > > On Thu, Mar 17, 2022 at 05:08:55PM +0800, Shengjiu Wang wrote: > > On Thu, Mar 17, 2022 at 4:28 PM Sascha Hauer > <[1][2]s.hauer@pengutronix.de> > > wrote: > > > > +struct sdma_peripheral_config { > > + int n_fifos_src; > > + int n_fifos_dst; > > + bool sw_done; > > +}; > > + > > #endif > > > > Hi Sascha > > This is our internal definition for this sdma_peripheral_config. > > Could you please adopt this? > > This structure is completely internal to the kernel and can be adjusted > when we need it. I don't see a reason to add unused fields to it just to > be compatible with a downstream kernel. > > Yes, it is not used by micfil. But the fifo_offset and words_per_fifo > is part the multi fifo script support scope, if only add fifo_num, it > looks > like this feature is not complete. No, it's not. I only added the parts that I am interested in and that I can test. I have some multichannel audio stuff in my pipeline, I might add more pieces later. > By the way, which multi fifo script version are you using? seems it is > not the latest compared with our release, right? I am using the latest firmware from linux-firmware.git. Sascha
On Fri, Mar 18, 2022 at 01:42:51PM +0800, Shengjiu Wang wrote: > Hi > On Thu, Mar 17, 2022 at 4:28 PM Sascha Hauer <[1]s.hauer@pengutronix.de> > wrote: > > Signed-off-by: Sascha Hauer <[2]s.hauer@pengutronix.de> > --- > drivers/dma/imx-sdma.c | 54 +++++++++++++++++++++++++++ > include/linux/platform_data/dma-imx.h | 7 ++++ > 2 files changed, 61 insertions(+) > > diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c > index 1038f6bc7f846..21e1cec2ffde9 100644 > --- a/drivers/dma/imx-sdma.c > +++ b/drivers/dma/imx-sdma.c > @@ -14,6 +14,7 @@ > #include <linux/iopoll.h> > #include <linux/module.h> > #include <linux/types.h> > +#include <linux/bitfield.h> > #include <linux/bitops.h> > #include <linux/mm.h> > #include <linux/interrupt.h> > @@ -73,6 +74,7 @@ > #define SDMA_CHNENBL0_IMX35 0x200 > #define SDMA_CHNENBL0_IMX31 0x080 > #define SDMA_CHNPRI_0 0x100 > +#define SDMA_DONE0_CONFIG 0x1000 > > /* > * Buffer descriptor status values. > @@ -180,6 +182,12 @@ > BIT(DMA_MEM_TO_DEV) | \ > BIT(DMA_DEV_TO_DEV)) > > +#define SDMA_WATERMARK_LEVEL_N_FIFOS GENMASK(15, 12) > +#define SDMA_WATERMARK_LEVEL_SW_DONE BIT(23) > + > +#define SDMA_DONE0_CONFIG_DONE_SEL BIT(7) > +#define SDMA_DONE0_CONFIG_DONE_DIS BIT(6) > + > /** > * struct sdma_script_start_addrs - SDMA script start pointers > * > @@ -441,6 +449,11 @@ struct sdma_channel { > struct work_struct terminate_worker; > struct list_head terminated; > bool is_ram_script; > + unsigned int n_fifos; > + unsigned int n_fifos_src; > + unsigned int n_fifos_dst; > + bool sw_done; > + u32 sw_done_sel; > > "sw_done_sel" is not used, and may not be needed. Ok, will drop. > And can we just add 'struct sdma_peripheral_config *pconfig' > to replace each item here ('n_fifos_src', 'n_fifos_dst', > 'sw_done')? I rather do not access the pointer to the peripheral_config outside of sdma_config because I know nothing about the lifetime of that structure. > the pconfig can point to the struct in dma_slave_config. > And 'n_fifos' can be moved to locally function in > sdma_set_watermarklevel_for_sais(), then use sdmac->direction > to select 'n_fifos_dst' or 'n_fifos_src'. Ok. Sascha
diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c index 1038f6bc7f846..21e1cec2ffde9 100644 --- a/drivers/dma/imx-sdma.c +++ b/drivers/dma/imx-sdma.c @@ -14,6 +14,7 @@ #include <linux/iopoll.h> #include <linux/module.h> #include <linux/types.h> +#include <linux/bitfield.h> #include <linux/bitops.h> #include <linux/mm.h> #include <linux/interrupt.h> @@ -73,6 +74,7 @@ #define SDMA_CHNENBL0_IMX35 0x200 #define SDMA_CHNENBL0_IMX31 0x080 #define SDMA_CHNPRI_0 0x100 +#define SDMA_DONE0_CONFIG 0x1000 /* * Buffer descriptor status values. @@ -180,6 +182,12 @@ BIT(DMA_MEM_TO_DEV) | \ BIT(DMA_DEV_TO_DEV)) +#define SDMA_WATERMARK_LEVEL_N_FIFOS GENMASK(15, 12) +#define SDMA_WATERMARK_LEVEL_SW_DONE BIT(23) + +#define SDMA_DONE0_CONFIG_DONE_SEL BIT(7) +#define SDMA_DONE0_CONFIG_DONE_DIS BIT(6) + /** * struct sdma_script_start_addrs - SDMA script start pointers * @@ -441,6 +449,11 @@ struct sdma_channel { struct work_struct terminate_worker; struct list_head terminated; bool is_ram_script; + unsigned int n_fifos; + unsigned int n_fifos_src; + unsigned int n_fifos_dst; + bool sw_done; + u32 sw_done_sel; }; #define IMX_DMA_SG_LOOP BIT(0) @@ -773,6 +786,14 @@ static void sdma_event_enable(struct sdma_channel *sdmac, unsigned int event) val = readl_relaxed(sdma->regs + chnenbl); __set_bit(channel, &val); writel_relaxed(val, sdma->regs + chnenbl); + + /* Set SDMA_DONEx_CONFIG is sw_done enabled */ + if (sdmac->sw_done) { + val = readl_relaxed(sdma->regs + SDMA_DONE0_CONFIG); + val |= SDMA_DONE0_CONFIG_DONE_SEL; + val &= ~SDMA_DONE0_CONFIG_DONE_DIS; + writel_relaxed(val, sdma->regs + SDMA_DONE0_CONFIG); + } } static void sdma_event_disable(struct sdma_channel *sdmac, unsigned int event) @@ -1022,6 +1043,10 @@ static int sdma_get_pc(struct sdma_channel *sdmac, case IMX_DMATYPE_IPU_MEMORY: emi_2_per = sdma->script_addrs->ext_mem_2_ipu_addr; break; + case IMX_DMATYPE_MULTI_SAI: + per_2_emi = sdma->script_addrs->sai_2_mcu_addr; + emi_2_per = sdma->script_addrs->mcu_2_sai_addr; + break; default: dev_err(sdma->dev, "Unsupported transfer type %d\n", peripheral_type); @@ -1198,6 +1223,15 @@ static void sdma_set_watermarklevel_for_p2p(struct sdma_channel *sdmac) sdmac->watermark_level |= SDMA_WATERMARK_LEVEL_CONT; } +static void sdma_set_watermarklevel_for_sais(struct sdma_channel *sdmac) +{ + if (sdmac->sw_done) + sdmac->watermark_level |= SDMA_WATERMARK_LEVEL_SW_DONE; + + sdmac->watermark_level |= + FIELD_PREP(SDMA_WATERMARK_LEVEL_N_FIFOS, sdmac->n_fifos); +} + static int sdma_config_channel(struct dma_chan *chan) { struct sdma_channel *sdmac = to_sdma_chan(chan); @@ -1234,6 +1268,10 @@ static int sdma_config_channel(struct dma_chan *chan) sdmac->peripheral_type == IMX_DMATYPE_ASRC) sdma_set_watermarklevel_for_p2p(sdmac); } else { + if (sdmac->peripheral_type == + IMX_DMATYPE_MULTI_SAI) + sdma_set_watermarklevel_for_sais(sdmac); + __set_bit(sdmac->event_id0, sdmac->event_mask); } @@ -1669,6 +1707,7 @@ static int sdma_config_write(struct dma_chan *chan, sdmac->watermark_level = dmaengine_cfg->src_maxburst * dmaengine_cfg->src_addr_width; sdmac->word_size = dmaengine_cfg->src_addr_width; + sdmac->n_fifos = sdmac->n_fifos_src; } else if (direction == DMA_DEV_TO_DEV) { sdmac->per_address2 = dmaengine_cfg->src_addr; sdmac->per_address = dmaengine_cfg->dst_addr; @@ -1682,6 +1721,7 @@ static int sdma_config_write(struct dma_chan *chan, sdmac->watermark_level = dmaengine_cfg->dst_maxburst * dmaengine_cfg->dst_addr_width; sdmac->word_size = dmaengine_cfg->dst_addr_width; + sdmac->n_fifos = sdmac->n_fifos_dst; } sdmac->direction = direction; return sdma_config_channel(chan); @@ -1691,9 +1731,23 @@ static int sdma_config(struct dma_chan *chan, struct dma_slave_config *dmaengine_cfg) { struct sdma_channel *sdmac = to_sdma_chan(chan); + struct sdma_engine *sdma = sdmac->sdma; memcpy(&sdmac->slave_config, dmaengine_cfg, sizeof(*dmaengine_cfg)); + if (dmaengine_cfg->peripheral_config) { + struct sdma_peripheral_config *sdmacfg = dmaengine_cfg->peripheral_config; + if (dmaengine_cfg->peripheral_size != sizeof(struct sdma_peripheral_config)) { + dev_err(sdma->dev, "Invalid peripheral size %zu, expected %zu\n", + dmaengine_cfg->peripheral_size, + sizeof(struct sdma_peripheral_config)); + return -EINVAL; + } + sdmac->n_fifos_src = sdmacfg->n_fifos_src; + sdmac->n_fifos_dst = sdmacfg->n_fifos_dst; + sdmac->sw_done = sdmacfg->sw_done; + } + /* Set ENBLn earlier to make sure dma request triggered after that */ if (sdmac->event_id0 >= sdmac->sdma->drvdata->num_events) return -EINVAL; diff --git a/include/linux/platform_data/dma-imx.h b/include/linux/platform_data/dma-imx.h index 281adbb26e6bd..4a43a048e1b4d 100644 --- a/include/linux/platform_data/dma-imx.h +++ b/include/linux/platform_data/dma-imx.h @@ -39,6 +39,7 @@ enum sdma_peripheral_type { IMX_DMATYPE_SSI_DUAL, /* SSI Dual FIFO */ IMX_DMATYPE_ASRC_SP, /* Shared ASRC */ IMX_DMATYPE_SAI, /* SAI */ + IMX_DMATYPE_MULTI_SAI, /* MULTI FIFOs For Audio */ }; enum imx_dma_prio { @@ -65,4 +66,10 @@ static inline int imx_dma_is_general_purpose(struct dma_chan *chan) !strcmp(chan->device->dev->driver->name, "imx-dma"); } +struct sdma_peripheral_config { + int n_fifos_src; + int n_fifos_dst; + bool sw_done; +}; + #endif
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- drivers/dma/imx-sdma.c | 54 +++++++++++++++++++++++++++ include/linux/platform_data/dma-imx.h | 7 ++++ 2 files changed, 61 insertions(+)