Blob Blame History Raw
From ad8c8e5503980295dd8e5e54a6285d2d7e32eb1e Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Thu, 22 Oct 2020 20:57:32 +0200
Subject: [PATCH 01/49] dlmisc: the snd_plugin_dir_set / snd_plugin_dir must be
 declared even for \!DL_ORIGIN_AVAILABLE

Fixes: 8580c081c2 ("dlsym: add support for ALSA_PLUGIN_DIR environment variable")
BugLink: https://github.com/alsa-project/alsa-lib/issues/91
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
 src/dlmisc.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/src/dlmisc.c b/src/dlmisc.c
index c9517c55..f20eb593 100644
--- a/src/dlmisc.c
+++ b/src/dlmisc.c
@@ -42,11 +42,9 @@
 #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)
 static pthread_mutex_t snd_dlpath_mutex = PTHREAD_MUTEX_INITIALIZER;
-- 
2.29.2


From 1d993b37ab4e0b9b6e6b795d7be84ce97b29e20b Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Thu, 29 Oct 2020 20:31:19 +0100
Subject: [PATCH 02/49] dlmisc: fix snd_plugin_dir locking for not
 DL_ORIGIN_AVAILABLE

Fixes: 8580c081c2 ("dlsym: add support for ALSA_PLUGIN_DIR environment variable")
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
 src/dlmisc.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/src/dlmisc.c b/src/dlmisc.c
index f20eb593..1dd91356 100644
--- a/src/dlmisc.c
+++ b/src/dlmisc.c
@@ -46,7 +46,7 @@ static int snd_plugin_dir_set = 0;
 static char *snd_plugin_dir = NULL;
 #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)
@@ -440,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
-- 
2.29.2


From 2757191e3b85d491705b31c6ecca2dbd96d26ade Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Thu, 29 Oct 2020 20:34:17 +0100
Subject: [PATCH 03/49] pcm: snd_pcm_mmap_readi - fix typo in comment

\param size frames to be *read*

Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
 src/pcm/pcm_mmap.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

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)
-- 
2.29.2


From 39bd0e1a5be3620f9123f7fe72ffa6cb7d463b21 Mon Sep 17 00:00:00 2001
From: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Date: Thu, 12 Nov 2020 10:29:38 -0600
Subject: [PATCH 04/49] topology: use inclusive language for bclk

use bclk_provider for structure fields, 'codec_provider' and
'codec_consumer' for options and modify #defines to use CP and CC
suffixes.

Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 include/sound/uapi/asoc.h | 11 +++++++----
 include/topology.h        |  2 +-
 src/topology/pcm.c        | 36 ++++++++++++++++++++++++++----------
 3 files changed, 34 insertions(+), 15 deletions(-)

diff --git a/include/sound/uapi/asoc.h b/include/sound/uapi/asoc.h
index 4efb4ec4..ceafb1a9 100644
--- a/include/sound/uapi/asoc.h
+++ b/include/sound/uapi/asoc.h
@@ -169,10 +169,13 @@
 #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
@@ -335,7 +338,7 @@ 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 bclk_provider;	/* SND_SOC_TPLG_BCLK_ value */
 	__u8 fsync_master;	/* SND_SOC_TPLG_FSYNC_ value */
 	__u8 mclk_direction;    /* SND_SOC_TPLG_MCLK_ value */
 	__le16 reserved;	/* for 32bit alignment */
diff --git a/include/topology.h b/include/topology.h
index 1f52e66e..6c970649 100644
--- a/include/topology.h
+++ b/include/topology.h
@@ -1028,7 +1028,7 @@ 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  bclk_provider;   /* SND_SOC_TPLG_BCLK_ value */
 	unsigned char  fsync_master;    /* SND_SOC_TPLG_FSYNC_ value */
 	unsigned char  mclk_direction;  /* SND_SOC_TPLG_MCLK_ value */
 	unsigned short reserved;        /* for 32bit alignment */
diff --git a/src/topology/pcm.c b/src/topology/pcm.c
index 191b7a0a..f05df348 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;
 		}
@@ -1623,10 +1639,10 @@ 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);
@@ -1791,7 +1807,7 @@ 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->bclk_provider = tpl->bclk_provider;
 	cfg->fsync_master = tpl->fsync_master;
 	cfg->mclk_direction = tpl->mclk_direction;
 	cfg->reserved = tpl->reserved;
@@ -2174,7 +2190,7 @@ 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->bclk_provider = link->hw_config[i].bclk_provider;
 		hw->fsync_master = link->hw_config[i].fsync_master;
 		hw->mclk_direction = link->hw_config[i].mclk_direction;
 		hw->mclk_rate = link->hw_config[i].mclk_rate;
-- 
2.29.2


From 706192341d1d0bbb906d690b227b9dee5c1fc4b5 Mon Sep 17 00:00:00 2001
From: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Date: Thu, 12 Nov 2020 10:29:39 -0600
Subject: [PATCH 05/49] topology: use inclusive language for fsync

use fsync_provider for structure fields, 'codec_provider' and
'codec_consumer' for options and modify #defines to use CP and CC
suffixes.

Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 include/sound/uapi/asoc.h | 11 +++++++----
 include/topology.h        |  2 +-
 src/topology/pcm.c        | 37 ++++++++++++++++++++++++++-----------
 3 files changed, 34 insertions(+), 16 deletions(-)

diff --git a/include/sound/uapi/asoc.h b/include/sound/uapi/asoc.h
index ceafb1a9..f32c5697 100644
--- a/include/sound/uapi/asoc.h
+++ b/include/sound/uapi/asoc.h
@@ -178,10 +178,13 @@
 #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.
