From: Takashi Iwai Date: Wed, 25 May 2016 13:03:51 +0000 (+0200) Subject: pcm: dmix: resume workaround for buggy driver X-Git-Tag: v1.1.2~122 X-Git-Url: https://git.alsa-project.org/?a=commitdiff_plain;h=6d1d620eadf32c6d963468ce56ff52cc3a2f32e2;p=alsa-lib.git pcm: dmix: resume workaround for buggy driver The previous commit removed the whole handling of resume in dmix, but this seems causing another regression; some buggy drivers assume that the device-resume needs to be triggered before transitioning to PREPARED state. As an ugly workaround, in this patch, when the slave PCM supports resume, snd_pcm_direct_resume() does resume of the slave PCM but immediately drop the stream after that. In that way, the device is brought to the sane active state, then the apps can prepare and restart the stream properly. Signed-off-by: Takashi Iwai --- diff --git a/src/pcm/pcm_direct.c b/src/pcm/pcm_direct.c index 53c49929..343fd3c6 100644 --- a/src/pcm/pcm_direct.c +++ b/src/pcm/pcm_direct.c @@ -837,6 +837,27 @@ int snd_pcm_direct_prepare(snd_pcm_t *pcm) int snd_pcm_direct_resume(snd_pcm_t *pcm) { + snd_pcm_direct_t *dmix = pcm->private_data; + snd_pcm_t *spcm = dmix->spcm; + + snd_pcm_direct_semaphore_down(dmix, DIRECT_IPC_SEM_CLIENT); + /* some buggy drivers require the device resumed before prepared; + * when a device has RESUME flag and is in SUSPENDED state, resume + * here but immediately drop to bring it to a sane active state. + */ + if ((spcm->info & SND_PCM_INFO_RESUME) && + snd_pcm_state(spcm) == SND_PCM_STATE_SUSPENDED) { + snd_pcm_resume(spcm); + snd_pcm_drop(spcm); + snd_pcm_direct_timer_stop(dmix); + snd_pcm_direct_clear_timer_queue(dmix); + snd_pcm_areas_silence(snd_pcm_mmap_areas(spcm), 0, + spcm->channels, spcm->buffer_size, + spcm->format); + snd_pcm_prepare(spcm); + snd_pcm_start(spcm); + } + snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT); return -ENOSYS; } @@ -845,7 +866,7 @@ int snd_pcm_direct_resume(snd_pcm_t *pcm) /* copy the slave setting */ static void save_slave_setting(snd_pcm_direct_t *dmix, snd_pcm_t *spcm) { - spcm->info &= ~(SND_PCM_INFO_PAUSE | SND_PCM_INFO_RESUME); + spcm->info &= ~SND_PCM_INFO_PAUSE; COPY_SLAVE(access); COPY_SLAVE(format); @@ -874,6 +895,8 @@ static void save_slave_setting(snd_pcm_direct_t *dmix, snd_pcm_t *spcm) COPY_SLAVE(buffer_time); COPY_SLAVE(sample_bits); COPY_SLAVE(frame_bits); + + dmix->shmptr->s.info &= ~SND_PCM_INFO_RESUME; } #undef COPY_SLAVE