a6cb93
From 1b436862ed6253629d79edc2e09826efd4e0f4e3 Mon Sep 17 00:00:00 2001
a6cb93
From: Jaroslav Kysela <perex@perex.cz>
a6cb93
Date: Wed, 2 Nov 2022 15:01:56 +0100
a6cb93
Subject: [PATCH 01/20] ucm: fix enhanced ID parsing in
a6cb93
 snd_use_case_parse_ctl_elem_id()
a6cb93
a6cb93
Reported-by: Takashi Iwai <tiwai@suse.de>
a6cb93
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
a6cb93
---
a6cb93
 src/ucm/main.c | 2 +-
a6cb93
 1 file changed, 1 insertion(+), 1 deletion(-)
a6cb93
a6cb93
diff --git a/src/ucm/main.c b/src/ucm/main.c
a6cb93
index 30ab1e41..28c60565 100644
a6cb93
--- a/src/ucm/main.c
a6cb93
+++ b/src/ucm/main.c
a6cb93
@@ -2793,7 +2793,7 @@ int snd_use_case_parse_ctl_elem_id(snd_ctl_elem_id_t *dst,
a6cb93
 	    strcmp(ucm_id, "CaptureSwitch"))
a6cb93
 		return -EINVAL;
a6cb93
 	snd_ctl_elem_id_clear(dst);
a6cb93
-	if (strcasestr(ucm_id, "name="))
a6cb93
+	if (strcasestr(value, "name="))
a6cb93
 		return __snd_ctl_ascii_elem_id_parse(dst, value, NULL);
a6cb93
 	iface = SND_CTL_ELEM_IFACE_MIXER;
a6cb93
 	if (jack_control)
a6cb93
-- 
a6cb93
2.39.0
a6cb93
a6cb93
a6cb93
From aa4f56c3c952269c36464cc0da9db5a1381648fa Mon Sep 17 00:00:00 2001
a6cb93
From: Jaroslav Kysela <perex@perex.cz>
a6cb93
Date: Wed, 9 Nov 2022 08:11:42 +0100
a6cb93
Subject: [PATCH 02/20] pcm: rate - fix the crash in
a6cb93
 snd_pcm_rate_may_wait_for_avail_min()
a6cb93
a6cb93
The pcm argument passed to the conversion function in
a6cb93
snd_pcm_plugin_may_wait_for_avail_min_conv() should be
a6cb93
pcm->fast_op_arg.
a6cb93
a6cb93
Test command: arecord -Dplughw:x -r12000 -c2 -fS16_LE -M temp.wav
a6cb93
a6cb93
Fixes: d9dbb57b ("pcm: rate - rewrite the may_wait_for_avail_min callback for the rate plugin")
a6cb93
a6cb93
BugLink: https://lore.kernel.org/alsa-devel/1667793912-18957-1-git-send-email-shengjiu.wang@nxp.com/
a6cb93
Fixes: https://github.com/alsa-project/alsa-lib/issues/282
a6cb93
Reported-by: Shengjiu Wang <shengjiu.wang@nxp.com>
a6cb93
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
a6cb93
---
a6cb93
 src/pcm/pcm_plugin.c | 2 +-
a6cb93
 1 file changed, 1 insertion(+), 1 deletion(-)