@@ -339,7 +342,7 @@ struct snd_soc_tplg_hw_config {
 	__u8 invert_bclk;	/* 1 for inverted BCLK, 0 for normal */
 	__u8 invert_fsync;	/* 1 for inverted frame clock, 0 for normal */
 	__u8 bclk_provider;	/* SND_SOC_TPLG_BCLK_ value */
-	__u8 fsync_master;	/* SND_SOC_TPLG_FSYNC_ 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 6c970649..4ade20df 100644
--- a/include/topology.h
+++ b/include/topology.h
@@ -1029,7 +1029,7 @@ struct snd_tplg_hw_config_template {
 	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_provider;   /* SND_SOC_TPLG_BCLK_ value */
-	unsigned char  fsync_master;    /* SND_SOC_TPLG_FSYNC_ 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/topology/pcm.c b/src/topology/pcm.c
index f05df348..c8f41862 100644
--- a/src/topology/pcm.c
+++ b/src/topology/pcm.c
@@ -1504,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;
 
@@ -1515,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;
 		}
@@ -1648,10 +1663,10 @@ int tplg_save_hw_config(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
 				       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);
@@ -1808,7 +1823,7 @@ static int set_link_hw_config(struct snd_soc_tplg_hw_config *cfg,
 	cfg->invert_bclk = tpl->invert_bclk;
 	cfg->invert_fsync = tpl->invert_fsync;
 	cfg->bclk_provider = tpl->bclk_provider;
-	cfg->fsync_master = tpl->fsync_master;
+	cfg->fsync_provider = tpl->fsync_provider;
 	cfg->mclk_direction = tpl->mclk_direction;
 	cfg->reserved = tpl->reserved;
 	cfg->mclk_rate = tpl->mclk_rate;
@@ -2191,7 +2206,7 @@ next:
 		hw->invert_bclk = link->hw_config[i].invert_bclk;
 		hw->invert_fsync = link->hw_config[i].invert_fsync;
 		hw->bclk_provider = link->hw_config[i].bclk_provider;
-		hw->fsync_master = link->hw_config[i].fsync_master;
+		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;
-- 
2.29.2


From e5c350d7bc6f3d45702059c0ae8d32b3603273c1 Mon Sep 17 00:00:00 2001
From: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Date: Thu, 12 Nov 2020 10:29:40 -0600
Subject: [PATCH 06/49] topology: use inclusive language in documentation

Use codec_provider and codec_consumer for bclk and fsync

Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 include/topology.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/topology.h b/include/topology.h
index 4ade20df..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>
  *
-- 
2.29.2


From 7d36895225d09ae26868997382445cc7ad2e9513 Mon Sep 17 00:00:00 2001
From: Jonas Holmberg <jonashg@axis.com>
Date: Wed, 4 Nov 2020 14:49:56 +0100
Subject: [PATCH 07/49] pcm: set the snd_pcm_ioplug_status() tstamp field

Set the status tstamp field so that it can be accessed with
snd_pcm_status_get_htstamp().

Signed-off-by: Jonas Holmberg <jonashg@axis.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 src/pcm/pcm_ioplug.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/pcm/pcm_ioplug.c b/src/pcm/pcm_ioplug.c
index a437ca32..9b1b8ac3 100644
--- a/src/pcm/pcm_ioplug.c
+++ b/src/pcm/pcm_ioplug.c
@@ -115,6 +115,7 @@ static int snd_pcm_ioplug_status(snd_pcm_t *pcm, snd_pcm_status_t * 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;
 	return 0;
-- 
2.29.2


From 6d3311fefb1b41c7484fd728e4ad4a6fb5b55ad4 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Thu, 10 Dec 2020 10:36:41 +0100
Subject: [PATCH 08/49] Makefile: Add README.md to EXTRA_DIST

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 Makefile.am | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

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
 
-- 
2.29.2


From ea02dbd20a535085638c63c6b8bec94e628486c4 Mon Sep 17 00:00:00 2001
From: David Henningsson <diwic@ubuntu.com>
Date: Wed, 16 Dec 2020 19:55:22 +0100
Subject: [PATCH 09/49] pcm: Add snd_pcm_audio_tstamp_type_t constants

These are mostly a copy-paste from the kernel headers. But since functions
snd_pcm_audio_tstamp_config make use of these they should be added to the
public API as well.

Reported-by: Alex Moon <alex.r.moon@gmail.com>
Signed-off-by: David Henningsson <diwic@ubuntu.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 include/pcm.h | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/include/pcm.h b/include/pcm.h
index 5b078231..cf1eea8b 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 = SNDRV_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;
-- 
2.29.2


From dcda999d0000cbdabe61d3d175943b5f23c30057 Mon Sep 17 00:00:00 2001
From: David Henningsson <diwic@ubuntu.com>
Date: Wed, 16 Dec 2020 20:02:52 +0100
Subject: [PATCH 10/49] test/audio_time: Make use of SND_PCM_AUDIO_TSTAMP_TYPE
 constants

Also fixup the usage row which seemed wrong to me.

Signed-off-by: David Henningsson <diwic@ubuntu.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 test/audio_time.c | 26 +++++++++++++-------------
 1 file changed, 13 insertions(+), 13 deletions(-)

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);
-- 
2.29.2


From a9cbfecd87777d76a83e5a912ca9bdcf48e31fa9 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Tue, 22 Dec 2020 16:10:16 +0100
Subject: [PATCH 11/49] pcm: Fix a typo in SND_PCM_AUDIO_TSTAMP_TYPE_LAST
 definition

It was wrongly defined with SNDRV_ prefix.  Fix it.

Fixes: ea02dbd20a53 ("pcm: Add snd_pcm_audio_tstamp_type_t constants")
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 include/pcm.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/pcm.h b/include/pcm.h
index cf1eea8b..e300b951 100644
--- a/include/pcm.h
+++ b/include/pcm.h
@@ -361,7 +361,7 @@ typedef enum _snd_pcm_audio_tstamp_type {
 	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 = SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK_SYNCHRONIZED
+	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 {
-- 
2.29.2


From 5275d170e05639473e68e5feb349aec65bf26428 Mon Sep 17 00:00:00 2001
From: Alex Henrie <alexhenrie24@gmail.com>
Date: Sat, 26 Dec 2020 14:35:39 -0700
Subject: [PATCH 12/49] conf: fix use after free in
 _snd_config_load_with_include

Signed-off-by: Alex Henrie <alexhenrie24@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 src/conf.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/conf.c b/src/conf.c
index 7df2b4e7..44d1bfde 100644
--- a/src/conf.c
+++ b/src/conf.c
@@ -1970,7 +1970,9 @@ 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;
-- 
2.29.2


From 0f4821ec1729cd72a3dde3ea63f7857e92a10919 Mon Sep 17 00:00:00 2001
From: Alex Henrie <alexhenrie24@gmail.com>
Date: Sat, 26 Dec 2020 14:35:40 -0700
Subject: [PATCH 13/49] ucm: fix bad frees in get_list0 and get_list20

Signed-off-by: Alex Henrie <alexhenrie24@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 src/ucm/main.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

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;
 }
 
-- 
2.29.2


From c56278cfda55b9f5d106890c7354176dba8c8f4d Mon Sep 17 00:00:00 2001
From: Alex Henrie <alexhenrie24@gmail.com>
Date: Sat, 26 Dec 2020 14:35:41 -0700
Subject: [PATCH 14/49] rawmidi: fix memory leak in snd_rawmidi_virtual_open

Signed-off-by: Alex Henrie <alexhenrie24@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 src/rawmidi/rawmidi_virt.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

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;
 }
 
-- 
2.29.2


From aa28847248f2f416d9ecc6cbfa75192455400f6f Mon Sep 17 00:00:00 2001
From: Alex Henrie <alexhenrie24@gmail.com>
Date: Sat, 26 Dec 2020 14:35:43 -0700
Subject: [PATCH 15/49] timer: fix sizeof operator mismatch in
 snd_timer_query_hw_open

Signed-off-by: Alex Henrie <alexhenrie24@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 src/timer/timer_query_hw.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

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;
-- 
2.29.2


From 2e470d59d84a563a9efa81572ddc48d9858ceb92 Mon Sep 17 00:00:00 2001
From: Alex Henrie <alexhenrie24@gmail.com>
Date: Sat, 26 Dec 2020 14:35:44 -0700
Subject: [PATCH 16/49] pcm: remove dead assignments from
 snd_pcm_rate_(commit_area|grab_next_period)

Signed-off-by: Alex Henrie <alexhenrie24@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 src/pcm/pcm_rate.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/src/pcm/pcm_rate.c b/src/pcm/pcm_rate.c
index 5bf7dbb9..dc38e95e 100644
--- a/src/pcm/pcm_rate.c
+++ b/src/pcm/pcm_rate.c
@@ -746,7 +746,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 +845,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;
-- 
2.29.2


From fc719bfe4e97bbfce899cc7e67df08ecd573c5d3 Mon Sep 17 00:00:00 2001
From: Alex Henrie <alexhenrie24@gmail.com>
Date: Sat, 26 Dec 2020 14:35:45 -0700
Subject: [PATCH 17/49] pcm_multi: remove dead assignment from
 _snd_pcm_multi_open

Signed-off-by: Alex Henrie <alexhenrie24@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 src/pcm/pcm_multi.c | 1 -
 1 file changed, 1 deletion(-)

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;
-- 
2.29.2


From 9ebd29d2d31df0f8967f3e60cf24bb63c95d4984 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Sun, 27 Dec 2020 13:17:26 +0100
Subject: [PATCH 18/49] conf: fix get_hexachar() return value

Reported-by: Alex Henrie <alexhenrie24@gmail.com>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
 src/conf.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/conf.c b/src/conf.c
index 44d1bfde..6cfe65bf 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)
-- 
2.29.2


From 36aff79747b23b9535e81befe8b7b2972837bce3 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Sun, 27 Dec 2020 13:29:33 +0100
Subject: [PATCH 19/49] pcm: fix __snd_pcm_state() return value

The __snd_pcm_state() must return a valid state, not an error value
when the plugin callback is not defined. Use the first state
SND_PCM_STATE_OPEN - the other functions will return the error
code depending on this state.

Link: https://lore.kernel.org/alsa-devel/20201226213547.175071-10-alexhenrie24@gmail.com/
Reported-by: Alex Henrie <alexhenrie24@gmail.com>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
 src/pcm/pcm_local.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

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);
 }
 
-- 
2.29.2


From a92ad2fea4b36d7282f4a571275fb492dd1bba75 Mon Sep 17 00:00:00 2001
From: Alex Henrie <alexhenrie24@gmail.com>
Date: Sun, 27 Dec 2020 18:43:15 -0700
Subject: [PATCH 20/49] confmisc: fix memory leak in snd_func_concat

Signed-off-by: Alex Henrie <alexhenrie24@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 src/confmisc.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

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
-- 
2.29.2


From 6c24cd2e60cc9c1fca809ffeeb7ffe8af94b201e Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Tue, 29 Dec 2020 11:15:46 +0100
Subject: [PATCH 21/49] conf: fix return code in _snd_config_load_with_include

Fixes: 5275d170e0 ("conf: fix use after free in _snd_config_load_with_include")
BugLink: https://github.com/alsa-project/alsa-lib/issues/108
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
 src/conf.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/conf.c b/src/conf.c
index 6cfe65bf..3c943db2 100644
--- a/src/conf.c
+++ b/src/conf.c
@@ -1977,6 +1977,7 @@ int _snd_config_load_with_include(snd_config_t *config, snd_input_t *in,
 		err = -EINVAL;
 		goto _end;
 	}
+	err = 0;
  _end:
 	while (fd->next) {
 		fd_next = fd->next;
-- 
2.29.2


From afe6ff3b33ee6e5ea3511fe458bfd4e516b10bcf Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Wed, 30 Dec 2020 09:31:10 +0100
Subject: [PATCH 22/49] pcm: plugin status - fix the return value (regression)

The snd_pcm_plugin_avail_update() error code in snd_pcm_plugin_status()
should not be reported to the caller. The state errors can be determined
using the state member in the status structure.

Fixes: 4f90392f07e ("pcm: fix the snd_pcm_plugin_status() avail and delay fields")
BugLink: https://github.com/alsa-project/alsa-lib/issues/107
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
 src/pcm/pcm_plugin.c | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/src/pcm/pcm_plugin.c b/src/pcm/pcm_plugin.c
index 5739cfc2..76a524fa 100644
--- a/src/pcm/pcm_plugin.c
+++ b/src/pcm/pcm_plugin.c
@@ -541,19 +541,17 @@ static snd_pcm_sframes_t snd_pcm_plugin_avail_update(snd_pcm_t *pcm)
 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;
+	snd_pcm_sframes_t err;
 
 	/* sync with the latest hw and appl ptrs */
-	avail = snd_pcm_plugin_avail_update(pcm);
-	if (avail < 0)
-		return avail;
+	snd_pcm_plugin_avail_update(pcm);
 
 	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->avail = snd_pcm_mmap_avail(pcm);
 	status->delay = snd_pcm_mmap_delay(pcm);
 	return 0;
 }
