- snd_power_lock(card);
- snd_pcm_stream_lock_irq(substream);
- switch (runtime->status->state) {
- case SNDRV_PCM_STATE_OPEN:
- res = -EBADFD;
- break;
- case SNDRV_PCM_STATE_SETUP:
- break;
- case SNDRV_PCM_STATE_PAUSED:
- snd_pcm_pause(substream, 0);
- /* Fall through */
- case SNDRV_PCM_STATE_RUNNING:
- case SNDRV_PCM_STATE_DRAINING:
- if (snd_pcm_update_hw_ptr(substream) >= 0) {
- snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP);
- break;
- }
- /* Fall through */
- case SNDRV_PCM_STATE_PREPARED:
- case SNDRV_PCM_STATE_XRUN:
- snd_pcm_change_state(substream, SNDRV_PCM_STATE_SETUP);
- break;
- case SNDRV_PCM_STATE_SUSPENDED:
- snd_pcm_stream_unlock_irq(substream);
- res = snd_power_wait(card, SNDRV_CTL_POWER_D0, substream->ffile);
- snd_pcm_stream_lock_irq(substream);
- if (res >= 0)
- snd_pcm_change_state(substream, SNDRV_PCM_STATE_SETUP);
- break;
- default:
- break;
- }
- runtime->control->appl_ptr = runtime->status->hw_ptr;
- snd_pcm_stream_unlock_irq(substream);
- snd_power_unlock(card);
- return res;
-}
-
-static int snd_pcm_capture_drain(snd_pcm_substream_t * substream)
-{
- snd_pcm_runtime_t *runtime = substream->runtime;
- snd_card_t *card = substream->pcm->card;
- int res = 0;
-
- snd_power_lock(card);
- snd_pcm_stream_lock_irq(substream);
- switch (runtime->status->state) {
- case SNDRV_PCM_STATE_OPEN:
- res = -EBADFD;
- break;
- case SNDRV_PCM_STATE_PREPARED:
- snd_pcm_change_state(substream, SNDRV_PCM_STATE_SETUP);
- break;
- case SNDRV_PCM_STATE_SETUP:
- case SNDRV_PCM_STATE_DRAINING:
- break;
- case SNDRV_PCM_STATE_PAUSED:
- snd_pcm_pause(substream, 0);
- /* Fall through */
- case SNDRV_PCM_STATE_RUNNING:
- if (snd_pcm_update_hw_ptr(substream) >= 0) {
- snd_pcm_stop(substream,
- snd_pcm_capture_avail(runtime) > 0 ?
- SNDRV_PCM_STATE_DRAINING : SNDRV_PCM_STATE_SETUP);
- break;
- }
- /* Fall through */
- case SNDRV_PCM_STATE_XRUN:
- _xrun_recovery:
- snd_pcm_change_state(substream,
- snd_pcm_capture_avail(runtime) > 0 ?
- SNDRV_PCM_STATE_DRAINING : SNDRV_PCM_STATE_SETUP);
- break;
- case SNDRV_PCM_STATE_SUSPENDED:
- snd_pcm_stream_unlock_irq(substream);
- res = snd_power_wait(card, SNDRV_CTL_POWER_D0, substream->ffile);
- snd_pcm_stream_lock_irq(substream);
- if (res >= 0)
- goto _xrun_recovery;
- break;
- default:
- break;
- }
- snd_pcm_stream_unlock_irq(substream);
- snd_power_unlock(card);
- return res;
-}