a6cb93
a6cb93
diff --git a/src/pcm/pcm_plugin.c b/src/pcm/pcm_plugin.c
a6cb93
index 6bb90b8b..ec64604c 100644
a6cb93
--- a/src/pcm/pcm_plugin.c
a6cb93
+++ b/src/pcm/pcm_plugin.c
a6cb93
@@ -622,7 +622,7 @@ int snd_pcm_plugin_may_wait_for_avail_min_conv(
a6cb93
 		 * This code is also used by extplug, but extplug does not allow to alter the sampling rate.
a6cb93
 		 */
a6cb93
 		if (conv)
a6cb93
-			needed_slave_avail_min = conv(pcm, needed_slave_avail_min);
a6cb93
+			needed_slave_avail_min = conv(pcm->fast_op_arg, needed_slave_avail_min);
a6cb93
 
a6cb93
 		if (slave->avail_min != needed_slave_avail_min) {
a6cb93
 			snd_pcm_sw_params_t *swparams;
a6cb93
-- 
a6cb93
2.39.0
a6cb93
a6cb93
a6cb93
From 39060852d810461dc8cd1464cfb2ffe84da42d56 Mon Sep 17 00:00:00 2001
a6cb93
From: Jaroslav Kysela <perex@perex.cz>
a6cb93
Date: Wed, 9 Nov 2022 09:31:34 +0100
a6cb93
Subject: [PATCH 03/20] pcm: rate - correct the previous fix for
a6cb93
 snd_pcm_rate_may_wait_for_avail_min()
a6cb93
a6cb93
The previous fix in aa4f56c3 was not correct. The root of the cause is
a6cb93
implementation in snd_pcm_may_wait_for_avail_min() inline function
a6cb93
where the improper pcm argument is passed to the fast_ops function.
a6cb93
a6cb93
Fixes: aa4f56c3 ("pcm: rate - fix the crash in snd_pcm_rate_may_wait_for_avail_min()")
a6cb93
Fixes: d9dbb57b ("pcm: rate - rewrite the may_wait_for_avail_min callback for the rate plugin")
a6cb93
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
a6cb93
---
a6cb93
 src/pcm/pcm_local.h  |  2 +-
a6cb93
 src/pcm/pcm_plugin.c | 10 +++++++---
a6cb93
 2 files changed, 8 insertions(+), 4 deletions(-)
a6cb93
a6cb93
diff --git a/src/pcm/pcm_local.h b/src/pcm/pcm_local.h
a6cb93
index 8d25971f..ae0c44bf 100644
a6cb93
--- a/src/pcm/pcm_local.h
a6cb93
+++ b/src/pcm/pcm_local.h
a6cb93
@@ -1144,7 +1144,7 @@ static inline int snd_pcm_may_wait_for_avail_min(snd_pcm_t *pcm, snd_pcm_uframes
a6cb93
 	if (avail >= pcm->avail_min)
a6cb93
 		return 0;
a6cb93
 	if (pcm->fast_ops->may_wait_for_avail_min)
a6cb93
-		return pcm->fast_ops->may_wait_for_avail_min(pcm, avail);
a6cb93
+		return pcm->fast_ops->may_wait_for_avail_min(pcm->fast_op_arg, avail);
a6cb93
 	return 1;
a6cb93
 }
a6cb93
 
a6cb93
diff --git a/src/pcm/pcm_plugin.c b/src/pcm/pcm_plugin.c
a6cb93
index ec64604c..b3af1fb7 100644
a6cb93
--- a/src/pcm/pcm_plugin.c
a6cb93
+++ b/src/pcm/pcm_plugin.c
a6cb93
@@ -597,8 +597,12 @@ int snd_pcm_plugin_may_wait_for_avail_min_conv(
a6cb93
 		 * a) the slave can provide contineous hw_ptr between periods
a6cb93
 		 * b) avail_min does not match one slave_period
a6cb93
 		 */
a6cb93
-		snd_pcm_plugin_t *plugin = pcm->private_data;
a6cb93
-		snd_pcm_t *slave = plugin->gen.slave;
a6cb93
+		snd_pcm_generic_t *generic = pcm->private_data;
a6cb93
+		/*
a6cb93
+		 * do not use snd_pcm_plugin_t pointer here
a6cb93
+		 * this code is used from the generic plugins, too
a6cb93
+		 */
a6cb93
+		snd_pcm_t *slave = generic->slave;
a6cb93
 		snd_pcm_uframes_t needed_slave_avail_min;
a6cb93
 		snd_pcm_sframes_t available;
a6cb93
 
a6cb93
@@ -622,7 +626,7 @@ int snd_pcm_plugin_may_wait_for_avail_min_conv(
a6cb93
 		 * This code is also used by extplug, but extplug does not allow to alter the sampling rate.
a6cb93
 		 */
a6cb93
 		if (conv)
a6cb93
-			needed_slave_avail_min = conv(pcm->fast_op_arg, needed_slave_avail_min);
a6cb93
+			needed_slave_avail_min = conv(pcm, needed_slave_avail_min);
a6cb93
 
a6cb93
 		if (slave->avail_min != needed_slave_avail_min) {
a6cb93
 			snd_pcm_sw_params_t *swparams;
a6cb93
-- 
a6cb93
2.39.0
a6cb93
a6cb93
a6cb93
From 161f47da5f196c291ac0e11d066fa5ff5f79fa04 Mon Sep 17 00:00:00 2001
a6cb93
From: Jaroslav Kysela <perex@perex.cz>
a6cb93
Date: Wed, 9 Nov 2022 14:37:45 +0100
a6cb93
Subject: [PATCH 04/20] include: pcm_old.h - use a macro for the symbol
a6cb93
 versioning
a6cb93
a6cb93
Make the header file more readable and error prone.
a6cb93
a6cb93
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
a6cb93
---
a6cb93
 include/pcm_old.h | 133 ++++++++++++++++++++++++----------------------
a6cb93
 1 file changed, 68 insertions(+), 65 deletions(-)
a6cb93
a6cb93
diff --git a/include/pcm_old.h b/include/pcm_old.h
a6cb93
index e6e050fc..a9f5308f 100644
a6cb93
--- a/include/pcm_old.h
a6cb93
+++ b/include/pcm_old.h
a6cb93
@@ -2,11 +2,14 @@
a6cb93
  * Old ALSA 0.9.x API
a6cb93
  */
a6cb93
 
a6cb93
+#define ___symbol_version(name, version) \
a6cb93
+	__asm__ (".symver " #name "," #name "@" version)
a6cb93
+
a6cb93
 #ifdef ALSA_PCM_OLD_HW_PARAMS_API
a6cb93
 
a6cb93
-asm(".symver snd_pcm_hw_params_get_access,snd_pcm_hw_params_get_access@ALSA_0.9");
a6cb93
-asm(".symver snd_pcm_hw_params_set_access_first,snd_pcm_hw_params_set_access_first@ALSA_0.9");
a6cb93
-asm(".symver snd_pcm_hw_params_set_access_last,snd_pcm_hw_params_set_access_last@ALSA_0.9");
a6cb93
+___symbol_version(snd_pcm_hw_params_get_access, "ALSA_0.9");
a6cb93
+___symbol_version(snd_pcm_hw_params_set_access_first, "ALSA_0.9");
a6cb93
+___symbol_version(snd_pcm_hw_params_set_access_last, "ALSA_0.9");
a6cb93
 
a6cb93
 int snd_pcm_hw_params_get_access(const snd_pcm_hw_params_t *params);
a6cb93
 int snd_pcm_hw_params_test_access(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_access_t val);
a6cb93
@@ -16,9 +19,9 @@ snd_pcm_access_t snd_pcm_hw_params_set_access_last(snd_pcm_t *pcm, snd_pcm_hw_pa
a6cb93
 int snd_pcm_hw_params_set_access_mask(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_access_mask_t *mask);
a6cb93
 void snd_pcm_hw_params_get_access_mask(snd_pcm_hw_params_t *params, snd_pcm_access_mask_t *mask);
a6cb93
 
a6cb93
-asm(".symver snd_pcm_hw_params_get_format,snd_pcm_hw_params_get_format@ALSA_0.9");
a6cb93
-asm(".symver snd_pcm_hw_params_set_format_first,snd_pcm_hw_params_set_format_first@ALSA_0.9");
a6cb93
-asm(".symver snd_pcm_hw_params_set_format_last,snd_pcm_hw_params_set_format_last@ALSA_0.9");
a6cb93
+___symbol_version(snd_pcm_hw_params_get_format, "ALSA_0.9");
a6cb93
+___symbol_version(snd_pcm_hw_params_set_format_first, "ALSA_0.9");
a6cb93
+___symbol_version(snd_pcm_hw_params_set_format_last, "ALSA_0.9");
a6cb93
 
a6cb93
 int snd_pcm_hw_params_get_format(const snd_pcm_hw_params_t *params);
a6cb93
 int snd_pcm_hw_params_test_format(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_format_t val);
a6cb93
@@ -28,9 +31,9 @@ snd_pcm_format_t snd_pcm_hw_params_set_format_last(snd_pcm_t *pcm, snd_pcm_hw_pa
a6cb93
 int snd_pcm_hw_params_set_format_mask(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_format_mask_t *mask);
a6cb93
 void snd_pcm_hw_params_get_format_mask(snd_pcm_hw_params_t *params, snd_pcm_format_mask_t *mask);
a6cb93
 
a6cb93
-asm(".symver snd_pcm_hw_params_get_subformat,snd_pcm_hw_params_get_subformat@ALSA_0.9");
a6cb93
-asm(".symver snd_pcm_hw_params_set_subformat_first,snd_pcm_hw_params_set_subformat_first@ALSA_0.9");
a6cb93
-asm(".symver snd_pcm_hw_params_set_subformat_last,snd_pcm_hw_params_set_subformat_last@ALSA_0.9");
a6cb93
+___symbol_version(snd_pcm_hw_params_get_subformat, "ALSA_0.9");
a6cb93
+___symbol_version(snd_pcm_hw_params_set_subformat_first, "ALSA_0.9");
a6cb93
+___symbol_version(snd_pcm_hw_params_set_subformat_last, "ALSA_0.9");
a6cb93
 
a6cb93
 int snd_pcm_hw_params_test_subformat(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_subformat_t val);
a6cb93
 int snd_pcm_hw_params_get_subformat(const snd_pcm_hw_params_t *params);
a6cb93
@@ -40,12 +43,12 @@ snd_pcm_subformat_t snd_pcm_hw_params_set_subformat_last(snd_pcm_t *pcm, snd_pcm
a6cb93
 int snd_pcm_hw_params_set_subformat_mask(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_subformat_mask_t *mask);
a6cb93
 void snd_pcm_hw_params_get_subformat_mask(snd_pcm_hw_params_t *params, snd_pcm_subformat_mask_t *mask);
a6cb93
 
a6cb93
-asm(".symver snd_pcm_hw_params_get_channels,snd_pcm_hw_params_get_channels@ALSA_0.9");
a6cb93
-asm(".symver snd_pcm_hw_params_get_channels_min,snd_pcm_hw_params_get_channels_min@ALSA_0.9");
a6cb93
-asm(".symver snd_pcm_hw_params_get_channels_max,snd_pcm_hw_params_get_channels_max@ALSA_0.9");
a6cb93
-asm(".symver snd_pcm_hw_params_set_channels_near,snd_pcm_hw_params_set_channels_near@ALSA_0.9");
a6cb93
-asm(".symver snd_pcm_hw_params_set_channels_first,snd_pcm_hw_params_set_channels_first@ALSA_0.9");
a6cb93
-asm(".symver snd_pcm_hw_params_set_channels_last,snd_pcm_hw_params_set_channels_last@ALSA_0.9");
a6cb93
+___symbol_version(snd_pcm_hw_params_get_channels, "ALSA_0.9");
a6cb93
+___symbol_version(snd_pcm_hw_params_get_channels_min, "ALSA_0.9");
a6cb93
+___symbol_version(snd_pcm_hw_params_get_channels_max, "ALSA_0.9");
a6cb93
+___symbol_version(snd_pcm_hw_params_set_channels_near, "ALSA_0.9");
a6cb93
+___symbol_version(snd_pcm_hw_params_set_channels_first, "ALSA_0.9");
a6cb93
+___symbol_version(snd_pcm_hw_params_set_channels_last, "ALSA_0.9");
a6cb93
 
a6cb93
 int snd_pcm_hw_params_get_channels(const snd_pcm_hw_params_t *params);
a6cb93
 unsigned int snd_pcm_hw_params_get_channels_min(const snd_pcm_hw_params_t *params);
a6cb93
@@ -59,12 +62,12 @@ unsigned int snd_pcm_hw_params_set_channels_near(snd_pcm_t *pcm, snd_pcm_hw_para
a6cb93
 unsigned int snd_pcm_hw_params_set_channels_first(snd_pcm_t *pcm, snd_pcm_hw_params_t *params);
a6cb93
 unsigned int snd_pcm_hw_params_set_channels_last(snd_pcm_t *pcm, snd_pcm_hw_params_t *params);
a6cb93
 
a6cb93
-asm(".symver snd_pcm_hw_params_get_rate,snd_pcm_hw_params_get_rate@ALSA_0.9");
a6cb93
-asm(".symver snd_pcm_hw_params_get_rate_min,snd_pcm_hw_params_get_rate_min@ALSA_0.9");
a6cb93
-asm(".symver snd_pcm_hw_params_get_rate_max,snd_pcm_hw_params_get_rate_max@ALSA_0.9");
a6cb93
-asm(".symver snd_pcm_hw_params_set_rate_near,snd_pcm_hw_params_set_rate_near@ALSA_0.9");
a6cb93
-asm(".symver snd_pcm_hw_params_set_rate_first,snd_pcm_hw_params_set_rate_first@ALSA_0.9");
a6cb93
-asm(".symver snd_pcm_hw_params_set_rate_last,snd_pcm_hw_params_set_rate_last@ALSA_0.9");
a6cb93
+___symbol_version(snd_pcm_hw_params_get_rate, "ALSA_0.9");
a6cb93
+___symbol_version(snd_pcm_hw_params_get_rate_min, "ALSA_0.9");
a6cb93
+___symbol_version(snd_pcm_hw_params_get_rate_max, "ALSA_0.9");
a6cb93
+___symbol_version(snd_pcm_hw_params_set_rate_near, "ALSA_0.9");
a6cb93
+___symbol_version(snd_pcm_hw_params_set_rate_first, "ALSA_0.9");
a6cb93
+___symbol_version(snd_pcm_hw_params_set_rate_last, "ALSA_0.9");
a6cb93
 
a6cb93
 int snd_pcm_hw_params_get_rate(const snd_pcm_hw_params_t *params, int *dir);
a6cb93
 unsigned int snd_pcm_hw_params_get_rate_min(const snd_pcm_hw_params_t *params, int *dir);
a6cb93
@@ -80,12 +83,12 @@ unsigned int snd_pcm_hw_params_set_rate_last(snd_pcm_t *pcm, snd_pcm_hw_params_t
a6cb93
 int snd_pcm_hw_params_set_rate_resample(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int val);
a6cb93
 int snd_pcm_hw_params_get_rate_resample(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val);
a6cb93
 
a6cb93
-asm(".symver snd_pcm_hw_params_get_period_time,snd_pcm_hw_params_get_period_time@ALSA_0.9");
a6cb93
-asm(".symver snd_pcm_hw_params_get_period_time_min,snd_pcm_hw_params_get_period_time_min@ALSA_0.9");
a6cb93
-asm(".symver snd_pcm_hw_params_get_period_time_max,snd_pcm_hw_params_get_period_time_max@ALSA_0.9");
a6cb93
-asm(".symver snd_pcm_hw_params_set_period_time_near,snd_pcm_hw_params_set_period_time_near@ALSA_0.9");
a6cb93
-asm(".symver snd_pcm_hw_params_set_period_time_first,snd_pcm_hw_params_set_period_time_first@ALSA_0.9");
a6cb93
-asm(".symver snd_pcm_hw_params_set_period_time_last,snd_pcm_hw_params_set_period_time_last@ALSA_0.9");
a6cb93
+___symbol_version(snd_pcm_hw_params_get_period_time, "ALSA_0.9");
a6cb93
+___symbol_version(snd_pcm_hw_params_get_period_time_min, "ALSA_0.9");
a6cb93
+___symbol_version(snd_pcm_hw_params_get_period_time_max, "ALSA_0.9");
a6cb93
+___symbol_version(snd_pcm_hw_params_set_period_time_near, "ALSA_0.9");
a6cb93
+___symbol_version(snd_pcm_hw_params_set_period_time_first, "ALSA_0.9");
a6cb93
+___symbol_version(snd_pcm_hw_params_set_period_time_last, "ALSA_0.9");
a6cb93
 
a6cb93
 int snd_pcm_hw_params_get_period_time(const snd_pcm_hw_params_t *params, int *dir);
a6cb93
 unsigned int snd_pcm_hw_params_get_period_time_min(const snd_pcm_hw_params_t *params, int *dir);
a6cb93
@@ -99,12 +102,12 @@ unsigned int snd_pcm_hw_params_set_period_time_near(snd_pcm_t *pcm, snd_pcm_hw_p
a6cb93
 unsigned int snd_pcm_hw_params_set_period_time_first(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, int *dir);
a6cb93
 unsigned int snd_pcm_hw_params_set_period_time_last(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, int *dir);
a6cb93
 
a6cb93
-asm(".symver snd_pcm_hw_params_get_period_size,snd_pcm_hw_params_get_period_size@ALSA_0.9");
a6cb93
-asm(".symver snd_pcm_hw_params_get_period_size_min,snd_pcm_hw_params_get_period_size_min@ALSA_0.9");
a6cb93
-asm(".symver snd_pcm_hw_params_get_period_size_max,snd_pcm_hw_params_get_period_size_max@ALSA_0.9");
a6cb93
-asm(".symver snd_pcm_hw_params_set_period_size_near,snd_pcm_hw_params_set_period_size_near@ALSA_0.9");
a6cb93
-asm(".symver snd_pcm_hw_params_set_period_size_first,snd_pcm_hw_params_set_period_size_first@ALSA_0.9");
a6cb93
-asm(".symver snd_pcm_hw_params_set_period_size_last,snd_pcm_hw_params_set_period_size_last@ALSA_0.9");
a6cb93
+___symbol_version(snd_pcm_hw_params_get_period_size, "ALSA_0.9");
a6cb93
+___symbol_version(snd_pcm_hw_params_get_period_size_min, "ALSA_0.9");
a6cb93
+___symbol_version(snd_pcm_hw_params_get_period_size_max, "ALSA_0.9");
a6cb93
+___symbol_version(snd_pcm_hw_params_set_period_size_near, "ALSA_0.9");
a6cb93
+___symbol_version(snd_pcm_hw_params_set_period_size_first, "ALSA_0.9");
a6cb93
+___symbol_version(snd_pcm_hw_params_set_period_size_last, "ALSA_0.9");
a6cb93
 
a6cb93
 snd_pcm_sframes_t snd_pcm_hw_params_get_period_size(const snd_pcm_hw_params_t *params, int *dir);
a6cb93
 snd_pcm_uframes_t snd_pcm_hw_params_get_period_size_min(const snd_pcm_hw_params_t *params, int *dir);
a6cb93
@@ -119,12 +122,12 @@ snd_pcm_uframes_t snd_pcm_hw_params_set_period_size_first(snd_pcm_t *pcm, snd_pc
a6cb93
 snd_pcm_uframes_t snd_pcm_hw_params_set_period_size_last(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, int *dir);
a6cb93
 int snd_pcm_hw_params_set_period_size_integer(snd_pcm_t *pcm, snd_pcm_hw_params_t *params);
a6cb93
 
a6cb93
-asm(".symver snd_pcm_hw_params_get_periods,snd_pcm_hw_params_get_periods@ALSA_0.9");
a6cb93
-asm(".symver snd_pcm_hw_params_get_periods_min,snd_pcm_hw_params_get_periods_min@ALSA_0.9");
a6cb93
-asm(".symver snd_pcm_hw_params_get_periods_max,snd_pcm_hw_params_get_periods_max@ALSA_0.9");
a6cb93
-asm(".symver snd_pcm_hw_params_set_periods_near,snd_pcm_hw_params_set_periods_near@ALSA_0.9");
a6cb93
-asm(".symver snd_pcm_hw_params_set_periods_first,snd_pcm_hw_params_set_periods_first@ALSA_0.9");
a6cb93
-asm(".symver snd_pcm_hw_params_set_periods_last,snd_pcm_hw_params_set_periods_last@ALSA_0.9");
a6cb93
+___symbol_version(snd_pcm_hw_params_get_periods, "ALSA_0.9");
a6cb93
+___symbol_version(snd_pcm_hw_params_get_periods_min, "ALSA_0.9");
a6cb93
+___symbol_version(snd_pcm_hw_params_get_periods_max, "ALSA_0.9");
a6cb93
+___symbol_version(snd_pcm_hw_params_set_periods_near, "ALSA_0.9");
a6cb93
+___symbol_version(snd_pcm_hw_params_set_periods_first, "ALSA_0.9");
a6cb93
+___symbol_version(snd_pcm_hw_params_set_periods_last, "ALSA_0.9");
a6cb93
 
a6cb93
 int snd_pcm_hw_params_get_periods(const snd_pcm_hw_params_t *params, int *dir);
a6cb93
 unsigned int snd_pcm_hw_params_get_periods_min(const snd_pcm_hw_params_t *params, int *dir);
a6cb93
@@ -139,12 +142,12 @@ unsigned int snd_pcm_hw_params_set_periods_first(snd_pcm_t *pcm, snd_pcm_hw_para
a6cb93
 unsigned int snd_pcm_hw_params_set_periods_last(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, int *dir);
a6cb93
 int snd_pcm_hw_params_set_periods_integer(snd_pcm_t *pcm, snd_pcm_hw_params_t *params);
a6cb93
 
a6cb93
-asm(".symver snd_pcm_hw_params_get_buffer_time,snd_pcm_hw_params_get_buffer_time@ALSA_0.9");
a6cb93
-asm(".symver snd_pcm_hw_params_get_buffer_time_min,snd_pcm_hw_params_get_buffer_time_min@ALSA_0.9");
a6cb93
-asm(".symver snd_pcm_hw_params_get_buffer_time_max,snd_pcm_hw_params_get_buffer_time_max@ALSA_0.9");
a6cb93
-asm(".symver snd_pcm_hw_params_set_buffer_time_near,snd_pcm_hw_params_set_buffer_time_near@ALSA_0.9");
a6cb93
-asm(".symver snd_pcm_hw_params_set_buffer_time_first,snd_pcm_hw_params_set_buffer_time_first@ALSA_0.9");
a6cb93
-asm(".symver snd_pcm_hw_params_set_buffer_time_last,snd_pcm_hw_params_set_buffer_time_last@ALSA_0.9");
a6cb93
+___symbol_version(snd_pcm_hw_params_get_buffer_time, "ALSA_0.9");
a6cb93
+___symbol_version(snd_pcm_hw_params_get_buffer_time_min, "ALSA_0.9");
a6cb93
+___symbol_version(snd_pcm_hw_params_get_buffer_time_max, "ALSA_0.9");
a6cb93
+___symbol_version(snd_pcm_hw_params_set_buffer_time_near, "ALSA_0.9");
a6cb93
+___symbol_version(snd_pcm_hw_params_set_buffer_time_first, "ALSA_0.9");
a6cb93
+___symbol_version(snd_pcm_hw_params_set_buffer_time_last, "ALSA_0.9");
a6cb93
 
a6cb93
 int snd_pcm_hw_params_get_buffer_time(const snd_pcm_hw_params_t *params, int *dir);
a6cb93
 unsigned int snd_pcm_hw_params_get_buffer_time_min(const snd_pcm_hw_params_t *params, int *dir);
a6cb93
@@ -158,12 +161,12 @@ unsigned int snd_pcm_hw_params_set_buffer_time_near(snd_pcm_t *pcm, snd_pcm_hw_p
a6cb93
 unsigned int snd_pcm_hw_params_set_buffer_time_first(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, int *dir);
a6cb93
 unsigned int snd_pcm_hw_params_set_buffer_time_last(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, int *dir);
a6cb93
 
a6cb93
-asm(".symver snd_pcm_hw_params_get_buffer_size,snd_pcm_hw_params_get_buffer_size@ALSA_0.9");
a6cb93
-asm(".symver snd_pcm_hw_params_get_buffer_size_min,snd_pcm_hw_params_get_buffer_size_min@ALSA_0.9");
a6cb93
-asm(".symver snd_pcm_hw_params_get_buffer_size_max,snd_pcm_hw_params_get_buffer_size_max@ALSA_0.9");
a6cb93
-asm(".symver snd_pcm_hw_params_set_buffer_size_near,snd_pcm_hw_params_set_buffer_size_near@ALSA_0.9");
a6cb93
-asm(".symver snd_pcm_hw_params_set_buffer_size_first,snd_pcm_hw_params_set_buffer_size_first@ALSA_0.9");
a6cb93
-asm(".symver snd_pcm_hw_params_set_buffer_size_last,snd_pcm_hw_params_set_buffer_size_last@ALSA_0.9");
a6cb93
+___symbol_version(snd_pcm_hw_params_get_buffer_size, "ALSA_0.9");
a6cb93
+___symbol_version(snd_pcm_hw_params_get_buffer_size_min, "ALSA_0.9");
a6cb93
+___symbol_version(snd_pcm_hw_params_get_buffer_size_max, "ALSA_0.9");
a6cb93
+___symbol_version(snd_pcm_hw_params_set_buffer_size_near, "ALSA_0.9");
a6cb93
+___symbol_version(snd_pcm_hw_params_set_buffer_size_first, "ALSA_0.9");
a6cb93
+___symbol_version(snd_pcm_hw_params_set_buffer_size_last, "ALSA_0.9");
a6cb93
 
a6cb93
 snd_pcm_sframes_t snd_pcm_hw_params_get_buffer_size(const snd_pcm_hw_params_t *params);
a6cb93
 snd_pcm_uframes_t snd_pcm_hw_params_get_buffer_size_min(const snd_pcm_hw_params_t *params);
a6cb93
@@ -177,12 +180,12 @@ snd_pcm_uframes_t snd_pcm_hw_params_set_buffer_size_near(snd_pcm_t *pcm, snd_pcm
a6cb93
 snd_pcm_uframes_t snd_pcm_hw_params_set_buffer_size_first(snd_pcm_t *pcm, snd_pcm_hw_params_t *params);
a6cb93
 snd_pcm_uframes_t snd_pcm_hw_params_set_buffer_size_last(snd_pcm_t *pcm, snd_pcm_hw_params_t *params);
a6cb93
 
a6cb93
-asm(".symver snd_pcm_hw_params_get_tick_time,snd_pcm_hw_params_get_tick_time@ALSA_0.9");
a6cb93
-asm(".symver snd_pcm_hw_params_get_tick_time_min,snd_pcm_hw_params_get_tick_time_min@ALSA_0.9");
a6cb93
-asm(".symver snd_pcm_hw_params_get_tick_time_max,snd_pcm_hw_params_get_tick_time_max@ALSA_0.9");
a6cb93
-asm(".symver snd_pcm_hw_params_set_tick_time_near,snd_pcm_hw_params_set_tick_time_near@ALSA_0.9");
a6cb93
-asm(".symver snd_pcm_hw_params_set_tick_time_first,snd_pcm_hw_params_set_tick_time_first@ALSA_0.9");
a6cb93
-asm(".symver snd_pcm_hw_params_set_tick_time_last,snd_pcm_hw_params_set_tick_time_last@ALSA_0.9");
a6cb93
+___symbol_version(snd_pcm_hw_params_get_tick_time, "ALSA_0.9");
a6cb93
+___symbol_version(snd_pcm_hw_params_get_tick_time_min, "ALSA_0.9");
a6cb93
+___symbol_version(snd_pcm_hw_params_get_tick_time_max, "ALSA_0.9");
a6cb93
+___symbol_version(snd_pcm_hw_params_set_tick_time_near, "ALSA_0.9");
a6cb93
+___symbol_version(snd_pcm_hw_params_set_tick_time_first, "ALSA_0.9");
a6cb93
+___symbol_version(snd_pcm_hw_params_set_tick_time_last, "ALSA_0.9");
a6cb93
 
a6cb93
 int snd_pcm_hw_params_get_tick_time(const snd_pcm_hw_params_t *params, int *dir);
a6cb93
 unsigned int snd_pcm_hw_params_get_tick_time_min(const snd_pcm_hw_params_t *params, int *dir);
a6cb93
@@ -201,14 +204,14 @@ unsigned int snd_pcm_hw_params_set_tick_time_last(snd_pcm_t *pcm, snd_pcm_hw_par
a6cb93
 
a6cb93
 #ifdef ALSA_PCM_OLD_SW_PARAMS_API
a6cb93
 
a6cb93
-asm(".symver snd_pcm_sw_params_get_tstamp_mode,snd_pcm_sw_params_get_tstamp_mode@ALSA_0.9");
a6cb93
-asm(".symver snd_pcm_sw_params_get_sleep_min,snd_pcm_sw_params_get_sleep_min@ALSA_0.9");
a6cb93
-asm(".symver snd_pcm_sw_params_get_avail_min,snd_pcm_sw_params_get_avail_min@ALSA_0.9");
a6cb93
-asm(".symver snd_pcm_sw_params_get_xfer_align,snd_pcm_sw_params_get_xfer_align@ALSA_0.9");
a6cb93
-asm(".symver snd_pcm_sw_params_get_start_threshold,snd_pcm_sw_params_get_start_threshold@ALSA_0.9");
a6cb93
-asm(".symver snd_pcm_sw_params_get_stop_threshold,snd_pcm_sw_params_get_stop_threshold@ALSA_0.9");
a6cb93
-asm(".symver snd_pcm_sw_params_get_silence_threshold,snd_pcm_sw_params_get_silence_threshold@ALSA_0.9");
a6cb93
-asm(".symver snd_pcm_sw_params_get_silence_size,snd_pcm_sw_params_get_silence_size@ALSA_0.9");
a6cb93
+___symbol_version(snd_pcm_sw_params_get_tstamp_mode, "ALSA_0.9");
a6cb93
+___symbol_version(snd_pcm_sw_params_get_sleep_min, "ALSA_0.9");
a6cb93
+___symbol_version(snd_pcm_sw_params_get_avail_min, "ALSA_0.9");
a6cb93
+___symbol_version(snd_pcm_sw_params_get_xfer_align, "ALSA_0.9");
a6cb93
+___symbol_version(snd_pcm_sw_params_get_start_threshold, "ALSA_0.9");
a6cb93
+___symbol_version(snd_pcm_sw_params_get_stop_threshold, "ALSA_0.9");
a6cb93
+___symbol_version(snd_pcm_sw_params_get_silence_threshold, "ALSA_0.9");
a6cb93
+___symbol_version(snd_pcm_sw_params_get_silence_size, "ALSA_0.9");
a6cb93
 
a6cb93
 int snd_pcm_sw_params_set_tstamp_mode(snd_pcm_t *pcm, snd_pcm_sw_params_t *params, snd_pcm_tstamp_t val);
a6cb93
 snd_pcm_tstamp_t snd_pcm_sw_params_get_tstamp_mode(const snd_pcm_sw_params_t *params);
a6cb93
-- 
a6cb93
2.39.0
a6cb93
a6cb93
a6cb93
From 152983f01b0bc1178ea0d461ebf66e2d2a8e2e02 Mon Sep 17 00:00:00 2001
a6cb93
From: Jaroslav Kysela <perex@perex.cz>
a6cb93
Date: Wed, 9 Nov 2022 15:04:06 +0100
a6cb93
Subject: [PATCH 05/20] include: alsa-symbols.h - use newer gcc symver function
a6cb93
 attribute
a6cb93
a6cb93
Use the symver function attribute for newer gccs (version 11+).
a6cb93
The symver function attribute was introduced probably earlier
a6cb93
(gcc-10). We can fix that on demand later.
a6cb93
a6cb93
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
a6cb93
---
a6cb93
 include/alsa-symbols.h | 7 +++++++
a6cb93
 1 file changed, 7 insertions(+)
a6cb93
a6cb93
diff --git a/include/alsa-symbols.h b/include/alsa-symbols.h
a6cb93
index 344f021a..f8c49103 100644
a6cb93
--- a/include/alsa-symbols.h
a6cb93
+++ b/include/alsa-symbols.h
a6cb93
@@ -29,10 +29,17 @@
a6cb93
 #define INTERNAL_CONCAT2_2(Pre, Post) Pre##Post
a6cb93
 #define INTERNAL(Name) INTERNAL_CONCAT2_2(__, Name)
a6cb93
 
a6cb93
+#if __GNUC__ > 10
a6cb93
+#define symbol_version(real, name, version) \
a6cb93
+	extern __typeof (real) real __attribute__((symver (#name "@" #version)))
a6cb93
+#define default_symbol_version(real, name, version) \
a6cb93
+	extern __typeof (real) real __attribute__((symver (#name "@@" #version)))
a6cb93
+#else
a6cb93
 #define symbol_version(real, name, version) \
a6cb93
 	__asm__ (".symver " ASM_NAME(#real) "," ASM_NAME(#name) "@" #version)
a6cb93
 #define default_symbol_version(real, name, version) \
a6cb93
 	__asm__ (".symver " ASM_NAME(#real) "," ASM_NAME(#name) "@@" #version)
a6cb93
+#endif
a6cb93
 
a6cb93
 #ifdef __clang__
a6cb93
 #define EXPORT_SYMBOL __attribute__((visibility("default")))
a6cb93
-- 
a6cb93
2.39.0
a6cb93
a6cb93
a6cb93
From 78b20e3caa7bba930095e05f3f8cbe665204fcfd Mon Sep 17 00:00:00 2001
a6cb93
From: Jaroslav Kysela <perex@perex.cz>
a6cb93
Date: Mon, 14 Nov 2022 12:36:04 +0100
a6cb93
Subject: [PATCH 06/20] test: latency - use snd_pcm_format_physical_width()
a6cb93
a6cb93
We need to allocate frames using the physical size not
a6cb93
the sample bit size.
a6cb93
a6cb93
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
a6cb93
---
a6cb93
 src/topology/ctl.c | 7 ++++++-
a6cb93
 test/latency.c     | 6 +++---
a6cb93
 2 files changed, 9 insertions(+), 4 deletions(-)
a6cb93
a6cb93
diff --git a/src/topology/ctl.c b/src/topology/ctl.c
a6cb93
index dd05424d..2c500ffc 100644
a6cb93
--- a/src/topology/ctl.c
a6cb93
+++ b/src/topology/ctl.c
a6cb93
@@ -17,9 +17,13 @@
a6cb93
            Liam Girdwood <liam.r.girdwood@linux.intel.com>
a6cb93
 */
a6cb93
 
a6cb93
+#define ALSA_PCM_OLD_HW_PARAMS_API 1
a6cb93
+#define ALSA_PCM_OLD_SW_PARAMS_API 1
a6cb93
+#include "../../include/asoundlib.h"
a6cb93
 #include "list.h"
a6cb93
 #include "tplg_local.h"
a6cb93
 
a6cb93
+
a6cb93
 #define ENUM_VAL_SIZE 	(SNDRV_CTL_ELEM_ID_NAME_MAXLEN >> 2)
a6cb93
 
a6cb93
 struct ctl_access_elem {
a6cb93
@@ -71,7 +75,8 @@ static int parse_access_values(snd_config_t *cfg,
a6cb93
 			}
a6cb93
 		}
a6cb93
 	}
a6cb93
-
a6cb93
+	return snd_pcm_hw_params_get_channels(NULL);
a6cb93
+	//return snd_pcm_hw_params_get_access(NULL);
a6cb93
 	return 0;
a6cb93
 }
a6cb93
 
a6cb93
diff --git a/test/latency.c b/test/latency.c
a6cb93
index 298bab8a..95b3c0ee 100644
a6cb93
--- a/test/latency.c
a6cb93
+++ b/test/latency.c
a6cb93
@@ -354,7 +354,7 @@ long readbuf(snd_pcm_t *handle, char *buf, long len, size_t *frames, size_t *max
a6cb93
 		}
a6cb93
 		// printf("read = %li\n", r);
a6cb93
 	} else {
a6cb93
-		int frame_bytes = (snd_pcm_format_width(format) / 8) * channels;
a6cb93
+		int frame_bytes = (snd_pcm_format_physical_width(format) / 8) * channels;
a6cb93
 		do {
a6cb93
 			r = snd_pcm_readi(handle, buf, len);
a6cb93
 			if (r > 0) {
a6cb93
@@ -374,7 +374,7 @@ long readbuf(snd_pcm_t *handle, char *buf, long len, size_t *frames, size_t *max
a6cb93
 long writebuf(snd_pcm_t *handle, char *buf, long len, size_t *frames)
a6cb93
 {
a6cb93
 	long r;
a6cb93
-	int frame_bytes = (snd_pcm_format_width(format) / 8) * channels;
a6cb93
+	int frame_bytes = (snd_pcm_format_physical_width(format) / 8) * channels;
a6cb93
 
a6cb93
 	while (len > 0) {
a6cb93
 		r = snd_pcm_writei(handle, buf, len);
a6cb93
@@ -579,7 +579,7 @@ int main(int argc, char *argv[])
a6cb93
 
a6cb93
 	loop_limit = loop_sec * rate;
a6cb93
 	latency = latency_min - 4;
a6cb93
-	buffer = malloc((latency_max * snd_pcm_format_width(format) / 8) * 2);
a6cb93
+	buffer = malloc((latency_max * snd_pcm_format_physical_width(format) / 8) * 2);
a6cb93
 
a6cb93
 	setscheduler();
a6cb93
 
a6cb93
-- 
a6cb93
2.39.0
a6cb93
a6cb93
a6cb93
From 425e4d1fbea4965ea0fb7529b1ee6cbb47eb7227 Mon Sep 17 00:00:00 2001
a6cb93
From: Jaroslav Kysela <perex@perex.cz>
a6cb93
Date: Mon, 14 Nov 2022 14:34:46 +0100
a6cb93
Subject: [PATCH 07/20] pcm: fix the fast_ops pcm argument for fast_ops
a6cb93
a6cb93
The fast_ops callback invocation must always pass the fast_op_arg
a6cb93
as the pcm argument. Plugins expect that.
a6cb93
a6cb93
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
a6cb93
---
a6cb93
 src/pcm/pcm.c        | 4 ++--
a6cb93
 src/pcm/pcm_direct.c | 2 +-
a6cb93
 src/pcm/pcm_hw.c     | 2 +-
a6cb93
 src/pcm/pcm_multi.c  | 5 +++--
a6cb93
 4 files changed, 7 insertions(+), 6 deletions(-)
a6cb93
a6cb93
diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c
a6cb93
index 927aa055..2b966d44 100644
a6cb93
--- a/src/pcm/pcm.c
a6cb93
+++ b/src/pcm/pcm.c
a6cb93
@@ -1705,7 +1705,7 @@ int snd_pcm_link(snd_pcm_t *pcm1, snd_pcm_t *pcm2)
a6cb93
 	assert(pcm1);
a6cb93
 	assert(pcm2);
a6cb93
 	if (pcm1->fast_ops->link)
a6cb93
-		err = pcm1->fast_ops->link(pcm1, pcm2);
a6cb93
+		err = pcm1->fast_ops->link(pcm1->fast_op_arg, pcm2);
a6cb93
 	else
a6cb93
 		err = -ENOSYS;
a6cb93
 	return err;
a6cb93
@@ -1722,7 +1722,7 @@ int snd_pcm_unlink(snd_pcm_t *pcm)
a6cb93
 
a6cb93
 	assert(pcm);
a6cb93
 	if (pcm->fast_ops->unlink)
a6cb93
-		err = pcm->fast_ops->unlink(pcm);
a6cb93
+		err = pcm->fast_ops->unlink(pcm->fast_op_arg);
a6cb93
 	else
a6cb93
 		err = -ENOSYS;
a6cb93
 	return err;
a6cb93
diff --git a/src/pcm/pcm_direct.c b/src/pcm/pcm_direct.c
a6cb93
index 4803b81b..3cc5305f 100644
a6cb93
--- a/src/pcm/pcm_direct.c
a6cb93
+++ b/src/pcm/pcm_direct.c
a6cb93
@@ -688,7 +688,7 @@ int snd_pcm_direct_check_xrun(snd_pcm_direct_t *direct, snd_pcm_t *pcm)
a6cb93
 		 * so don't increment but just update to actual counter
a6cb93
 		 */
a6cb93
 		direct->recoveries = direct->shmptr->s.recoveries;
a6cb93
-		pcm->fast_ops->drop(pcm);
a6cb93
+		pcm->fast_ops->drop(pcm->fast_op_arg);
a6cb93
 		/* trigger_tstamp update is missing in drop callbacks */
a6cb93
 		gettimestamp(&direct->trigger_tstamp, pcm->tstamp_type);
a6cb93
 		/* no timer clear:
a6cb93
diff --git a/src/pcm/pcm_hw.c b/src/pcm/pcm_hw.c
a6cb93
index 5dfe32ee..0588ce5e 100644
a6cb93
--- a/src/pcm/pcm_hw.c
a6cb93
+++ b/src/pcm/pcm_hw.c
a6cb93
@@ -838,7 +838,7 @@ static int snd_pcm_hw_link(snd_pcm_t *pcm1, snd_pcm_t *pcm2)
a6cb93
 {
a6cb93
 	if (pcm2->type != SND_PCM_TYPE_HW) {
a6cb93
 		if (pcm2->fast_ops->link_slaves)
a6cb93
-			return pcm2->fast_ops->link_slaves(pcm2, pcm1);
a6cb93
+			return pcm2->fast_ops->link_slaves(pcm2->fast_op_arg, pcm1);
a6cb93
 		return -ENOSYS;
a6cb93
 	}
a6cb93
 	return hw_link(pcm1, pcm2);
a6cb93
diff --git a/src/pcm/pcm_multi.c b/src/pcm/pcm_multi.c
a6cb93
index bec6d06f..3e7ce82c 100644
a6cb93
--- a/src/pcm/pcm_multi.c
a6cb93
+++ b/src/pcm/pcm_multi.c
a6cb93
@@ -759,8 +759,9 @@ static int snd_pcm_multi_link_slaves(snd_pcm_t *pcm, snd_pcm_t *master)
a6cb93
 static int snd_pcm_multi_link(snd_pcm_t *pcm1, snd_pcm_t *pcm2)
a6cb93
 {
a6cb93
 	snd_pcm_multi_t *multi = pcm1->private_data;
a6cb93
-	if (multi->slaves[0].pcm->fast_ops->link)
a6cb93
-		return multi->slaves[0].pcm->fast_ops->link(multi->slaves[0].pcm, pcm2);
a6cb93
+	snd_pcm_t *main_pcm = multi->slaves[0].pcm;
a6cb93
+	if (main_pcm->fast_ops->link)
a6cb93
+		return main_pcm->fast_ops->link(main_pcm->fast_op_arg, pcm2);
a6cb93
 	return -ENOSYS;
a6cb93
 }
a6cb93
 
a6cb93
-- 
a6cb93
2.39.0
a6cb93
a6cb93
a6cb93
From 3e4aeba25bf4a4808183c4b64270f7321b436c13 Mon Sep 17 00:00:00 2001
a6cb93
From: Jaroslav Kysela <perex@perex.cz>
a6cb93
Date: Mon, 14 Nov 2022 20:42:10 +0100
a6cb93
Subject: [PATCH 08/20] test: latency - add more realtime tests
a6cb93
a6cb93
Add '-x' and '-X' tests and '-U' - I/O update mode based
a6cb93
on the system timing.
a6cb93
a6cb93
It may be required to check the position updates for the specific hardware.
a6cb93
Print the real time / stream time differences.
a6cb93
a6cb93
Also include code to make valgrind happy (including the wrong memory
a6cb93
llocation for the stream buffer).
a6cb93
a6cb93
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
a6cb93
---
a6cb93
 test/latency.c | 163 +++++++++++++++++++++++++++++++++++++++++++++----
a6cb93
 1 file changed, 151 insertions(+), 12 deletions(-)
a6cb93
a6cb93
diff --git a/test/latency.c b/test/latency.c
a6cb93
index 95b3c0ee..91bef1a1 100644
a6cb93
--- a/test/latency.c
a6cb93
+++ b/test/latency.c
a6cb93
@@ -33,10 +33,13 @@
a6cb93
 #include <sched.h>
a6cb93
 #include <errno.h>
a6cb93
 #include <getopt.h>
a6cb93
+#include <time.h>
a6cb93
 #include "../include/asoundlib.h"
a6cb93
 #include <sys/time.h>
a6cb93
 #include <math.h>
a6cb93
 
a6cb93
+typedef struct timespec timestamp_t;
a6cb93
+
a6cb93
 char *pdevice = "hw:0,0";
a6cb93
 char *cdevice = "hw:0,0";
a6cb93
 snd_pcm_format_t format = SND_PCM_FORMAT_S16_LE;
a6cb93
@@ -50,10 +53,40 @@ int loop_sec = 30;		/* seconds */
a6cb93
 int block = 0;			/* block mode */
a6cb93
 int use_poll = 0;
a6cb93
 int resample = 1;
a6cb93
+int sys_latency = 0;		/* data I/O: use system timings instead driver wakeups */
a6cb93
+int pos_dump = 0;		/* dump positions */
a6cb93
+int realtime_check = 0;
a6cb93
 unsigned long loop_limit;
a6cb93
+snd_pcm_uframes_t playback_buffer_size;
a6cb93
 
a6cb93
 snd_output_t *output = NULL;
a6cb93
 
a6cb93
+static inline long long frames_to_micro(size_t frames)
a6cb93
+{
a6cb93
+	return (long long)((frames * 1000000LL) + (rate / 2)) / rate;
a6cb93
+}
a6cb93
+
a6cb93
+void timestamp_now(timestamp_t *tstamp)
a6cb93
+{
a6cb93
+	if (clock_gettime(CLOCK_MONOTONIC_RAW, tstamp))
a6cb93
+		printf("clock_gettime() failed\n");
a6cb93
+}
a6cb93
+
a6cb93
+long long timestamp_diff_micro(timestamp_t *tstamp)
a6cb93
+{
a6cb93
+	timestamp_t now, diff;
a6cb93
+	timestamp_now(&now;;
a6cb93
+	if (tstamp->tv_nsec > now.tv_nsec) {
a6cb93
+		diff.tv_sec = now.tv_sec - tstamp->tv_sec - 1;
a6cb93
+		diff.tv_nsec = (now.tv_nsec + 1000000000L) - tstamp->tv_nsec;
a6cb93
+	} else {
a6cb93
+		diff.tv_sec = now.tv_sec - tstamp->tv_sec;
a6cb93
+		diff.tv_nsec = now.tv_nsec - tstamp->tv_nsec;
a6cb93
+	}
a6cb93
+	/* microseconds */
a6cb93
+	return (diff.tv_sec * 1000000) + ((diff.tv_nsec + 500L) / 1000L);
a6cb93
+}
a6cb93
+
a6cb93
 int setparams_stream(snd_pcm_t *handle,
a6cb93
 		     snd_pcm_hw_params_t *params,
a6cb93
 		     const char *id)
a6cb93
@@ -96,6 +129,14 @@ int setparams_stream(snd_pcm_t *handle,
a6cb93
 		printf("Rate doesn't match (requested %iHz, get %iHz)\n", rate, err);
a6cb93
 		return -EINVAL;
a6cb93
 	}
a6cb93
+	/* we do not want driver wakeups */
a6cb93
+	if (sys_latency > 0 && snd_pcm_hw_params_can_disable_period_wakeup(params)) {
a6cb93
+		err = snd_pcm_hw_params_set_period_wakeup(handle, params, 0);
a6cb93
+		if (err < 0) {
a6cb93
+			printf("Cannot disable period wakeups for %s\n", id);
a6cb93
+			return err;
a6cb93
+		}
a6cb93
+	}
a6cb93
 	return 0;
a6cb93
 }
a6cb93
 
a6cb93
@@ -227,6 +268,7 @@ int setparams(snd_pcm_t *phandle, snd_pcm_t *chandle, int *bufsize)
a6cb93
 		goto __again;
a6cb93
 
a6cb93
 	snd_pcm_hw_params_get_buffer_size(p_params, &p_size);
a6cb93
+	playback_buffer_size = p_size;
a6cb93
 	if (p_psize * 2 < p_size) {
a6cb93
                 snd_pcm_hw_params_get_periods_min(p_params, &val, NULL);
a6cb93
                 if (val > 2) {
a6cb93
@@ -390,7 +432,7 @@ long writebuf(snd_pcm_t *handle, char *buf, long len, size_t *frames)
a6cb93
 	}
a6cb93
 	return 0;
a6cb93
 }
a6cb93
-			
a6cb93
+
a6cb93
 #define FILTERSWEEP_LFO_CENTER 2000.
a6cb93
 #define FILTERSWEEP_LFO_DEPTH 1800.
a6cb93
 #define FILTERSWEEP_LFO_FREQ 0.2
a6cb93
@@ -434,6 +476,19 @@ void applyeffect(char* buffer,int r)
a6cb93
 	}
a6cb93
 }
a6cb93
 
a6cb93
+static ssize_t get_avail(snd_pcm_t *pcm)
a6cb93
+{
a6cb93
+	ssize_t avail;
a6cb93
+
a6cb93
+	while (1) {
a6cb93
+		avail = snd_pcm_avail(pcm);
a6cb93
+		if (avail == -EAGAIN)
a6cb93
+			continue;
a6cb93
+		break;
a6cb93
+	}
a6cb93
+	return avail;
a6cb93
+}
a6cb93
+
a6cb93
 void help(void)
a6cb93
 {
a6cb93
 	int k;
a6cb93
@@ -444,6 +499,7 @@ void help(void)
a6cb93
 "-C,--cdevice   capture device\n"
a6cb93
 "-m,--min       minimum latency in frames\n"
a6cb93
 "-M,--max       maximum latency in frames\n"
a6cb93
+"-U,--updates   I/O updates in milliseconds (0 = off)\n"
a6cb93
 "-F,--frames    frames to transfer\n"
a6cb93
 "-f,--format    sample format\n"
a6cb93
 "-c,--channels  channels\n"
a6cb93
@@ -454,6 +510,8 @@ void help(void)
a6cb93
 "-b,--block     block mode\n"
a6cb93
 "-p,--poll      use poll (wait for event - reduces CPU usage)\n"
a6cb93
 "-e,--effect    apply an effect (bandpass filter sweep)\n"
a6cb93
+"-x,--posdump   dump buffer positions\n"
a6cb93
+"-X,--realtime  do a realtime check (buffering)\n"
a6cb93
 );
a6cb93
         printf("Recognized sample formats are:");
a6cb93
         for (k = 0; k < SND_PCM_FORMAT_LAST; ++k) {
a6cb93
@@ -480,6 +538,7 @@ int main(int argc, char *argv[])
a6cb93
 		{"cdevice", 1, NULL, 'C'},
a6cb93
 		{"min", 1, NULL, 'm'},
a6cb93
 		{"max", 1, NULL, 'M'},
a6cb93
+		{"updates", 1, NULL, 'U'},
a6cb93
 		{"frames", 1, NULL, 'F'},
a6cb93
 		{"format", 1, NULL, 'f'},
a6cb93
 		{"channels", 1, NULL, 'c'},
a6cb93
@@ -490,20 +549,23 @@ int main(int argc, char *argv[])
a6cb93
 		{"block", 0, NULL, 'b'},
a6cb93
 		{"poll", 0, NULL, 'p'},
a6cb93
 		{"effect", 0, NULL, 'e'},
a6cb93
+		{"posdump", 0, NULL, 'x'},
a6cb93
+		{"realtime", 0, NULL, 'X'},
a6cb93
 		{NULL, 0, NULL, 0},
a6cb93
 	};
a6cb93
 	snd_pcm_t *phandle, *chandle;
a6cb93
 	char *buffer;
a6cb93
 	int err, latency, morehelp;
a6cb93
-	int ok;
a6cb93
+	int ok, first_avail;
a6cb93
 	snd_timestamp_t p_tstamp, c_tstamp;
a6cb93
-	ssize_t r;
a6cb93
+	ssize_t r, cap_avail, cap_avail_max, pbk_fill, pbk_fill_min;
a6cb93
 	size_t frames_in, frames_out, in_max;
a6cb93
+	timestamp_t tstamp_start;
a6cb93
 	int effect = 0;
a6cb93
 	morehelp = 0;
a6cb93
 	while (1) {
a6cb93
 		int c;
a6cb93
-		if ((c = getopt_long(argc, argv, "hP:C:m:M:F:f:c:r:B:E:s:bpen", long_option, NULL)) < 0)
a6cb93
+		if ((c = getopt_long(argc, argv, "hP:C:m:M:U:F:f:c:r:B:E:s:bpenxX", long_option, NULL)) < 0)
a6cb93
 			break;
a6cb93
 		switch (c) {
a6cb93
 		case 'h':
a6cb93
@@ -525,6 +587,10 @@ int main(int argc, char *argv[])
a6cb93
 			err = atoi(optarg) / 2;
a6cb93
 			latency_max = latency_min > err ? latency_min : err;
a6cb93
 			break;
a6cb93
+		case 'U':
a6cb93
+			err = atoi(optarg);
a6cb93
+			sys_latency = err <= 0 ? 0 : err;
a6cb93
+			break;
a6cb93
 		case 'f':
a6cb93
 			format = snd_pcm_format_value(optarg);
a6cb93
 			if (format == SND_PCM_FORMAT_UNKNOWN) {
a6cb93
@@ -564,6 +630,12 @@ int main(int argc, char *argv[])
a6cb93
 		case 'n':
a6cb93
 			resample = 0;
a6cb93
 			break;
a6cb93
+		case 'x':
a6cb93
+			pos_dump = 1;
a6cb93
+			break;
a6cb93
+		case 'X':
a6cb93
+			realtime_check = 1;
a6cb93
+			break;
a6cb93
 		}
a6cb93
 	}
a6cb93
 
a6cb93
@@ -579,15 +651,27 @@ int main(int argc, char *argv[])
a6cb93
 
a6cb93
 	loop_limit = loop_sec * rate;
a6cb93
 	latency = latency_min - 4;
a6cb93
-	buffer = malloc((latency_max * snd_pcm_format_physical_width(format) / 8) * 2);
a6cb93
+	buffer = malloc((latency_max * 2 * snd_pcm_format_physical_width(format) / 8) * channels);
a6cb93
+
a6cb93
+	/* I/O updates based on a system timer */
a6cb93
+	if (sys_latency > 0) {
a6cb93
+		block = 0;
a6cb93
+		use_poll = 0;
a6cb93
+	}
a6cb93
 
a6cb93
 	setscheduler();
a6cb93
 
a6cb93
 	printf("Playback device is %s\n", pdevice);
a6cb93
 	printf("Capture device is %s\n", cdevice);
a6cb93
-	printf("Parameters are %iHz, %s, %i channels, %s mode\n", rate, snd_pcm_format_name(format), channels, block ? "blocking" : "non-blocking");
a6cb93
-	printf("Poll mode: %s\n", use_poll ? "yes" : "no");
a6cb93
-	printf("Loop limit is %lu frames, minimum latency = %i, maximum latency = %i\n", loop_limit, latency_min * 2, latency_max * 2);
a6cb93
+	printf("Parameters are %iHz, %s, %i channels, %s mode, use poll %s\n",
a6cb93
+			rate, snd_pcm_format_name(format),
a6cb93
+			channels, block ? "blocking" : "non-blocking",
a6cb93
+			use_poll ? "yes" : "no");
a6cb93
+	printf("Loop limit is %lu frames, minimum latency = %i, maximum latency = %i",
a6cb93
+			loop_limit, latency_min * 2, latency_max * 2);
a6cb93
+	if (sys_latency > 0)
a6cb93
+		printf(", I/O updates %ims", sys_latency);
a6cb93
+	printf("\n");
a6cb93
 
a6cb93
 	if ((err = snd_pcm_open(&phandle, pdevice, SND_PCM_STREAM_PLAYBACK, block ? 0 : SND_PCM_NONBLOCK)) < 0) {
a6cb93
 		printf("Playback open error: %s\n", snd_strerror(err));
a6cb93
@@ -613,6 +697,9 @@ int main(int argc, char *argv[])
a6cb93
 		y[1] = (float*) malloc(channels*sizeof(float));		
a6cb93
 		y[2] = (float*) malloc(channels*sizeof(float));		
a6cb93
 	}
a6cb93
+
a6cb93
+	cap_avail_max = 0;
a6cb93
+	pbk_fill_min = latency * 2;
a6cb93
 			  
a6cb93
 	while (1) {
a6cb93
 		frames_in = frames_out = 0;
a6cb93
@@ -623,7 +710,7 @@ int main(int argc, char *argv[])
a6cb93
 			printf("Streams link error: %s\n", snd_strerror(err));
a6cb93
 			exit(0);
a6cb93
 		}
a6cb93
-		if (snd_pcm_format_set_silence(format, buffer, latency*channels) < 0) {
a6cb93
+		if (snd_pcm_format_set_silence(format, buffer, latency * channels) < 0) {
a6cb93
 			fprintf(stderr, "silence error\n");
a6cb93
 			break;
a6cb93
 		}
a6cb93
@@ -640,6 +727,8 @@ int main(int argc, char *argv[])
a6cb93
 			printf("Go error: %s\n", snd_strerror(err));
a6cb93
 			exit(0);
a6cb93
 		}
a6cb93
+		if (realtime_check)
a6cb93
+			timestamp_now(&tstamp_start);
a6cb93
 		gettimestamp(phandle, &p_tstamp);
a6cb93
 		gettimestamp(chandle, &c_tstamp);
a6cb93
 #if 0
a6cb93
@@ -651,16 +740,54 @@ int main(int argc, char *argv[])
a6cb93
 
a6cb93
 		ok = 1;
a6cb93
 		in_max = 0;
a6cb93
+		first_avail = 1;
a6cb93
 		while (ok && frames_in < loop_limit) {
a6cb93
-			if (use_poll) {
a6cb93
+			cap_avail = latency;
a6cb93
+			if (sys_latency > 0) {
a6cb93
+				poll(NULL, 0, sys_latency);
a6cb93
+				cap_avail = get_avail(chandle);
a6cb93
+				if (cap_avail < 0) {
a6cb93
+					printf("Avail failed: %s\n", snd_strerror(cap_avail));
a6cb93
+					ok = 0;
a6cb93
+					break;
a6cb93
+				}
a6cb93
+				if (first_avail && realtime_check) {
a6cb93
+					long long diff = timestamp_diff_micro(&tstamp_start);
a6cb93
+					long long pos = frames_to_micro(cap_avail);
a6cb93
+					printf("POS FIRST CHECK: c=%zd (rt=%lldus)\n", cap_avail, pos - diff);
a6cb93
+					first_avail = 0;
a6cb93
+				}
a6cb93
+			} else if (use_poll) {
a6cb93
 				/* use poll to wait for next event */
a6cb93
 				snd_pcm_wait(chandle, 1000);
a6cb93
 			}
a6cb93
-			if ((r = readbuf(chandle, buffer, latency, &frames_in, &in_max)) < 0)
a6cb93
+			if (pos_dump || realtime_check) {
a6cb93
+				if (sys_latency <= 0)
a6cb93
+					cap_avail = get_avail(chandle);
a6cb93
+				pbk_fill = get_avail(phandle);
a6cb93
+				if (pbk_fill >= 0)
a6cb93
+					pbk_fill = playback_buffer_size - pbk_fill;
a6cb93
+				if (cap_avail > cap_avail_max)
a6cb93
+					cap_avail_max = cap_avail;
a6cb93
+				if (pbk_fill >= 0 && pbk_fill < pbk_fill_min)
a6cb93
+					pbk_fill_min = pbk_fill;
a6cb93
+				if (realtime_check) {
a6cb93
+					long long diff = timestamp_diff_micro(&tstamp_start);
a6cb93
+					long long cap_pos = frames_to_micro(frames_in + cap_avail);
a6cb93
+					long long pbk_pos = frames_to_micro(frames_out - pbk_fill);
a6cb93
+					printf("POS: p=%zd (min=%zd, rt=%lldus) c=%zd (max=%zd, rt=%lldus)\n",
a6cb93
+							pbk_fill, pbk_fill_min, pbk_pos - diff,
a6cb93
+							cap_avail, cap_avail_max, cap_pos - diff);
a6cb93
+				} else if (pos_dump) {
a6cb93
+					printf("POS: p=%zd (min=%zd), c=%zd (max=%zd)\n",
a6cb93
+							pbk_fill, pbk_fill_min, cap_avail, cap_avail_max);
a6cb93
+				}
a6cb93
+			}
a6cb93
+			if ((r = readbuf(chandle, buffer, cap_avail, &frames_in, &in_max)) < 0)
a6cb93
 				ok = 0;
a6cb93
 			else {
a6cb93
 				if (effect)
a6cb93
-					applyeffect(buffer,r);
a6cb93
+					applyeffect(buffer, r);
a6cb93
 			 	if (writebuf(phandle, buffer, r, &frames_out) < 0)
a6cb93
 					ok = 0;
a6cb93
 			}
a6cb93
@@ -677,6 +804,13 @@ int main(int argc, char *argv[])
a6cb93
 		if (p_tstamp.tv_sec == c_tstamp.tv_sec &&
a6cb93
 		    p_tstamp.tv_usec == c_tstamp.tv_usec)
a6cb93
 			printf("Hardware sync\n");
a6cb93
+		if (realtime_check) {
a6cb93
+			long long diff = timestamp_diff_micro(&tstamp_start);
a6cb93
+			long long mtime = frames_to_micro(frames_in);
a6cb93
+			printf("Elapsed real time: %lldus\n", diff);
a6cb93
+			printf("Elapsed device time: %lldus\n", mtime);
a6cb93
+			printf("Test time diff (device - real): %lldus\n", mtime - diff);
a6cb93
+		}
a6cb93
 		snd_pcm_drop(chandle);
a6cb93
 		snd_pcm_nonblock(phandle, 0);
a6cb93
 		snd_pcm_drain(phandle);
a6cb93
@@ -698,5 +832,10 @@ int main(int argc, char *argv[])
a6cb93
 	}
a6cb93
 	snd_pcm_close(phandle);
a6cb93
 	snd_pcm_close(chandle);
a6cb93
+	snd_output_close(output);
a6cb93
+	snd_config_update_free_global();
a6cb93
+	free(buffer);
a6cb93
+	free(pdevice);
a6cb93
+	free(cdevice);
a6cb93
 	return 0;
a6cb93
 }
a6cb93
-- 
a6cb93
2.39.0
a6cb93
a6cb93
a6cb93
From a0836e2af1f2c37b66e723d8caf399e80b76825b Mon Sep 17 00:00:00 2001
a6cb93
From: Jaroslav Kysela <perex@perex.cz>
a6cb93
Date: Mon, 14 Nov 2022 21:26:39 +0100
a6cb93
Subject: [PATCH 09/20] latency: add timestamps to the POS lines
a6cb93
a6cb93
- remove first capture pos line
a6cb93
- measure the snd_pcm_start() call, too
a6cb93
a6cb93
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
a6cb93
---
a6cb93
 test/latency.c | 17 ++++++-----------
a6cb93
 1 file changed, 6 insertions(+), 11 deletions(-)
a6cb93
a6cb93
diff --git a/test/latency.c b/test/latency.c
a6cb93
index 91bef1a1..3aff37c1 100644
a6cb93
--- a/test/latency.c
a6cb93
+++ b/test/latency.c
a6cb93
@@ -556,7 +556,7 @@ int main(int argc, char *argv[])
a6cb93
 	snd_pcm_t *phandle, *chandle;
a6cb93
 	char *buffer;
a6cb93
 	int err, latency, morehelp;
a6cb93
-	int ok, first_avail;
a6cb93
+	int ok;
a6cb93
 	snd_timestamp_t p_tstamp, c_tstamp;
a6cb93
 	ssize_t r, cap_avail, cap_avail_max, pbk_fill, pbk_fill_min;
a6cb93
 	size_t frames_in, frames_out, in_max;
a6cb93
@@ -723,12 +723,14 @@ int main(int argc, char *argv[])
a6cb93
 			break;
a6cb93
 		}
a6cb93
 
a6cb93
+		if (realtime_check)
a6cb93
+			timestamp_now(&tstamp_start);
a6cb93
 		if ((err = snd_pcm_start(chandle)) < 0) {
a6cb93
 			printf("Go error: %s\n", snd_strerror(err));
a6cb93
 			exit(0);
a6cb93
 		}
a6cb93
 		if (realtime_check)
a6cb93
-			timestamp_now(&tstamp_start);
a6cb93
+			printf("[%lldus] Stream start\n", timestamp_diff_micro(&tstamp_start));
a6cb93
 		gettimestamp(phandle, &p_tstamp);
a6cb93
 		gettimestamp(chandle, &c_tstamp);
a6cb93
 #if 0
a6cb93
@@ -740,7 +742,6 @@ int main(int argc, char *argv[])
a6cb93
 
a6cb93
 		ok = 1;
a6cb93
 		in_max = 0;
a6cb93
-		first_avail = 1;
a6cb93
 		while (ok && frames_in < loop_limit) {
a6cb93
 			cap_avail = latency;
a6cb93
 			if (sys_latency > 0) {
a6cb93
@@ -751,12 +752,6 @@ int main(int argc, char *argv[])
a6cb93
 					ok = 0;
a6cb93
 					break;
a6cb93
 				}
a6cb93
-				if (first_avail && realtime_check) {
a6cb93
-					long long diff = timestamp_diff_micro(&tstamp_start);
a6cb93
-					long long pos = frames_to_micro(cap_avail);
a6cb93
-					printf("POS FIRST CHECK: c=%zd (rt=%lldus)\n", cap_avail, pos - diff);
a6cb93
-					first_avail = 0;
a6cb93
-				}
a6cb93
 			} else if (use_poll) {
a6cb93
 				/* use poll to wait for next event */
a6cb93
 				snd_pcm_wait(chandle, 1000);
a6cb93
@@ -775,8 +770,8 @@ int main(int argc, char *argv[])
a6cb93
 					long long diff = timestamp_diff_micro(&tstamp_start);
a6cb93
 					long long cap_pos = frames_to_micro(frames_in + cap_avail);
a6cb93
 					long long pbk_pos = frames_to_micro(frames_out - pbk_fill);
a6cb93
-					printf("POS: p=%zd (min=%zd, rt=%lldus) c=%zd (max=%zd, rt=%lldus)\n",
a6cb93
-							pbk_fill, pbk_fill_min, pbk_pos - diff,
a6cb93
+					printf("[%lldus] POS: p=%zd (min=%zd, rt=%lldus) c=%zd (max=%zd, rt=%lldus)\n",
a6cb93
+							diff, pbk_fill, pbk_fill_min, pbk_pos - diff,
a6cb93
 							cap_avail, cap_avail_max, cap_pos - diff);
a6cb93
 				} else if (pos_dump) {
a6cb93
 					printf("POS: p=%zd (min=%zd), c=%zd (max=%zd)\n",
a6cb93
-- 
a6cb93
2.39.0
a6cb93
a6cb93
a6cb93
From 8b64f22459b6c55ec54f985f35ff701e18800616 Mon Sep 17 00:00:00 2001
a6cb93
From: Jaroslav Kysela <perex@perex.cz>
a6cb93
Date: Tue, 15 Nov 2022 17:25:59 +0100
a6cb93
Subject: [PATCH 10/20] ucm: clarify set_defaults calls
a6cb93
a6cb93
- do full reset in snd_use_case_mgr_reload
a6cb93
a6cb93
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
a6cb93
---
a6cb93
 src/ucm/main.c | 36 +++++++++++++++++++++++++-----------
a6cb93
 1 file changed, 25 insertions(+), 11 deletions(-)
a6cb93
a6cb93
diff --git a/src/ucm/main.c b/src/ucm/main.c
a6cb93
index 28c60565..4f36648c 100644
a6cb93
--- a/src/ucm/main.c
a6cb93
+++ b/src/ucm/main.c
a6cb93
@@ -998,13 +998,14 @@ static int add_auto_values(snd_use_case_mgr_t *uc_mgr)
a6cb93
 /**
a6cb93
  * \brief execute default commands
a6cb93
  * \param uc_mgr Use case manager
a6cb93
+ * \param force Force run
a6cb93
  * \return zero on success, otherwise a negative error code
a6cb93
  */
a6cb93
-static int set_defaults(snd_use_case_mgr_t *uc_mgr)
a6cb93
+static int set_defaults(snd_use_case_mgr_t *uc_mgr, bool force)
a6cb93
 {
a6cb93
 	int err;
a6cb93
 
a6cb93
-	if (uc_mgr->default_list_executed)
a6cb93
+	if (!force && uc_mgr->default_list_executed)
a6cb93
 		return 0;
a6cb93
 	err = execute_sequence(uc_mgr, NULL, &uc_mgr->default_list,
a6cb93
 			       &uc_mgr->value_list, NULL, NULL);
a6cb93
@@ -1351,7 +1352,7 @@ static int set_verb(snd_use_case_mgr_t *uc_mgr,
a6cb93
 	int err;
a6cb93
 
a6cb93
 	if (enable) {
a6cb93
-		err = set_defaults(uc_mgr);
a6cb93
+		err = set_defaults(uc_mgr, false);
a6cb93
 		if (err < 0)
a6cb93
 			return err;
a6cb93
 		seq = &verb->enable_list;
a6cb93
@@ -1435,6 +1436,22 @@ static int set_device(snd_use_case_mgr_t *uc_mgr,
a6cb93
 	return err;
a6cb93
 }
a6cb93
 
a6cb93
+/**
a6cb93
+ * \brief Do the full reset
a6cb93
+ * \param uc_mgr Use case manager
a6cb93
+ * \return zero on success, otherwise a negative error code
a6cb93
+ */
a6cb93
+static int do_reset(snd_use_case_mgr_t *uc_mgr)
a6cb93
+{
a6cb93
+	int err;
a6cb93
+
a6cb93
+	err = set_defaults(uc_mgr, true);
a6cb93
+	INIT_LIST_HEAD(&uc_mgr->active_modifiers);
a6cb93
+	INIT_LIST_HEAD(&uc_mgr->active_devices);
a6cb93
+	uc_mgr->active_verb = NULL;
a6cb93
+	return err;
a6cb93
+}
a6cb93
+
a6cb93
 /**
a6cb93
  * \brief Parse open arguments
a6cb93
  * \param uc_mgr Use case manager
a6cb93
@@ -1569,6 +1586,8 @@ int snd_use_case_mgr_reload(snd_use_case_mgr_t *uc_mgr)
a6cb93
 
a6cb93
 	pthread_mutex_lock(&uc_mgr->mutex);
a6cb93
 
a6cb93
+	do_reset(uc_mgr);
a6cb93
+
a6cb93
 	uc_mgr_free_verb(uc_mgr);
a6cb93
 
a6cb93
 	uc_mgr->default_list_executed = 0;
a6cb93
@@ -1633,8 +1652,7 @@ static int dismantle_use_case(snd_use_case_mgr_t *uc_mgr)
a6cb93
 	}
a6cb93
 	uc_mgr->active_verb = NULL;
a6cb93
 
a6cb93
-	err = execute_sequence(uc_mgr, NULL, &uc_mgr->default_list,
a6cb93
-			       &uc_mgr->value_list, NULL, NULL);
a6cb93
+	err = set_defaults(uc_mgr, true);
a6cb93
 	
a6cb93
 	return err;
a6cb93
 }
a6cb93
@@ -1649,11 +1667,7 @@ int snd_use_case_mgr_reset(snd_use_case_mgr_t *uc_mgr)
a6cb93
 	int err;
a6cb93
 
a6cb93
 	pthread_mutex_lock(&uc_mgr->mutex);
a6cb93
-	err = execute_sequence(uc_mgr, NULL, &uc_mgr->default_list,
a6cb93
-			       &uc_mgr->value_list, NULL, NULL);
a6cb93
-	INIT_LIST_HEAD(&uc_mgr->active_modifiers);
a6cb93
-	INIT_LIST_HEAD(&uc_mgr->active_devices);
a6cb93
-	uc_mgr->active_verb = NULL;
a6cb93
+	err = do_reset(uc_mgr);
a6cb93
 	pthread_mutex_unlock(&uc_mgr->mutex);
a6cb93
 	return err;
a6cb93
 }
a6cb93
@@ -2512,7 +2526,7 @@ static int set_defaults_user(snd_use_case_mgr_t *uc_mgr,
a6cb93
 		uc_error("error: wrong value for _defaults (%s)", value);
a6cb93
 		return -EINVAL;
a6cb93
 	}
a6cb93
-	return set_defaults(uc_mgr);
a6cb93
+	return set_defaults(uc_mgr, false);
a6cb93
 }
a6cb93
 
a6cb93
 static int handle_transition_verb(snd_use_case_mgr_t *uc_mgr,
a6cb93
-- 
a6cb93
2.39.0
a6cb93
a6cb93
a6cb93
From 9649b64c6f72984c53f469dad8dd4221d307e06d Mon Sep 17 00:00:00 2001
a6cb93
From: Jaroslav Kysela <perex@perex.cz>
a6cb93
Date: Tue, 22 Nov 2022 09:59:04 +0100
a6cb93
Subject: [PATCH 11/20] ucm: handle empty string also for ${env:} substitution
a6cb93
a6cb93
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
a6cb93
---
a6cb93
 src/ucm/ucm_subs.c | 8 +++++++-
a6cb93
 1 file changed, 7 insertions(+), 1 deletion(-)
a6cb93
a6cb93
diff --git a/src/ucm/ucm_subs.c b/src/ucm/ucm_subs.c
a6cb93
index 2261bdc2..e62290ea 100644
a6cb93
--- a/src/ucm/ucm_subs.c
a6cb93
+++ b/src/ucm/ucm_subs.c
a6cb93
@@ -490,7 +490,13 @@ static char *rval_env(snd_use_case_mgr_t *uc_mgr ATTRIBUTE_UNUSED, const char *i
a6cb93
 {
a6cb93
 	char *e;
a6cb93
 
a6cb93
-	e = getenv(id);
a6cb93
+	if (*id == '-') {
a6cb93
+		e = getenv(id + 1);
a6cb93
+		if (e == NULL)
a6cb93
+			e = "";
a6cb93
+	} else {
a6cb93
+		e = getenv(id);
a6cb93
+	}
a6cb93
 	if (e)
a6cb93
 		return strdup(e);
a6cb93
 	return NULL;
a6cb93
-- 
a6cb93
2.39.0
a6cb93
a6cb93
a6cb93
From f0f054517c05ff4ef7a1615851a686a3a202b9ff Mon Sep 17 00:00:00 2001
a6cb93
From: Jaroslav Kysela <perex@perex.cz>
a6cb93
Date: Wed, 23 Nov 2022 17:56:20 +0100
a6cb93
Subject: [PATCH 12/20] test: latency - add -y option (I/O usleep)
a6cb93
a6cb93
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
a6cb93
---
a6cb93
 test/latency.c | 13 ++++++++++++-
a6cb93
 1 file changed, 12 insertions(+), 1 deletion(-)
a6cb93
a6cb93
diff --git a/test/latency.c b/test/latency.c
a6cb93
index 3aff37c1..161d1f68 100644
a6cb93
--- a/test/latency.c
a6cb93
+++ b/test/latency.c
a6cb93
@@ -52,6 +52,7 @@ int latency_max = 2048;		/* in frames / 2 */
a6cb93
 int loop_sec = 30;		/* seconds */
a6cb93
 int block = 0;			/* block mode */
a6cb93
 int use_poll = 0;
a6cb93
+int usleep_val = 0;
a6cb93
 int resample = 1;
a6cb93
 int sys_latency = 0;		/* data I/O: use system timings instead driver wakeups */
a6cb93
 int pos_dump = 0;		/* dump positions */
a6cb93
@@ -509,6 +510,8 @@ void help(void)
a6cb93
 "-s,--seconds   duration of test in seconds\n"
a6cb93
 "-b,--block     block mode\n"
a6cb93
 "-p,--poll      use poll (wait for event - reduces CPU usage)\n"
a6cb93
+"-y,--usleep    sleep for the specified amount of microseconds between\n"
a6cb93
+"               stream updates (default 0 - off)\n"
a6cb93
 "-e,--effect    apply an effect (bandpass filter sweep)\n"
a6cb93
 "-x,--posdump   dump buffer positions\n"
a6cb93
 "-X,--realtime  do a realtime check (buffering)\n"
a6cb93
@@ -548,6 +551,7 @@ int main(int argc, char *argv[])
a6cb93
 		{"seconds", 1, NULL, 's'},
a6cb93
 		{"block", 0, NULL, 'b'},
a6cb93
 		{"poll", 0, NULL, 'p'},
a6cb93
+		{"usleep", 1, NULL, 'y'},
a6cb93
 		{"effect", 0, NULL, 'e'},
a6cb93
 		{"posdump", 0, NULL, 'x'},
a6cb93
 		{"realtime", 0, NULL, 'X'},
a6cb93
@@ -565,7 +569,7 @@ int main(int argc, char *argv[])
a6cb93
 	morehelp = 0;
a6cb93
 	while (1) {
a6cb93
 		int c;
a6cb93
-		if ((c = getopt_long(argc, argv, "hP:C:m:M:U:F:f:c:r:B:E:s:bpenxX", long_option, NULL)) < 0)
a6cb93
+		if ((c = getopt_long(argc, argv, "hP:C:m:M:U:F:f:c:r:B:E:s:y:bpenxX", long_option, NULL)) < 0)
a6cb93
 			break;
a6cb93
 		switch (c) {
a6cb93
 		case 'h':
a6cb93
@@ -624,6 +628,9 @@ int main(int argc, char *argv[])
a6cb93
 		case 'p':
a6cb93
 			use_poll = 1;
a6cb93
 			break;
a6cb93
+		case 'y':
a6cb93
+			usleep_val = atoi(optarg);
a6cb93
+			break;
a6cb93
 		case 'e':
a6cb93
 			effect = 1;
a6cb93
 			break;
a6cb93
@@ -671,6 +678,8 @@ int main(int argc, char *argv[])
a6cb93
 			loop_limit, latency_min * 2, latency_max * 2);
a6cb93
 	if (sys_latency > 0)
a6cb93
 		printf(", I/O updates %ims", sys_latency);
a6cb93
+	else if (!block)
a6cb93
+		printf(", I/O usleep %ius", usleep_val);
a6cb93
 	printf("\n");
a6cb93
 
a6cb93
 	if ((err = snd_pcm_open(&phandle, pdevice, SND_PCM_STREAM_PLAYBACK, block ? 0 : SND_PCM_NONBLOCK)) < 0) {
a6cb93
@@ -755,6 +764,8 @@ int main(int argc, char *argv[])
a6cb93
 			} else if (use_poll) {
a6cb93
 				/* use poll to wait for next event */
a6cb93
 				snd_pcm_wait(chandle, 1000);
a6cb93
+			} else if (usleep_val > 0) {
a6cb93
+				usleep(usleep_val);
a6cb93
 			}
a6cb93
 			if (pos_dump || realtime_check) {
a6cb93
 				if (sys_latency <= 0)
a6cb93
-- 
a6cb93
2.39.0
a6cb93
a6cb93
a6cb93
From 536c93928bc57d941a7cd146dbcbd62df0be2d83 Mon Sep 17 00:00:00 2001
a6cb93
From: Jaroslav Kysela <perex@perex.cz>
a6cb93
Date: Wed, 23 Nov 2022 19:45:15 +0100
a6cb93
Subject: [PATCH 13/20] test: latency - usleep should not be used in the block
a6cb93
 mode
a6cb93
a6cb93
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
a6cb93
---
a6cb93
 test/latency.c | 4 ++--
a6cb93
 1 file changed, 2 insertions(+), 2 deletions(-)
a6cb93
a6cb93
diff --git a/test/latency.c b/test/latency.c
a6cb93
index 161d1f68..1b4848d6 100644
a6cb93
--- a/test/latency.c
a6cb93
+++ b/test/latency.c
a6cb93
@@ -678,7 +678,7 @@ int main(int argc, char *argv[])
a6cb93
 			loop_limit, latency_min * 2, latency_max * 2);
a6cb93
 	if (sys_latency > 0)
a6cb93
 		printf(", I/O updates %ims", sys_latency);
a6cb93
-	else if (!block)
a6cb93
+	else if (!block && !use_poll)
a6cb93
 		printf(", I/O usleep %ius", usleep_val);
a6cb93
 	printf("\n");
a6cb93
 
a6cb93
@@ -764,7 +764,7 @@ int main(int argc, char *argv[])
a6cb93
 			} else if (use_poll) {
a6cb93
 				/* use poll to wait for next event */
a6cb93
 				snd_pcm_wait(chandle, 1000);
a6cb93
-			} else if (usleep_val > 0) {
a6cb93
+			} else if (!block && usleep_val > 0) {
a6cb93
 				usleep(usleep_val);
a6cb93
 			}
a6cb93
 			if (pos_dump || realtime_check) {
a6cb93
-- 
a6cb93
2.39.0
a6cb93
a6cb93
a6cb93
From ea0850f3f3780652869c2b4550576894bc21684f Mon Sep 17 00:00:00 2001
a6cb93
From: Jaroslav Kysela <perex@perex.cz>
a6cb93
Date: Thu, 24 Nov 2022 08:33:47 +0100
a6cb93
Subject: [PATCH 14/20] test: latency - add --policy option to allow using
a6cb93
 SCHED_FIFO
a6cb93
a6cb93
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
a6cb93
---
a6cb93
 test/latency.c | 22 +++++++++++++++++-----
a6cb93
 1 file changed, 17 insertions(+), 5 deletions(-)
a6cb93
a6cb93
diff --git a/test/latency.c b/test/latency.c
a6cb93
index 1b4848d6..3b20e1c1 100644
a6cb93
--- a/test/latency.c
a6cb93
+++ b/test/latency.c
a6cb93
@@ -40,6 +40,7 @@
a6cb93
 
a6cb93
 typedef struct timespec timestamp_t;
a6cb93
 
a6cb93
+char *sched_policy = "rr";
a6cb93
 char *pdevice = "hw:0,0";
a6cb93
 char *cdevice = "hw:0,0";
a6cb93
 snd_pcm_format_t format = SND_PCM_FORMAT_S16_LE;
a6cb93
@@ -354,18 +355,24 @@ void gettimestamp(snd_pcm_t *handle, snd_timestamp_t *timestamp)
a6cb93
 void setscheduler(void)
a6cb93
 {
a6cb93
 	struct sched_param sched_param;
a6cb93
+	int policy = SCHED_RR;
a6cb93
+	const char *spolicy = "Round Robin";
a6cb93
 
a6cb93
+	if (strcasecmp(sched_policy, "fifo") == 0) {
a6cb93
+		policy = SCHED_FIFO;
a6cb93
+		spolicy = "FIFO";
a6cb93
+	}
a6cb93
 	if (sched_getparam(0, &sched_param) < 0) {
a6cb93
 		printf("Scheduler getparam failed...\n");
a6cb93
 		return;
a6cb93
 	}
a6cb93
-	sched_param.sched_priority = sched_get_priority_max(SCHED_RR);
a6cb93
-	if (!sched_setscheduler(0, SCHED_RR, &sched_param)) {
a6cb93
-		printf("Scheduler set to Round Robin with priority %i...\n", sched_param.sched_priority);
a6cb93
+	sched_param.sched_priority = sched_get_priority_max(policy);
a6cb93
+	if (!sched_setscheduler(0, policy, &sched_param)) {
a6cb93
+		printf("Scheduler set to %s with priority %i...\n", spolicy, sched_param.sched_priority);
a6cb93
 		fflush(stdout);
a6cb93
 		return;
a6cb93
 	}
a6cb93
-	printf("!!!Scheduler set to Round Robin with priority %i FAILED!!!\n", sched_param.sched_priority);
a6cb93
+	printf("!!!Scheduler set to %s with priority %i FAILED!!!\n", spolicy, sched_param.sched_priority);
a6cb93
 }
a6cb93
 
a6cb93
 long timediff(snd_timestamp_t t1, snd_timestamp_t t2)
a6cb93
@@ -515,6 +522,7 @@ void help(void)
a6cb93
 "-e,--effect    apply an effect (bandpass filter sweep)\n"
a6cb93
 "-x,--posdump   dump buffer positions\n"
a6cb93
 "-X,--realtime  do a realtime check (buffering)\n"
a6cb93
+"-O,--policy    set scheduler policy (RR or FIFO)\n"
a6cb93
 );
a6cb93
         printf("Recognized sample formats are:");
a6cb93
         for (k = 0; k < SND_PCM_FORMAT_LAST; ++k) {
a6cb93
@@ -555,6 +563,7 @@ int main(int argc, char *argv[])
a6cb93
 		{"effect", 0, NULL, 'e'},
a6cb93
 		{"posdump", 0, NULL, 'x'},
a6cb93
 		{"realtime", 0, NULL, 'X'},
a6cb93
+		{"policy", 1, NULL, 'O'},
a6cb93
 		{NULL, 0, NULL, 0},
a6cb93
 	};
a6cb93
 	snd_pcm_t *phandle, *chandle;
a6cb93
@@ -569,7 +578,7 @@ int main(int argc, char *argv[])
a6cb93
 	morehelp = 0;
a6cb93
 	while (1) {
a6cb93
 		int c;
a6cb93
-		if ((c = getopt_long(argc, argv, "hP:C:m:M:U:F:f:c:r:B:E:s:y:bpenxX", long_option, NULL)) < 0)
a6cb93
+		if ((c = getopt_long(argc, argv, "hP:C:m:M:U:F:f:c:r:B:E:s:y:O:bpenxX", long_option, NULL)) < 0)
a6cb93
 			break;
a6cb93
 		switch (c) {
a6cb93
 		case 'h':
a6cb93
@@ -643,6 +652,9 @@ int main(int argc, char *argv[])
a6cb93
 		case 'X':
a6cb93
 			realtime_check = 1;
a6cb93
 			break;
a6cb93
+		case 'O':
a6cb93
+			sched_policy = optarg;
a6cb93
+			break;
a6cb93
 		}
a6cb93
 	}
a6cb93
 
a6cb93
-- 
a6cb93
2.39.0
a6cb93
a6cb93
a6cb93
From 75f8e2e73e03f628a4f2ba55ca8aa3e9f50cdbd9 Mon Sep 17 00:00:00 2001
a6cb93
From: Jaroslav Kysela <perex@perex.cz>
a6cb93
Date: Thu, 24 Nov 2022 10:55:32 +0100
a6cb93
Subject: [PATCH 15/20] test: latency - --policy option - allow using
a6cb93
 SCHED_OTHER
a6cb93
a6cb93
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
a6cb93
---
a6cb93
 test/latency.c | 5 ++++-
a6cb93
 1 file changed, 4 insertions(+), 1 deletion(-)
a6cb93
a6cb93
diff --git a/test/latency.c b/test/latency.c
a6cb93
index 3b20e1c1..5e67015c 100644
a6cb93
--- a/test/latency.c
a6cb93
+++ b/test/latency.c
a6cb93
@@ -361,6 +361,9 @@ void setscheduler(void)
a6cb93
 	if (strcasecmp(sched_policy, "fifo") == 0) {
a6cb93
 		policy = SCHED_FIFO;
a6cb93
 		spolicy = "FIFO";
a6cb93
+	} else if (strcasecmp(sched_policy, "other") == 0) {
a6cb93
+		policy = SCHED_OTHER;
a6cb93
+		spolicy = "OTHER";
a6cb93
 	}
a6cb93
 	if (sched_getparam(0, &sched_param) < 0) {
a6cb93
 		printf("Scheduler getparam failed...\n");
a6cb93
@@ -522,7 +525,7 @@ void help(void)
a6cb93
 "-e,--effect    apply an effect (bandpass filter sweep)\n"
a6cb93
 "-x,--posdump   dump buffer positions\n"
a6cb93
 "-X,--realtime  do a realtime check (buffering)\n"
a6cb93
-"-O,--policy    set scheduler policy (RR or FIFO)\n"
a6cb93
+"-O,--policy    set scheduler policy (RR, FIFO or OTHER)\n"
a6cb93
 );
a6cb93
         printf("Recognized sample formats are:");
a6cb93
         for (k = 0; k < SND_PCM_FORMAT_LAST; ++k) {
a6cb93
-- 
a6cb93
2.39.0
a6cb93
a6cb93
a6cb93
From d28e8cb29485cc93f741b01dc65893c798359963 Mon Sep 17 00:00:00 2001
a6cb93
From: Jaroslav Kysela <perex@perex.cz>
a6cb93
Date: Tue, 29 Nov 2022 19:42:13 +0100
a6cb93
Subject: [PATCH 16/20] topology: ctl - remove the wrong (debug) code
a6cb93
a6cb93
This code was commited by mistake. It was used for testing
a6cb93
of ALSA_PCM_OLD_HW/SW_PARAMS_API.
a6cb93
a6cb93
BugLink: https://github.com/thesofproject/sof/issues/6667
a6cb93
Related-to: 78b20e3c ("test: latency - use snd_pcm_format_physical_width()")
a6cb93
Reported-by: Jaska Uimonen <jaska.uimonen@linux.intel.com>
a6cb93
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
a6cb93
---
a6cb93
 src/topology/ctl.c | 7 +------
a6cb93
 1 file changed, 1 insertion(+), 6 deletions(-)
a6cb93
a6cb93
diff --git a/src/topology/ctl.c b/src/topology/ctl.c
a6cb93
index 2c500ffc..dd05424d 100644
a6cb93
--- a/src/topology/ctl.c
a6cb93
+++ b/src/topology/ctl.c
a6cb93
@@ -17,13 +17,9 @@
a6cb93
            Liam Girdwood <liam.r.girdwood@linux.intel.com>
a6cb93
 */
a6cb93
 
a6cb93
-#define ALSA_PCM_OLD_HW_PARAMS_API 1
a6cb93
-#define ALSA_PCM_OLD_SW_PARAMS_API 1
a6cb93
-#include "../../include/asoundlib.h"
a6cb93
 #include "list.h"
a6cb93
 #include "tplg_local.h"
a6cb93
 
a6cb93
-
a6cb93
 #define ENUM_VAL_SIZE 	(SNDRV_CTL_ELEM_ID_NAME_MAXLEN >> 2)
a6cb93
 
a6cb93
 struct ctl_access_elem {
a6cb93
@@ -75,8 +71,7 @@ static int parse_access_values(snd_config_t *cfg,
a6cb93
 			}
a6cb93
 		}
a6cb93
 	}
a6cb93
-	return snd_pcm_hw_params_get_channels(NULL);
a6cb93
-	//return snd_pcm_hw_params_get_access(NULL);
a6cb93
+
a6cb93
 	return 0;
a6cb93
 }
a6cb93
 
a6cb93
-- 
a6cb93
2.39.0
a6cb93
a6cb93
a6cb93
From e29413a2205099b2bffe584210d7a2b59f531f90 Mon Sep 17 00:00:00 2001
a6cb93
From: Jaroslav Kysela <perex@perex.cz>
a6cb93
Date: Wed, 7 Dec 2022 14:49:48 +0100
a6cb93
Subject: [PATCH 17/20] ucm: execute_sysw - fix possible use-after-free
a6cb93
a6cb93
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
a6cb93
---
a6cb93
 src/ucm/main.c | 5 +++--
a6cb93
 1 file changed, 3 insertions(+), 2 deletions(-)
a6cb93
a6cb93
diff --git a/src/ucm/main.c b/src/ucm/main.c
a6cb93
index 4f36648c..2ff4d3f3 100644
a6cb93
--- a/src/ucm/main.c
a6cb93
+++ b/src/ucm/main.c
a6cb93
@@ -572,16 +572,17 @@ static int execute_sysw(const char *sysw)
a6cb93
 	wlen = write(fd, value, len);
a6cb93
 	myerrno = errno;
a6cb93
 	close(fd);
a6cb93
-	free(s);
a6cb93
 
a6cb93
 	if (ignore_error)
a6cb93
-		return 0;
a6cb93
+		goto __end;
a6cb93
 
a6cb93
 	if (wlen != (ssize_t)len) {
a6cb93
 		uc_error("unable to write '%s' to '%s': %s", value, path, strerror(myerrno));
a6cb93
 		return -EINVAL;
a6cb93
 	}
a6cb93
 
a6cb93
+__end:
a6cb93
+	free(s);
a6cb93
 	return 0;
a6cb93
 }
a6cb93
 
a6cb93
-- 
a6cb93
2.39.0
a6cb93
a6cb93
a6cb93
From 13e31fb1ecd5f666ffda09e87ef1aa53b4fae022 Mon Sep 17 00:00:00 2001
a6cb93
From: Jaroslav Kysela <perex@perex.cz>
a6cb93
Date: Wed, 7 Dec 2022 14:54:30 +0100
a6cb93
Subject: [PATCH 18/20] alsa-lib: conf - fix possible use-after-free in
a6cb93
 get_char_skip_comments
a6cb93
a6cb93
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
a6cb93
---
a6cb93
 src/conf.c | 3 ++-
a6cb93
 1 file changed, 2 insertions(+), 1 deletion(-)
a6cb93
a6cb93
diff --git a/src/conf.c b/src/conf.c
a6cb93
index eb38c344..65f2e1a7 100644
a6cb93
--- a/src/conf.c
a6cb93
+++ b/src/conf.c
a6cb93
@@ -814,11 +814,12 @@ static int get_char_skip_comments(input_t *input)
a6cb93
 				closedir(dirp);
a6cb93
 
a6cb93
 				err = add_include_path(input->current, str);
a6cb93
-				free(str);
a6cb93
 				if (err < 0) {
a6cb93
 					SNDERR("Cannot add search dir %s", str);
a6cb93
+					free(str);
a6cb93
 					return err;
a6cb93
 				}
a6cb93
+				free(str);
a6cb93
 				continue;
a6cb93
 			}
a6cb93
 
a6cb93
-- 
a6cb93
2.39.0
a6cb93
a6cb93
a6cb93
From 9f2c68cef716aa45942b502a42d94b84289f23bc Mon Sep 17 00:00:00 2001
a6cb93
From: Jaroslav Kysela <perex@perex.cz>
a6cb93
Date: Tue, 13 Dec 2022 10:31:32 +0100
a6cb93
Subject: [PATCH 19/20] pcm: route/softvol use snd_config_get_ireal vs get_real
a6cb93
 to handle also integers
a6cb93
a6cb93
Link: https://lore.kernel.org/alsa-devel/f9a7ad6a256d4ad7a31642dcf875d436@axis.com/
a6cb93
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
a6cb93
---
a6cb93
 src/pcm/pcm_route.c   | 11 +++--------
a6cb93
 src/pcm/pcm_softvol.c |  4 ++--
a6cb93
 2 files changed, 5 insertions(+), 10 deletions(-)
a6cb93
a6cb93
diff --git a/src/pcm/pcm_route.c b/src/pcm/pcm_route.c
a6cb93
index d3e5f3ff..21b869cc 100644
a6cb93
--- a/src/pcm/pcm_route.c
a6cb93
+++ b/src/pcm/pcm_route.c
a6cb93
@@ -1182,15 +1182,10 @@ static int _snd_pcm_route_load_ttable(snd_config_t *tt, snd_pcm_route_ttable_ent
a6cb93
 				return -EINVAL;
a6cb93
 			}
a6cb93
 
a6cb93
-			err = snd_config_get_real(jnode, &value);
a6cb93
+			err = snd_config_get_ireal(jnode, &value);
a6cb93
 			if (err < 0) {
a6cb93
-				long v;
a6cb93
-				err = snd_config_get_integer(jnode, &v);
a6cb93
-				if (err < 0) {
a6cb93
-					SNDERR("Invalid type for %s", id);
a6cb93
-					return -EINVAL;
a6cb93
-				}
a6cb93
-				value = v;
a6cb93
+				SNDERR("Invalid type for %s", id);
a6cb93
+				return -EINVAL;
a6cb93
 			}
a6cb93
 
a6cb93
 			for (k = 0; (int) k < ss; k++) {
a6cb93
diff --git a/src/pcm/pcm_softvol.c b/src/pcm/pcm_softvol.c
a6cb93
index 99d0d32e..3e3dbc79 100644
a6cb93
--- a/src/pcm/pcm_softvol.c
a6cb93
+++ b/src/pcm/pcm_softvol.c
a6cb93
@@ -1190,7 +1190,7 @@ int _snd_pcm_softvol_open(snd_pcm_t **pcmp, const char *name,
a6cb93
 			continue;
a6cb93
 		}
a6cb93
 		if (strcmp(id, "min_dB") == 0) {
a6cb93
-			err = snd_config_get_real(n, &min_dB);
a6cb93
+			err = snd_config_get_ireal(n, &min_dB);
a6cb93
 			if (err < 0) {
a6cb93
 				SNDERR("Invalid min_dB value");
a6cb93
 				return err;
a6cb93
@@ -1198,7 +1198,7 @@ int _snd_pcm_softvol_open(snd_pcm_t **pcmp, const char *name,
a6cb93
 			continue;
a6cb93
 		}
a6cb93
 		if (strcmp(id, "max_dB") == 0) {
a6cb93
-			err = snd_config_get_real(n, &max_dB);
a6cb93
+			err = snd_config_get_ireal(n, &max_dB);
a6cb93
 			if (err < 0) {
a6cb93
 				SNDERR("Invalid max_dB value");
a6cb93
 				return err;
a6cb93
-- 
a6cb93
2.39.0
a6cb93
a6cb93
a6cb93
From 2e82060ebcd68f5ea1fe3dccc5a6518008132a54 Mon Sep 17 00:00:00 2001
a6cb93
From: Alan Young <consult.awy@gmail.com>
a6cb93
Date: Fri, 30 Dec 2022 16:48:14 +0000
a6cb93
Subject: [PATCH 20/20] pcm: rate: fix last_commit_ptr boundary wrapping
a6cb93
a6cb93
Wrap last_commit_ptr using boundary. Was just wrapped to 0, which is
a6cb93
correct only if the buffer size, and hence the boundary, is an integer
a6cb93
multiple of the period size.
a6cb93
a6cb93
Fixes: 467d69c5bc1 ("Fix CPU hog with combination of rate plugin")
a6cb93
Fixes: 29041c52207 ("fix infinite draining of the rate plugin in SND_PCM_NONBLOCK mode")
a6cb93
Link: https://lore.kernel.org/alsa-devel/20221230164814.901457-1-consult.awy@gmail.com/
a6cb93
Signed-off-by: Alan Young <consult.awy@gmail.com>
a6cb93
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
a6cb93
---
a6cb93
 src/pcm/pcm_rate.c | 4 ++--
a6cb93
 1 file changed, 2 insertions(+), 2 deletions(-)
a6cb93
a6cb93
diff --git a/src/pcm/pcm_rate.c b/src/pcm/pcm_rate.c
a6cb93
index e5d8eddd..c8076859 100644
a6cb93
--- a/src/pcm/pcm_rate.c
a6cb93
+++ b/src/pcm/pcm_rate.c
a6cb93
@@ -1018,7 +1018,7 @@ static int snd_pcm_rate_sync_playback_area(snd_pcm_t *pcm, snd_pcm_uframes_t app
a6cb93
 		slave_size -= rate->gen.slave->period_size;
a6cb93
 		rate->last_commit_ptr += pcm->period_size;
a6cb93
 		if (rate->last_commit_ptr >= pcm->boundary)
a6cb93
-			rate->last_commit_ptr = 0;
a6cb93
+			rate->last_commit_ptr -= pcm->boundary;
a6cb93
 	}
a6cb93
 	return 0;
a6cb93
 }
a6cb93
@@ -1163,7 +1163,7 @@ static int snd_pcm_rate_drain(snd_pcm_t *pcm)
a6cb93
 			if (commit_err == 1) {
a6cb93
 				rate->last_commit_ptr += psize;
a6cb93
 				if (rate->last_commit_ptr >= pcm->boundary)
a6cb93
-					rate->last_commit_ptr = 0;
a6cb93
+					rate->last_commit_ptr -= pcm->boundary;
a6cb93
 			} else if (commit_err == 0) {
a6cb93
 				if (pcm->mode & SND_PCM_NONBLOCK) {
a6cb93
 					commit_err = -EAGAIN;
a6cb93
-- 
a6cb93
2.39.0
a6cb93