[alsa-devel] [PATCH alsa-lib 1/4] pcm: hw: Add the support for explicit sync of appl_ptr

Takashi Iwai tiwai at suse.de
Tue Jun 20 17:35:21 CEST 2017


The recent kernel informs user-space when a driver requires the
explicit notification of appl_ptr update via a new flag,
SNDRV_PCM_INFO_SYNC_APPLPTR.  When this flag is set, the user-space is
supposed to report the appl_ptr via SNDRV_PCM_IOCTL_SYNC_PTR ioctl.

This patch implements the requested behavior in the PCM hw plugin.

Signed-off-by: Takashi Iwai <tiwai at suse.de>
---
 include/sound/asound.h |  1 +
 src/pcm/pcm_hw.c       | 27 +++++++++++++++++++++------
 2 files changed, 22 insertions(+), 6 deletions(-)

diff --git a/include/sound/asound.h b/include/sound/asound.h
index fb8d7d7ef8ad..346db40e5932 100644
--- a/include/sound/asound.h
+++ b/include/sound/asound.h
@@ -268,6 +268,7 @@ 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 */
+#define SNDRV_PCM_INFO_SYNC_APPLPTR	0x00000020	/* need the explicit sync of appl_ptr update */
 #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) */
diff --git a/src/pcm/pcm_hw.c b/src/pcm/pcm_hw.c
index 30cd5d0f6503..8855868f5ea2 100644
--- a/src/pcm/pcm_hw.c
+++ b/src/pcm/pcm_hw.c
@@ -91,6 +91,7 @@ typedef struct {
 	int fd;
 	int card, device, subdevice;
 	int sync_ptr_ioctl;
+	int sync_applptr;
 	volatile struct snd_pcm_mmap_status * mmap_status;
 	struct snd_pcm_mmap_control *mmap_control;
 	struct snd_pcm_sync_ptr *sync_ptr;
@@ -128,11 +129,13 @@ struct timespec snd_pcm_hw_fast_tstamp(snd_pcm_t *pcm)
 }
 #endif /* DOC_HIDDEN */
 
-static int sync_ptr1(snd_pcm_hw_t *hw, unsigned int flags)
+static int sync_ptr1(snd_pcm_hw_t *hw, struct snd_pcm_sync_ptr *ptr,
+		     unsigned int flags)
 {
 	int err;
-	hw->sync_ptr->flags = flags;
-	err = ioctl((hw)->fd, SNDRV_PCM_IOCTL_SYNC_PTR, (hw)->sync_ptr);
+
+	ptr->flags = flags;
+	err = ioctl(hw->fd, SNDRV_PCM_IOCTL_SYNC_PTR, ptr);
 	if (err < 0) {
 		err = -errno;
 		SYSMSG("SNDRV_PCM_IOCTL_SYNC_PTR failed (%i)", err);
@@ -143,7 +146,15 @@ static int sync_ptr1(snd_pcm_hw_t *hw, unsigned int flags)
 
 static inline int sync_ptr(snd_pcm_hw_t *hw, unsigned int flags)
 {
-	return hw->sync_ptr ? sync_ptr1(hw, flags) : 0;
+	return hw->sync_ptr ? sync_ptr1(hw, hw->sync_ptr, flags) : 0;
+}
+
+/* explicit notification of appl_ptr update to kernel */
+static int sync_applptr(snd_pcm_hw_t *hw)
+{
+	struct snd_pcm_sync_ptr ptr;
+	ptr.c.control = *hw->mmap_control;
+	return sync_ptr1(hw, &ptr, 0);
 }
 
 static int snd_pcm_hw_clear_timer_queue(snd_pcm_hw_t *hw)
@@ -327,6 +338,7 @@ static int snd_pcm_hw_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params)
 		SYSMSG("SNDRV_PCM_IOCTL_HW_PARAMS failed (%i)", err);
 		return err;
 	}
+	hw->sync_applptr = !!(params->info & SNDRV_PCM_INFO_SYNC_APPLPTR);
 	params->info &= ~0xf0000000;
 	if (pcm->tstamp_type != SND_PCM_TSTAMP_TYPE_GETTIMEOFDAY)
 		params->info |= SND_PCM_INFO_MONOTONIC;
@@ -568,7 +580,7 @@ static int snd_pcm_hw_hwsync(snd_pcm_t *pcm)
 	int fd = hw->fd, err;
 	if (SNDRV_PROTOCOL_VERSION(2, 0, 3) <= hw->version) {
 		if (hw->sync_ptr) {
-			err = sync_ptr1(hw, SNDRV_PCM_SYNC_PTR_HWSYNC);
+			err = sync_ptr1(hw, hw->sync_ptr, SNDRV_PCM_SYNC_PTR_HWSYNC);
 			if (err < 0)
 				return err;
 		} else {
@@ -995,7 +1007,10 @@ static snd_pcm_sframes_t snd_pcm_hw_mmap_commit(snd_pcm_t *pcm,
 	snd_pcm_hw_t *hw = pcm->private_data;
 
 	snd_pcm_mmap_appl_forward(pcm, size);
-	sync_ptr(hw, 0);
+	if (hw->sync_ptr)
+		sync_ptr(hw, 0);
+	else if (hw->sync_applptr)
+		sync_applptr(hw);
 #ifdef DEBUG_MMAP
 	fprintf(stderr, "appl_forward: hw_ptr = %li, appl_ptr = %li, size = %li\n", *pcm->hw.ptr, *pcm->appl.ptr, size);
 #endif
-- 
2.13.1



More information about the Alsa-devel mailing list