[alsa-devel] Is there a function I can call from my ISR to tell ALSA to abort playback?
In my ISR, I call snd_pcm_period_elapsed() to tell it that a period has elapsed. I can also detect if playback has aborted for some reason (e.g. DMA controller has died). Is there a function I can call in my ISR to tell ALSA to abort playback or capture?
On Wed, 14 Nov 2007, Timur Tabi wrote:
In my ISR, I call snd_pcm_period_elapsed() to tell it that a period has elapsed. I can also detect if playback has aborted for some reason (e.g. DMA controller has died). Is there a function I can call in my ISR to tell ALSA to abort playback or capture?
Yes, call snd_pcm_stop() function. The call must be protected with snd_pcm_stream_lock... See to i2c/other/ak4117.c for an example.
Jaroslav
----- Jaroslav Kysela perex@perex.cz Linux Kernel Sound Maintainer ALSA Project
Jaroslav Kysela wrote:
Yes, call snd_pcm_stop() function. The call must be protected with snd_pcm_stream_lock... See to i2c/other/ak4117.c for an example.
That code calls snd_pcm_stop() from a timer, not an ISR. Do I need the call to wake_up() as well?
At Thu, 15 Nov 2007 09:00:54 -0600, Timur Tabi wrote:
Jaroslav Kysela wrote:
Yes, call snd_pcm_stop() function. The call must be protected with snd_pcm_stream_lock... See to i2c/other/ak4117.c for an example.
That code calls snd_pcm_stop() from a timer, not an ISR. Do I need the call to wake_up() as well?
snd_pcm_stop() can be called from ISR, too (e.g. snd_pcm_period_elapsed() may call snd_pcm_stop() when XRUN occurs). You only need to protect it via snd_pcm_stream_lock*().
Takashi
Takashi Iwai wrote:
At Thu, 15 Nov 2007 09:00:54 -0600, Timur Tabi wrote:
Jaroslav Kysela wrote:
Yes, call snd_pcm_stop() function. The call must be protected with snd_pcm_stream_lock... See to i2c/other/ak4117.c for an example.
That code calls snd_pcm_stop() from a timer, not an ISR. Do I need the call to wake_up() as well?
snd_pcm_stop() can be called from ISR, too (e.g. snd_pcm_period_elapsed() may call snd_pcm_stop() when XRUN occurs). You only need to protect it via snd_pcm_stream_lock*().
It doesn't seem to do much. Here's the function I wrote:
static void fsl_dma_abort_stream(struct snd_pcm_substream *substream) { unsigned long flags;
snd_pcm_stream_lock_irqsave(substream, flags); if (snd_pcm_running(substream)) { snd_pcm_stop(substream, SNDRV_PCM_STATE_DRAINING); wake_up(&substream->runtime->sleep); } snd_pcm_stream_unlock_irqrestore(substream, flags); }
When I play a file, my DMA controller is incorrectly programmed (test case) and this function gets triggered. The application (aplay) does not terminate.
I tried it with the wake_up() call, but it didn't make a difference.
At Thu, 15 Nov 2007 14:28:14 -0600, Timur Tabi wrote:
Takashi Iwai wrote:
At Thu, 15 Nov 2007 09:00:54 -0600, Timur Tabi wrote:
Jaroslav Kysela wrote:
Yes, call snd_pcm_stop() function. The call must be protected with snd_pcm_stream_lock... See to i2c/other/ak4117.c for an example.
That code calls snd_pcm_stop() from a timer, not an ISR. Do I need the call to wake_up() as well?
snd_pcm_stop() can be called from ISR, too (e.g. snd_pcm_period_elapsed() may call snd_pcm_stop() when XRUN occurs). You only need to protect it via snd_pcm_stream_lock*().
It doesn't seem to do much. Here's the function I wrote:
static void fsl_dma_abort_stream(struct snd_pcm_substream *substream) { unsigned long flags;
snd_pcm_stream_lock_irqsave(substream, flags); if (snd_pcm_running(substream)) { snd_pcm_stop(substream, SNDRV_PCM_STATE_DRAINING);
You passed a wrong state. Usually snd_pcm_stop() passes either SNDRV_PCM_STATE_SETUP (for post-draining) or SNDRV_PCM_STATE_XRUN (for errors).
wake_up(&substream->runtime->sleep);
} snd_pcm_stream_unlock_irqrestore(substream, flags); }
This wake_up is superfluous. Now I understand your question in the last mail...
When I play a file, my DMA controller is incorrectly programmed (test case) and this function gets triggered. The application (aplay) does not terminate.
The app is *not* terminated, of course, but it must get an error when it accesses to the PCM (-EPIPE in the case XRUN).
Takashi
On Fri, 16 Nov 2007, Takashi Iwai wrote:
At Thu, 15 Nov 2007 14:28:14 -0600, Timur Tabi wrote:
Takashi Iwai wrote:
At Thu, 15 Nov 2007 09:00:54 -0600, Timur Tabi wrote:
Jaroslav Kysela wrote:
Yes, call snd_pcm_stop() function. The call must be protected with snd_pcm_stream_lock... See to i2c/other/ak4117.c for an example.
That code calls snd_pcm_stop() from a timer, not an ISR. Do I need the call to wake_up() as well?
snd_pcm_stop() can be called from ISR, too (e.g. snd_pcm_period_elapsed() may call snd_pcm_stop() when XRUN occurs). You only need to protect it via snd_pcm_stream_lock*().
It doesn't seem to do much. Here's the function I wrote:
static void fsl_dma_abort_stream(struct snd_pcm_substream *substream) { unsigned long flags;
snd_pcm_stream_lock_irqsave(substream, flags); if (snd_pcm_running(substream)) { snd_pcm_stop(substream, SNDRV_PCM_STATE_DRAINING);
You passed a wrong state. Usually snd_pcm_stop() passes either SNDRV_PCM_STATE_SETUP (for post-draining) or SNDRV_PCM_STATE_XRUN (for errors).
wake_up(&substream->runtime->sleep);
} snd_pcm_stream_unlock_irqrestore(substream, flags); }
This wake_up is superfluous. Now I understand your question in the last mail...
I'm not sure if the wake call is superfluous, if driver ends to call elapsed callbacks, there is no way to wakeup process when it sleeps somewhere. I think that code might be covered with a nice macro with a name like 'snd_pcm_hw_stopped()' or so.
Jaroslav
----- Jaroslav Kysela perex@perex.cz Linux Kernel Sound Maintainer ALSA Project
At Fri, 16 Nov 2007 11:41:51 +0100 (CET), Jaroslav Kysela wrote:
On Fri, 16 Nov 2007, Takashi Iwai wrote:
At Thu, 15 Nov 2007 14:28:14 -0600, Timur Tabi wrote:
Takashi Iwai wrote:
At Thu, 15 Nov 2007 09:00:54 -0600, Timur Tabi wrote:
Jaroslav Kysela wrote:
Yes, call snd_pcm_stop() function. The call must be protected with snd_pcm_stream_lock... See to i2c/other/ak4117.c for an example.
That code calls snd_pcm_stop() from a timer, not an ISR. Do I need the call to wake_up() as well?
snd_pcm_stop() can be called from ISR, too (e.g. snd_pcm_period_elapsed() may call snd_pcm_stop() when XRUN occurs). You only need to protect it via snd_pcm_stream_lock*().
It doesn't seem to do much. Here's the function I wrote:
static void fsl_dma_abort_stream(struct snd_pcm_substream *substream) { unsigned long flags;
snd_pcm_stream_lock_irqsave(substream, flags); if (snd_pcm_running(substream)) { snd_pcm_stop(substream, SNDRV_PCM_STATE_DRAINING);
You passed a wrong state. Usually snd_pcm_stop() passes either SNDRV_PCM_STATE_SETUP (for post-draining) or SNDRV_PCM_STATE_XRUN (for errors).
wake_up(&substream->runtime->sleep);
} snd_pcm_stream_unlock_irqrestore(substream, flags); }
This wake_up is superfluous. Now I understand your question in the last mail...
I'm not sure if the wake call is superfluous, if driver ends to call elapsed callbacks, there is no way to wakeup process when it sleeps somewhere. I think that code might be covered with a nice macro with a name like 'snd_pcm_hw_stopped()' or so.
But wake_up() is already in snd_pcm_post_stop(). How can this second call help?
thanks,
Takashi
On Fri, 16 Nov 2007, Takashi Iwai wrote:
At Fri, 16 Nov 2007 11:41:51 +0100 (CET), Jaroslav Kysela wrote:
On Fri, 16 Nov 2007, Takashi Iwai wrote:
At Thu, 15 Nov 2007 14:28:14 -0600, Timur Tabi wrote:
Takashi Iwai wrote:
At Thu, 15 Nov 2007 09:00:54 -0600, Timur Tabi wrote:
Jaroslav Kysela wrote:
> Yes, call snd_pcm_stop() function. The call must be protected with > snd_pcm_stream_lock... See to i2c/other/ak4117.c for an example. That code calls snd_pcm_stop() from a timer, not an ISR. Do I need the call to wake_up() as well?
snd_pcm_stop() can be called from ISR, too (e.g. snd_pcm_period_elapsed() may call snd_pcm_stop() when XRUN occurs). You only need to protect it via snd_pcm_stream_lock*().
It doesn't seem to do much. Here's the function I wrote:
static void fsl_dma_abort_stream(struct snd_pcm_substream *substream) { unsigned long flags;
snd_pcm_stream_lock_irqsave(substream, flags); if (snd_pcm_running(substream)) { snd_pcm_stop(substream, SNDRV_PCM_STATE_DRAINING);
You passed a wrong state. Usually snd_pcm_stop() passes either SNDRV_PCM_STATE_SETUP (for post-draining) or SNDRV_PCM_STATE_XRUN (for errors).
wake_up(&substream->runtime->sleep);
} snd_pcm_stream_unlock_irqrestore(substream, flags); }
This wake_up is superfluous. Now I understand your question in the last mail...
I'm not sure if the wake call is superfluous, if driver ends to call elapsed callbacks, there is no way to wakeup process when it sleeps somewhere. I think that code might be covered with a nice macro with a name like 'snd_pcm_hw_stopped()' or so.
But wake_up() is already in snd_pcm_post_stop(). How can this second call help?
Overlooked. Thanks.
Jaroslav
----- Jaroslav Kysela perex@perex.cz Linux Kernel Sound Maintainer ALSA Project
participants (3)
-
Jaroslav Kysela
-
Takashi Iwai
-
Timur Tabi