-- 
2.29.2


From 49eea5d7bc7d39f9a4cc1f3b3a813e90b90519eb Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Sun, 3 Jan 2021 16:16:10 +0100
Subject: [PATCH 23/49] pcm: plugin status - revert the recent changes

It's no reason to sync the avail/delay fields using the mirrored
buffer pointers. The slave information must be valid.

The original report probably tries to fix something for
the specific plugin. Revert all changes.

Fixes: afe6ff3b33e ("pcm: plugin status - fix the return value (regression)")
Fixes: 4f90392f07e ("pcm: fix the snd_pcm_plugin_status() avail and delay fields")
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
 src/pcm/pcm_plugin.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/src/pcm/pcm_plugin.c b/src/pcm/pcm_plugin.c
index 76a524fa..ea60eb98 100644
--- a/src/pcm/pcm_plugin.c
+++ b/src/pcm/pcm_plugin.c
@@ -551,8 +551,6 @@ static int snd_pcm_plugin_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
 		return err;
 	status->appl_ptr = *pcm->appl.ptr;
 	status->hw_ptr = *pcm->hw.ptr;
-	status->avail = snd_pcm_mmap_avail(pcm);
-	status->delay = snd_pcm_mmap_delay(pcm);
 	return 0;
 }
 
-- 
2.29.2


From fa1895aa2b4f3f154e537bee92860fe793045643 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Sun, 3 Jan 2021 16:34:04 +0100
Subject: [PATCH 24/49] pcm: plugin - tidy snd_pcm_plugin_avail_update()

No functional changes - move the code to snd_pcm_plugin_sync_hw_ptr()
and put the mmap capture updates to separate function for readability.

Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
 src/pcm/pcm_plugin.c | 142 +++++++++++++++++++++++--------------------
 1 file changed, 76 insertions(+), 66 deletions(-)

