Blame SOURCES/alsa-git.patch

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