[alsa-devel] [PATCH 4/7] ALSA: core: add report of max inflight bytes

Takashi Iwai tiwai at suse.de
Fri Sep 30 15:44:02 CEST 2016


On Fri, 30 Sep 2016 14:43:27 +0200,
Subhransu S. Prusty wrote:
> 
> From: Pierre-Louis Bossart <pierre-louis.bossart at linux.intel.com>
> 
> Report size of data burst before updating the hw_ptr, e.g. while DMA
> operations are on-going.
> 
> This can help fix two issues with stale data discussed many times over
> on the alsa-devel mailing list (refilling/reading ring buffer too late
> during capture or rewinding too close to the hw_ptr during playback)
> 
> This patch only reports the maximum burst of data and does not provide
> hooks to negotiate its size. This might be useful to lower power or
> reduce latency, but isn't typically supported by fixed-function DMA
> hardware.

This needs to be discussed rather from the actual demand.

 From the API change POV, the only (and the biggest) question is
whether hw_params is the best API.  It looks feasible, so far, but
someone else might have a better idea.  Let's see.


Takashi


> 
> The use of IOCTL1 is not really required but keep for symmetry with
> existing code used to retried fifo_size
> 
> Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart at linux.intel.com>
> Signed-off-by: Subhransu S. Prusty <subhransu.s.prusty at intel.com>
> ---
>  include/sound/pcm.h         |  2 ++
>  include/uapi/sound/asound.h |  5 +++--
>  sound/core/pcm_lib.c        | 20 ++++++++++++++++++++
>  sound/core/pcm_native.c     |  7 +++++++
>  4 files changed, 32 insertions(+), 2 deletions(-)
> 
> diff --git a/include/sound/pcm.h b/include/sound/pcm.h
> index 1accb8b..8c9d80a 100644
> --- a/include/sound/pcm.h
> +++ b/include/sound/pcm.h
> @@ -56,6 +56,7 @@ struct snd_pcm_hardware {
>  	unsigned int periods_min;	/* min # of periods */
>  	unsigned int periods_max;	/* max # of periods */
>  	size_t fifo_size;		/* fifo size in bytes */
> +	unsigned int max_inflight_bytes;/* hw_ptr precision/fuzziness, e.g. due to DMA transfers */
>  };
>  
>  struct snd_pcm_substream;
> @@ -105,6 +106,7 @@ struct snd_pcm_ops {
>  #define SNDRV_PCM_IOCTL1_CHANNEL_INFO	2
>  #define SNDRV_PCM_IOCTL1_GSTATE		3
>  #define SNDRV_PCM_IOCTL1_FIFO_SIZE	4
> +#define SNDRV_PCM_IOCTL1_MAX_INFLIGHT_BYTES	5
>  
>  #define SNDRV_PCM_TRIGGER_STOP		0
>  #define SNDRV_PCM_TRIGGER_START		1
> diff --git a/include/uapi/sound/asound.h b/include/uapi/sound/asound.h
> index 6828ed2..5f539d7 100644
> --- a/include/uapi/sound/asound.h
> +++ b/include/uapi/sound/asound.h
> @@ -392,8 +392,9 @@ struct snd_pcm_hw_params {
>  	unsigned int msbits;		/* R: used most significant bits */
>  	unsigned int rate_num;		/* R: rate numerator */
>  	unsigned int rate_den;		/* R: rate denominator */
> -	snd_pcm_uframes_t fifo_size;	/* R: chip FIFO size in frames */
> -	unsigned char reserved[64];	/* reserved for future */
> +	snd_pcm_uframes_t fifo_size;	/* R: chip FIFO size in frames, indicates buffering after hw_ptr updates */
> +	unsigned int max_inflight_bytes;/* R: typically DMA burst in bytes, indicates buffering before hw_ptr updates */
> +	unsigned char reserved[60];	/* reserved for future */
>  };
>  
>  enum {
> diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
> index 1656ca9..06b44ed 100644
> --- a/sound/core/pcm_lib.c
> +++ b/sound/core/pcm_lib.c
> @@ -1827,6 +1827,23 @@ static int snd_pcm_lib_ioctl_fifo_size(struct snd_pcm_substream *substream,
>  	return 0;
>  }
>  
> +static int snd_pcm_lib_ioctl_max_inflight_bytes(
> +	struct snd_pcm_substream *substream,
> +	void *arg)
> +{
> +	struct snd_pcm_hw_params *params = arg;
> +
> +	params->max_inflight_bytes = substream->runtime->hw.max_inflight_bytes;
> +	/*
> +	 * Sanity check that max_inflight_bytes isn't larger than buffer_size,
> +	 * couldn't think of any other checks
> +	 */
> +	if (params->max_inflight_bytes > substream->runtime->buffer_size)
> +		params->max_inflight_bytes = substream->runtime->buffer_size;
> +
> +	return 0;
> +}
> +
>  /**
>   * snd_pcm_lib_ioctl - a generic PCM ioctl callback
>   * @substream: the pcm substream instance
> @@ -1850,6 +1867,9 @@ int snd_pcm_lib_ioctl(struct snd_pcm_substream *substream,
>  		return snd_pcm_lib_ioctl_channel_info(substream, arg);
>  	case SNDRV_PCM_IOCTL1_FIFO_SIZE:
>  		return snd_pcm_lib_ioctl_fifo_size(substream, arg);
> +	case SNDRV_PCM_IOCTL1_MAX_INFLIGHT_BYTES:
> +		return snd_pcm_lib_ioctl_max_inflight_bytes(substream, arg);
> +
>  	}
>  	return -ENXIO;
>  }
> diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
> index 1965d83..a29b5af 100644
> --- a/sound/core/pcm_native.c
> +++ b/sound/core/pcm_native.c
> @@ -292,6 +292,7 @@ int snd_pcm_hw_refine(struct snd_pcm_substream *substream,
>  
>  	params->info = 0;
>  	params->fifo_size = 0;
> +	params->max_inflight_bytes = 0;
>  	if (params->rmask & (1 << SNDRV_PCM_HW_PARAM_SAMPLE_BITS))
>  		params->msbits = 0;
>  	if (params->rmask & (1 << SNDRV_PCM_HW_PARAM_RATE)) {
> @@ -449,6 +450,12 @@ int snd_pcm_hw_refine(struct snd_pcm_substream *substream,
>  				return changed;
>  		}
>  	}
> +	if (!params->max_inflight_bytes) {
> +		changed = substream->ops->ioctl(substream,
> +				SNDRV_PCM_IOCTL1_MAX_INFLIGHT_BYTES, params);
> +		if (changed < 0)
> +			return changed;
> +	}
>  	params->rmask = 0;
>  	return 0;
>  }
> -- 
> 1.9.1
> 


More information about the Alsa-devel mailing list