diff --git a/src/pcm/pcm_plugin.c b/src/pcm/pcm_plugin.c
index ea60eb98..83793397 100644
--- a/src/pcm/pcm_plugin.c
+++ b/src/pcm/pcm_plugin.c
@@ -460,82 +460,92 @@ 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)
-- 
2.29.2


From 28cc099d9ea3962b033cb1cb9c3e07db828d9ff7 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Sun, 3 Jan 2021 16:41:29 +0100
Subject: [PATCH 25/49] pcm: plugin - optimize sync in snd_pcm_plugin_status()

Do hw_ptr sync only once after the status call. This avoids
double update.

Also, the application pointer must not change when
the status is called. Add assert() call for this condition.

Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
 src/pcm/pcm_plugin.c | 7 ++-----
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/src/pcm/pcm_plugin.c b/src/pcm/pcm_plugin.c
index 83793397..6a815145 100644
--- a/src/pcm/pcm_plugin.c
+++ b/src/pcm/pcm_plugin.c
@@ -553,14 +553,11 @@ 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;
 
-	/* sync with the latest hw and appl ptrs */
-	snd_pcm_plugin_avail_update(pcm);
-
 	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;
+	assert(status->appl_ptr == *pcm->appl.ptr);
+	snd_pcm_plugin_sync_hw_ptr(pcm, status->hw_ptr, status->avail);
 	return 0;
 }
 
-- 
2.29.2


From 21549e6583f1dfe5b2fe1aaa88345e4645dd96d0 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Wed, 30 Dec 2020 17:49:33 +0100
Subject: [PATCH 26/49] Revert "pcm_plugin: fix delay"

This reverts commit aba87e509898ec9ddb3e319267d7c267409ff100.

The commit does not look good. The plugins must handle
the delay value correctly.

Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
 src/pcm/pcm_plugin.c | 6 ------
 1 file changed, 6 deletions(-)

diff --git a/src/pcm/pcm_plugin.c b/src/pcm/pcm_plugin.c
index 6a815145..5787a43d 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;
 }
-- 
2.29.2


From 6ca01c07ee13435d6c2db4e9121d9a86cc4b1457 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Wed, 30 Dec 2020 19:14:25 +0100
Subject: [PATCH 27/49] pcm: ioplug - fix the delay calculation in the status
 callback

Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
 src/pcm/pcm_ioplug.c | 32 ++++++++++++++++++--------------
 1 file changed, 18 insertions(+), 14 deletions(-)

diff --git a/src/pcm/pcm_ioplug.c b/src/pcm/pcm_ioplug.c
index 9b1b8ac3..f2315a10 100644
--- a/src/pcm/pcm_ioplug.c
+++ b/src/pcm/pcm_ioplug.c
@@ -107,9 +107,24 @@ 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_hw_avail(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);
@@ -118,6 +133,9 @@ static int snd_pcm_ioplug_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
 	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;
 }
 
@@ -133,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;
-- 
2.29.2


From 5988bb3ff42827ab4c13f248291ad1767c8d973d Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Sun, 3 Jan 2021 16:56:38 +0100
Subject: [PATCH 28/49] pcm: rate - tidy up snd_pcm_rate_avail_update()

No functional change - just move the capture code to
a separate function for the better readability.

Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
 src/pcm/pcm_rate.c | 37 +++++++++++++++++++++----------------
 1 file changed, 21 insertions(+), 16 deletions(-)

diff --git a/src/pcm/pcm_rate.c b/src/pcm/pcm_rate.c
index dc38e95e..7073f8ab 100644
--- a/src/pcm/pcm_rate.c
+++ b/src/pcm/pcm_rate.c
@@ -964,29 +964,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;
@@ -994,13 +983,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,
-- 
2.29.2


From 6cee452eabc5cfdf0a6955033b8ac8f6e12ea883 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Sun, 3 Jan 2021 17:13:50 +0100
Subject: [PATCH 29/49] pcm: ioplug - fix the delay calculation for old plugins

Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
 src/pcm/pcm_ioplug.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/pcm/pcm_ioplug.c b/src/pcm/pcm_ioplug.c
index f2315a10..e141b1f9 100644
--- a/src/pcm/pcm_ioplug.c
+++ b/src/pcm/pcm_ioplug.c
@@ -116,7 +116,7 @@ static int snd_pcm_ioplug_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
 		return io->data->callback->delay(io->data, delayp);
 	else {
 		snd_pcm_ioplug_hw_ptr_update(pcm);
-		*delayp = snd_pcm_mmap_hw_avail(pcm);
+		*delayp = snd_pcm_mmap_delay(pcm);
 	}
 	return 0;
 }
-- 
2.29.2


From fc0f7af9ee7bd4c31c2bab229e8e79eb96e908fa Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Mon, 4 Jan 2021 12:29:00 +0100
Subject: [PATCH 30/49] pcm: rate - use pcm_frame_diff() in
 snd_pcm_rate_playback_internal_delay()

Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
 src/pcm/pcm_rate.c | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/src/pcm/pcm_rate.c b/src/pcm/pcm_rate.c
index 7073f8ab..abb2753f 100644
--- a/src/pcm/pcm_rate.c
+++ b/src/pcm/pcm_rate.c
@@ -612,11 +612,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)
-- 
2.29.2


From da5b70d3fae091a8568b80a476c1cf340965805a Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Mon, 4 Jan 2021 12:32:25 +0100
Subject: [PATCH 31/49] pcm: plugin - fix status code for capture

The recent updates do not take in account the possible
calls for the capture stream. Fix the avail and delay
inconsistencies (and assert).

Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
 src/pcm/pcm_plugin.c | 21 +++++++++++++++++++--
 1 file changed, 19 insertions(+), 2 deletions(-)

diff --git a/src/pcm/pcm_plugin.c b/src/pcm/pcm_plugin.c
index 5787a43d..7ed6f25a 100644
--- a/src/pcm/pcm_plugin.c
+++ b/src/pcm/pcm_plugin.c
@@ -545,13 +545,30 @@ static snd_pcm_sframes_t snd_pcm_plugin_avail_update(snd_pcm_t *pcm)
 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;
+	snd_pcm_sframes_t err, diff;
 
 	err = snd_pcm_status(plugin->gen.slave, status);
 	if (err < 0)
 		return err;
-	assert(status->appl_ptr == *pcm->appl.ptr);
 	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;
 }
 
-- 
2.29.2


From ac520b2ed11f31e789a4da1d55e360e3eaeac50d Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Mon, 4 Jan 2021 17:14:42 +0100
Subject: [PATCH 32/49] pcm: rate - use pcm_frame_diff() on related places

Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
 src/pcm/pcm_rate.c | 20 +++++++-------------
 1 file changed, 7 insertions(+), 13 deletions(-)

diff --git a/src/pcm/pcm_rate.c b/src/pcm/pcm_rate.c
index abb2753f..3d301d0e 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
@@ -922,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);
@@ -1059,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;
-- 
2.29.2


