diff options
| -rw-r--r-- | sound/drivers/aloop.c | 32 |
1 files changed, 19 insertions, 13 deletions
diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c index 66786ea6f480..38e8351e935d 100644 --- a/sound/drivers/aloop.c +++ b/sound/drivers/aloop.c | |||
| @@ -263,13 +263,17 @@ static int loopback_trigger(struct snd_pcm_substream *substream, int cmd) | |||
| 263 | return err; | 263 | return err; |
| 264 | dpcm->last_jiffies = jiffies; | 264 | dpcm->last_jiffies = jiffies; |
| 265 | dpcm->pcm_rate_shift = 0; | 265 | dpcm->pcm_rate_shift = 0; |
| 266 | loopback_timer_start(dpcm); | 266 | spin_lock(&cable->lock); |
| 267 | cable->running |= (1 << substream->stream); | 267 | cable->running |= (1 << substream->stream); |
| 268 | spin_unlock(&cable->lock); | ||
| 269 | loopback_timer_start(dpcm); | ||
| 268 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 270 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
| 269 | loopback_active_notify(dpcm); | 271 | loopback_active_notify(dpcm); |
| 270 | break; | 272 | break; |
| 271 | case SNDRV_PCM_TRIGGER_STOP: | 273 | case SNDRV_PCM_TRIGGER_STOP: |
| 274 | spin_lock(&cable->lock); | ||
| 272 | cable->running &= ~(1 << substream->stream); | 275 | cable->running &= ~(1 << substream->stream); |
| 276 | spin_unlock(&cable->lock); | ||
| 273 | loopback_timer_stop(dpcm); | 277 | loopback_timer_stop(dpcm); |
| 274 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 278 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
| 275 | loopback_active_notify(dpcm); | 279 | loopback_active_notify(dpcm); |
| @@ -454,28 +458,30 @@ static void loopback_bytepos_update(struct loopback_pcm *dpcm, | |||
| 454 | } | 458 | } |
| 455 | } | 459 | } |
| 456 | 460 | ||
| 457 | static void loopback_pos_update(struct loopback_cable *cable) | 461 | static unsigned int loopback_pos_update(struct loopback_cable *cable) |
| 458 | { | 462 | { |
| 459 | struct loopback_pcm *dpcm_play = | 463 | struct loopback_pcm *dpcm_play = |
| 460 | cable->streams[SNDRV_PCM_STREAM_PLAYBACK]; | 464 | cable->streams[SNDRV_PCM_STREAM_PLAYBACK]; |
| 461 | struct loopback_pcm *dpcm_capt = | 465 | struct loopback_pcm *dpcm_capt = |
| 462 | cable->streams[SNDRV_PCM_STREAM_CAPTURE]; | 466 | cable->streams[SNDRV_PCM_STREAM_CAPTURE]; |
| 463 | unsigned long delta_play = 0, delta_capt = 0; | 467 | unsigned long delta_play = 0, delta_capt = 0; |
| 468 | unsigned int running; | ||
| 464 | 469 | ||
| 465 | spin_lock(&cable->lock); | 470 | spin_lock(&cable->lock); |
| 466 | if (cable->running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) { | 471 | running = cable->running; |
| 472 | if (running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) { | ||
| 467 | delta_play = jiffies - dpcm_play->last_jiffies; | 473 | delta_play = jiffies - dpcm_play->last_jiffies; |
| 468 | dpcm_play->last_jiffies += delta_play; | 474 | dpcm_play->last_jiffies += delta_play; |
| 469 | } | 475 | } |
| 470 | 476 | ||
| 471 | if (cable->running & (1 << SNDRV_PCM_STREAM_CAPTURE)) { | 477 | if (running & (1 << SNDRV_PCM_STREAM_CAPTURE)) { |
| 472 | delta_capt = jiffies - dpcm_capt->last_jiffies; | 478 | delta_capt = jiffies - dpcm_capt->last_jiffies; |
| 473 | dpcm_capt->last_jiffies += delta_capt; | 479 | dpcm_capt->last_jiffies += delta_capt; |
| 474 | } | 480 | } |
| 475 | 481 | ||
| 476 | if (delta_play == 0 && delta_capt == 0) { | 482 | if (delta_play == 0 && delta_capt == 0) { |
| 477 | spin_unlock(&cable->lock); | 483 | spin_unlock(&cable->lock); |
| 478 | return; | 484 | return running; |
| 479 | } | 485 | } |
| 480 | 486 | ||
| 481 | if (delta_play > delta_capt) { | 487 | if (delta_play > delta_capt) { |
| @@ -490,27 +496,27 @@ static void loopback_pos_update(struct loopback_cable *cable) | |||
| 490 | 496 | ||
| 491 | if (delta_play == 0 && delta_capt == 0) { | 497 | if (delta_play == 0 && delta_capt == 0) { |
| 492 | spin_unlock(&cable->lock); | 498 | spin_unlock(&cable->lock); |
| 493 | return; | 499 | return running; |
| 494 | } | 500 | } |
| 495 | /* note delta_capt == delta_play at this moment */ | 501 | /* note delta_capt == delta_play at this moment */ |
| 496 | loopback_bytepos_update(dpcm_capt, delta_capt, BYTEPOS_UPDATE_COPY); | 502 | loopback_bytepos_update(dpcm_capt, delta_capt, BYTEPOS_UPDATE_COPY); |
| 497 | loopback_bytepos_update(dpcm_play, delta_play, BYTEPOS_UPDATE_POSONLY); | 503 | loopback_bytepos_update(dpcm_play, delta_play, BYTEPOS_UPDATE_POSONLY); |
| 498 | spin_unlock(&cable->lock); | 504 | spin_unlock(&cable->lock); |
| 505 | return running; | ||
| 499 | } | 506 | } |
| 500 | 507 | ||
| 501 | static void loopback_timer_function(unsigned long data) | 508 | static void loopback_timer_function(unsigned long data) |
| 502 | { | 509 | { |
| 503 | struct loopback_pcm *dpcm = (struct loopback_pcm *)data; | 510 | struct loopback_pcm *dpcm = (struct loopback_pcm *)data; |
| 504 | int stream; | 511 | unsigned int running; |
| 505 | 512 | ||
| 506 | loopback_pos_update(dpcm->cable); | 513 | running = loopback_pos_update(dpcm->cable); |
| 507 | stream = dpcm->substream->stream; | 514 | if (running & (1 << dpcm->substream->stream)) { |
| 508 | if (dpcm->cable->running & (1 << stream)) | ||
| 509 | loopback_timer_start(dpcm); | 515 | loopback_timer_start(dpcm); |
| 510 | if (dpcm->period_update_pending) { | 516 | if (dpcm->period_update_pending) { |
| 511 | dpcm->period_update_pending = 0; | 517 | dpcm->period_update_pending = 0; |
| 512 | if (dpcm->cable->running & (1 << stream)) | ||
| 513 | snd_pcm_period_elapsed(dpcm->substream); | 518 | snd_pcm_period_elapsed(dpcm->substream); |
| 519 | } | ||
| 514 | } | 520 | } |
| 515 | } | 521 | } |
| 516 | 522 | ||
