Blob Blame History Raw
diff --git a/Makefile.am b/Makefile.am
index c484d4da..ff4c963a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -16,7 +16,7 @@ SUBDIRS += alsalisp
 endif
 endif
 SUBDIRS += test utils
-EXTRA_DIST=ChangeLog INSTALL TODO NOTES configure gitcompile libtool \
+EXTRA_DIST=README.md ChangeLog INSTALL TODO NOTES configure gitcompile libtool \
 	   depcomp version MEMORY-LEAK m4/attributes.m4
 AUTOMAKE_OPTIONS=foreign
 
diff --git a/include/pcm.h b/include/pcm.h
index 5b078231..e300b951 100644
--- a/include/pcm.h
+++ b/include/pcm.h
@@ -350,6 +350,20 @@ typedef enum _snd_pcm_tstamp_type {
 	SND_PCM_TSTAMP_TYPE_LAST = SND_PCM_TSTAMP_TYPE_MONOTONIC_RAW,
 } snd_pcm_tstamp_type_t;
 
+typedef enum _snd_pcm_audio_tstamp_type {
+	/**
+	 * first definition for backwards compatibility only,
+	 * maps to wallclock/link time for HDAudio playback and DEFAULT/DMA time for everything else
+	 */
+	SND_PCM_AUDIO_TSTAMP_TYPE_COMPAT = 0,
+	SND_PCM_AUDIO_TSTAMP_TYPE_DEFAULT = 1,           /**< DMA time, reported as per hw_ptr */
+	SND_PCM_AUDIO_TSTAMP_TYPE_LINK = 2,	           /**< link time reported by sample or wallclock counter, reset on startup */
+	SND_PCM_AUDIO_TSTAMP_TYPE_LINK_ABSOLUTE = 3,	   /**< link time reported by sample or wallclock counter, not reset on startup */
+	SND_PCM_AUDIO_TSTAMP_TYPE_LINK_ESTIMATED = 4,    /**< link time estimated indirectly */
+	SND_PCM_AUDIO_TSTAMP_TYPE_LINK_SYNCHRONIZED = 5, /**< link time synchronized with system time */
+	SND_PCM_AUDIO_TSTAMP_TYPE_LAST = SND_PCM_AUDIO_TSTAMP_TYPE_LINK_SYNCHRONIZED
+} snd_pcm_audio_tstamp_type_t;
+
 typedef struct _snd_pcm_audio_tstamp_config {
 	/* 5 of max 16 bits used */
 	unsigned int type_requested:4;
diff --git a/include/sound/uapi/asoc.h b/include/sound/uapi/asoc.h
index 4efb4ec4..f32c5697 100644
--- a/include/sound/uapi/asoc.h
+++ b/include/sound/uapi/asoc.h
@@ -169,16 +169,22 @@
 #define SND_SOC_TPLG_LNK_FLGBIT_VOICE_WAKEUP            (1 << 3)
 
 /* DAI topology BCLK parameter
- * For the backwards capability, by default codec is bclk master
+ * For the backwards capability, by default codec is bclk provider
  */
-#define SND_SOC_TPLG_BCLK_CM         0 /* codec is bclk master */
-#define SND_SOC_TPLG_BCLK_CS         1 /* codec is bclk slave */
+#define SND_SOC_TPLG_BCLK_CP         0 /* codec is bclk provider */
+#define SND_SOC_TPLG_BCLK_CC         1 /* codec is bclk consumer */
+/* keep previous definitions for compatibility */
+#define SND_SOC_TPLG_BCLK_CM         SND_SOC_TPLG_BCLK_CP
+#define SND_SOC_TPLG_BCLK_CS         SND_SOC_TPLG_BCLK_CC
 
 /* DAI topology FSYNC parameter
- * For the backwards capability, by default codec is fsync master
+ * For the backwards capability, by default codec is fsync provider
  */
-#define SND_SOC_TPLG_FSYNC_CM         0 /* codec is fsync master */
-#define SND_SOC_TPLG_FSYNC_CS         1 /* codec is fsync slave */
+#define SND_SOC_TPLG_FSYNC_CP         0 /* codec is fsync provider */
+#define SND_SOC_TPLG_FSYNC_CC         1 /* codec is fsync consumer */
+/* keep previous definitions for compatibility */
+#define SND_SOC_TPLG_FSYNC_CM         SND_SOC_TPLG_FSYNC_CP
+#define SND_SOC_TPLG_FSYNC_CS         SND_SOC_TPLG_FSYNC_CC
 
 /*
  * Block Header.
@@ -335,8 +341,8 @@ struct snd_soc_tplg_hw_config {
 	__u8 clock_gated;	/* SND_SOC_TPLG_DAI_CLK_GATE_ value */
 	__u8 invert_bclk;	/* 1 for inverted BCLK, 0 for normal */
 	__u8 invert_fsync;	/* 1 for inverted frame clock, 0 for normal */
-	__u8 bclk_master;	/* SND_SOC_TPLG_BCLK_ value */
-	__u8 fsync_master;	/* SND_SOC_TPLG_FSYNC_ value */
+	__u8 bclk_provider;	/* SND_SOC_TPLG_BCLK_ value */
+	__u8 fsync_provider;	/* SND_SOC_TPLG_FSYNC_ value */
 	__u8 mclk_direction;    /* SND_SOC_TPLG_MCLK_ value */
 	__le16 reserved;	/* for 32bit alignment */
 	__le32 mclk_rate;	/* MCLK or SYSCLK freqency in Hz */
diff --git a/include/topology.h b/include/topology.h
index 1f52e66e..d1feee4d 100644
--- a/include/topology.h
+++ b/include/topology.h
@@ -658,8 +658,8 @@ extern "C" {
  *
  *	id "1"				# used for binding to the config
  *	format "I2S"			# physical audio format.
- *	bclk   "master"			# Platform is master of bit clock
- *	fsync  "slave"			# Platform is slave of fsync
+ *	bclk   "codec_provider"		# Codec provides the bit clock
+ *	fsync  "codec_consumer"		# Codec follows the fsync
  * }
  * </pre>
  *
@@ -1028,8 +1028,8 @@ struct snd_tplg_hw_config_template {
 	unsigned char clock_gated;      /* SND_SOC_TPLG_DAI_CLK_GATE_ value */
 	unsigned char  invert_bclk;     /* 1 for inverted BCLK, 0 for normal */
 	unsigned char  invert_fsync;    /* 1 for inverted frame clock, 0 for normal */
-	unsigned char  bclk_master;     /* SND_SOC_TPLG_BCLK_ value */
-	unsigned char  fsync_master;    /* SND_SOC_TPLG_FSYNC_ value */
+	unsigned char  bclk_provider;   /* SND_SOC_TPLG_BCLK_ value */
+	unsigned char  fsync_provider;  /* SND_SOC_TPLG_FSYNC_ value */
 	unsigned char  mclk_direction;  /* SND_SOC_TPLG_MCLK_ value */
 	unsigned short reserved;        /* for 32bit alignment */
 	unsigned int mclk_rate;	        /* MCLK or SYSCLK freqency in Hz */
diff --git a/src/conf.c b/src/conf.c
index 7df2b4e7..3c943db2 100644
--- a/src/conf.c
+++ b/src/conf.c
@@ -887,7 +887,7 @@ static inline int get_hexachar(input_t *input)
 	if (c >= '0' && c <= '9') num |= (c - '0') << 0;
 	else if (c >= 'a' && c <= 'f') num |= (c - 'a') << 0;
 	else if (c >= 'A' && c <= 'F') num |= (c - 'A') << 0;
-	return c;
+	return num;
 }
 
 static int get_quotedchar(input_t *input)
@@ -1970,11 +1970,14 @@ int _snd_config_load_with_include(snd_config_t *config, snd_input_t *in,
 		SNDERR("%s:%d:%d:%s", fd->name ? fd->name : "_toplevel_", fd->line, fd->column, str);
 		goto _end;
 	}
-	if (get_char(&input) != LOCAL_UNEXPECTED_EOF) {
+	err = get_char(&input);
+	fd = input.current;
+	if (err != LOCAL_UNEXPECTED_EOF) {
 		SNDERR("%s:%d:%d:Unexpected }", fd->name ? fd->name : "", fd->line, fd->column);
 		err = -EINVAL;
 		goto _end;
 	}
+	err = 0;
  _end:
 	while (fd->next) {
 		fd_next = fd->next;
diff --git a/src/conf/cards/USB-Audio.conf b/src/conf/cards/USB-Audio.conf
index 9b64af3c..b1b74b02 100644
--- a/src/conf/cards/USB-Audio.conf
+++ b/src/conf/cards/USB-Audio.conf
@@ -39,6 +39,7 @@ USB-Audio.pcm.iec958_device {
 	# "NoiseBlaster 3000" 42
 	"USB Sound Blaster HD" 1
 	"Xonar U7" 1
+	"Xonar U7 MKII" 1
 	"ASUS XONAR U5" 1
 	"XONAR U5" 1
 	"XONAR SOUND CARD" 1
diff --git a/src/confmisc.c b/src/confmisc.c
index eb8218c1..3ce95c7a 100644
--- a/src/confmisc.c
+++ b/src/confmisc.c
@@ -419,7 +419,6 @@ int snd_func_concat(snd_config_t **dst, snd_config_t *root, snd_config_t *src,
 				tmp = realloc(res, len + len1 + 1);
 				if (tmp == NULL) {
 					free(ptr);
-					free(res);
 					err = -ENOMEM;
 					goto __error;
 				}
@@ -440,8 +439,8 @@ int snd_func_concat(snd_config_t **dst, snd_config_t *root, snd_config_t *src,
 	err = snd_config_get_id(src, &id);
 	if (err >= 0)
 		err = snd_config_imake_string(dst, id, res);
-	free(res);
       __error:
+	free(res);
 	return err;
 }
 #ifndef DOC_HIDDEN
diff --git a/src/dlmisc.c b/src/dlmisc.c
index c9517c55..1dd91356 100644
--- a/src/dlmisc.c
+++ b/src/dlmisc.c
@@ -42,13 +42,11 @@
 #ifndef PIC
 struct snd_dlsym_link *snd_dlsym_start = NULL;
 #endif
-#ifdef DL_ORIGIN_AVAILABLE
 static int snd_plugin_dir_set = 0;
 static char *snd_plugin_dir = NULL;
 #endif
-#endif
 
-#if defined(DL_ORIGIN_AVAILABLE) && defined(HAVE_LIBPTHREAD)
+#ifdef HAVE_LIBPTHREAD
 static pthread_mutex_t snd_dlpath_mutex = PTHREAD_MUTEX_INITIALIZER;
 
 static inline void snd_dlpath_lock(void)
@@ -442,12 +440,10 @@ void snd_dlobj_cache_cleanup(void)
 		free(c);
 	}
 	snd_dlobj_unlock();
-#ifdef DL_ORIGIN_AVAILABLE
 	snd_dlpath_lock();
 	snd_plugin_dir_set = 0;
 	free(snd_plugin_dir);
 	snd_plugin_dir = NULL;
 	snd_dlpath_unlock();
-#endif
 }
 #endif
diff --git a/src/pcm/pcm_ioplug.c b/src/pcm/pcm_ioplug.c
index a437ca32..e141b1f9 100644
--- a/src/pcm/pcm_ioplug.c
+++ b/src/pcm/pcm_ioplug.c
@@ -107,16 +107,35 @@ static int snd_pcm_ioplug_channel_info(snd_pcm_t *pcm, snd_pcm_channel_info_t *i
 	return snd_pcm_channel_info_shm(pcm, info, -1);
 }
 
+static int snd_pcm_ioplug_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
+{
+	ioplug_priv_t *io = pcm->private_data;
+
+	if (io->data->version >= 0x010001 &&
+	    io->data->callback->delay)
+		return io->data->callback->delay(io->data, delayp);
+	else {
+		snd_pcm_ioplug_hw_ptr_update(pcm);
+		*delayp = snd_pcm_mmap_delay(pcm);
+	}
+	return 0;
+}
+
 static int snd_pcm_ioplug_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
 {
 	ioplug_priv_t *io = pcm->private_data;
+	snd_pcm_sframes_t sd;
 
 	memset(status, 0, sizeof(*status));
 	snd_pcm_ioplug_hw_ptr_update(pcm);
 	status->state = io->data->state;
 	status->trigger_tstamp = io->trigger_tstamp;
+	gettimestamp(&status->tstamp, pcm->tstamp_type);
 	status->avail = snd_pcm_mmap_avail(pcm);
 	status->avail_max = io->avail_max;
+	if (snd_pcm_ioplug_delay(pcm, &sd) < 0)
+		sd = snd_pcm_mmap_delay(pcm);
+	status->delay = sd;
 	return 0;
 }
 
@@ -132,20 +151,6 @@ static int snd_pcm_ioplug_hwsync(snd_pcm_t *pcm)
 	return 0;
 }
 
-static int snd_pcm_ioplug_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
-{
-	ioplug_priv_t *io = pcm->private_data;
-
-	if (io->data->version >= 0x010001 &&
-	    io->data->callback->delay)
-		return io->data->callback->delay(io->data, delayp);
-	else {
-		snd_pcm_ioplug_hw_ptr_update(pcm);
-		*delayp = snd_pcm_mmap_hw_avail(pcm);
-	}
-	return 0;
-}
-
 static int snd_pcm_ioplug_reset(snd_pcm_t *pcm)
 {
 	ioplug_priv_t *io = pcm->private_data;
diff --git a/src/pcm/pcm_local.h b/src/pcm/pcm_local.h
index fe77e50d..bec5a408 100644
--- a/src/pcm/pcm_local.h
+++ b/src/pcm/pcm_local.h
@@ -444,7 +444,7 @@ static inline int __snd_pcm_start(snd_pcm_t *pcm)
 static inline snd_pcm_state_t __snd_pcm_state(snd_pcm_t *pcm)
 {
 	if (!pcm->fast_ops->state)
-		return -ENOSYS;
+		return SND_PCM_STATE_OPEN;
 	return pcm->fast_ops->state(pcm->fast_op_arg);
 }
 
diff --git a/src/pcm/pcm_mmap.c b/src/pcm/pcm_mmap.c
index 9600c383..9cbaae05 100644
--- a/src/pcm/pcm_mmap.c
+++ b/src/pcm/pcm_mmap.c
@@ -183,7 +183,7 @@ snd_pcm_sframes_t snd_pcm_mmap_writen(snd_pcm_t *pcm, void **bufs, snd_pcm_ufram
  * \brief Read interleaved frames from a PCM using direct buffer (mmap)
  * \param pcm PCM handle
  * \param buffer frames containing buffer
- * \param size frames to be written
+ * \param size frames to be read
  * \return a positive number of frames actually read otherwise a
  * negative error code
  * \retval -EBADFD PCM is not in the right state (#SND_PCM_STATE_PREPARED or #SND_PCM_STATE_RUNNING)
diff --git a/src/pcm/pcm_multi.c b/src/pcm/pcm_multi.c
index 53c414d5..5fa09b9b 100644
--- a/src/pcm/pcm_multi.c
+++ b/src/pcm/pcm_multi.c
@@ -1323,7 +1323,6 @@ int _snd_pcm_multi_open(snd_pcm_t **pcmp, const char *name,
 		err = -ENOMEM;
 		goto _free;
 	}
-	idx = 0;
 	for (idx = 0; idx < channels_count; ++idx)
 		channels_sidx[idx] = -1;
 	idx = 0;
diff --git a/src/pcm/pcm_plugin.c b/src/pcm/pcm_plugin.c
index 5739cfc2..7ed6f25a 100644
--- a/src/pcm/pcm_plugin.c
+++ b/src/pcm/pcm_plugin.c
@@ -142,12 +142,6 @@ static int snd_pcm_plugin_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
 	int err = snd_pcm_delay(plugin->gen.slave, &sd);
 	if (err < 0)
 		return err;
-        if (pcm->stream == SND_PCM_STREAM_CAPTURE &&
-	    pcm->access != SND_PCM_ACCESS_RW_INTERLEAVED &&
-	    pcm->access != SND_PCM_ACCESS_RW_NONINTERLEAVED) {
-                sd += snd_pcm_mmap_capture_avail(pcm);
-        }        
-
 	*delayp = sd;
 	return 0;
 }
@@ -460,101 +454,121 @@ snd_pcm_plugin_mmap_commit(snd_pcm_t *pcm,
 	return xfer > 0 ? xfer : err;
 }
 
-static snd_pcm_sframes_t snd_pcm_plugin_avail_update(snd_pcm_t *pcm)
+static snd_pcm_sframes_t
+snd_pcm_plugin_sync_hw_ptr_capture(snd_pcm_t *pcm,
+				   snd_pcm_sframes_t slave_size)
 {
 	snd_pcm_plugin_t *plugin = pcm->private_data;
 	snd_pcm_t *slave = plugin->gen.slave;
-	snd_pcm_sframes_t slave_size;
+	const snd_pcm_channel_area_t *areas;
+	snd_pcm_uframes_t xfer, hw_offset, size;
 	int err;
 
-	slave_size = snd_pcm_avail_update(slave);
+	xfer = snd_pcm_mmap_capture_avail(pcm);
+	size = pcm->buffer_size - xfer;
+	areas = snd_pcm_mmap_areas(pcm);
+	hw_offset = snd_pcm_mmap_hw_offset(pcm);
+	while (size > 0 && slave_size > 0) {
+		snd_pcm_uframes_t frames = size;
+		snd_pcm_uframes_t cont = pcm->buffer_size - hw_offset;
+		const snd_pcm_channel_area_t *slave_areas;
+		snd_pcm_uframes_t slave_offset;
+		snd_pcm_uframes_t slave_frames = ULONG_MAX;
+		snd_pcm_sframes_t result;
+		/* As mentioned in the ALSA API (see pcm/pcm.c:942):
+		 * The function #snd_pcm_avail_update()
+		 * have to be called before any mmap begin+commit operation.
+		 * Otherwise the snd_pcm_areas_copy will not called a second time.
+		 * But this is needed, if the ring buffer wrap is reached and
+		 * there is more data available.
+		 */
+		slave_size = snd_pcm_avail_update(slave);
+		result = snd_pcm_mmap_begin(slave, &slave_areas, &slave_offset, &slave_frames);
+		if (result < 0) {
+			err = result;
+			goto error;
+		}
+		if (frames > cont)
+			frames = cont;
+		frames = (plugin->read)(pcm, areas, hw_offset, frames,
+					slave_areas, slave_offset, &slave_frames);
+		result = snd_pcm_mmap_commit(slave, slave_offset, slave_frames);
+		if (result > 0 && (snd_pcm_uframes_t)result != slave_frames) {
+			snd_pcm_sframes_t res;
+			res = plugin->undo_read(slave, areas, hw_offset, frames, slave_frames - result);
+			if (res < 0) {
+				err = res;
+				goto error;
+			}
+			frames -= res;
+		}
+		if (result <= 0) {
+			err = result;
+			goto error;
+		}
+		snd_pcm_mmap_hw_forward(pcm, frames);
+		if (frames == cont)
+			hw_offset = 0;
+		else
+			hw_offset += frames;
+		size -= frames;
+		slave_size -= slave_frames;
+		xfer += frames;
+	}
+	return (snd_pcm_sframes_t)xfer;
+error:
+	return xfer > 0 ? (snd_pcm_sframes_t)xfer : err;
+}
+
+static snd_pcm_sframes_t snd_pcm_plugin_sync_hw_ptr(snd_pcm_t *pcm,
+						    snd_pcm_uframes_t slave_hw_ptr,
+						    snd_pcm_sframes_t slave_size)
+{
 	if (pcm->stream == SND_PCM_STREAM_CAPTURE &&
 	    pcm->access != SND_PCM_ACCESS_RW_INTERLEAVED &&
 	    pcm->access != SND_PCM_ACCESS_RW_NONINTERLEAVED)
-		goto _capture;
-        *pcm->hw.ptr = *slave->hw.ptr;
+		return snd_pcm_plugin_sync_hw_ptr_capture(pcm, slave_size);
+        *pcm->hw.ptr = slave_hw_ptr;
         return slave_size;
- _capture:
- 	{
-		const snd_pcm_channel_area_t *areas;
-		snd_pcm_uframes_t xfer, hw_offset, size;
-		
-		xfer = snd_pcm_mmap_capture_avail(pcm);
-		size = pcm->buffer_size - xfer;
-		areas = snd_pcm_mmap_areas(pcm);
-		hw_offset = snd_pcm_mmap_hw_offset(pcm);
-		while (size > 0 && slave_size > 0) {
-			snd_pcm_uframes_t frames = size;
-			snd_pcm_uframes_t cont = pcm->buffer_size - hw_offset;
-			const snd_pcm_channel_area_t *slave_areas;
-			snd_pcm_uframes_t slave_offset;
-			snd_pcm_uframes_t slave_frames = ULONG_MAX;
-			snd_pcm_sframes_t result;
-			/* As mentioned in the ALSA API (see pcm/pcm.c:942):
-			 * The function #snd_pcm_avail_update()
-			 * have to be called before any mmap begin+commit operation.
-			 * Otherwise the snd_pcm_areas_copy will not called a second time.
-			 * But this is needed, if the ring buffer wrap is reached and
-			 * there is more data available.
-			 */
-			slave_size = snd_pcm_avail_update(slave);
-			result = snd_pcm_mmap_begin(slave, &slave_areas, &slave_offset, &slave_frames);
-			if (result < 0) {
-				err = result;
-				goto error;
-			}
-			if (frames > cont)
-				frames = cont;
-			frames = (plugin->read)(pcm, areas, hw_offset, frames,
-					      slave_areas, slave_offset, &slave_frames);
-			result = snd_pcm_mmap_commit(slave, slave_offset, slave_frames);
-			if (result > 0 && (snd_pcm_uframes_t)result != slave_frames) {
-				snd_pcm_sframes_t res;
-				
-				res = plugin->undo_read(slave, areas, hw_offset, frames, slave_frames - result);
-				if (res < 0) {
-					err = res;
-					goto error;
-				}
-				frames -= res;
-			}
-			if (result <= 0) {
-				err = result;
-				goto error;
-			}
-			snd_pcm_mmap_hw_forward(pcm, frames);
-			if (frames == cont)
-				hw_offset = 0;
-			else
-				hw_offset += frames;
-			size -= frames;
-			slave_size -= slave_frames;
-			xfer += frames;
-		}
-		return (snd_pcm_sframes_t)xfer;
+}
 
-	error:
-		return xfer > 0 ? (snd_pcm_sframes_t)xfer : err;
-	}
+static snd_pcm_sframes_t snd_pcm_plugin_avail_update(snd_pcm_t *pcm)
+{
+	snd_pcm_plugin_t *plugin = pcm->private_data;
+	snd_pcm_t *slave = plugin->gen.slave;
+	snd_pcm_sframes_t slave_size;
+
+	slave_size = snd_pcm_avail_update(slave);
+	return snd_pcm_plugin_sync_hw_ptr(pcm, *slave->hw.ptr, slave_size);
 }
 
 static int snd_pcm_plugin_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
 {
 	snd_pcm_plugin_t *plugin = pcm->private_data;
-	snd_pcm_sframes_t err, avail;
-
-	/* sync with the latest hw and appl ptrs */
-	avail = snd_pcm_plugin_avail_update(pcm);
-	if (avail < 0)
-		return avail;
+	snd_pcm_sframes_t err, diff;
 
 	err = snd_pcm_status(plugin->gen.slave, status);
 	if (err < 0)
 		return err;
-	status->appl_ptr = *pcm->appl.ptr;
-	status->hw_ptr = *pcm->hw.ptr;
-	status->avail = avail;
-	status->delay = snd_pcm_mmap_delay(pcm);
+	snd_pcm_plugin_sync_hw_ptr(pcm, status->hw_ptr, status->avail);
+	/*
+	 * For capture stream, the situation is more complicated, because
+	 * snd_pcm_plugin_avail_update() commits the data to the slave pcm.
+	 * It means that the slave appl_ptr is updated. Calculate diff and
+	 * update the delay and avail.
+	 *
+	 * This resolves the data inconsistency for immediate calls:
+	 *    snd_pcm_avail_update()
+	 *    snd_pcm_status()
+	 */
+	if (pcm->stream == SND_PCM_STREAM_CAPTURE) {
+		status->appl_ptr = *pcm->appl.ptr;
+		diff = pcm_frame_diff(status->appl_ptr, *pcm->appl.ptr, pcm->boundary);
+		status->avail += diff;
+		status->delay += diff;
+	} else {
+		assert(status->appl_ptr == *pcm->appl.ptr);
+	}
 	return 0;
 }
 
diff --git a/src/pcm/pcm_rate.c b/src/pcm/pcm_rate.c
index 5bf7dbb9..770aafea 100644
--- a/src/pcm/pcm_rate.c
+++ b/src/pcm/pcm_rate.c
@@ -561,17 +561,16 @@ snd_pcm_rate_read_areas1(snd_pcm_t *pcm,
 
 static inline void snd_pcm_rate_sync_hwptr0(snd_pcm_t *pcm, snd_pcm_uframes_t slave_hw_ptr)
 {
-	snd_pcm_rate_t *rate = pcm->private_data;
-
-	snd_pcm_sframes_t slave_hw_ptr_diff = slave_hw_ptr - rate->last_slave_hw_ptr;
+	snd_pcm_rate_t *rate;
+	snd_pcm_sframes_t slave_hw_ptr_diff;
 	snd_pcm_sframes_t last_slave_hw_ptr_frac;
 
 	if (pcm->stream != SND_PCM_STREAM_PLAYBACK)
 		return;
 
-	if (slave_hw_ptr_diff < 0)
-		slave_hw_ptr_diff += rate->gen.slave->boundary; /* slave boundary wraparound */
-	else if (slave_hw_ptr_diff == 0)
+	rate = pcm->private_data;
+	slave_hw_ptr_diff = pcm_frame_diff(slave_hw_ptr, rate->last_slave_hw_ptr, rate->gen.slave->boundary);
+	if (slave_hw_ptr_diff == 0)
 		return;
 	last_slave_hw_ptr_frac = rate->last_slave_hw_ptr % rate->gen.slave->period_size;
 	/* While handling fraction part fo slave period, rounded value will be
@@ -612,11 +611,7 @@ static snd_pcm_uframes_t snd_pcm_rate_playback_internal_delay(snd_pcm_t *pcm)
 {
 	snd_pcm_rate_t *rate = pcm->private_data;
 
-	if (rate->appl_ptr < rate->last_commit_ptr) {
-		return rate->appl_ptr - rate->last_commit_ptr + pcm->boundary;
-	} else {
-		return rate->appl_ptr - rate->last_commit_ptr;
-	}
+	return pcm_frame_diff(rate->appl_ptr, rate->last_commit_ptr, pcm->boundary);
 }
 
 static int snd_pcm_rate_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
@@ -637,7 +632,7 @@ static int snd_pcm_rate_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
 				+ snd_pcm_rate_playback_internal_delay(pcm);
 	} else {
 		*delayp = rate->ops.output_frames(rate->obj, slave_delay)
-				+ snd_pcm_mmap_capture_hw_avail(pcm);
+				+ snd_pcm_mmap_capture_delay(pcm);
 	}
 	return 0;
 }
@@ -746,7 +741,6 @@ static int snd_pcm_rate_commit_area(snd_pcm_t *pcm, snd_pcm_rate_t *rate,
 		if (result < 0)
 			return result;
 	      __partial:
-		xfer = 0;
 		cont = slave_frames;
 		if (cont > slave_size)
 			cont = slave_size;
@@ -846,7 +840,6 @@ static int snd_pcm_rate_grab_next_period(snd_pcm_t *pcm, snd_pcm_uframes_t hw_of
 		if (result < 0)
 			return result;
 	      __partial:
-		xfer = 0;
 		cont = slave_frames;
 		if (cont > rate->gen.slave->period_size)
 			cont = rate->gen.slave->period_size;
@@ -928,10 +921,7 @@ static int snd_pcm_rate_sync_playback_area(snd_pcm_t *pcm, snd_pcm_uframes_t app
 	if (slave_size < 0)
 		return slave_size;
 
-	if (appl_ptr < rate->last_commit_ptr)
-		xfer = appl_ptr - rate->last_commit_ptr + pcm->boundary;
-	else
-		xfer = appl_ptr - rate->last_commit_ptr;
+	xfer = pcm_frame_diff(appl_ptr, rate->last_commit_ptr, pcm->boundary);
 	while (xfer >= pcm->period_size &&
 	       (snd_pcm_uframes_t)slave_size >= rate->gen.slave->period_size) {
 		err = snd_pcm_rate_commit_next_period(pcm, rate->last_commit_ptr % pcm->buffer_size);
@@ -966,29 +956,18 @@ static snd_pcm_sframes_t snd_pcm_rate_mmap_commit(snd_pcm_t *pcm,
 	return size;
 }
 
-static snd_pcm_sframes_t snd_pcm_rate_avail_update(snd_pcm_t *pcm)
+static snd_pcm_sframes_t snd_pcm_rate_avail_update_capture(snd_pcm_t *pcm,
+							   snd_pcm_sframes_t slave_size)
 {
 	snd_pcm_rate_t *rate = pcm->private_data;
 	snd_pcm_t *slave = rate->gen.slave;
-	snd_pcm_sframes_t slave_size;
-
-	slave_size = snd_pcm_avail_update(slave);
-	if (slave_size < 0)
-		return slave_size;
-
-	if (pcm->stream == SND_PCM_STREAM_CAPTURE)
-		goto _capture;
-	snd_pcm_rate_sync_hwptr(pcm);
-	snd_pcm_rate_sync_playback_area(pcm, rate->appl_ptr);
-	return snd_pcm_mmap_avail(pcm);
- _capture: {
 	snd_pcm_uframes_t xfer, hw_offset, size;
 	
 	xfer = snd_pcm_mmap_capture_avail(pcm);
 	size = pcm->buffer_size - xfer;
 	hw_offset = snd_pcm_mmap_hw_offset(pcm);
 	while (size >= pcm->period_size &&
-	       (snd_pcm_uframes_t)slave_size >= rate->gen.slave->period_size) {
+	       (snd_pcm_uframes_t)slave_size >= slave->period_size) {
 		int err = snd_pcm_rate_grab_next_period(pcm, hw_offset);
 		if (err < 0)
 			return err;
@@ -996,13 +975,29 @@ static snd_pcm_sframes_t snd_pcm_rate_avail_update(snd_pcm_t *pcm)
 			return (snd_pcm_sframes_t)xfer;
 		xfer += pcm->period_size;
 		size -= pcm->period_size;
-		slave_size -= rate->gen.slave->period_size;
+		slave_size -= slave->period_size;
 		hw_offset += pcm->period_size;
 		hw_offset %= pcm->buffer_size;
 		snd_pcm_mmap_hw_forward(pcm, pcm->period_size);
 	}
 	return (snd_pcm_sframes_t)xfer;
- }
+}
+
+static snd_pcm_sframes_t snd_pcm_rate_avail_update(snd_pcm_t *pcm)
+{
+	snd_pcm_rate_t *rate = pcm->private_data;
+	snd_pcm_sframes_t slave_size;
+
+	slave_size = snd_pcm_avail_update(rate->gen.slave);
+	if (slave_size < 0)
+		return slave_size;
+
+	if (pcm->stream == SND_PCM_STREAM_CAPTURE)
+		return snd_pcm_rate_avail_update_capture(pcm, slave_size);
+
+	snd_pcm_rate_sync_hwptr(pcm);
+	snd_pcm_rate_sync_playback_area(pcm, rate->appl_ptr);
+	return snd_pcm_mmap_avail(pcm);
 }
 
 static int snd_pcm_rate_htimestamp(snd_pcm_t *pcm,
@@ -1060,9 +1055,7 @@ static int snd_pcm_rate_drain(snd_pcm_t *pcm)
 		sw_params.avail_min = 1;
 		snd_pcm_sw_params(rate->gen.slave, &sw_params);
 
-		size = rate->appl_ptr - rate->last_commit_ptr;
-		if (size > pcm->boundary)
-			size -= pcm->boundary;
+		size = pcm_frame_diff(rate->appl_ptr, rate->last_commit_ptr, pcm->boundary);
 		ofs = rate->last_commit_ptr % pcm->buffer_size;
 		while (size > 0) {
 			snd_pcm_uframes_t psize, spsize;
@@ -1164,12 +1157,8 @@ static int snd_pcm_rate_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
 		status->avail = snd_pcm_mmap_playback_avail(pcm);
 		status->avail_max = rate->ops.input_frames(rate->obj, status->avail_max);
 	} else {
-		/* FIXME: Maybe possible to somthing similar to
-		 * snd_pcm_rate_playback_internal_delay()
-		 * for the capture case.
-		 */
 		status->delay = rate->ops.output_frames(rate->obj, status->delay)
-					+ snd_pcm_mmap_capture_hw_avail(pcm);
+					+ snd_pcm_mmap_capture_delay(pcm);
 		status->avail = snd_pcm_mmap_capture_avail(pcm);
 		status->avail_max = rate->ops.output_frames(rate->obj, status->avail_max);
 	}
diff --git a/src/rawmidi/rawmidi_virt.c b/src/rawmidi/rawmidi_virt.c
index 2c4c27f5..884b8ff8 100644
--- a/src/rawmidi/rawmidi_virt.c
+++ b/src/rawmidi/rawmidi_virt.c
@@ -315,7 +315,7 @@ int snd_rawmidi_virtual_open(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp,
 			     int merge, int mode)
 {
 	int err;
-	snd_rawmidi_t *rmidi;
+	snd_rawmidi_t *rmidi = NULL;
 	snd_rawmidi_virtual_t *virt = NULL;
 	struct pollfd pfd;
 
@@ -392,6 +392,7 @@ int snd_rawmidi_virtual_open(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp,
 		free(*inputp);
 	if (outputp)
 		free(*outputp);
+	free(rmidi);
 	return err;
 }
 
diff --git a/src/timer/timer_query_hw.c b/src/timer/timer_query_hw.c
index dad228c8..d8bac6e7 100644
--- a/src/timer/timer_query_hw.c
+++ b/src/timer/timer_query_hw.c
@@ -104,7 +104,7 @@ int snd_timer_query_hw_open(snd_timer_query_t **handle, const char *name, int mo
 		close(fd);
 		return -SND_ERROR_INCOMPATIBLE_VERSION;
 	}
-	tmr = (snd_timer_query_t *) calloc(1, sizeof(snd_timer_t));
+	tmr = (snd_timer_query_t *) calloc(1, sizeof(snd_timer_query_t));
 	if (tmr == NULL) {
 		close(fd);
 		return -ENOMEM;
diff --git a/src/topology/dapm.c b/src/topology/dapm.c
index 92dc01aa..f6a84a60 100644
--- a/src/topology/dapm.c
+++ b/src/topology/dapm.c
@@ -836,6 +836,7 @@ int tplg_add_widget_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t)
 		default:
 			SNDERR("widget %s: invalid type %d for ctl %d",
 				wt->name, ct->type, i);
+			ret = -EINVAL;
 			break;
 		}
 
diff --git a/src/topology/data.c b/src/topology/data.c
index c2931bd2..5633cdc3 100644
--- a/src/topology/data.c
+++ b/src/topology/data.c
@@ -860,7 +860,7 @@ static int parse_tuple_set(snd_config_t *cfg,
 			}
 
 			if ((type == SND_SOC_TPLG_TUPLE_TYPE_WORD
-					&& tuple_val > UINT_MAX)
+					/* && tuple_val > UINT_MAX */)
 				|| (type == SND_SOC_TPLG_TUPLE_TYPE_SHORT
 					&& tuple_val > USHRT_MAX)
 				|| (type == SND_SOC_TPLG_TUPLE_TYPE_BYTE
diff --git a/src/topology/pcm.c b/src/topology/pcm.c
index 191b7a0a..a473b59b 100644
--- a/src/topology/pcm.c
+++ b/src/topology/pcm.c
@@ -1411,6 +1411,7 @@ int tplg_parse_hw_config(snd_tplg_t *tplg, snd_config_t *cfg,
 	snd_config_t *n;
 	const char *id, *val = NULL;
 	int ret, ival;
+	bool provider_legacy;
 
 	elem = tplg_elem_new_common(tplg, cfg, NULL, SND_TPLG_TYPE_HW_CONFIG);
 	if (!elem)
@@ -1451,8 +1452,15 @@ int tplg_parse_hw_config(snd_tplg_t *tplg, snd_config_t *cfg,
 			continue;
 		}
 
-		if (strcmp(id, "bclk") == 0 ||
-		    strcmp(id, "bclk_master") == 0) {
+		provider_legacy = false;
+		if (strcmp(id, "bclk_master") == 0) {
+			SNDERR("deprecated option %s, please use 'bclk'\n", id);
+			provider_legacy = true;
+		}
+
+		if (provider_legacy ||
+		    strcmp(id, "bclk") == 0) {
+
 			if (snd_config_get_string(n, &val) < 0)
 				return -EINVAL;
 
@@ -1462,11 +1470,19 @@ int tplg_parse_hw_config(snd_tplg_t *tplg, snd_config_t *cfg,
 				 */
 				SNDERR("deprecated bclk value '%s'", val);
 
-				hw_cfg->bclk_master = SND_SOC_TPLG_BCLK_CS;
+				hw_cfg->bclk_provider = SND_SOC_TPLG_BCLK_CC;
 			} else if (!strcmp(val, "codec_slave")) {
-				hw_cfg->bclk_master = SND_SOC_TPLG_BCLK_CS;
+				SNDERR("deprecated bclk value '%s', use 'codec_consumer'", val);
+
+				hw_cfg->bclk_provider = SND_SOC_TPLG_BCLK_CC;
+			} else if (!strcmp(val, "codec_consumer")) {
+				hw_cfg->bclk_provider = SND_SOC_TPLG_BCLK_CC;
 			} else if (!strcmp(val, "codec_master")) {
-				hw_cfg->bclk_master = SND_SOC_TPLG_BCLK_CM;
+				SNDERR("deprecated bclk value '%s', use 'codec_provider", val);
+
+				hw_cfg->bclk_provider = SND_SOC_TPLG_BCLK_CP;
+			} else if (!strcmp(val, "codec_provider")) {
+				hw_cfg->bclk_provider = SND_SOC_TPLG_BCLK_CP;
 			}
 			continue;
 		}
@@ -1488,8 +1504,15 @@ int tplg_parse_hw_config(snd_tplg_t *tplg, snd_config_t *cfg,
 			continue;
 		}
 
-		if (strcmp(id, "fsync") == 0 ||
-		    strcmp(id, "fsync_master") == 0) {
+		provider_legacy = false;
+		if (strcmp(id, "fsync_master") == 0) {
+			SNDERR("deprecated option %s, please use 'fsync'\n", id);
+			provider_legacy = true;
+		}
+
+		if (provider_legacy ||
+		    strcmp(id, "fsync") == 0) {
+
 			if (snd_config_get_string(n, &val) < 0)
 				return -EINVAL;
 
@@ -1499,11 +1522,19 @@ int tplg_parse_hw_config(snd_tplg_t *tplg, snd_config_t *cfg,
 				 */
 				SNDERR("deprecated fsync value '%s'", val);
 
-				hw_cfg->fsync_master = SND_SOC_TPLG_FSYNC_CS;
+				hw_cfg->fsync_provider = SND_SOC_TPLG_FSYNC_CC;
 			} else if (!strcmp(val, "codec_slave")) {
-				hw_cfg->fsync_master = SND_SOC_TPLG_FSYNC_CS;
+				SNDERR("deprecated fsync value '%s', use 'codec_consumer'", val);
+
+				hw_cfg->fsync_provider = SND_SOC_TPLG_FSYNC_CC;
+			} else if (!strcmp(val, "codec_consumer")) {
+				hw_cfg->fsync_provider = SND_SOC_TPLG_FSYNC_CC;
 			} else if (!strcmp(val, "codec_master")) {
-				hw_cfg->fsync_master = SND_SOC_TPLG_FSYNC_CM;
+				SNDERR("deprecated fsync value '%s', use 'codec_provider'", val);
+
+				hw_cfg->fsync_provider = SND_SOC_TPLG_FSYNC_CP;
+			} else if (!strcmp(val, "codec_provider")) {
+				hw_cfg->fsync_provider = SND_SOC_TPLG_FSYNC_CP;
 			}
 			continue;
 		}
@@ -1623,19 +1654,19 @@ int tplg_save_hw_config(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
 	if (err >= 0 && hc->fmt)
 		err = tplg_save_printf(dst, pfx, "\tformat '%s'\n",
 				       get_audio_hw_format_name(hc->fmt));
-	if (err >= 0 && hc->bclk_master)
+	if (err >= 0 && hc->bclk_provider)
 		err = tplg_save_printf(dst, pfx, "\tbclk '%s'\n",
-				       hc->bclk_master == SND_SOC_TPLG_BCLK_CS ?
-						"codec_slave" : "codec_master");
+				       hc->bclk_provider == SND_SOC_TPLG_BCLK_CC ?
+						"codec_consumer" : "codec_provider");
 	if (err >= 0 && hc->bclk_rate)
 		err = tplg_save_printf(dst, pfx, "\tbclk_freq %u\n",
 				       hc->bclk_rate);
 	if (err >= 0 && hc->invert_bclk)
 		err = tplg_save_printf(dst, pfx, "\tbclk_invert 1\n");
-	if (err >= 0 && hc->fsync_master)
-		err = tplg_save_printf(dst, pfx, "\tfsync_master '%s'\n",
-				       hc->fsync_master == SND_SOC_TPLG_FSYNC_CS ?
-						"codec_slave" : "codec_master");
+	if (err >= 0 && hc->fsync_provider)
+		err = tplg_save_printf(dst, pfx, "\tfsync_provider '%s'\n",
+				       hc->fsync_provider == SND_SOC_TPLG_FSYNC_CC ?
+						"codec_consumer" : "codec_provider");
 	if (err >= 0 && hc->fsync_rate)
 		err = tplg_save_printf(dst, pfx, "\tfsync_freq %u\n",
 				       hc->fsync_rate);
@@ -1791,8 +1822,8 @@ static int set_link_hw_config(struct snd_soc_tplg_hw_config *cfg,
 	cfg->clock_gated = tpl->clock_gated;
 	cfg->invert_bclk = tpl->invert_bclk;
 	cfg->invert_fsync = tpl->invert_fsync;
-	cfg->bclk_master = tpl->bclk_master;
-	cfg->fsync_master = tpl->fsync_master;
+	cfg->bclk_provider = tpl->bclk_provider;
+	cfg->fsync_provider = tpl->fsync_provider;
 	cfg->mclk_direction = tpl->mclk_direction;
 	cfg->reserved = tpl->reserved;
 	cfg->mclk_rate = tpl->mclk_rate;
@@ -1989,7 +2020,7 @@ next:
 	pt->playback = pcm->playback;
 	pt->capture = pcm->capture;
 	pt->compress = pcm->compress;
-	tplg_log(tplg, 'D', pos, "pcm: playback %d capture %d compress",
+	tplg_log(tplg, 'D', pos, "pcm: playback %d capture %d compress %d",
 		 pt->playback, pt->capture, pt->compress);
 	pt->num_streams = pcm->num_streams;
 	pt->flag_mask = pcm->flag_mask;
@@ -2174,8 +2205,8 @@ next:
 		hw->clock_gated = link->hw_config[i].clock_gated;
 		hw->invert_bclk = link->hw_config[i].invert_bclk;
 		hw->invert_fsync = link->hw_config[i].invert_fsync;
-		hw->bclk_master = link->hw_config[i].bclk_master;
-		hw->fsync_master = link->hw_config[i].fsync_master;
+		hw->bclk_provider = link->hw_config[i].bclk_provider;
+		hw->fsync_provider = link->hw_config[i].fsync_provider;
 		hw->mclk_direction = link->hw_config[i].mclk_direction;
 		hw->mclk_rate = link->hw_config[i].mclk_rate;
 		hw->bclk_rate = link->hw_config[i].bclk_rate;
diff --git a/src/topology/save.c b/src/topology/save.c
index c7a5a801..fecbc6a5 100644
--- a/src/topology/save.c
+++ b/src/topology/save.c
@@ -133,6 +133,8 @@ static int tplg_pprint_integer(snd_config_t *n, char **ret)
 		if (llval < INT_MIN || llval > UINT_MAX)
 			return snd_config_get_ascii(n, ret);
 		lval = llval;
+	} else {
+		lval = 0;
 	}
 	err = tplg_nice_value_format(buf, sizeof(buf), (unsigned int)lval);
 	if (err < 0)
@@ -178,29 +180,28 @@ static snd_config_t *sort_config(const char *id, snd_config_t *src)
 	}
 	if (array <= 0)
 		qsort(a, count, sizeof(a[0]), _compar);
-	if (snd_config_make_compound(&dst, id, count == 1)) {
-		free(a);
-		return NULL;
-	}
+	if (snd_config_make_compound(&dst, id, count == 1))
+		goto lerr;
 	for (index = 0; index < count; index++) {
 		snd_config_t *s = a[index];
 		const char *id2;
 		if (snd_config_get_id(s, &id2)) {
 			snd_config_delete(dst);
-			free(a);
-			return NULL;
+			goto lerr;
 		}
 		s = sort_config(id2, s);
 		if (s == NULL || snd_config_add(dst, s)) {
 			if (s)
 				snd_config_delete(s);
 			snd_config_delete(dst);
-			free(a);
-			return NULL;
+			goto lerr;
 		}
 	}
 	free(a);
 	return dst;
+lerr:
+	free(a);
+	return NULL;
 }
 
 static int tplg_check_quoted(const unsigned char *p)
diff --git a/src/ucm/main.c b/src/ucm/main.c
index 3871d5aa..754b967e 100644
--- a/src/ucm/main.c
+++ b/src/ucm/main.c
@@ -666,7 +666,7 @@ static int get_list0(struct list_head *list,
 	}
 	return cnt;
       __fail:
-        snd_use_case_free_list((const char **)res, cnt);
+        snd_use_case_free_list(*result, cnt);
         return -ENOMEM;
 }
 
@@ -724,7 +724,7 @@ static int get_list20(struct list_head *list,
 	}
 	return cnt;
       __fail:
-        snd_use_case_free_list((const char **)res, cnt);
+        snd_use_case_free_list(*result, cnt);
         return -ENOMEM;
 }
 
diff --git a/src/ucm/parser.c b/src/ucm/parser.c
index 75b78826..c8bee1f2 100644
--- a/src/ucm/parser.c
+++ b/src/ucm/parser.c
@@ -1575,7 +1575,7 @@ static int parse_verb_file(snd_use_case_mgr_t *uc_mgr,
 	/* in-place evaluation */
 	err = uc_mgr_evaluate_inplace(uc_mgr, cfg);
 	if (err < 0)
-		return err;
+		goto _err;
 
 	/* parse master config sections */
 	snd_config_for_each(i, next, cfg) {
diff --git a/src/ucm/ucm_subs.c b/src/ucm/ucm_subs.c
index f608bb09..df6d736f 100644
--- a/src/ucm/ucm_subs.c
+++ b/src/ucm/ucm_subs.c
@@ -417,11 +417,12 @@ int uc_mgr_substitute_tree(snd_use_case_mgr_t *uc_mgr, snd_config_t *node)
 		if (err < 0)
 			return err;
 		err = snd_config_set_id(node, s);
-		free(s);
 		if (err < 0) {
 			uc_error("unable to set substituted id '%s' (old id '%s')", s, id);
+			free(s);
 			return err;
 		}
+		free(s);
 	}
 	if (snd_config_get_type(node) != SND_CONFIG_TYPE_COMPOUND) {
 		if (snd_config_get_type(node) == SND_CONFIG_TYPE_STRING) {
diff --git a/test/audio_time.c b/test/audio_time.c
index 530922d9..e4d4a944 100644
--- a/test/audio_time.c
+++ b/test/audio_time.c
@@ -32,7 +32,7 @@ static void usage(char *command)
 		"-d, --delay             add delay \n"
 		"-D, --device=NAME       select PCM by name \n"
 		"-p, --playback          playback tstamps \n"
-		"-t, --ts_type=TYPE      Default(0),link(1),link_estimated(2),synchronized(3) \n"
+		"-t, --ts_type=TYPE      Compat(0),default(1),link(2),link_absolute(3),link_estimated(4),link_synchronized(5) \n"
 		"-r, --report            show audio timestamp and accuracy validity\n"
 		, command);
 }
@@ -201,17 +201,17 @@ int main(int argc, char *argv[])
 			goto _exit;
 		}
 
-		if (snd_pcm_hw_params_supports_audio_ts_type(hwparams_p, 0))
+		if (snd_pcm_hw_params_supports_audio_ts_type(hwparams_p, SND_PCM_AUDIO_TSTAMP_TYPE_COMPAT))
 			printf("Playback supports audio compat timestamps\n");
-		if (snd_pcm_hw_params_supports_audio_ts_type(hwparams_p, 1))
+		if (snd_pcm_hw_params_supports_audio_ts_type(hwparams_p, SND_PCM_AUDIO_TSTAMP_TYPE_DEFAULT))
 			printf("Playback supports audio default timestamps\n");
-		if (snd_pcm_hw_params_supports_audio_ts_type(hwparams_p, 2))
+		if (snd_pcm_hw_params_supports_audio_ts_type(hwparams_p, SND_PCM_AUDIO_TSTAMP_TYPE_LINK))
 			printf("Playback supports audio link timestamps\n");
-		if (snd_pcm_hw_params_supports_audio_ts_type(hwparams_p, 3))
+		if (snd_pcm_hw_params_supports_audio_ts_type(hwparams_p, SND_PCM_AUDIO_TSTAMP_TYPE_LINK_ABSOLUTE))
 			printf("Playback supports audio link absolute timestamps\n");
-		if (snd_pcm_hw_params_supports_audio_ts_type(hwparams_p, 4))
+		if (snd_pcm_hw_params_supports_audio_ts_type(hwparams_p, SND_PCM_AUDIO_TSTAMP_TYPE_LINK_ESTIMATED))
 			printf("Playback supports audio link estimated timestamps\n");
-		if (snd_pcm_hw_params_supports_audio_ts_type(hwparams_p, 5))
+		if (snd_pcm_hw_params_supports_audio_ts_type(hwparams_p, SND_PCM_AUDIO_TSTAMP_TYPE_LINK_SYNCHRONIZED))
 			printf("Playback supports audio link synchronized timestamps\n");
 
 		snd_pcm_sw_params_alloca(&swparams_p);
@@ -269,17 +269,17 @@ int main(int argc, char *argv[])
 			goto _exit;
 		}
 
-		if (snd_pcm_hw_params_supports_audio_ts_type(hwparams_c, 0))
+		if (snd_pcm_hw_params_supports_audio_ts_type(hwparams_c, SND_PCM_AUDIO_TSTAMP_TYPE_COMPAT))
 			printf("Capture supports audio compat timestamps\n");
-		if (snd_pcm_hw_params_supports_audio_ts_type(hwparams_c, 1))
+		if (snd_pcm_hw_params_supports_audio_ts_type(hwparams_c, SND_PCM_AUDIO_TSTAMP_TYPE_DEFAULT))
 			printf("Capture supports audio default timestamps\n");
-		if (snd_pcm_hw_params_supports_audio_ts_type(hwparams_c, 2))
+		if (snd_pcm_hw_params_supports_audio_ts_type(hwparams_c, SND_PCM_AUDIO_TSTAMP_TYPE_LINK))
 			printf("Capture supports audio link timestamps\n");
-		if (snd_pcm_hw_params_supports_audio_ts_type(hwparams_c, 3))
+		if (snd_pcm_hw_params_supports_audio_ts_type(hwparams_c, SND_PCM_AUDIO_TSTAMP_TYPE_LINK_ABSOLUTE))
 			printf("Capture supports audio link absolute timestamps\n");
-		if (snd_pcm_hw_params_supports_audio_ts_type(hwparams_c, 4))
+		if (snd_pcm_hw_params_supports_audio_ts_type(hwparams_c, SND_PCM_AUDIO_TSTAMP_TYPE_LINK_ESTIMATED))
 			printf("Capture supports audio link estimated timestamps\n");
-		if (snd_pcm_hw_params_supports_audio_ts_type(hwparams_c, 5))
+		if (snd_pcm_hw_params_supports_audio_ts_type(hwparams_c, SND_PCM_AUDIO_TSTAMP_TYPE_LINK_SYNCHRONIZED))
 			printf("Capture supports audio link synchronized timestamps\n");
 
 		snd_pcm_sw_params_alloca(&swparams_c);