From b62f66442bfbcea7c11afe4917e196fa95a65083 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Mon, 4 Jan 2021 17:27:32 +0100
Subject: [PATCH 33/49] pcm: rate - fix the capture delay values

Use the correct snd_pcm_mmap_capture_delay() function instead
snd_pcm_mmap_capture_hw_avail().

Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
 src/pcm/pcm_rate.c | 8 ++------
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/src/pcm/pcm_rate.c b/src/pcm/pcm_rate.c
index 3d301d0e..770aafea 100644
--- a/src/pcm/pcm_rate.c
+++ b/src/pcm/pcm_rate.c
@@ -632,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;
 }
@@ -1157,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);
 	}
-- 
2.29.2


From 437b5b3aae8b1d9f65289f563deb0fa6356a0fa6 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Thu, 7 Jan 2021 17:32:11 +0100
Subject: [PATCH 34/49] ucm: fix possible memory leak in parse_verb_file()

Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
 src/ucm/parser.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

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) {
-- 
2.29.2


From d0bb8f84c92357bfd0e024efe5f6d53a963c4d7a Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Thu, 7 Jan 2021 17:34:00 +0100
Subject: [PATCH 35/49] topology: tplg_pprint_integer() fix coverity
 uninitalized variable error

Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
 src/topology/save.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/topology/save.c b/src/topology/save.c
index c7a5a801..f7af7af3 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)
-- 
2.29.2


From b8764a061b83284be60adc01c1f7b035c4484ace Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Thu, 7 Jan 2021 17:36:04 +0100
Subject: [PATCH 36/49] topology: tplg_add_widget_object() - do not use invalid
 elem_ctl

Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
 src/topology/dapm.c | 1 +
 1 file changed, 1 insertion(+)

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;
 		}
 
-- 
2.29.2


From 0dbaba95f4bc59602bf2d3fb12a60db7444e5892 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Thu, 7 Jan 2021 17:38:50 +0100
Subject: [PATCH 37/49] topology: tplg_decode_pcm() - add missing log argument
 (compress)

Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
 src/topology/pcm.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/topology/pcm.c b/src/topology/pcm.c
index c8f41862..a473b59b 100644
--- a/src/topology/pcm.c
+++ b/src/topology/pcm.c
@@ -2020,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;
-- 
2.29.2


From 51e1d486ce4535923692bd1d7e59d5aa3a29cd50 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Thu, 7 Jan 2021 17:40:42 +0100
Subject: [PATCH 38/49] topology: parse_tuple_set() - remove dead condition
 code

Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
 src/topology/data.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

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
-- 
2.29.2


From 3f63dc26445ae7c215e48a57af83b6da325f166d Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Thu, 7 Jan 2021 17:41:38 +0100
Subject: [PATCH 39/49] ucm: uc_mgr_substitute_tree() fix use after free

Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
 src/ucm/ucm_subs.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

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) {
-- 
2.29.2


From 45f503632acf24877c466a7c1c74d8a26414bf3e Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Thu, 7 Jan 2021 17:45:27 +0100
Subject: [PATCH 40/49] topology: sort_config() cleanups - use goto for the
 error path

Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
 src/topology/save.c | 15 +++++++--------
 1 file changed, 7 insertions(+), 8 deletions(-)

diff --git a/src/topology/save.c b/src/topology/save.c
index f7af7af3..fecbc6a5 100644
--- a/src/topology/save.c
+++ b/src/topology/save.c
@@ -180,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)
-- 
2.29.2


From 93752fb4de397554e92a4eb9079f77dabaec7d7f Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Thu, 7 Jan 2021 17:49:25 +0100
Subject: [PATCH 41/49] conf: USB - add "Xonar U7 MKII" to
 USB-Audio.pcm.iec958_device

BugLink: https://github.com/alsa-project/alsa-lib/issues/100
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
 src/conf/cards/USB-Audio.conf | 1 +
 1 file changed, 1 insertion(+)

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
-- 
2.29.2


From 644514e85da169670e4a490b7b15b5ecfcec92c0 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Mon, 18 Jan 2021 21:09:43 +0100
Subject: [PATCH 42/49] pcm_plugin: set the initial hw_ptr/appl_ptr from the
 child pcm

The direct plugins (dmix & etc.) sets own initial
hw_ptr and appl_ptr. Use this initial settings
to export correct values in snd_pcm_status().

Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
 src/pcm/pcm_plugin.c | 32 +++++++++++++++++---------------
 1 file changed, 17 insertions(+), 15 deletions(-)

diff --git a/src/pcm/pcm_plugin.c b/src/pcm/pcm_plugin.c
index 7ed6f25a..ff254eba 100644
--- a/src/pcm/pcm_plugin.c
+++ b/src/pcm/pcm_plugin.c
@@ -146,15 +146,14 @@ static int snd_pcm_plugin_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
 	return 0;
 }
 
