From: Peter Ujfalusi <hidden> Date: 2012-09-12 11:46:43
Hello,
This series will switch the OMAP audio to use dmaengine.
The final patch which does the switch was based on Russell King's earlier patch.
The first 10 patch is to prepare the OMAP audio drivers for a smooth change to
dmaengine:
- sDMA FRAME sync mode is removed and replaced with PACKET mode
- dai drivers no longer need to configure sDMA sync mode
- dai drivers does not need to specify the DMA word length - with the exception
of the omap-hdmi driver which requires 32bit word length regardless of the
audio format in use
- the McPDM driver used (to my surprise) hackish way of getting the DMA channel
and address - via defines from some header files
I have tested the series on:
- BeagleBoard (audio via McBSP) with aplay/arecord. In element mode and in
threshold mode with different period sizes
- OMAP4 Blaze (audio via McPDM and DMIC)
With this conversion the NO_PERIOD_WAKEUP is not supported at the moment. I'll
be looking at the dmaengine core and omap parts to add this feature back.
The patches has been generated against:
git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-3.7
Janusz: Can you retest this series on OMAP1 to be sure I have not broken it?
Ricardo: Can you test the omap-hmdi if it is still working?
Regards,
Peter
---
Peter Ujfalusi (11):
dmaengine: omap: Support for element mode in cyclic DMA
ASoC: omap-mcbsp: Use sDMA packet mode instead of frame mode
ASoC: omap-pcm: Select sDMA synchronization based on packet_size
ASoC: OMAP: Remove sync_mode from omap_pcm_dma_data struct
ASoC: omap-pcm: Prepare to configure the DMA data_type based on
stream properties
ARM: OMAP4: hwmod_data: Add resource names to McPDM memory ranges
ASoC: omap-mcpdm: Use platform_get_resource_* to get resources
ASoC: OMAP: mcbsp, mcpdm, dmic: Let omap-pcm to pick the dma_type
ASoC: omap-pcm, omap-hdmi: Change the use of
omap_pcm_dma_data->data_type
ASoC: OMAP: mcbsp, mcpdm, dmic, hdmi: Set dma_data at startup time
ASoC: omap-pcm: Convert to use dmaengine
arch/arm/mach-omap2/omap_hwmod_44xx_data.c | 2 +
drivers/dma/omap-dma.c | 5 +-
sound/soc/omap/Kconfig | 3 +-
sound/soc/omap/omap-dmic.c | 9 +-
sound/soc/omap/omap-hdmi.c | 17 +-
sound/soc/omap/omap-mcbsp.c | 60 +++----
sound/soc/omap/omap-mcpdm.c | 41 +++--
sound/soc/omap/omap-pcm.c | 246 ++++++++---------------------
sound/soc/omap/omap-pcm.h | 4 +-
9 files changed, 136 insertions(+), 251 deletions(-)
--
1.7.12
From: Peter Ujfalusi <hidden> Date: 2012-09-12 11:46:49
When src_maxburst/dst_maxburst is set to 0 by the users of cyclic DMA
(mostly audio) indicates that we should configure the omap DMA to element
sync mode instead of packet mode.
Signed-off-by: Peter Ujfalusi <redacted>
---
drivers/dma/omap-dma.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
From: Peter Ujfalusi <hidden> Date: 2012-09-12 11:46:51
When McBSP is configured in threshold mode we can use sDMA packet mode in
all cases.
Signed-off-by: Peter Ujfalusi <redacted>
---
sound/soc/omap/omap-mcbsp.c | 47 ++++++++++++++++-----------------------------
1 file changed, 17 insertions(+), 30 deletions(-)
@@ -251,6 +248,7 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,dma_data->set_threshold=omap_mcbsp_set_threshold;if(mcbsp->dma_op_mode==MCBSP_DMA_MODE_THRESHOLD){intperiod_words,max_thrsh;+intdivider=0;period_words=params_period_bytes(params)/(wlen/8);if(substream->stream==SNDRV_PCM_STREAM_PLAYBACK)
@@ -258,34 +256,23 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,elsemax_thrsh=mcbsp->max_rx_thres;/*-*Iftheperiodcontainslessorequalnumberofwords,-*weareusingtheoriginalthresholdmodesetup:-*McBSPthreshold=sDMAframesize=period_size-*OtherwiseweswitchtosDMApacketmode:-*McBSPthreshold=sDMApacketsize-*sDMAframesize=periodsize+*UsesDMApacketmodeifMcBSPisinthresholdmode:+*IfperiodwordslessthantheFIFOsizethepacket+*sizeissettothenumberofperiodwords,otherwise+*Lookforthebiggestthresholdvaluewhichdivides+*theperiodsizeevenly.*/-if(period_words>max_thrsh){-intdivider=0;--/*-*Lookforthebiggestthresholdvalue,which-*dividestheperiodsizeevenly.-*/-divider=period_words/max_thrsh;-if(period_words%max_thrsh)-divider++;-while(period_words%divider&&-divider<period_words)-divider++;-if(divider==period_words)-return-EINVAL;--pkt_size=period_words/divider;-sync_mode=OMAP_DMA_SYNC_PACKET;-}else{-sync_mode=OMAP_DMA_SYNC_FRAME;-}+divider=period_words/max_thrsh;+if(period_words%max_thrsh)+divider++;+while(period_words%divider&&+divider<period_words)+divider++;+if(divider==period_words)+return-EINVAL;++pkt_size=period_words/divider;+sync_mode=OMAP_DMA_SYNC_PACKET;}elseif(channels>1){/* Use packet mode for non mono streams */pkt_size=channels;
From: Peter Ujfalusi <hidden> Date: 2012-09-12 11:46:54
Since we only have element or packet synchronization we can use the
dma_data->packet_size to select the desired mode:
if packet_size is 0 we use ELEMENT mode
if packet_size is not 0 we use PACKET mode for sDMA synchronization.
Signed-off-by: Peter Ujfalusi <redacted>
---
sound/soc/omap/omap-pcm.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
From: Peter Ujfalusi <hidden> Date: 2012-09-12 11:47:05
The omap-pcm platform driver no longer needs this parameter to select
between ELEMENT and PACKET mode. The selection is based on the configured
packet_size.
Signed-off-by: Peter Ujfalusi <redacted>
---
sound/soc/omap/omap-dmic.c | 1 -
sound/soc/omap/omap-hdmi.c | 1 -
sound/soc/omap/omap-mcbsp.c | 5 +----
sound/soc/omap/omap-mcpdm.c | 2 --
sound/soc/omap/omap-pcm.h | 1 -
5 files changed, 1 insertion(+), 9 deletions(-)
@@ -225,7 +225,7 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,structomap_mcbsp*mcbsp=snd_soc_dai_get_drvdata(cpu_dai);structomap_mcbsp_reg_cfg*regs=&mcbsp->cfg_regs;structomap_pcm_dma_data*dma_data;-intwlen,channels,wpf,sync_mode=OMAP_DMA_SYNC_ELEMENT;+intwlen,channels,wpf;intpkt_size=0;unsignedintformat,div,framesize,master;
@@ -272,15 +272,12 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,return-EINVAL;pkt_size=period_words/divider;-sync_mode=OMAP_DMA_SYNC_PACKET;}elseif(channels>1){/* Use packet mode for non mono streams */pkt_size=channels;-sync_mode=OMAP_DMA_SYNC_PACKET;}}-dma_data->sync_mode=sync_mode;dma_data->packet_size=pkt_size;snd_soc_dai_set_dma_data(cpu_dai,substream,dma_data);
From: Peter Ujfalusi <hidden> Date: 2012-09-12 11:47:13
omap-pcm can figure out the correct dma_type based on the stream's format.
In this way we can get rid of the plat/dma.h include from these drivers.
Signed-off-by: Peter Ujfalusi <redacted>
---
sound/soc/omap/omap-dmic.c | 2 --
sound/soc/omap/omap-mcbsp.c | 3 ---
sound/soc/omap/omap-mcpdm.c | 3 ---
3 files changed, 8 deletions(-)
From: Peter Ujfalusi <hidden> Date: 2012-09-12 11:47:19
Set the dma_data for the stream (snd_soc_dai_set_dma_data) at dai_startup
time so omap-pcm will have access to the needed information regarding to
the DMA channel earlier.
This is needed for the clean dmaengine support.
Signed-off-by: Peter Ujfalusi <redacted>
---
sound/soc/omap/omap-dmic.c | 6 ++++--
sound/soc/omap/omap-hdmi.c | 15 +++++++++------
sound/soc/omap/omap-mcbsp.c | 7 ++++---
sound/soc/omap/omap-mcpdm.c | 8 ++++----
4 files changed, 21 insertions(+), 15 deletions(-)
From: Peter Ujfalusi <hidden> Date: 2012-09-12 11:47:37
Original author: Russell King [off-list ref]
Switch the omap-pcm to use dmaengine.
Certain features are not supported by after dmaengine conversion:
1. No period wakeup mode
DMA engine has no way to communicate this information through
standard channels.
2. Pause/Resume
OMAP DMA engine backend does not support pausing and resuming
an in-progress transfer. It is unclear from the specs what
effect clearing the enable bit has on the DMA position of a
destination synchronized transfer, and whether the transfer
can be restarted from the exact point that it was paused (or
whether the data in the FIFO read from memory is simply
discarded.)
Signed-off-by: Peter Ujfalusi <redacted>
CC: Russell King <redacted>
---
sound/soc/omap/Kconfig | 3 +-
sound/soc/omap/omap-pcm.c | 279 +++++++++++-----------------------------------
2 files changed, 67 insertions(+), 215 deletions(-)
@@ -49,61 +52,34 @@ static const struct snd_pcm_hardware omap_pcm_hardware = {.buffer_bytes_max=128*1024,};-structomap_runtime_data{-spinlock_tlock;-structomap_pcm_dma_data*dma_data;-intdma_ch;-intperiod_index;-};--staticvoidomap_pcm_dma_irq(intch,u16stat,void*data)+staticintomap_pcm_get_dma_buswidth(intnum_bits){-structsnd_pcm_substream*substream=data;-structsnd_pcm_runtime*runtime=substream->runtime;-structomap_runtime_data*prtd=runtime->private_data;-unsignedlongflags;--if((cpu_is_omap1510())){-/*-*OMAP1510doesn'tfullysupportDMAprogresscounter-*andthereisnosoftwareemulationimplementedyet,-*sohavetomaintainourownprogresscounters-*thatcanbeusedbyomap_pcm_pointer()instead.-*/-spin_lock_irqsave(&prtd->lock,flags);-if((stat==OMAP_DMA_LAST_IRQ)&&-(prtd->period_index==runtime->periods-1)){-/* we are in sync, do nothing */-spin_unlock_irqrestore(&prtd->lock,flags);-return;-}-if(prtd->period_index>=0){-if(stat&OMAP_DMA_BLOCK_IRQ){-/* end of buffer reached, loop back */-prtd->period_index=0;-}elseif(stat&OMAP_DMA_LAST_IRQ){-/* update the counter for the last period */-prtd->period_index=runtime->periods-1;-}elseif(++prtd->period_index>=runtime->periods){-/* end of buffer missed? loop back */-prtd->period_index=0;-}-}-spin_unlock_irqrestore(&prtd->lock,flags);-}+intbuswidth;-snd_pcm_period_elapsed(substream);+switch(num_bits){+case16:+buswidth=DMA_SLAVE_BUSWIDTH_2_BYTES;+break;+case32:+buswidth=DMA_SLAVE_BUSWIDTH_4_BYTES;+break;+default:+buswidth=-EINVAL;+break;+}+returnbuswidth;}+/* this may get called several times by oss emulation */staticintomap_pcm_hw_params(structsnd_pcm_substream*substream,structsnd_pcm_hw_params*params){structsnd_pcm_runtime*runtime=substream->runtime;structsnd_soc_pcm_runtime*rtd=substream->private_data;-structomap_runtime_data*prtd=runtime->private_data;structomap_pcm_dma_data*dma_data;-+structdma_slave_configconfig;+structdma_chan*chan;interr=0;dma_data=snd_soc_dai_get_dma_data(rtd->cpu_dai,substream);
@@ -116,195 +92,78 @@ static int omap_pcm_hw_params(struct snd_pcm_substream *substream,snd_pcm_set_runtime_buffer(substream,&substream->dma_buffer);runtime->dma_bytes=params_buffer_bytes(params);-if(prtd->dma_data)-return0;-prtd->dma_data=dma_data;-err=omap_request_dma(dma_data->dma_req,dma_data->name,-omap_pcm_dma_irq,substream,&prtd->dma_ch);-if(!err){-/*-*LinkchannelwithitselfsoDMAdoesn'tneedany-*reprogrammingwhileloopingthebuffer-*/-omap_dma_link_lch(prtd->dma_ch,prtd->dma_ch);-}--returnerr;-}--staticintomap_pcm_hw_free(structsnd_pcm_substream*substream)-{-structsnd_pcm_runtime*runtime=substream->runtime;-structomap_runtime_data*prtd=runtime->private_data;--if(prtd->dma_data==NULL)-return0;+chan=snd_dmaengine_pcm_get_chan(substream);+if(!chan)+return-EINVAL;-omap_dma_unlink_lch(prtd->dma_ch,prtd->dma_ch);-omap_free_dma(prtd->dma_ch);-prtd->dma_data=NULL;+/* fills in addr_width and direction */+err=snd_hwparams_to_dma_slave_config(substream,params,&config);+if(err)+returnerr;-snd_pcm_set_runtime_buffer(substream,NULL);+/* Override the *_dma addr_width if requested by the DAI driver */+if(dma_data->data_type){+intbuswidth=omap_pcm_get_dma_buswidth(dma_data->data_type);-return0;-}+if(substream->stream==SNDRV_PCM_STREAM_PLAYBACK)+config.dst_addr_width=buswidth;+else+config.src_addr_width=buswidth;+}-staticintomap_pcm_get_dma_type(intnum_bits)-{-intdata_type;+config.src_addr=dma_data->port_addr;+config.dst_addr=dma_data->port_addr;+config.src_maxburst=dma_data->packet_size;+config.dst_maxburst=dma_data->packet_size;-switch(num_bits){-case16:-data_type=OMAP_DMA_DATA_TYPE_S16;-break;-case32:-data_type=OMAP_DMA_DATA_TYPE_S32;-break;-default:-data_type=-EINVAL;-break;-}-returndata_type;+returndmaengine_slave_config(chan,&config);}-staticintomap_pcm_prepare(structsnd_pcm_substream*substream)+staticintomap_pcm_hw_free(structsnd_pcm_substream*substream){-structsnd_pcm_runtime*runtime=substream->runtime;-structomap_runtime_data*prtd=runtime->private_data;-structomap_pcm_dma_data*dma_data=prtd->dma_data;-structomap_dma_channel_paramsdma_params;-intbytes;--/* return if this is a bufferless transfer e.g.-*codec<-->BTcodecorGSMmodem--lgFIXME*/-if(!prtd->dma_data)-return0;--memset(&dma_params,0,sizeof(dma_params));--if(dma_data->data_type)-dma_params.data_type=omap_pcm_get_dma_type(-dma_data->data_type);-else-dma_params.data_type=omap_pcm_get_dma_type(-snd_pcm_format_physical_width(runtime->format));--if(dma_params.data_type<0)-returndma_params.data_type;--dma_params.trigger=dma_data->dma_req;--if(dma_data->packet_size)-dma_params.sync_mode=OMAP_DMA_SYNC_PACKET;-else-dma_params.sync_mode=OMAP_DMA_SYNC_ELEMENT;--if(substream->stream==SNDRV_PCM_STREAM_PLAYBACK){-dma_params.src_amode=OMAP_DMA_AMODE_POST_INC;-dma_params.dst_amode=OMAP_DMA_AMODE_CONSTANT;-dma_params.src_or_dst_synch=OMAP_DMA_DST_SYNC;-dma_params.src_start=runtime->dma_addr;-dma_params.dst_start=dma_data->port_addr;-dma_params.dst_port=OMAP_DMA_PORT_MPUI;-dma_params.dst_fi=dma_data->packet_size;-}else{-dma_params.src_amode=OMAP_DMA_AMODE_CONSTANT;-dma_params.dst_amode=OMAP_DMA_AMODE_POST_INC;-dma_params.src_or_dst_synch=OMAP_DMA_SRC_SYNC;-dma_params.src_start=dma_data->port_addr;-dma_params.dst_start=runtime->dma_addr;-dma_params.src_port=OMAP_DMA_PORT_MPUI;-dma_params.src_fi=dma_data->packet_size;-}-/*-*SetDMAtransferframesizeequaltoALSAperiodsizeandframe-*countasno.ofALSAperiods.ThenwithDMAframeinterruptenabled,-*wecantransferthewholeALSAbufferwithsingleDMAtransferbut-*stillcangetaninterruptateachperiodbounary-*/-bytes=snd_pcm_lib_period_bytes(substream);-dma_params.elem_count=bytes>>dma_params.data_type;-dma_params.frame_count=runtime->periods;-omap_set_dma_params(prtd->dma_ch,&dma_params);--if((cpu_is_omap1510()))-omap_enable_dma_irq(prtd->dma_ch,OMAP_DMA_FRAME_IRQ|-OMAP_DMA_LAST_IRQ|OMAP_DMA_BLOCK_IRQ);-elseif(!substream->runtime->no_period_wakeup)-omap_enable_dma_irq(prtd->dma_ch,OMAP_DMA_FRAME_IRQ);-else{-/*-*Noperiodwakeup:-*weneedtodisableBLOCK_IRQ,whichisenabledbytheomap-*dmacoreatrequestdmatime.-*/-omap_disable_dma_irq(prtd->dma_ch,OMAP_DMA_BLOCK_IRQ);-}--if(!(cpu_class_is_omap1())){-omap_set_dma_src_burst_mode(prtd->dma_ch,-OMAP_DMA_DATA_BURST_16);-omap_set_dma_dest_burst_mode(prtd->dma_ch,-OMAP_DMA_DATA_BURST_16);-}-+snd_pcm_set_runtime_buffer(substream,NULL);return0;}staticintomap_pcm_trigger(structsnd_pcm_substream*substream,intcmd){-structsnd_pcm_runtime*runtime=substream->runtime;-structomap_runtime_data*prtd=runtime->private_data;-structomap_pcm_dma_data*dma_data=prtd->dma_data;-unsignedlongflags;+structsnd_soc_pcm_runtime*rtd=substream->private_data;+structomap_pcm_dma_data*dma_data;intret=0;-spin_lock_irqsave(&prtd->lock,flags);+dma_data=snd_soc_dai_get_dma_data(rtd->cpu_dai,substream);+switch(cmd){caseSNDRV_PCM_TRIGGER_START:caseSNDRV_PCM_TRIGGER_RESUME:caseSNDRV_PCM_TRIGGER_PAUSE_RELEASE:-prtd->period_index=0;/* Configure McBSP internal buffer usage */if(dma_data->set_threshold)dma_data->set_threshold(substream);--omap_start_dma(prtd->dma_ch);break;caseSNDRV_PCM_TRIGGER_STOP:caseSNDRV_PCM_TRIGGER_SUSPEND:caseSNDRV_PCM_TRIGGER_PAUSE_PUSH:-prtd->period_index=-1;-omap_stop_dma(prtd->dma_ch);break;default:ret=-EINVAL;}-spin_unlock_irqrestore(&prtd->lock,flags);++if(ret==0)+ret=snd_dmaengine_pcm_trigger(substream,cmd);returnret;}staticsnd_pcm_uframes_tomap_pcm_pointer(structsnd_pcm_substream*substream){-structsnd_pcm_runtime*runtime=substream->runtime;-structomap_runtime_data*prtd=runtime->private_data;-dma_addr_tptr;snd_pcm_uframes_toffset;-if(cpu_is_omap1510()){-offset=prtd->period_index*runtime->period_size;-}elseif(substream->stream==SNDRV_PCM_STREAM_CAPTURE){-ptr=omap_get_dma_dst_pos(prtd->dma_ch);-offset=bytes_to_frames(runtime,ptr-runtime->dma_addr);-}else{-ptr=omap_get_dma_src_pos(prtd->dma_ch);-offset=bytes_to_frames(runtime,ptr-runtime->dma_addr);-}--if(offset>=runtime->buffer_size)-offset=0;+if(cpu_is_omap1510())+offset=snd_dmaengine_pcm_pointer_no_residue(substream);+else+offset=snd_dmaengine_pcm_pointer(substream);returnoffset;}
From: Russell King - ARM Linux <hidden> Date: 2012-09-12 12:02:14
On Wed, Sep 12, 2012 at 02:47:07PM +0300, Peter Ujfalusi wrote:
2. Pause/Resume
OMAP DMA engine backend does not support pausing and resuming
an in-progress transfer. It is unclear from the specs what
effect clearing the enable bit has on the DMA position of a
destination synchronized transfer, and whether the transfer
can be restarted from the exact point that it was paused (or
whether the data in the FIFO read from memory is simply
discarded.)
It's worth noting that this comment (which was in my original patch)
is there to spark _comment_ and _discussion_ and should not make its
way into the final version of these patches.
Given that suspend/resume is important on OMAP platforms, it's something
that needs to be resolved - in a way that complies with what ALSA expects.
I do not believe that the way the existing drivers do this is compliant
as the manuals imply that stopping memory->peripheral transfers results
in data being discarded from the DMA's FIFOs. As I understand it, ALSA
requires no data to be discarded.
As we have no way to know how much data may be discarded from the DMA
FIFO...
From: Peter Ujfalusi <hidden> Date: 2012-09-12 12:53:13
On 09/12/2012 03:00 PM, Russell King - ARM Linux wrote:
On Wed, Sep 12, 2012 at 02:47:07PM +0300, Peter Ujfalusi wrote:
quoted
2. Pause/Resume
OMAP DMA engine backend does not support pausing and resuming
an in-progress transfer. It is unclear from the specs what
effect clearing the enable bit has on the DMA position of a
destination synchronized transfer, and whether the transfer
can be restarted from the exact point that it was paused (or
whether the data in the FIFO read from memory is simply
discarded.)
It's worth noting that this comment (which was in my original patch)
is there to spark _comment_ and _discussion_ and should not make its
way into the final version of these patches.
Given that suspend/resume is important on OMAP platforms, it's something
that needs to be resolved - in a way that complies with what ALSA expects.
I do not believe that the way the existing drivers do this is compliant
as the manuals imply that stopping memory->peripheral transfers results
in data being discarded from the DMA's FIFOs. As I understand it, ALSA
requires no data to be discarded.
As we have no way to know how much data may be discarded from the DMA
FIFO...
I need to look at this, but at first look we do wait for the drain in
omap_stop_dma(). We used to use omap_stop_dma/omap_start_dma for pause/resume
operations.
But sDMA also have a bit: CDPi: PAUSE_LINK_LIST which should do what we are
looking for.
Need to read the relevant parts of the TRM, but AFAIK we are using normal mode
with linked list (self linking).
I already have the patch for this, I just need to test it on HW.
--
P?ter
From: Peter Ujfalusi <hidden> Date: 2012-09-12 14:35:25
On 09/12/2012 03:53 PM, Peter Ujfalusi wrote:
I need to look at this, but at first look we do wait for the drain in
omap_stop_dma(). We used to use omap_stop_dma/omap_start_dma for pause/resume
operations.
But sDMA also have a bit: CDPi: PAUSE_LINK_LIST which should do what we are
looking for.
Need to read the relevant parts of the TRM, but AFAIK we are using normal mode
with linked list (self linking).
I already have the patch for this, I just need to test it on HW.
We can get the PAUSE/RESUME work either:
1.
drivers/dma/omap-dma.c
static int omap_dma_pause(struct omap_chan *c)
{
- /* FIXME: not supported by platform private API */
- return -EINVAL;
+ /* Only in cyclic mode */
+ if (!c->cyclic)
+ return -EINVAL;
+
+ if (!c->paused) {
+ omap_stop_dma(c->dma_ch);
+ c->paused = true;
+ }
+
+ return 0;
}
static int omap_dma_resume(struct omap_chan *c)
{
- /* FIXME: not supported by platform private API */
- return -EINVAL;
+ /* Only in cyclic mode */
+ if (!c->cyclic)
+ return -EINVAL;
+
+ if (c->paused) {
+ omap_start_dma(c->dma_ch);
+ c->paused = false;
+ }
+
+ return 0;
}
2.
arch/arm/plat-omap/dma.c
+void omap_pause_linked_dma(int lch)
+{
+ u32 l;
+ unsigned long flags;
+
+ local_irq_save(flags);
+ l = p->dma_read(CDP, lch);
+ l |= 0x80; /* PAUSE_LINK_LIST */
+ p->dma_write(l, CDP, lch);
+ local_irq_restore(flags);
+}
+EXPORT_SYMBOL(omap_pause_linked_dma);
+
+void omap_resume_linked_dma(int lch)
+{
+ u32 l;
+ unsigned long flags;
+
+ local_irq_save(flags);
+ l = p->dma_read(CDP, lch);
+ l &= (~0x80); /* PAUSE_LINK_LIST */
+ p->dma_write(l, CDP, lch);
+ local_irq_restore(flags);
+}
+EXPORT_SYMBOL(omap_resume_linked_dma);
drivers/dma/omap-dma.c
static int omap_dma_pause(struct omap_chan *c)
{
- /* FIXME: not supported by platform private API */
- return -EINVAL;
+ /* Only in cyclic mode */
+ if (!c->cyclic)
+ return -EINVAL;
+
+ if (!c->paused) {
+ omap_pause_linked_dma(c->dma_ch);
+ c->paused = true;
+ }
+
+ return 0;
}
static int omap_dma_resume(struct omap_chan *c)
{
- /* FIXME: not supported by platform private API */
- return -EINVAL;
+ /* Only in cyclic mode */
+ if (!c->cyclic)
+ return -EINVAL;
+
+ if (c->paused) {
+ omap_resume_linked_dma(c->dma_ch);
+ c->paused = false;
+ }
+
+ return 0;
}
Both works fine (have tested it on BeagleBoard with mplayer).
With [1] we have identical way of dealing with the PAUSE/RESUME as we had
previously, so it is know to work fine on OMAP1/2/3/4/5
We have never used [2] in the past, but I think that is not going to work on
OMAP1 and OMAP2420. Also we need to add code to arch/arm/plat-omap/dma.c for
this...
I can resend the series with either of these to fix this regression caused by
the dmaengine conversion (after cleanup off course).
--
P?ter
At Wed, 12 Sep 2012 13:00:28 +0100,
Russell King - ARM Linux wrote:
On Wed, Sep 12, 2012 at 02:47:07PM +0300, Peter Ujfalusi wrote:
quoted
2. Pause/Resume
OMAP DMA engine backend does not support pausing and resuming
an in-progress transfer. It is unclear from the specs what
effect clearing the enable bit has on the DMA position of a
destination synchronized transfer, and whether the transfer
can be restarted from the exact point that it was paused (or
whether the data in the FIFO read from memory is simply
discarded.)
It's worth noting that this comment (which was in my original patch)
is there to spark _comment_ and _discussion_ and should not make its
way into the final version of these patches.
I agree this can be regarded as a sort of regression...
Given that suspend/resume is important on OMAP platforms, it's something
that needs to be resolved - in a way that complies with what ALSA expects.
I do not believe that the way the existing drivers do this is compliant
as the manuals imply that stopping memory->peripheral transfers results
in data being discarded from the DMA's FIFOs. As I understand it, ALSA
requires no data to be discarded.
... but in general you don't need to implement the full PAUSE and
RESUME operations for PCM. For example, when SNDRV_PCM_INFO_RESUME
bit isn't set, user-space is supposed to do a clean restart of the
stream at wake up. So, it shouldn't break the apps severely in
theory (but in practice, who knows :)
As we have no way to know how much data may be discarded from the DMA
FIFO...
Yeah, the FIFO and the amount of other on flight data can be better
managed.
Takashi
From: Peter Ujfalusi <hidden> Date: 2012-09-12 11:48:03
Instead of the OMAP DMA data type definition the data_type will be used to
specify the number of bits the DMA word should be configured or 0 in case
when based on the stream's format the omap-pcm can decide the needed DMA
word size.
This feature is needed for the omap-hdmi where the sDMA need to be
configured for 32bit word type regardless of the audio format used.
Signed-off-by: Peter Ujfalusi <redacted>
---
sound/soc/omap/omap-hdmi.c | 3 +--
sound/soc/omap/omap-pcm.c | 3 ++-
sound/soc/omap/omap-pcm.h | 3 ++-
3 files changed, 5 insertions(+), 4 deletions(-)
@@ -32,7 +32,8 @@ struct omap_pcm_dma_data {intdma_req;/* DMA request line */unsignedlongport_addr;/* transmit/receive register */void(*set_threshold)(structsnd_pcm_substream*substream);-intdata_type;/* data type 8,16,32 */+intdata_type;/* 8, 16, 32 (bits) or 0 to let omap-pcm+*todecidethesDMAdatatype*/intpacket_size;/* packet size only in PACKET mode */};
From: Peter Ujfalusi <hidden> Date: 2012-09-12 11:48:25
Get the needed resources in a correct way and avoid using defines for them.
Signed-off-by: Peter Ujfalusi <redacted>
---
sound/soc/omap/omap-mcpdm.c | 28 +++++++++++++++++++++++-----
1 file changed, 23 insertions(+), 5 deletions(-)
From: Peter Ujfalusi <hidden> Date: 2012-09-12 11:48:47
To help the driver to get the correct memory range to access McPDM
registers.
Signed-off-by: Peter Ujfalusi <redacted>
---
arch/arm/mach-omap2/omap_hwmod_44xx_data.c | 2 ++
1 file changed, 2 insertions(+)
From: Peter Ujfalusi <hidden> Date: 2012-09-12 11:48:48
Based on the format of the stream the omap-pcm can decide alone what data
type should be used with by the sDMA.
Keep the possibility for OMAP dai drivers to tell omap-pcm if they want to
use different data type. This is needed for the omap-hdmi for example which
needs 32bit data type even if the stream format is S16_LE.
The check if (dma_data->data_type) is safe at the moment since omap-pcm
does not support 8bit samples (OMAP_DMA_DATA_TYPE_S8 == 0x00).
The next step is to redefine the meaning of dma_data->data_type to unblock
this limitation.
Signed-off-by: Peter Ujfalusi <redacted>
---
sound/soc/omap/omap-pcm.c | 31 +++++++++++++++++++++++++++++--
1 file changed, 29 insertions(+), 2 deletions(-)
From: Mark Brown <hidden> Date: 2012-09-13 08:12:02
On Wed, Sep 12, 2012 at 02:46:56PM +0300, Peter Ujfalusi wrote:
Hello,
This series will switch the OMAP audio to use dmaengine.
The final patch which does the switch was based on Russell King's earlier patch.
I'm fine with this from the ASoC side but it sounds like you're going to
respin anyway. Are the earlier bits of the series safe to apply without
the last bit, it seems like that's the only bit that really needs a
respin so we may as well go ahead and apply the earlier bits now?
From: Peter Ujfalusi <hidden> Date: 2012-09-13 09:20:09
On 09/13/2012 11:11 AM, Mark Brown wrote:
On Wed, Sep 12, 2012 at 02:46:56PM +0300, Peter Ujfalusi wrote:
quoted
Hello,
This series will switch the OMAP audio to use dmaengine.
The final patch which does the switch was based on Russell King's earlier patch.
I'm fine with this from the ASoC side but it sounds like you're going to
respin anyway. Are the earlier bits of the series safe to apply without
the last bit, it seems like that's the only bit that really needs a
respin so we may as well go ahead and apply the earlier bits now?
Yes, I'm preparing the second series (adding the pause/resume support).
Patch 2-10 is to prepare the OMAP audio drivers for the dmaengine conversion
they can be applied earlier IMHO.
I can in turn can send only dmaengine related patches in v2 (patch 1 and 10
from this series and additional ones).
Anyways I need some time to figure out how to add back the support for
SNDRV_PCM_INFO_NO_PERIOD_WAKEUP.
Either way is good for me.
--
P?ter