+ 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;