-static int snd_pcm_plugin_prepare(snd_pcm_t *pcm)
+static int snd_pcm_plugin_call_init_cb(snd_pcm_t *pcm, snd_pcm_plugin_t *plugin)
 {
-	snd_pcm_plugin_t *plugin = pcm->private_data;
+	snd_pcm_t *slave = plugin->gen.slave;
 	int err;
-	err = snd_pcm_prepare(plugin->gen.slave);
-	if (err < 0)
-		return err;
-	*pcm->hw.ptr = 0;
-	*pcm->appl.ptr = 0;
+
+	assert(pcm->boundary == slave->boundary);
+	*pcm->hw.ptr = *slave->hw.ptr;
+	*pcm->appl.ptr = *slave->appl.ptr;
 	if (plugin->init) {
 		err = plugin->init(pcm);
 		if (err < 0)
@@ -163,6 +162,16 @@ static int snd_pcm_plugin_prepare(snd_pcm_t *pcm)
 	return 0;
 }
 
+static int snd_pcm_plugin_prepare(snd_pcm_t *pcm)
+{
+	snd_pcm_plugin_t *plugin = pcm->private_data;
+	int err;
+	err = snd_pcm_prepare(plugin->gen.slave);
+	if (err < 0)
+		return err;
+	return snd_pcm_plugin_call_init_cb(pcm, plugin);
+}
+
 static int snd_pcm_plugin_reset(snd_pcm_t *pcm)
 {
 	snd_pcm_plugin_t *plugin = pcm->private_data;
@@ -170,14 +179,7 @@ static int snd_pcm_plugin_reset(snd_pcm_t *pcm)
 	err = snd_pcm_reset(plugin->gen.slave);
 	if (err < 0)
 		return err;
-	*pcm->hw.ptr = 0;
-	*pcm->appl.ptr = 0;
-	if (plugin->init) {
-		err = plugin->init(pcm);
-		if (err < 0)
-			return err;
-	}
-	return 0;
+	return snd_pcm_plugin_call_init_cb(pcm, plugin);
 }
 
 static snd_pcm_sframes_t snd_pcm_plugin_rewindable(snd_pcm_t *pcm)
-- 
2.29.2


From 0de72e63d7bd180566c71f6fb01d7719525ee326 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Tue, 19 Jan 2021 11:17:00 +0100
Subject: [PATCH 43/49] pcm: dmix/dshare - delay calculation fixes and cleanups

Unfortunately, we cannot use status->avail from slave, because this value
does not wrap to the buffer size and it may even overflow slave boundary
(endless run). We can use only hw_ptr from slave.

Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
 src/pcm/pcm_dmix.c   | 5 ++---
 src/pcm/pcm_dshare.c | 5 ++---
 2 files changed, 4 insertions(+), 6 deletions(-)

diff --git a/src/pcm/pcm_dmix.c b/src/pcm/pcm_dmix.c
index 5b7472d9..be2675af 100644
--- a/src/pcm/pcm_dmix.c
+++ b/src/pcm/pcm_dmix.c
@@ -488,8 +488,7 @@ static int snd_pcm_dmix_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
 	case SNDRV_PCM_STATE_DRAINING:
 	case SNDRV_PCM_STATE_RUNNING:
 		snd_pcm_dmix_sync_ptr0(pcm, status->hw_ptr);
-		status->delay += snd_pcm_mmap_playback_delay(pcm)
-				+ status->avail - dmix->spcm->buffer_size;
+		status->delay = snd_pcm_mmap_playback_delay(pcm);
 		break;
 	default:
 		break;
@@ -518,7 +517,7 @@ static int snd_pcm_dmix_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
 	case SNDRV_PCM_STATE_PREPARED:
 	case SNDRV_PCM_STATE_SUSPENDED:
 	case STATE_RUN_PENDING:
-		*delayp = snd_pcm_mmap_playback_hw_avail(pcm);
+		*delayp = snd_pcm_mmap_playback_delay(pcm);
 		return 0;
 	case SNDRV_PCM_STATE_XRUN:
 		return -EPIPE;
diff --git a/src/pcm/pcm_dshare.c b/src/pcm/pcm_dshare.c
index 8a672572..10243013 100644
--- a/src/pcm/pcm_dshare.c
+++ b/src/pcm/pcm_dshare.c
@@ -237,8 +237,7 @@ static int snd_pcm_dshare_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
 	case SNDRV_PCM_STATE_DRAINING:
 	case SNDRV_PCM_STATE_RUNNING:
 		snd_pcm_dshare_sync_ptr0(pcm, status->hw_ptr);
-		status->delay += snd_pcm_mmap_playback_delay(pcm)
-				+ status->avail - dshare->spcm->buffer_size;
+		status->delay += snd_pcm_mmap_playback_delay(pcm);
 		break;
 	default:
 		break;
@@ -290,7 +289,7 @@ static int snd_pcm_dshare_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
 	case SNDRV_PCM_STATE_PREPARED:
 	case SNDRV_PCM_STATE_SUSPENDED:
 	case STATE_RUN_PENDING:
-		*delayp = snd_pcm_mmap_playback_hw_avail(pcm);
+		*delayp = snd_pcm_mmap_playback_delay(pcm);
 		return 0;
 	case SNDRV_PCM_STATE_XRUN:
 		return -EPIPE;
-- 
2.29.2


From ae7362c996e0b991c399cc26c6d0b3c8e295e83c Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Wed, 20 Jan 2021 16:58:33 +0100
Subject: [PATCH 44/49] topology: fix 'parse_tuple_set() - remove dead
 condition code'

The whole SND_SOC_TPLG_TUPLE_TYPE_WORD condition part must be
commented out, otherwise the condition is always true.

Fixes: 51e1d486ce ("topology: parse_tuple_set() - remove dead condition code")
BugLink: https://github.com/alsa-project/alsa-lib/issues/114
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
 src/topology/data.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/src/topology/data.c b/src/topology/data.c
index 5633cdc3..0546d63e 100644
--- a/src/topology/data.c
+++ b/src/topology/data.c
@@ -859,11 +859,11 @@ static int parse_tuple_set(snd_config_t *cfg,
 				goto err;
 			}
 
-			if ((type == SND_SOC_TPLG_TUPLE_TYPE_WORD
-					/* && tuple_val > UINT_MAX */)
-				|| (type == SND_SOC_TPLG_TUPLE_TYPE_SHORT
-					&& tuple_val > USHRT_MAX)
-				|| (type == SND_SOC_TPLG_TUPLE_TYPE_BYTE
+			if (/* (type == SND_SOC_TPLG_TUPLE_TYPE_WORD
+					&& tuple_val > UINT_MAX) || */
+				(type == SND_SOC_TPLG_TUPLE_TYPE_SHORT
+					&& tuple_val > USHRT_MAX) ||
+				(type == SND_SOC_TPLG_TUPLE_TYPE_BYTE
 					&& tuple_val > UCHAR_MAX)) {
 				SNDERR("tuple %s: invalid value", id);
 				goto err;
-- 
2.29.2


From f2c1a9f3279a30cbd8dcba1eaf0d52f50b56b886 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Fri, 22 Jan 2021 15:48:39 +0100
Subject: [PATCH 45/49] pcm: direct: Fix the missing appl_ptr update

A snd_pcm_status() call for the direct plugins receives the status
from the slave PCM, but this doesn't contain a valid appl_ptr, since
the slave PCM for the direct plugins is in a free-wheel mode, hence
the appl_ptr is always zero.  This result in the inconsistent
status->appl_ptr and pcm->appl.ptr, hitting the recently introduced
assert() call.

Fix it by transferring the plugin's appl_ptr to the upper caller.

BugLink: https://bugzilla.opensuse.org/show_bug.cgi?id=1181194
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
 src/pcm/pcm_dmix.c   | 1 +
 src/pcm/pcm_dshare.c | 1 +
 src/pcm/pcm_dsnoop.c | 1 +
 3 files changed, 3 insertions(+)

diff --git a/src/pcm/pcm_dmix.c b/src/pcm/pcm_dmix.c
index be2675af..d8495065 100644
--- a/src/pcm/pcm_dmix.c
+++ b/src/pcm/pcm_dmix.c
@@ -495,6 +495,7 @@ static int snd_pcm_dmix_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
 	}
 
 	status->state = snd_pcm_dmix_state(pcm);
+	status->appl_ptr = *pcm->appl.ptr; /* slave PCM doesn't set appl_ptr */
 	status->trigger_tstamp = dmix->trigger_tstamp;
 	status->avail = snd_pcm_mmap_playback_avail(pcm);
 	status->avail_max = status->avail > dmix->avail_max ? status->avail : dmix->avail_max;
diff --git a/src/pcm/pcm_dshare.c b/src/pcm/pcm_dshare.c
index 10243013..dccb137b 100644
--- a/src/pcm/pcm_dshare.c
+++ b/src/pcm/pcm_dshare.c
@@ -243,6 +243,7 @@ static int snd_pcm_dshare_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
 		break;
 	}
 	status->state = snd_pcm_dshare_state(pcm);
+	status->appl_ptr = *pcm->appl.ptr; /* slave PCM doesn't set appl_ptr */
 	status->trigger_tstamp = dshare->trigger_tstamp;
 	status->avail = snd_pcm_mmap_playback_avail(pcm);
 	status->avail_max = status->avail > dshare->avail_max ? status->avail : dshare->avail_max;
diff --git a/src/pcm/pcm_dsnoop.c b/src/pcm/pcm_dsnoop.c
index c6e8cd27..695bf4aa 100644
--- a/src/pcm/pcm_dsnoop.c
+++ b/src/pcm/pcm_dsnoop.c
@@ -193,6 +193,7 @@ static int snd_pcm_dsnoop_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
 	snd_pcm_status(dsnoop->spcm, status);
 	state = snd_pcm_state(dsnoop->spcm);
 	status->state = state == SND_PCM_STATE_RUNNING ? dsnoop->state : state;
+	status->appl_ptr = *pcm->appl.ptr; /* slave PCM doesn't set appl_ptr */
 	status->trigger_tstamp = dsnoop->trigger_tstamp;
 	status->avail = snd_pcm_mmap_capture_avail(pcm);
 	status->avail_max = status->avail > dsnoop->avail_max ? status->avail : dsnoop->avail_max;
-- 
2.29.2


From 26fdcb98e6be186016d53f87d06ae47aabe5b7fc Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Fri, 22 Jan 2021 15:48:40 +0100
Subject: [PATCH 46/49] pcm: ioplug: Pass appl_ptr and hw_ptr in
 snd_pcm_status()

The snd_pcm_status() of the ioplug doesn't return the current
positions of hw_ptr and appl_ptr as advertised.  Fix it by copying the
current values stored in the plugin data.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
 src/pcm/pcm_ioplug.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/pcm/pcm_ioplug.c b/src/pcm/pcm_ioplug.c
index e141b1f9..a1463bf6 100644
--- a/src/pcm/pcm_ioplug.c
+++ b/src/pcm/pcm_ioplug.c
@@ -133,6 +133,8 @@ static int snd_pcm_ioplug_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
 	gettimestamp(&status->tstamp, pcm->tstamp_type);
 	status->avail = snd_pcm_mmap_avail(pcm);
 	status->avail_max = io->avail_max;
+	status->appl_ptr = *pcm->appl.ptr;
+	status->hw_ptr = *pcm->hw.ptr;
 	if (snd_pcm_ioplug_delay(pcm, &sd) < 0)
 		sd = snd_pcm_mmap_delay(pcm);
 	status->delay = sd;
-- 
2.29.2


From bcc762f99ad642cc0dd9eaceb51f228eba9fe68c Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Fri, 22 Jan 2021 15:48:41 +0100
Subject: [PATCH 47/49] pcm: null: Pass appl_ptr and hw_ptr in snd_pcm_status()

Just like the previous fix for ioplug, the null plugin also misses the
appl_ptr and hw_ptr updates for snd_pcm_status().  Fix it as well.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
 src/pcm/pcm_null.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/pcm/pcm_null.c b/src/pcm/pcm_null.c
index 1d815485..c8ea9b38 100644
--- a/src/pcm/pcm_null.c
+++ b/src/pcm/pcm_null.c
@@ -96,6 +96,8 @@ static int snd_pcm_null_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
 	memset(status, 0, sizeof(*status));
 	status->state = null->state;
 	status->trigger_tstamp = null->trigger_tstamp;
+	status->appl_ptr = *pcm->appl.ptr;
+	status->hw_ptr = *pcm->hw.ptr;
 	gettimestamp(&status->tstamp, pcm->tstamp_type);
 	status->avail = snd_pcm_null_avail_update(pcm);
 	status->avail_max = pcm->buffer_size;
-- 
2.29.2


From 55d59821ffb8f44395cf2b7a424d6523da58e66a Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Fri, 22 Jan 2021 15:48:42 +0100
Subject: [PATCH 48/49] pcm: share: Pass appl_ptr and hw_ptr in
 snd_pcm_status()

This one also has the same problem as others; the appl_ptr and hw_ptr
of share plugin aren't updated in snd_pcm_status() call.  Fix it.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
 src/pcm/pcm_share.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/pcm/pcm_share.c b/src/pcm/pcm_share.c
index bff9507d..72509491 100644
--- a/src/pcm/pcm_share.c
+++ b/src/pcm/pcm_share.c
@@ -711,6 +711,8 @@ static int snd_pcm_share_status(snd_pcm_t *pcm, snd_pcm_status_t *status)
  _notrunning:
 	status->delay = sd + d;
 	status->state = share->state;
+	status->appl_ptr = *pcm->appl.ptr;
+	status->hw_ptr = *pcm->hw.ptr;
 	status->trigger_tstamp = share->trigger_tstamp;
  _end:
 	Pthread_mutex_unlock(&slave->mutex);
-- 
2.29.2


From 00eafe98eebff8ecd1ecdc58470068bfd610cc8d Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Thu, 21 Jan 2021 15:45:49 +0100
Subject: [PATCH 49/49] pcm: pcm_ioplug - fix the avail_update mmap capture
 copy issue

It seems that the commit "pcm: ioplug: Transfer all available data"
introduced new regressions (wrong memory access). The second issue
is that the avail_update in ioplug does not move appl_ptr nor hw_ptr,
so it's possible that the transfers may be repetitive.

This patch moves the transfer calls to mmap_begin callback where it
should be. The pointer wraps are handled by design now.

Fixes: 1714332719 ("pcm: ioplug: Transfer all available data")
BugLink: https://github.com/alsa-project/alsa-lib/pull/103
Tested-by: Andreas Pape <apape@de.adit-jv.com>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
 src/pcm/pcm.c        | 20 ++++++++++-----
 src/pcm/pcm_ioplug.c | 60 +++++++++++++++++++++++++-------------------
 src/pcm/pcm_local.h  |  2 ++
 3 files changed, 50 insertions(+), 32 deletions(-)

diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c
index 24030b31..a57ce5d9 100644
--- a/src/pcm/pcm.c
+++ b/src/pcm/pcm.c
@@ -7218,9 +7218,8 @@ int snd_pcm_mmap_begin(snd_pcm_t *pcm,
 }
 
 #ifndef DOC_HIDDEN
-/* locked version */
-int __snd_pcm_mmap_begin(snd_pcm_t *pcm, const snd_pcm_channel_area_t **areas,
-		       snd_pcm_uframes_t *offset, snd_pcm_uframes_t *frames)
+int __snd_pcm_mmap_begin_generic(snd_pcm_t *pcm, const snd_pcm_channel_area_t **areas,
+				 snd_pcm_uframes_t *offset, snd_pcm_uframes_t *frames)
 {
 	snd_pcm_uframes_t cont;
 	snd_pcm_uframes_t f;
@@ -7229,9 +7228,6 @@ int __snd_pcm_mmap_begin(snd_pcm_t *pcm, const snd_pcm_channel_area_t **areas,
 
 	assert(pcm && areas && offset && frames);
 
-	if (pcm->fast_ops->mmap_begin)
-		return pcm->fast_ops->mmap_begin(pcm->fast_op_arg, areas, offset, frames);
-
 	/* fallback for plugins that do not specify new callback */
 	xareas = snd_pcm_mmap_areas(pcm);
 	if (xareas == NULL)
@@ -7250,6 +7246,18 @@ int __snd_pcm_mmap_begin(snd_pcm_t *pcm, const snd_pcm_channel_area_t **areas,
 	*frames = f;
 	return 0;
 }
+
+/* locked version */
+int __snd_pcm_mmap_begin(snd_pcm_t *pcm, const snd_pcm_channel_area_t **areas,
+			 snd_pcm_uframes_t *offset, snd_pcm_uframes_t *frames)
+{
+	assert(pcm && areas && offset && frames);
+
+	if (pcm->fast_ops->mmap_begin)
+		return pcm->fast_ops->mmap_begin(pcm->fast_op_arg, areas, offset, frames);
+
+	return __snd_pcm_mmap_begin_generic(pcm, areas, offset, frames);
+}
 #endif
 
 /**
diff --git a/src/pcm/pcm_ioplug.c b/src/pcm/pcm_ioplug.c
index a1463bf6..98184398 100644
--- a/src/pcm/pcm_ioplug.c
+++ b/src/pcm/pcm_ioplug.c
@@ -697,6 +697,38 @@ static snd_pcm_sframes_t snd_pcm_ioplug_readn(snd_pcm_t *pcm, void **bufs, snd_p
 	}
 }
 
+static int snd_pcm_ioplug_mmap_begin_capture(snd_pcm_t *pcm,
+					     const snd_pcm_channel_area_t **areas,
+					     snd_pcm_uframes_t *offset,
+					     snd_pcm_uframes_t *frames)
+{
+	ioplug_priv_t *io = pcm->private_data;
+	int err;
+
+	err = __snd_pcm_mmap_begin_generic(pcm, areas, offset, frames);
+	if (err < 0)
+		return err;
+
+	if (io->data->callback->transfer &&
+	    pcm->access != SND_PCM_ACCESS_RW_INTERLEAVED &&
+	    pcm->access != SND_PCM_ACCESS_RW_NONINTERLEAVED) {
+		snd_pcm_sframes_t result;
+		result = io->data->callback->transfer(io->data, *areas, *offset, *frames);
+		if (result < 0)
+			return result;
+	}
+
+	return err;
+}
+
+static int snd_pcm_ioplug_mmap_begin(snd_pcm_t *pcm, const snd_pcm_channel_area_t **areas,
+				     snd_pcm_uframes_t *offset, snd_pcm_uframes_t *frames)
+{
+	if (pcm->stream == SND_PCM_STREAM_PLAYBACK)
+		return __snd_pcm_mmap_begin_generic(pcm, areas, offset, frames);
+	return snd_pcm_ioplug_mmap_begin_capture(pcm, areas, offset, frames);
+}
+
 static snd_pcm_sframes_t snd_pcm_ioplug_mmap_commit(snd_pcm_t *pcm,
 						    snd_pcm_uframes_t offset,
 						    snd_pcm_uframes_t size)
@@ -707,7 +739,7 @@ static snd_pcm_sframes_t snd_pcm_ioplug_mmap_commit(snd_pcm_t *pcm,
 		const snd_pcm_channel_area_t *areas;
 		snd_pcm_uframes_t ofs, frames = size;
 
-		__snd_pcm_mmap_begin(pcm, &areas, &ofs, &frames);
+		__snd_pcm_mmap_begin_generic(pcm, &areas, &ofs, &frames);
 		if (ofs != offset)
 			return -EIO;
 		return ioplug_priv_transfer_areas(pcm, areas, offset, frames);
@@ -727,31 +759,6 @@ static snd_pcm_sframes_t snd_pcm_ioplug_avail_update(snd_pcm_t *pcm)
 		return -EPIPE;
 
 	avail = snd_pcm_mmap_avail(pcm);
-	if (pcm->stream == SND_PCM_STREAM_CAPTURE &&
-	    pcm->access != SND_PCM_ACCESS_RW_INTERLEAVED &&
-	    pcm->access != SND_PCM_ACCESS_RW_NONINTERLEAVED) {
-		if (io->data->callback->transfer) {
-			const snd_pcm_channel_area_t *areas;
-			snd_pcm_uframes_t offset, size = UINT_MAX;
-			snd_pcm_sframes_t result;
-
-			__snd_pcm_mmap_begin(pcm, &areas, &offset, &size);
-			result = io->data->callback->transfer(io->data, areas, offset, size);
-			if (result < 0)
-				return result;
-
-			/* If the available data doesn't fit in the
-			   contiguous area at the end of the mmap we
-			   must transfer the remaining data to the
-			   beginning of the mmap. */
-			if (size < avail) {
-				result = io->data->callback->transfer(io->data, areas,
-								      0, avail - size);
-				if (result < 0)
-					return result;
-			}
-		}
-	}
 	if (avail > io->avail_max)
 		io->avail_max = avail;
 	return (snd_pcm_sframes_t)avail;
@@ -947,6 +954,7 @@ static const snd_pcm_fast_ops_t snd_pcm_ioplug_fast_ops = {
 	.poll_descriptors_count = snd_pcm_ioplug_poll_descriptors_count,
 	.poll_descriptors = snd_pcm_ioplug_poll_descriptors,
 	.poll_revents = snd_pcm_ioplug_poll_revents,
+	.mmap_begin = snd_pcm_ioplug_mmap_begin,
 };
 
 #endif /* !DOC_HIDDEN */
diff --git a/src/pcm/pcm_local.h b/src/pcm/pcm_local.h
index bec5a408..a63f4be0 100644
--- a/src/pcm/pcm_local.h
+++ b/src/pcm/pcm_local.h
@@ -420,6 +420,8 @@ int _snd_pcm_poll_descriptor(snd_pcm_t *pcm);
 #define _snd_pcm_async_descriptor _snd_pcm_poll_descriptor /* FIXME */
 
 /* locked versions */
+int __snd_pcm_mmap_begin_generic(snd_pcm_t *pcm, const snd_pcm_channel_area_t **areas,
+				 snd_pcm_uframes_t *offset, snd_pcm_uframes_t *frames);
 int __snd_pcm_mmap_begin(snd_pcm_t *pcm, const snd_pcm_channel_area_t **areas,
 			 snd_pcm_uframes_t *offset, snd_pcm_uframes_t *frames);
 snd_pcm_sframes_t __snd_pcm_mmap_commit(snd_pcm_t *pcm,
-- 
2.29.2