[alsa-devel] [PATCH] pcm: Don't store the state for SND_PCM_STATE_SUSPENDED

Shengjiu Wang shengjiu.wang at nxp.com
Tue May 31 11:27:39 CEST 2016


Hi

> 
> On Tue, 24 May 2016 12:18:18 +0200,
> Takashi Iwai wrote:
> >
> > On Tue, 24 May 2016 12:12:49 +0200,
> > Shengjiu Wang wrote:
> > >
> > > Hi
> > >
> > > > -----Original Message-----
> > > > From: Takashi Iwai [mailto:tiwai at suse.de]
> > > > Sent: Friday, May 20, 2016 10:32 PM
> > > > To: Shengjiu Wang
> > > > Cc: perex at perex.cz; alsa-devel at alsa-project.org
> > > > Subject: Re: [PATCH] pcm: Don't store the state for
> > > > SND_PCM_STATE_SUSPENDED
> > > >
> > > > On Fri, 20 May 2016 12:46:37 +0200,
> > > > Takashi Iwai wrote:
> > > > >
> > > > > On Fri, 20 May 2016 11:41:25 +0200,
> > > > > Shengjiu Wang wrote:
> > > > > >
> > > > > > Hi Takashi
> > > > > >
> > > > > >    I tested your patch, after suspend and resume, the
> playback is
> > > > stopped.
> > > > > > It is caused by the DMA. DMA is not started after resume.
> > > > > >
> > > > > > With your patch, DMA is not terminated but then is re-started.
> The
> > > > driver don't
> > > > > > support this behavior.
> > > > >
> > > > > If so, it's simply a driver bug.  Blame the kernel driver
> instead.
> > > >
> > > > Which driver did you see the problem?  We should fix it.
> > >
> > > But my thought is when suspended, the dmaengine_pause() is called,
> then
> > > dmaengine_resume() should be called in resume(). If there is no
> resume()
> > > Just call the prepare() and start(), it seems not reasonable. What
> do
> > > you think?
> >
> > There are several ways to fix the problem, but the point is that,
> from
> > the API POV, the direct state change from SUSPENDED to PREPARED is
> > valid.  So, the kernel driver has to support such a state change, no
> > matter how.
> >
> > An easier way would be to add a check and some trigger in PCM core
> > side.  OTOH, this would affect effectively all drivers, thus we'd
> need
> > a wider test coverage, too.
> >
> > Judging from your comment, the broken driver is ASoC one, right?
> 
> Thinking of this again, I'm inclined to have a workaround for such
> buggy drivers.  In the end, alsa-lib should work for older kernels,
> too.
> 
> Does the patch below work on your device?
> 
> Maybe better to clear the buffer beforehand for avoiding the
> unnecessary noise.  But it can be done later.
> 

I test this patch, there will be error after resume.

aplay: pcm_write:1940: write error: Input/output error


The reason is that the snd_pcm_state(dmix->spcm) is SETUP, the
snd_pcm_direct_prepare() won't do snd_pcm_prepare().

Best regards
Wang shengjiu
> 
> Takashi
> 
> ---
> From: Takashi Iwai <tiwai at suse.de>
> Subject: [PATCH] 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 <tiwai at suse.de>
> ---
>  src/pcm/pcm_direct.c | 19 ++++++++++++++++++-
>  1 file changed, 18 insertions(+), 1 deletion(-)
> 
> diff --git a/src/pcm/pcm_direct.c b/src/pcm/pcm_direct.c
> index 53c49929cb1f..169758d18a29 100644
> --- a/src/pcm/pcm_direct.c
> +++ b/src/pcm/pcm_direct.c
> @@ -837,6 +837,21 @@ 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_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 ((dmix->spcm->info & SND_PCM_INFO_RESUME) &&
> +	    snd_pcm_state(dmix->spcm) == SND_PCM_STATE_SUSPENDED) {
> +		snd_pcm_resume(dmix->spcm);
> +		snd_pcm_drop(dmix->spcm);
> +		snd_pcm_direct_timer_stop(dmix);
> +		snd_pcm_direct_clear_timer_queue(dmix);
> +	}
> +	snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT);
>  	return -ENOSYS;
>  }
> 
> @@ -845,7 +860,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 +889,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
> --
> 2.8.3



More information about the Alsa-devel mailing list