Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ALSA: dmaengine: Synchronize dma channel after drop()

Sometimes the stream may be stopped due to XRUN events, in which case
the userspace can call snd_pcm_drop() and snd_pcm_prepare() to stop and
start the stream again.

In these cases, we must wait for the DMA channel to synchronize before
marking the stream as prepared for playback, as the DMA channel gets
stopped by drop() without any synchronization. Make sure the ALSA core
synchronizes the DMA channel by adding a sync_stop() hook.

Reviewed-by: Peter Ujfalusi <peter.ujfalusi@gmail.com>
Signed-off-by: Jai Luthra <j-luthra@ti.com>
Link: https://lore.kernel.org/r/20240611-asoc_next-v3-1-fcfd84b12164@ti.com
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Jai Luthra and committed by
Mark Brown
e8343410 b9dd212b

+19
+1
include/sound/dmaengine_pcm.h
··· 36 36 int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream, 37 37 struct dma_chan *chan); 38 38 int snd_dmaengine_pcm_close(struct snd_pcm_substream *substream); 39 + int snd_dmaengine_pcm_sync_stop(struct snd_pcm_substream *substream); 39 40 40 41 int snd_dmaengine_pcm_open_request_chan(struct snd_pcm_substream *substream, 41 42 dma_filter_fn filter_fn, void *filter_data);
+10
sound/core/pcm_dmaengine.c
··· 349 349 } 350 350 EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_open_request_chan); 351 351 352 + int snd_dmaengine_pcm_sync_stop(struct snd_pcm_substream *substream) 353 + { 354 + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); 355 + 356 + dmaengine_synchronize(prtd->dma_chan); 357 + 358 + return 0; 359 + } 360 + EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_sync_stop); 361 + 352 362 /** 353 363 * snd_dmaengine_pcm_close - Close a dmaengine based PCM substream 354 364 * @substream: PCM substream
+8
sound/soc/soc-generic-dmaengine-pcm.c
··· 318 318 return 0; 319 319 } 320 320 321 + static int dmaengine_pcm_sync_stop(struct snd_soc_component *component, 322 + struct snd_pcm_substream *substream) 323 + { 324 + return snd_dmaengine_pcm_sync_stop(substream); 325 + } 326 + 321 327 static const struct snd_soc_component_driver dmaengine_pcm_component = { 322 328 .name = SND_DMAENGINE_PCM_DRV_NAME, 323 329 .probe_order = SND_SOC_COMP_ORDER_LATE, ··· 333 327 .trigger = dmaengine_pcm_trigger, 334 328 .pointer = dmaengine_pcm_pointer, 335 329 .pcm_construct = dmaengine_pcm_new, 330 + .sync_stop = dmaengine_pcm_sync_stop, 336 331 }; 337 332 338 333 static const struct snd_soc_component_driver dmaengine_pcm_component_process = { ··· 346 339 .pointer = dmaengine_pcm_pointer, 347 340 .copy = dmaengine_copy, 348 341 .pcm_construct = dmaengine_pcm_new, 342 + .sync_stop = dmaengine_pcm_sync_stop, 349 343 }; 350 344 351 345 static const char * const dmaengine_pcm_dma_channel_names[] = {