[alsa-cvslog] alsa-kernel: Official ALSA project GIT repository for Linux 2.6 branch, devel now at
Brought to you by:
perex
From: <nor...@al...> - 2010-10-20 07:36:00
|
Hello, This is an automated email from the git hooks/update script, it was generated because a ref change was pushed to the repository. Updating branch, devel, via 5de9e45fcfccdf8151a82fc1a521e7042cbe482a (commit) via dd04bb12d047a4d4461772093472a40dbe171e5f (commit) from e74670b6fdc37b15ebee11825849d8983e52a74a (commit) - Log ----------------------------------------------------------------- commit 5de9e45fcfccdf8151a82fc1a521e7042cbe482a Author: Jaroslav Kysela <pe...@pe...> AuthorDate: Wed Oct 20 09:33:03 2010 +0200 Commit: Jaroslav Kysela <pe...@pe...> CommitDate: Wed Oct 20 09:35:43 2010 +0200 ALSA: snd-aloop - add pause support Signed-off-by: Jaroslav Kysela <pe...@pe...> commit dd04bb12d047a4d4461772093472a40dbe171e5f Author: Jaroslav Kysela <pe...@pe...> AuthorDate: Wed Oct 20 08:27:02 2010 +0200 Commit: Jaroslav Kysela <pe...@pe...> CommitDate: Wed Oct 20 09:35:38 2010 +0200 ALSA: snd-aloop - fix locking issues (running flag updates) On SMP machines, the cable->running update must be atomic, otherwise stream is not started correctly sometimes. Signed-off-by: Jaroslav Kysela <pe...@pe...> ----------------------------------------------------------------------- Diffstat: sound/drivers/aloop.c | 55 ++++++++++++++++++++++++++++++++++-------------- 1 files changed, 39 insertions(+), 16 deletions(-) Patch -------------- (max 1500 lines) diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c index 66786ea..12b44b0 100644 --- a/sound/drivers/aloop.c +++ b/sound/drivers/aloop.c @@ -77,6 +77,7 @@ struct loopback_cable { /* flags */ unsigned int valid; unsigned int running; + unsigned int pause; }; struct loopback_setup { @@ -254,7 +255,7 @@ static int loopback_trigger(struct snd_pcm_substream *substream, int cmd) struct snd_pcm_runtime *runtime = substream->runtime; struct loopback_pcm *dpcm = runtime->private_data; struct loopback_cable *cable = dpcm->cable; - int err; + int err, stream = 1 << substream->stream; switch (cmd) { case SNDRV_PCM_TRIGGER_START: @@ -263,17 +264,36 @@ static int loopback_trigger(struct snd_pcm_substream *substream, int cmd) return err; dpcm->last_jiffies = jiffies; dpcm->pcm_rate_shift = 0; + spin_lock(&cable->lock); + cable->running |= stream; + cable->pause &= ~stream; + spin_unlock(&cable->lock); loopback_timer_start(dpcm); - cable->running |= (1 << substream->stream); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) loopback_active_notify(dpcm); break; case SNDRV_PCM_TRIGGER_STOP: - cable->running &= ~(1 << substream->stream); + spin_lock(&cable->lock); + cable->running &= ~stream; + cable->pause &= ~stream; + spin_unlock(&cable->lock); loopback_timer_stop(dpcm); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) loopback_active_notify(dpcm); break; + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + spin_lock(&cable->lock); + cable->pause |= stream; + spin_unlock(&cable->lock); + loopback_timer_stop(dpcm); + break; + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + spin_lock(&cable->lock); + dpcm->last_jiffies = jiffies; + cable->pause &= ~stream; + spin_unlock(&cable->lock); + loopback_timer_start(dpcm); + break; default: return -EINVAL; } @@ -454,28 +474,30 @@ static void loopback_bytepos_update(struct loopback_pcm *dpcm, } } -static void loopback_pos_update(struct loopback_cable *cable) +static unsigned int loopback_pos_update(struct loopback_cable *cable) { struct loopback_pcm *dpcm_play = cable->streams[SNDRV_PCM_STREAM_PLAYBACK]; struct loopback_pcm *dpcm_capt = cable->streams[SNDRV_PCM_STREAM_CAPTURE]; unsigned long delta_play = 0, delta_capt = 0; + unsigned int running; spin_lock(&cable->lock); - if (cable->running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) { + running = cable->running ^ cable->pause; + if (running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) { delta_play = jiffies - dpcm_play->last_jiffies; dpcm_play->last_jiffies += delta_play; } - if (cable->running & (1 << SNDRV_PCM_STREAM_CAPTURE)) { + if (running & (1 << SNDRV_PCM_STREAM_CAPTURE)) { delta_capt = jiffies - dpcm_capt->last_jiffies; dpcm_capt->last_jiffies += delta_capt; } if (delta_play == 0 && delta_capt == 0) { spin_unlock(&cable->lock); - return; + return running; } if (delta_play > delta_capt) { @@ -490,27 +512,27 @@ static void loopback_pos_update(struct loopback_cable *cable) if (delta_play == 0 && delta_capt == 0) { spin_unlock(&cable->lock); - return; + return running; } /* note delta_capt == delta_play at this moment */ loopback_bytepos_update(dpcm_capt, delta_capt, BYTEPOS_UPDATE_COPY); loopback_bytepos_update(dpcm_play, delta_play, BYTEPOS_UPDATE_POSONLY); spin_unlock(&cable->lock); + return running; } static void loopback_timer_function(unsigned long data) { struct loopback_pcm *dpcm = (struct loopback_pcm *)data; - int stream; + unsigned int running; - loopback_pos_update(dpcm->cable); - stream = dpcm->substream->stream; - if (dpcm->cable->running & (1 << stream)) + running = loopback_pos_update(dpcm->cable); + if (running & (1 << dpcm->substream->stream)) { loopback_timer_start(dpcm); - if (dpcm->period_update_pending) { - dpcm->period_update_pending = 0; - if (dpcm->cable->running & (1 << stream)) + if (dpcm->period_update_pending) { + dpcm->period_update_pending = 0; snd_pcm_period_elapsed(dpcm->substream); + } } } @@ -526,7 +548,7 @@ static snd_pcm_uframes_t loopback_pointer(struct snd_pcm_substream *substream) static struct snd_pcm_hardware loopback_pcm_hardware = { .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID), + SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_PAUSE), .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE | SNDRV_PCM_FMTBIT_FLOAT_LE | SNDRV_PCM_FMTBIT_FLOAT_BE), @@ -1054,6 +1076,7 @@ static void print_substream_info(struct snd_info_buffer *buffer, } snd_iprintf(buffer, " valid: %u\n", cable->valid); snd_iprintf(buffer, " running: %u\n", cable->running); + snd_iprintf(buffer, " pause: %u\n", cable->pause); print_dpcm_info(buffer, cable->streams[0], "Playback"); print_dpcm_info(buffer, cable->streams[1], "Capture"); } ------- End of patch hooks/update --- Git Source Code Management System hooks/update refs/heads/devel \ e74670b6fdc37b15ebee11825849d8983e52a74a \ 5de9e45fcfccdf8151a82fc1a521e7042cbe482a |