[alsa-devel] [RFC] [PATCH] ASoC: OMAP: full duplex mode fix

Janusz Krzysztofik jkrzyszt at tis.icnet.pl
Tue Aug 4 22:46:09 CEST 2009

Monday 03 August 2009 17:14:05 Jarkko Nikula wrote:
> So it looks that McBSP-DMA for another stream cease to work if there is
> more than certain delay between first stream start and second one but
> omap_mcbsp_pollwrite or _pollread will clear the error condition. Can
> you debug is this due clearing the possible XSYNC_ERR, waiting for
> transmit/receive confirmation or playing with data registers there?

I have temporarily modified those omap_mcbsp_pollwrite/_pollread() to do 
nothing but reporting, put them into omap_mcbsp_dai_trigger() as before and 
additionally into a newly created and registered omap_mcbsp_dai_prepare(), 
called before omap_start_dma(), and got the following result:

For both playback start while capturing and capture start while playing, 
XSYNC_ERR/RSYNC_ERR is clear and XRDY/RRDY is ready, respectively, both 
before and after omap_start_dma(). No DMA transfer is actually started, so 
the operation fails with i/o error.

My interpretation based on my SPRU592 and SPRU674 understanding:

While starting the first stream, omap_mcbsp_start(), called by 
omap_mcbsp_dai_trigger(), instructs McBSP to start shifting bits in both 
directions, no matter which one has just been requested. After that, the 
direction, for which a corresponding DMA transfer has just been started from 
omap_pcm_trigger() with omap_start_dma(), starts doing its job, while the 
opposite direction, after shifting in one word in case of capture, issues a 
DMA event that is missed and waits for an I/O to occur.

Then, when omap_pcm_trigger() starts DMA for the opposite direction, the DMA 
controller, configured for synchronized transfer, waits for a corresponding 
DMA event before it performs its first I/O operation. That event already 
occurred far before and will not occur again, so the transfer will not start 
without any intervention. This time, omap_mcbsp_start() is not called again 
for an already started hardware action (correct), so there is no chance for 
the transfer to start that way.

With my patch, performing an I/O operation by calling 
omap_mcbsp_pollwrite/_pollread() forces McBSP to issue next DMA event, that 
initiates the transfer.

While starting both streams (semi)simultaneously, it may happen that the DMA 
event for the opposite direction will occur after the DMA has just been 
started for that direction as well and will not be missed, so both streams 
will run correctly.

Does it make sense, or am I missing something?

If my analysis is correct, the best solution I can see would be starting McBSP 
transfer for one direction only, not both, so the opposite direction can be 
started when needed. That requires deeper and wider OMAP knowledge and a 
change in omap_mcbsp_start() API though. I am not in a position to deal with 
this myself, I'm afraid.


PS: Not CCing arch/arm/plat-omap/mcbsp.c author as his email address is 
probably out-of-date.

More information about the Alsa-devel mailing list