[alsa-devel] [PATCH 1/1] ALSA: pcm: introduce ACK_APPLPTR flag and bump up interface version to 2.0.14

Takashi Sakamoto o-takashi at sakamocchi.jp
Sun Jun 18 18:49:19 CEST 2017


In a development period for v4.13, it's clear that there's a type of
devices which demand userspace applications to change their behaviour.
These devices can take care of application-side pointer on PCM buffer
for their data transmission. As a result, these devices achieve some
advantages. For these devices, drivers need to get feedback about
current position of the pointer from applications when they
queue/dequeue PCM frames on the buffer.

When applications operates with SNDRV_PCM_IOCTL_[READ|WRITE][N|I] command
for ioctl(2) to transmit/receive PCM frames, the above is achieved with
an assist of ALSA PCM core. On the other hand, when applications run with
mmap operations, the above is not achieved. In this case, they should call
ioctl(2) with SNDRV_PCM_IOCTL_SYNC_PTR after operating any PCM frames on
the buffer. But existent applications are not programmed to do it.

This commit adds a new flag; SNDRV_PCM_INFO_ACK_APPLPTR. When
applications find this flag on 'struct snd_pcm_hw_params.info', they're
expected to perform as the above. When programmed so, they should set
SNDRV_PCM_HW_PARAMS_ACK_APPLPTR flag to the structure in advance. Else,
they're not allowed to do mmap operation. This is for backward
compatibility because existent stuffs in user land don't perform like
the above.

As of this type of device, digital signal processor (DSP) integrated
to Intel's processor is reported. The DSP can prefetch the PCM frames on
the buffer and go to a deep sleep mode till next awakening. The awakening
is done by drivers. When applications deliver information about the number
of handled PCM frames to a corresponding driver in kernel land, then the
driver calculates according to the number, then awakens the DSP from the
sleep.

Additionally, there's two types of devices which potentially receive
advantages from this change. One is packet-oriented drivers, and another
is drivers with ALSA indirect layer. The former may process packets
immediately in process context when handling the feedback. This results
in reduction of audio latency. The latter may copy PCM frames in process
context. This results in reduction CPU time on any interrupt context.

Anyway, this flag requires userspace applications to change their
behaviour. This commit bumps up interface version to v2.0.14.

Signed-off-by: Takashi Sakamoto <o-takashi at sakamocchi.jp>
---
 include/uapi/sound/asound.h | 11 ++++++++++-
 sound/core/pcm_native.c     | 25 +++++++++++++++++++++++++
 2 files changed, 35 insertions(+), 1 deletion(-)

diff --git a/include/uapi/sound/asound.h b/include/uapi/sound/asound.h
index fd41697cb4d3..ff7bb89e65a6 100644
--- a/include/uapi/sound/asound.h
+++ b/include/uapi/sound/asound.h
@@ -152,7 +152,7 @@ struct snd_hwdep_dsp_image {
  *                                                                           *
  *****************************************************************************/
 
-#define SNDRV_PCM_VERSION		SNDRV_PROTOCOL_VERSION(2, 0, 13)
+#define SNDRV_PCM_VERSION		SNDRV_PROTOCOL_VERSION(2, 0, 14)
 
 typedef unsigned long snd_pcm_uframes_t;
 typedef signed long snd_pcm_sframes_t;
@@ -268,6 +268,8 @@ typedef int __bitwise snd_pcm_subformat_t;
 #define SNDRV_PCM_INFO_MMAP_VALID	0x00000002	/* period data are valid during transfer */
 #define SNDRV_PCM_INFO_DOUBLE		0x00000004	/* Double buffering needed for PCM start/stop */
 #define SNDRV_PCM_INFO_BATCH		0x00000010	/* double buffering */
+/* Driver/hardware acknowledge current appl_ptr for specific purposes. */
+#define SNDRV_PCM_INFO_ACK_APPLPTR	0x00000012
 #define SNDRV_PCM_INFO_INTERLEAVED	0x00000100	/* channels are interleaved */
 #define SNDRV_PCM_INFO_NONINTERLEAVED	0x00000200	/* channels are not interleaved */
 #define SNDRV_PCM_INFO_COMPLEX		0x00000400	/* complex frame organization (mmap only) */
@@ -365,6 +367,13 @@ typedef int snd_pcm_hw_param_t;
 #define SNDRV_PCM_HW_PARAMS_NORESAMPLE	(1<<0)	/* avoid rate resampling */
 #define SNDRV_PCM_HW_PARAMS_EXPORT_BUFFER	(1<<1)	/* export buffer */
 #define SNDRV_PCM_HW_PARAMS_NO_PERIOD_WAKEUP	(1<<2)	/* disable period wakeups */
+/*
+ * When applications are programmed to execute ioctl(2) with
+ * SNDRV_PCM_IOCTL_SYNC_PTR for notification of current appl_ptr after handling
+ * any frames on mapped PCM buffer for driver/hardware with
+ * SNDRV_PCM_INFO_ACK_APPLPTR, this should be set.
+ */
+#define SNDRV_PCM_HW_PARAMS_ACK_APPLPTR	(1<<3)
 
 struct snd_interval {
 	unsigned int min, max;
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 7e8f3656b695..48772a2bd027 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -249,6 +249,27 @@ static bool hw_support_mmap(struct snd_pcm_substream *substream)
 	return true;
 }
 
+static int constrain_params_with_precondition(struct snd_pcm_substream *substream,
+					      struct snd_pcm_hw_params *params)
+{
+	struct snd_mask *mask;
+
+	/*
+	 * When drivers require applications' cooperation to report current
+	 * appl_ptr and the applications voluntarily perform it, mmap operation
+	 * is allowed. Else, read/write operations are allowed.
+	 */
+	if ((substream->runtime->hw.info & SNDRV_PCM_INFO_ACK_APPLPTR) &&
+	    !(params->flags & SNDRV_PCM_HW_PARAMS_ACK_APPLPTR)) {
+		mask = hw_param_mask(params, SNDRV_PCM_HW_PARAM_ACCESS);
+		snd_mask_reset(mask, SNDRV_PCM_ACCESS_MMAP_INTERLEAVED);
+		snd_mask_reset(mask, SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED);
+		snd_mask_reset(mask, SNDRV_PCM_ACCESS_MMAP_COMPLEX);
+	}
+
+	return 0;
+}
+
 static int constrain_mask_params(struct snd_pcm_substream *substream,
 				 struct snd_pcm_hw_params *params)
 {
@@ -495,6 +516,10 @@ int snd_pcm_hw_refine(struct snd_pcm_substream *substream,
 		params->rate_den = 0;
 	}
 
+	err = constrain_params_with_precondition(substream, params);
+	if (err < 0)
+		return err;
+
 	err = constrain_mask_params(substream, params);
 	if (err < 0)
 		return err;
-- 
2.11.0



More information about the Alsa-devel mailing list