[PATCH v3 4/4] ASoC: SOF: Intel: add .ack support for HDaudio platforms

Takashi Iwai tiwai at suse.de
Sun Oct 17 09:43:04 CEST 2021


On Fri, 15 Oct 2021 21:59:32 +0200,
Pierre-Louis Bossart wrote:
> 
> From: Ranjani Sridharan <ranjani.sridharan at linux.intel.com>
> 
> When we disable rewinds, then the .ack can be used to program SPIB
> with the application pointer, which allows the HDaudio DMA to save
> power by opportunistically bursting data transfers when the path to
> memory is enabled (and conversely to shut it down when there are no
> transfer requests).
> 
> The SPIB register can only be programmed with incremental values with
> wrap-around after the DMA RUN bits are set. For simplicity, we set the
> INFO_NO_REWINDS flag in the .open callback when we already need to
> program the SNDRV_PCM_INFO_EXPLICIT_SYNC flag.

Using this flag itself isn't wrong, but if we need to check only
appl_ptr updates, a more appropriate flag is
SNDRV_PCM_INFO_SYNC_APPLPTR.  This will still allow the mmap of status
(i.e. hwptr update) while the mmap of control is disabled for
appl_ptr.  SNDRV_PCM_INFO_EXPLICIT_SYNC flag disables both, instead.


thanks,

Takashi

