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