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