> Rewinds are not used by many applications. One notable application
> using rewinds is PulseAudio. Practical experiments with
> Ubuntu/PulseAudio default settings did not show any audible issues,
> but the user may hear volume changes and notification with a delay,
> depending on the size of the ring buffer and latency constraints.
> 
> The choice of disabling rewinds is exposed as a kernel parameter and
> not a Kconfig option to avoid any undesirable side-effects.
> 
> Reviewed-by: Péter Ujfalusi <peter.ujfalusi at linux.intel.com>
> Reviewed-by: Kai Vehmanen <kai.vehmanen at linux.intel.com>
> Reviewed-by: Ranjani Sridharan <ranjani.sridharan at linux.intel.com>
> Co-developed-by: Pierre-Louis Bossart <pierre-louis.bossart at linux.intel.com>
> Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart at linux.intel.com>
> Signed-off-by: Ranjani Sridharan <ranjani.sridharan at linux.intel.com>
> ---
>  sound/soc/sof/intel/apl.c        |  1 +
>  sound/soc/sof/intel/cnl.c        |  1 +
>  sound/soc/sof/intel/hda-pcm.c    | 41 ++++++++++++++++++++++++++++++--
>  sound/soc/sof/intel/hda-stream.c |  2 ++
>  sound/soc/sof/intel/hda.h        |  1 +
>  sound/soc/sof/intel/tgl.c        |  1 +
>  6 files changed, 45 insertions(+), 2 deletions(-)
> 
> diff --git a/sound/soc/sof/intel/apl.c b/sound/soc/sof/intel/apl.c
> index 917f78cf6daf..689679014ade 100644
> --- a/sound/soc/sof/intel/apl.c
> +++ b/sound/soc/sof/intel/apl.c
> @@ -78,6 +78,7 @@ const struct snd_sof_dsp_ops sof_apl_ops = {
>  	.pcm_hw_free	= hda_dsp_stream_hw_free,
>  	.pcm_trigger	= hda_dsp_pcm_trigger,
>  	.pcm_pointer	= hda_dsp_pcm_pointer,
> +	.pcm_ack	= hda_dsp_pcm_ack,
>  
>  #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_PROBES)
>  	/* probe callbacks */
> diff --git a/sound/soc/sof/intel/cnl.c b/sound/soc/sof/intel/cnl.c
> index 3957e2b3db32..d128c08ba726 100644
> --- a/sound/soc/sof/intel/cnl.c
> +++ b/sound/soc/sof/intel/cnl.c
> @@ -283,6 +283,7 @@ const struct snd_sof_dsp_ops sof_cnl_ops = {
>  	.pcm_hw_free	= hda_dsp_stream_hw_free,
>  	.pcm_trigger	= hda_dsp_pcm_trigger,
>  	.pcm_pointer	= hda_dsp_pcm_pointer,
> +	.pcm_ack	= hda_dsp_pcm_ack,
>  
>  #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_PROBES)
>  	/* probe callbacks */
> diff --git a/sound/soc/sof/intel/hda-pcm.c b/sound/soc/sof/intel/hda-pcm.c
> index cc8ddef37f37..875350283eac 100644
> --- a/sound/soc/sof/intel/hda-pcm.c
> +++ b/sound/soc/sof/intel/hda-pcm.c
> @@ -32,6 +32,10 @@ static bool hda_always_enable_dmi_l1;
>  module_param_named(always_enable_dmi_l1, hda_always_enable_dmi_l1, bool, 0444);
>  MODULE_PARM_DESC(always_enable_dmi_l1, "SOF HDA always enable DMI l1");
>  
> +static bool hda_disable_rewinds = IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_DISABLE_REWINDS);
> +module_param_named(disable_rewinds, hda_disable_rewinds, bool, 0444);
> +MODULE_PARM_DESC(disable_rewinds, "SOF HDA disable rewinds");
> +
>  u32 hda_dsp_get_mult_div(struct snd_sof_dev *sdev, int rate)
>  {
>  	switch (rate) {
> @@ -120,8 +124,11 @@ int hda_dsp_pcm_hw_params(struct snd_sof_dev *sdev,
>  		return ret;
>  	}
>  
> -	/* disable SPIB, to enable buffer wrap for stream */
> -	hda_dsp_stream_spib_config(sdev, stream, HDA_DSP_SPIB_DISABLE, 0);
> +	/* enable SPIB when rewinds are disabled */
> +	if (hda_disable_rewinds)
> +		hda_dsp_stream_spib_config(sdev, stream, HDA_DSP_SPIB_ENABLE, 0);
> +	else
> +		hda_dsp_stream_spib_config(sdev, stream, HDA_DSP_SPIB_DISABLE, 0);
>  
>  	/* update no_stream_position flag for ipc params */
>  	if (hda && hda->no_ipc_position) {
> @@ -140,6 +147,29 @@ int hda_dsp_pcm_hw_params(struct snd_sof_dev *sdev,
>  	return 0;
>  }
>  
> +/* update SPIB register with appl position */
> +int hda_dsp_pcm_ack(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream)
> +{
> +	struct hdac_stream *hstream = substream->runtime->private_data;
> +	struct hdac_ext_stream *stream = stream_to_hdac_ext_stream(hstream);
> +	struct snd_pcm_runtime *runtime = substream->runtime;
> +	ssize_t appl_pos, buf_size;
> +	u32 spib;
> +
> +	appl_pos = frames_to_bytes(runtime, runtime->control->appl_ptr);
> +	buf_size = frames_to_bytes(runtime, runtime->buffer_size);
> +
> +	spib = appl_pos % buf_size;
> +
> +	/* Allowable value for SPIB is 1 byte to max buffer size */
> +	if (!spib)
> +		spib = buf_size;
> +
> +	sof_io_write(sdev, stream->spib_addr, spib);
> +
> +	return 0;
> +}
> +
>  int hda_dsp_pcm_trigger(struct snd_sof_dev *sdev,
>  			struct snd_pcm_substream *substream, int cmd)
>  {
> @@ -234,6 +264,13 @@ int hda_dsp_pcm_open(struct snd_sof_dev *sdev,
>  		return -EINVAL;
>  	}
>  
> +	/*
> +	 * if we want the .ack to work, we need to prevent the status and
> +	 * control from being mapped
> +	 */
> +	if (hda_disable_rewinds)
> +		runtime->hw.info |= SNDRV_PCM_INFO_NO_REWINDS | SNDRV_PCM_INFO_EXPLICIT_SYNC;
> +
>  	/*
>  	 * All playback streams are DMI L1 capable, capture streams need
>  	 * pause push/release to be disabled
> diff --git a/sound/soc/sof/intel/hda-stream.c b/sound/soc/sof/intel/hda-stream.c
> index 1d845c2cbc33..b6f037815344 100644
> --- a/sound/soc/sof/intel/hda-stream.c
> +++ b/sound/soc/sof/intel/hda-stream.c
> @@ -655,6 +655,8 @@ int hda_dsp_stream_hw_free(struct snd_sof_dev *sdev,
>  					SOF_HDA_REG_PP_PPCTL, mask, 0);
>  	spin_unlock_irq(&bus->reg_lock);
>  
> +	hda_dsp_stream_spib_config(sdev, link_dev, HDA_DSP_SPIB_DISABLE, 0);
> +
>  	stream->substream = NULL;
>  
>  	return 0;
> diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h
> index 1195018a1f4f..6829d36fbfe9 100644
> --- a/sound/soc/sof/intel/hda.h
> +++ b/sound/soc/sof/intel/hda.h
> @@ -533,6 +533,7 @@ int hda_dsp_pcm_trigger(struct snd_sof_dev *sdev,
>  			struct snd_pcm_substream *substream, int cmd);
>  snd_pcm_uframes_t hda_dsp_pcm_pointer(struct snd_sof_dev *sdev,
>  				      struct snd_pcm_substream *substream);
> +int hda_dsp_pcm_ack(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream);
>  
>  /*
>   * DSP Stream Operations.
> diff --git a/sound/soc/sof/intel/tgl.c b/sound/soc/sof/intel/tgl.c
> index 48da8e7a67bc..2a29058e0c20 100644
> --- a/sound/soc/sof/intel/tgl.c
> +++ b/sound/soc/sof/intel/tgl.c
> @@ -73,6 +73,7 @@ const struct snd_sof_dsp_ops sof_tgl_ops = {
>  	.pcm_hw_free	= hda_dsp_stream_hw_free,
>  	.pcm_trigger	= hda_dsp_pcm_trigger,
>  	.pcm_pointer	= hda_dsp_pcm_pointer,
> +	.pcm_ack	= hda_dsp_pcm_ack,
>  
>  #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_PROBES)
>  	/* probe callbacks */
> -- 
> 2.25.1
> 


More information about the Alsa-devel mailing list