Blame SOURCES/alsa-lib-1.1.3-post.patch

b63a84
From 6ad2a9763d9aaab30c0470d039877b1bb61dda3b Mon Sep 17 00:00:00 2001
b63a84
From: Mengdong Lin <mengdong.lin@linux.intel.com>
b63a84
Date: Tue, 27 Dec 2016 18:08:58 +0800
b63a84
Subject: [PATCH 01/37] ucm: Add ATTRIBUTE_UNUSED for unused parameters of
b63a84
 execute_component_seq()
b63a84
MIME-Version: 1.0
b63a84
Content-Type: text/plain; charset=UTF-8
b63a84
Content-Transfer-Encoding: 8bit
b63a84
b63a84
To fix the following warnings:
b63a84
b63a84
main.c: In function ‘execute_component_seq’:
b63a84
main.c:489:24: warning: unused parameter ‘value_list1’ [-Wunused-parameter]
b63a84
      struct list_head *value_list1,
b63a84
                        ^
b63a84
main.c:490:24: warning: unused parameter ‘value_list2’ [-Wunused-parameter]
b63a84
      struct list_head *value_list2,
b63a84
                        ^
b63a84
main.c:491:24: warning: unused parameter ‘value_list3’ [-Wunused-parameter]
b63a84
      struct list_head *value_list3,
b63a84
                        ^
b63a84
b63a84
Signed-off-by: Mengdong Lin <mengdong.lin@linux.intel.com>
b63a84
Signed-off-by: Takashi Iwai <tiwai@suse.de>
b63a84
---
b63a84
 src/ucm/main.c | 6 +++---
b63a84
 1 file changed, 3 insertions(+), 3 deletions(-)
b63a84
b63a84
diff --git a/src/ucm/main.c b/src/ucm/main.c
b63a84
index 750e65d..38a5e81 100644
b63a84
--- a/src/ucm/main.c
b63a84
+++ b/src/ucm/main.c
b63a84
@@ -486,9 +486,9 @@ static int execute_sequence(snd_use_case_mgr_t *uc_mgr,
b63a84
  */
b63a84
 static int execute_component_seq(snd_use_case_mgr_t *uc_mgr,
b63a84
 				 struct component_sequence *cmpt_seq,
b63a84
-				 struct list_head *value_list1,
b63a84
-				 struct list_head *value_list2,
b63a84
-				 struct list_head *value_list3,
b63a84
+				 struct list_head *value_list1 ATTRIBUTE_UNUSED,
b63a84
+				 struct list_head *value_list2 ATTRIBUTE_UNUSED,
b63a84
+				 struct list_head *value_list3 ATTRIBUTE_UNUSED,
b63a84
 				 char *cdev)
b63a84
 {
b63a84
 	struct use_case_device *device = cmpt_seq->device;
b63a84
-- 
b63a84
2.9.3
b63a84
b63a84
b63a84
From 9ed4075f05a4242f32331f7f2c365767970f5003 Mon Sep 17 00:00:00 2001
b63a84
From: Gustavo Zacarias <gustavo@zacarias.com.ar>
b63a84
Date: Wed, 21 Dec 2016 19:46:34 -0300
b63a84
Subject: [PATCH 02/37] ucm: parser needs limits.h
b63a84
b63a84
It's using PATH_MAX which is defined there, otherwise the build fails on
b63a84
musl libc.
b63a84
b63a84
Signed-off-by: Gustavo Zacarias <gustavo@zacarias.com.ar>
b63a84
Signed-off-by: Takashi Iwai <tiwai@suse.de>
b63a84
---
b63a84
 src/ucm/parser.c | 1 +
b63a84
 1 file changed, 1 insertion(+)
b63a84
b63a84
diff --git a/src/ucm/parser.c b/src/ucm/parser.c
b63a84
index c98373a..f520abc 100644
b63a84
--- a/src/ucm/parser.c
b63a84
+++ b/src/ucm/parser.c
b63a84
@@ -32,6 +32,7 @@
b63a84
 
b63a84
 #include "ucm_local.h"
b63a84
 #include <dirent.h>
b63a84
+#include <limits.h>
b63a84
 
b63a84
 /** The name of the environment variable containing the UCM directory */
b63a84
 #define ALSA_CONFIG_UCM_VAR "ALSA_CONFIG_UCM"
b63a84
-- 
b63a84
2.9.3
b63a84
b63a84
b63a84
From 0a61c796810fcec8b386e5311e871b1744b45a67 Mon Sep 17 00:00:00 2001
b63a84
From: Joshua Frkuska <joshua_frkuska@mentor.com>
b63a84
Date: Fri, 30 Dec 2016 11:56:15 +0530
b63a84
Subject: [PATCH 03/37] pcm: direct: allow users to configure different period
b63a84
 sizes
b63a84
b63a84
This patch allows the effective period size to be a multiple of the
b63a84
slave-pcm period size.
b63a84
Allowing only exact multiple of original period size is achieved by
b63a84
borrowing code from the kernel hwrules implementation.
b63a84
b63a84
This patch is intended to save cpu workload when for example, the
b63a84
slave operates with very small periods but a user does not need that
b63a84
small periods.
b63a84
b63a84
This feature is enabled by default and can be disabled by adding
b63a84
config option 'var_periodsize 0'.
b63a84
b63a84
Signed-off-by: Alexander Jahn <ajahn@de.adit-jv.com>
b63a84
Signed-off-by: Andreas Pape <apape@de.adit-jv.com>
b63a84
Signed-off-by: Takashi Iwai <tiwai@suse.de>
b63a84
---
b63a84
 src/pcm/pcm_direct.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++------
b63a84
 src/pcm/pcm_direct.h |  3 ++
b63a84
 src/pcm/pcm_dmix.c   |  1 +
b63a84
 src/pcm/pcm_dshare.c |  1 +
b63a84
 src/pcm/pcm_dsnoop.c |  1 +
b63a84
 5 files changed, 84 insertions(+), 10 deletions(-)
b63a84
b63a84
diff --git a/src/pcm/pcm_direct.c b/src/pcm/pcm_direct.c
b63a84
index 6434983..f5d922f 100644
b63a84
--- a/src/pcm/pcm_direct.c
b63a84
+++ b/src/pcm/pcm_direct.c
b63a84
@@ -660,6 +660,29 @@ static int hw_param_interval_refine_minmax(snd_pcm_hw_params_t *params,
b63a84
 	return hw_param_interval_refine_one(params, var, &t);
b63a84
 }
b63a84
 
b63a84
+/* this code is used 'as-is' from the alsa kernel code */
b63a84
+static int snd_interval_step(struct snd_interval *i, unsigned int min,
b63a84
+			     unsigned int step)
b63a84
+{
b63a84
+	unsigned int n;
b63a84
+	int changed = 0;
b63a84
+	n = (i->min - min) % step;
b63a84
+	if (n != 0 || i->openmin) {
b63a84
+		i->min += step - n;
b63a84
+		changed = 1;
b63a84
+	}
b63a84
+	n = (i->max - min) % step;
b63a84
+	if (n != 0 || i->openmax) {
b63a84
+		i->max -= n;
b63a84
+		changed = 1;
b63a84
+	}
b63a84
+	if (snd_interval_checkempty(i)) {
b63a84
+		i->empty = 1;
b63a84
+		return -EINVAL;
b63a84
+	}
b63a84
+	return changed;
b63a84
+}
b63a84
+
b63a84
 #undef REFINE_DEBUG
b63a84
 
b63a84
 int snd_pcm_direct_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
b63a84
@@ -710,15 +733,16 @@ int snd_pcm_direct_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
b63a84
 					   &dshare->shmptr->hw.rate);
b63a84
 	if (err < 0)
b63a84
 		return err;
b63a84
-	err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_PERIOD_SIZE,
b63a84
-					   &dshare->shmptr->hw.period_size);
b63a84
-	if (err < 0)
b63a84
-		return err;
b63a84
-	err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_PERIOD_TIME,
b63a84
-					   &dshare->shmptr->hw.period_time);
b63a84
-	if (err < 0)
b63a84
-		return err;
b63a84
+
b63a84
 	if (dshare->max_periods < 0) {
b63a84
+		err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_PERIOD_SIZE,
b63a84
+						   &dshare->shmptr->hw.period_size);
b63a84
+		if (err < 0)
b63a84
+			return err;
b63a84
+		err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_PERIOD_TIME,
b63a84
+						   &dshare->shmptr->hw.period_time);
b63a84
+		if (err < 0)
b63a84
+			return err;
b63a84
 		err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_BUFFER_SIZE,
b63a84
 						   &dshare->shmptr->hw.buffer_size);
b63a84
 		if (err < 0)
b63a84
@@ -730,11 +754,38 @@ int snd_pcm_direct_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
b63a84
 	} else if (params->rmask & ((1<
b63a84
 				    (1<
b63a84
 				    (1<
b63a84
-				    (1<
b63a84
+				    (1<
b63a84
+				    (1<
b63a84
+				    (1<
b63a84
+				    (1<
b63a84
+		snd_interval_t period_size = dshare->shmptr->hw.period_size;
b63a84
+		snd_interval_t period_time = dshare->shmptr->hw.period_time;
b63a84
 		int changed;
b63a84
 		unsigned int max_periods = dshare->max_periods;
b63a84
 		if (max_periods < 2)
b63a84
 			max_periods = dshare->slave_buffer_size / dshare->slave_period_size;
b63a84
+
b63a84
+		/* make sure buffer size does not exceed slave buffer size */
b63a84
+		err = hw_param_interval_refine_minmax(params, SND_PCM_HW_PARAM_BUFFER_SIZE,
b63a84
+					2 * dshare->slave_period_size, dshare->slave_buffer_size);
b63a84
+		if (err < 0)
b63a84
+			return err;
b63a84
+		if (dshare->var_periodsize) {
b63a84
+			/* more tolerant settings... */
b63a84
+			if (dshare->shmptr->hw.buffer_size.max / 2 > period_size.max)
b63a84
+				period_size.max = dshare->shmptr->hw.buffer_size.max / 2;
b63a84
+			if (dshare->shmptr->hw.buffer_time.max / 2 > period_time.max)
b63a84
+				period_time.max = dshare->shmptr->hw.buffer_time.max / 2;
b63a84
+		}
b63a84
+
b63a84
+		err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_PERIOD_SIZE,
b63a84
+						   &period_size);
b63a84
+		if (err < 0)
b63a84
+			return err;
b63a84
+		err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_PERIOD_TIME,
b63a84
+						   &period_time);
b63a84
+		if (err < 0)
b63a84
+			return err;
b63a84
 		do {
b63a84
 			changed = 0;
b63a84
 			err = hw_param_interval_refine_minmax(params, SND_PCM_HW_PARAM_PERIODS,
b63a84
@@ -746,8 +797,16 @@ int snd_pcm_direct_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
b63a84
 			if (err < 0)
b63a84
 				return err;
b63a84
 			changed |= err;
b63a84
+			err = snd_interval_step(hw_param_interval(params, SND_PCM_HW_PARAM_PERIOD_SIZE),
b63a84
+								0, dshare->slave_period_size);
b63a84
+			if (err < 0)
b63a84
+				return err;
b63a84
+			changed |= err;
b63a84
+			if (err)
b63a84
+				params->rmask |= (1 << SND_PCM_HW_PARAM_PERIOD_SIZE);
b63a84
 		} while (changed);
b63a84
 	}
b63a84
+	dshare->timer_ticks = hw_param_interval(params, SND_PCM_HW_PARAM_PERIOD_SIZE)->max / dshare->slave_period_size;
b63a84
 	params->info = dshare->shmptr->s.info;
b63a84
 #ifdef REFINE_DEBUG
b63a84
 	snd_output_puts(log, "DMIX REFINE (end):\n");
b63a84
@@ -1183,6 +1242,7 @@ int snd_pcm_direct_initialize_poll_fd(snd_pcm_direct_t *dmix)
b63a84
 
b63a84
 	dmix->tread = 1;
b63a84
 	dmix->timer_need_poll = 0;
b63a84
+	dmix->timer_ticks = 1;
b63a84
 	ret = snd_pcm_info(dmix->spcm, &info;;
b63a84
 	if (ret < 0) {
b63a84
 		SNDERR("unable to info for slave pcm");
b63a84
@@ -1366,7 +1426,7 @@ int snd_pcm_direct_set_timer_params(snd_pcm_direct_t *dmix)
b63a84
 	snd_timer_params_set_auto_start(&params, 1);
b63a84
 	if (dmix->type != SND_PCM_TYPE_DSNOOP)
b63a84
 		snd_timer_params_set_early_event(&params, 1);
b63a84
-	snd_timer_params_set_ticks(&params, 1);
b63a84
+	snd_timer_params_set_ticks(&params, dmix->timer_ticks);
b63a84
 	if (dmix->tread) {
b63a84
 		filter = (1<
b63a84
 			 dmix->timer_events;
b63a84
@@ -1656,6 +1716,7 @@ int snd_pcm_direct_parse_open_conf(snd_config_t *root, snd_config_t *conf,
b63a84
 	rec->ipc_gid = -1;
b63a84
 	rec->slowptr = 1;
b63a84
 	rec->max_periods = 0;
b63a84
+	rec->var_periodsize = 1;
b63a84
 
b63a84
 	/* read defaults */
b63a84
 	if (snd_config_search(root, "defaults.pcm.dmix_max_periods", &n) >= 0) {
b63a84
@@ -1762,6 +1823,13 @@ int snd_pcm_direct_parse_open_conf(snd_config_t *root, snd_config_t *conf,
b63a84
 			rec->max_periods = val;
b63a84
 			continue;
b63a84
 		}
b63a84
+		if (strcmp(id, "var_periodsize") == 0) {
b63a84
+			err = snd_config_get_bool(n);
b63a84
+			if (err < 0)
b63a84
+				return err;
b63a84
+			rec->var_periodsize = err;
b63a84
+			continue;
b63a84
+		}
b63a84
 		SNDERR("Unknown field %s", id);
b63a84
 		return -EINVAL;
b63a84
 	}
b63a84
diff --git a/src/pcm/pcm_direct.h b/src/pcm/pcm_direct.h
b63a84
index 611ad29..91e816c 100644
b63a84
--- a/src/pcm/pcm_direct.h
b63a84
+++ b/src/pcm/pcm_direct.h
b63a84
@@ -147,12 +147,14 @@ struct snd_pcm_direct {
b63a84
 	int tread: 1;
b63a84
 	int timer_need_poll: 1;
b63a84
 	unsigned int timer_events;
b63a84
+	unsigned int timer_ticks;
b63a84
 	int server_fd;
b63a84
 	pid_t server_pid;
b63a84
 	snd_timer_t *timer; 		/* timer used as poll_fd */
b63a84
 	int interleaved;	 	/* we have interleaved buffer */
b63a84
 	int slowptr;			/* use slow but more precise ptr updates */
b63a84
 	int max_periods;		/* max periods (-1 = fixed periods, 0 = max buffer size) */
b63a84
+	int var_periodsize;		/* allow variable period size if max_periods is != -1*/
b63a84
 	unsigned int channels;		/* client's channels */
b63a84
 	unsigned int *bindings;
b63a84
 	union {
b63a84
@@ -326,6 +328,7 @@ struct snd_pcm_direct_open_conf {
b63a84
 	int ipc_gid;
b63a84
 	int slowptr;
b63a84
 	int max_periods;
b63a84
+	int var_periodsize;
b63a84
 	snd_config_t *slave;
b63a84
 	snd_config_t *bindings;
b63a84
 };
b63a84
diff --git a/src/pcm/pcm_dmix.c b/src/pcm/pcm_dmix.c
b63a84
index 825677f..0ab7323 100644
b63a84
--- a/src/pcm/pcm_dmix.c
b63a84
+++ b/src/pcm/pcm_dmix.c
b63a84
@@ -1040,6 +1040,7 @@ int snd_pcm_dmix_open(snd_pcm_t **pcmp, const char *name,
b63a84
 	dmix->state = SND_PCM_STATE_OPEN;
b63a84
 	dmix->slowptr = opts->slowptr;
b63a84
 	dmix->max_periods = opts->max_periods;
b63a84
+	dmix->var_periodsize = opts->var_periodsize;
b63a84
 	dmix->sync_ptr = snd_pcm_dmix_sync_ptr;
b63a84
 
b63a84
  retry:
b63a84
diff --git a/src/pcm/pcm_dshare.c b/src/pcm/pcm_dshare.c
b63a84
index 29cd6c6..a1fed5d 100644
b63a84
--- a/src/pcm/pcm_dshare.c
b63a84
+++ b/src/pcm/pcm_dshare.c
b63a84
@@ -725,6 +725,7 @@ int snd_pcm_dshare_open(snd_pcm_t **pcmp, const char *name,
b63a84
 	dshare->state = SND_PCM_STATE_OPEN;
b63a84
 	dshare->slowptr = opts->slowptr;
b63a84
 	dshare->max_periods = opts->max_periods;
b63a84
+	dshare->var_periodsize = opts->var_periodsize;
b63a84
 	dshare->sync_ptr = snd_pcm_dshare_sync_ptr;
b63a84
 
b63a84
  retry:
b63a84
diff --git a/src/pcm/pcm_dsnoop.c b/src/pcm/pcm_dsnoop.c
b63a84
index 1aedf3c..85f0ff4 100644
b63a84
--- a/src/pcm/pcm_dsnoop.c
b63a84
+++ b/src/pcm/pcm_dsnoop.c
b63a84
@@ -606,6 +606,7 @@ int snd_pcm_dsnoop_open(snd_pcm_t **pcmp, const char *name,
b63a84
 	dsnoop->state = SND_PCM_STATE_OPEN;
b63a84
 	dsnoop->slowptr = opts->slowptr;
b63a84
 	dsnoop->max_periods = opts->max_periods;
b63a84
+	dsnoop->var_periodsize = opts->var_periodsize;
b63a84
 	dsnoop->sync_ptr = snd_pcm_dsnoop_sync_ptr;
b63a84
 
b63a84
  retry:
b63a84
-- 
b63a84
2.9.3
b63a84
b63a84
b63a84
From 8eeee1ab7d7db3110b7b3bb31cfb989304dced94 Mon Sep 17 00:00:00 2001
b63a84
From: Alexander Jahn <ajahn@de.adit-jv.com>
b63a84
Date: Fri, 30 Dec 2016 11:59:11 +0530
b63a84
Subject: [PATCH 04/37] pcm: dshare: enable silence
b63a84
b63a84
This issue depends on system load - if the process using dshare is
b63a84
scheduled fast enough, then there is no noise. A delay of e.g >~2ms
b63a84
produces hearable noise.
b63a84
b63a84
Reproduction with instrumented aplay(sleep every 100th period for a
b63a84
given time):
b63a84
During the sleep time of 2000000us (2s) the hardware plays old samples
b63a84
in a loop before xrun is detected and recovered after the sleep.
b63a84
This is resolved by placing it in silence, in case of dshare plugin.
b63a84
b63a84
Signed-off-by: Alexander Jahn <ajahn@de.adit-jv.com>
b63a84
Signed-off-by: Andreas Pape <apape@de.adit-jv.com>
b63a84
Signed-off-by: Takashi Iwai <tiwai@suse.de>
b63a84
---
b63a84
 src/pcm/pcm_direct.c | 3 ++-
b63a84
 1 file changed, 2 insertions(+), 1 deletion(-)
b63a84
b63a84
diff --git a/src/pcm/pcm_direct.c b/src/pcm/pcm_direct.c
b63a84
index f5d922f..0770abc 100644
b63a84
--- a/src/pcm/pcm_direct.c
b63a84
+++ b/src/pcm/pcm_direct.c
b63a84
@@ -1161,7 +1161,8 @@ int snd_pcm_direct_initialize_slave(snd_pcm_direct_t *dmix, snd_pcm_t *spcm, str
b63a84
 		return ret;
b63a84
 	}
b63a84
 
b63a84
-	if (dmix->type != SND_PCM_TYPE_DMIX)
b63a84
+	if (dmix->type != SND_PCM_TYPE_DMIX &&
b63a84
+	    dmix->type != SND_PCM_TYPE_DSHARE)
b63a84
 		goto __skip_silencing;
b63a84
 
b63a84
 	ret = snd_pcm_sw_params_set_silence_threshold(spcm, &sw_params, 0);
b63a84
-- 
b63a84
2.9.3
b63a84
b63a84
b63a84
From 7570e5d77514d8d8af387da04a010fa2ccaf543c Mon Sep 17 00:00:00 2001
b63a84
From: "mahendran.k" <mahendran.kuppusamy@in.bosch.com>
b63a84
Date: Fri, 30 Dec 2016 11:59:27 +0530
b63a84
Subject: [PATCH 05/37] pcm: rate: fix the hw_ptr update until the boundary
b63a84
 available
b63a84
b63a84
For long time test case, the slave_hw_ptr will exceed the boundary
b63a84
and wraparound the slave_hw_ptr. This slave boundary wraparound will
b63a84
cause the rate->hw_ptr to wraparound irrespective of the
b63a84
rate->boundary availability and due to that the available size goes
b63a84
wrong.
b63a84
b63a84
Hence, to get the correct available size,
b63a84
- Its necessary to increment the rate->hw_ptr upto the rate->boundary
b63a84
and then wraparound the rate->hw_ptr.
b63a84
- While handling fraction part of slave period, rounded value will be
b63a84
introduced by input_frames(). To eliminate rounding issue on
b63a84
rate->hw_ptr, subtract last rounded value from rate->hw_ptr and add
b63a84
new rounded value of present slave_hw_ptr fraction part to
b63a84
rate->hw_ptr.
b63a84
b63a84
Signed-off-by: mahendran.k <mahendran.kuppusamy@in.bosch.com>
b63a84
Signed-off-by: Mounesh Sutar <mounesh_sutar@mentor.com>
b63a84
Signed-off-by: Takashi Iwai <tiwai@suse.de>
b63a84
---
b63a84
 src/pcm/pcm_rate.c | 31 +++++++++++++++++++++++++------
b63a84
 1 file changed, 25 insertions(+), 6 deletions(-)
b63a84
b63a84
diff --git a/src/pcm/pcm_rate.c b/src/pcm/pcm_rate.c
b63a84
index 1f830dd..61cf979 100644
b63a84
--- a/src/pcm/pcm_rate.c
b63a84
+++ b/src/pcm/pcm_rate.c
b63a84
@@ -50,7 +50,7 @@ typedef struct _snd_pcm_rate snd_pcm_rate_t;
b63a84
 
b63a84
 struct _snd_pcm_rate {
b63a84
 	snd_pcm_generic_t gen;
b63a84
-	snd_pcm_uframes_t appl_ptr, hw_ptr;
b63a84
+	snd_pcm_uframes_t appl_ptr, hw_ptr, last_slave_hw_ptr;
b63a84
 	snd_pcm_uframes_t last_commit_ptr;
b63a84
 	snd_pcm_uframes_t orig_avail_min;
b63a84
 	snd_pcm_sw_params_t sw_params;
b63a84
@@ -563,14 +563,31 @@ static inline void snd_pcm_rate_sync_hwptr0(snd_pcm_t *pcm, snd_pcm_uframes_t sl
b63a84
 {
b63a84
 	snd_pcm_rate_t *rate = pcm->private_data;
b63a84
 
b63a84
+	snd_pcm_sframes_t slave_hw_ptr_diff = slave_hw_ptr - rate->last_slave_hw_ptr;
b63a84
+	snd_pcm_sframes_t last_slave_hw_ptr_frac;
b63a84
+
b63a84
 	if (pcm->stream != SND_PCM_STREAM_PLAYBACK)
b63a84
 		return;
b63a84
-	/* FIXME: boundary overlap of slave hw_ptr isn't evaluated here!
b63a84
-	 *        e.g. if slave rate is small... 
b63a84
+
b63a84
+	if (slave_hw_ptr_diff < 0)
b63a84
+		slave_hw_ptr_diff += rate->gen.slave->boundary; /* slave boundary wraparound */
b63a84
+	else if (slave_hw_ptr_diff == 0)
b63a84
+		return;
b63a84
+	last_slave_hw_ptr_frac = rate->last_slave_hw_ptr % rate->gen.slave->period_size;
b63a84
+	/* While handling fraction part fo slave period, rounded value will be
b63a84
+	 * introduced by input_frames().
b63a84
+	 * To eliminate rounding issue on rate->hw_ptr, subtract last rounded
b63a84
+	 * value from rate->hw_ptr and add new rounded value of present
b63a84
+	 * slave_hw_ptr fraction part to rate->hw_ptr. Hence,
b63a84
+	 * rate->hw_ptr += [ (no. of updated slave periods * pcm rate period size) -
b63a84
+	 * 	fractional part of last_slave_hw_ptr rounded value +
b63a84
+	 * 	fractional part of updated slave hw ptr's rounded value ]
b63a84
 	 */
b63a84
-	rate->hw_ptr =
b63a84
-		(slave_hw_ptr / rate->gen.slave->period_size) * pcm->period_size +
b63a84
-		rate->ops.input_frames(rate->obj, slave_hw_ptr % rate->gen.slave->period_size);
b63a84
+	rate->hw_ptr += (
b63a84
+			(((last_slave_hw_ptr_frac + slave_hw_ptr_diff) / rate->gen.slave->period_size) * pcm->period_size) -
b63a84
+			rate->ops.input_frames(rate->obj, last_slave_hw_ptr_frac) +
b63a84
+			rate->ops.input_frames(rate->obj, (last_slave_hw_ptr_frac + slave_hw_ptr_diff) % rate->gen.slave->period_size));
b63a84
+	rate->last_slave_hw_ptr = slave_hw_ptr;
b63a84
 
b63a84
 	rate->hw_ptr %= pcm->boundary;
b63a84
 }
b63a84
@@ -635,6 +652,7 @@ static int snd_pcm_rate_prepare(snd_pcm_t *pcm)
b63a84
 		return err;
b63a84
 	*pcm->hw.ptr = 0;
b63a84
 	*pcm->appl.ptr = 0;
b63a84
+	rate->last_slave_hw_ptr = 0;
b63a84
 	err = snd_pcm_rate_init(pcm);
b63a84
 	if (err < 0)
b63a84
 		return err;
b63a84
@@ -650,6 +668,7 @@ static int snd_pcm_rate_reset(snd_pcm_t *pcm)
b63a84
 		return err;
b63a84
 	*pcm->hw.ptr = 0;
b63a84
 	*pcm->appl.ptr = 0;
b63a84
+	rate->last_slave_hw_ptr = 0;
b63a84
 	err = snd_pcm_rate_init(pcm);
b63a84
 	if (err < 0)
b63a84
 		return err;
b63a84
-- 
b63a84
2.9.3
b63a84
b63a84
b63a84
From 88e4ae27bb4e47029ed57cc8e02fb1ddf2157fd9 Mon Sep 17 00:00:00 2001
b63a84
From: Andreas Pape <apape@de.adit-jv.com>
b63a84
Date: Mon, 19 Dec 2016 12:37:50 +0900
b63a84
Subject: [PATCH 06/37] plugin: dynamically update avail_min on slave
b63a84
b63a84
mmapped capture access on some plugins can fetch data from
b63a84
slave in the 'background'. A subsequent snd_pcm_wait waits
b63a84
for too long time to reach avail_min threshold again.
b63a84
Waiting too long leads to xruns on other devices waiting for
b63a84
the capture data.
b63a84
As a fix the avail_min on slave is recalculated dynamically.
b63a84
b63a84
V2: updated patch to fix within 80 characters per line
b63a84
b63a84
Signed-off-by: Andreas Pape <apape@de.adit-jv.com>
b63a84
Signed-off-by: Jiada Wang <jiada_wang@mentor.com>
b63a84
Signed-off-by: Takashi Iwai <tiwai@suse.de>
b63a84
---
b63a84
 src/pcm/pcm_plugin.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++-
b63a84
 1 file changed, 63 insertions(+), 1 deletion(-)
b63a84
b63a84
diff --git a/src/pcm/pcm_plugin.c b/src/pcm/pcm_plugin.c
b63a84
index e53c5bb..5b65ac3 100644
b63a84
--- a/src/pcm/pcm_plugin.c
b63a84
+++ b/src/pcm/pcm_plugin.c
b63a84
@@ -535,6 +535,68 @@ static int snd_pcm_plugin_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
b63a84
 	return 0;
b63a84
 }
b63a84
 
b63a84
+static int snd_pcm_plugin_may_wait_for_avail_min(snd_pcm_t *pcm,
b63a84
+						 snd_pcm_uframes_t avail)
b63a84
+{
b63a84
+	if (pcm->stream == SND_PCM_STREAM_CAPTURE &&
b63a84
+	    pcm->access != SND_PCM_ACCESS_RW_INTERLEAVED &&
b63a84
+	    pcm->access != SND_PCM_ACCESS_RW_NONINTERLEAVED) {
b63a84
+		/* mmap access on capture device already consumes data from
b63a84
+		 * slave in avail_update operation. Entering snd_pcm_wait after
b63a84
+		 * having already consumed some fragments leads to waiting for
b63a84
+		 * too long time, as slave will unnecessarily wait for avail_min
b63a84
+		 * condition reached again. To avoid unnecessary wait times we
b63a84
+		 * adapt the avail_min threshold on slave dynamically. Just
b63a84
+		 * modifying slave->avail_min as a shortcut and lightweight
b63a84
+		 * solution does not work for all slave plugin types and in
b63a84
+		 * addition it will not propagate the change through all
b63a84
+		 * downstream plugins, so we have to use the sw_params API.
b63a84
+		 * note: reading fragmental parts from slave will only happen
b63a84
+		 * in case
b63a84
+		 * a) the slave can provide contineous hw_ptr between periods
b63a84
+		 * b) avail_min does not match one slave_period
b63a84
+		 */
b63a84
+		snd_pcm_plugin_t *plugin = pcm->private_data;
b63a84
+		snd_pcm_t *slave = plugin->gen.slave;
b63a84
+		snd_pcm_uframes_t needed_slave_avail_min;
b63a84
+		snd_pcm_sframes_t available;
b63a84
+
b63a84
+		/* update, as it might have changed. This will also call
b63a84
+		 * avail_update on slave and also can return error
b63a84
+		 */
b63a84
+		available = snd_pcm_avail_update(pcm);
b63a84
+		if (available < 0)
b63a84
+			return 0;
b63a84
+
b63a84
+		if (available >= pcm->avail_min)
b63a84
+			/* don't wait at all. As we can't configure avail_min
b63a84
+			 * of slave to 0 return here
b63a84
+			 */
b63a84
+			return 0;
b63a84
+
b63a84
+		needed_slave_avail_min = pcm->avail_min - available;
b63a84
+		if (slave->avail_min != needed_slave_avail_min) {
b63a84
+			snd_pcm_sw_params_t *swparams;
b63a84
+			snd_pcm_sw_params_alloca(&swparams);
b63a84
+			/* pray that changing sw_params while running is
b63a84
+			 * properly implemented in all downstream plugins...
b63a84
+			 * it's legal but not commonly used.
b63a84
+			 */
b63a84
+			snd_pcm_sw_params_current(slave, swparams);
b63a84
+			/* snd_pcm_sw_params_set_avail_min() restricts setting
b63a84
+			 * to >= period size. This conflicts at least with our
b63a84
+			 * dshare patch which allows combining multiple periods
b63a84
+			 * or with slaves which return hw postions between
b63a84
+			 * periods -> set directly in sw_param structure
b63a84
+			 */
b63a84
+			swparams->avail_min = needed_slave_avail_min;
b63a84
+			snd_pcm_sw_params(slave, swparams);
b63a84
+		}
b63a84
+		avail = available;
b63a84
+	}
b63a84
+	return snd_pcm_generic_may_wait_for_avail_min(pcm, avail);
b63a84
+}
b63a84
+
b63a84
 const snd_pcm_fast_ops_t snd_pcm_plugin_fast_ops = {
b63a84
 	.status = snd_pcm_plugin_status,
b63a84
 	.state = snd_pcm_generic_state,
b63a84
@@ -564,7 +626,7 @@ const snd_pcm_fast_ops_t snd_pcm_plugin_fast_ops = {
b63a84
 	.poll_descriptors_count = snd_pcm_generic_poll_descriptors_count,
b63a84
 	.poll_descriptors = snd_pcm_generic_poll_descriptors,
b63a84
 	.poll_revents = snd_pcm_generic_poll_revents,
b63a84
-	.may_wait_for_avail_min = snd_pcm_generic_may_wait_for_avail_min,
b63a84
+	.may_wait_for_avail_min = snd_pcm_plugin_may_wait_for_avail_min,
b63a84
 };
b63a84
 
b63a84
 #endif
b63a84
-- 
b63a84
2.9.3
b63a84
b63a84
b63a84
From ff1f669df4b05da3c44dc4a79ce00233fe9de9b7 Mon Sep 17 00:00:00 2001
b63a84
From: Andreas Pape <apape@de.adit-jv.com>
b63a84
Date: Mon, 19 Dec 2016 12:37:51 +0900
b63a84
Subject: [PATCH 07/37] rate: dynamic update avail_min on slave
b63a84
b63a84
Signed-off-by: Andreas Pape <apape@de.adit-jv.com>
b63a84
Signed-off-by: Jiada Wang <jiada_wang@mentor.com>
b63a84
Signed-off-by: Takashi Iwai <tiwai@suse.de>
b63a84
---
b63a84
 src/pcm/pcm_plugin.c | 4 ++--
b63a84
 src/pcm/pcm_plugin.h | 3 +++
b63a84
 src/pcm/pcm_rate.c   | 2 +-
b63a84
 3 files changed, 6 insertions(+), 3 deletions(-)
b63a84
b63a84
diff --git a/src/pcm/pcm_plugin.c b/src/pcm/pcm_plugin.c
b63a84
index 5b65ac3..ad4a102 100644
b63a84
--- a/src/pcm/pcm_plugin.c
b63a84
+++ b/src/pcm/pcm_plugin.c
b63a84
@@ -535,8 +535,8 @@ static int snd_pcm_plugin_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
b63a84
 	return 0;
b63a84
 }
b63a84
 
b63a84
-static int snd_pcm_plugin_may_wait_for_avail_min(snd_pcm_t *pcm,
b63a84
-						 snd_pcm_uframes_t avail)
b63a84
+int snd_pcm_plugin_may_wait_for_avail_min(snd_pcm_t *pcm,
b63a84
+					  snd_pcm_uframes_t avail)
b63a84
 {
b63a84
 	if (pcm->stream == SND_PCM_STREAM_CAPTURE &&
b63a84
 	    pcm->access != SND_PCM_ACCESS_RW_INTERLEAVED &&
b63a84
diff --git a/src/pcm/pcm_plugin.h b/src/pcm/pcm_plugin.h
b63a84
index 217f075..95aacb3 100644
b63a84
--- a/src/pcm/pcm_plugin.h
b63a84
+++ b/src/pcm/pcm_plugin.h
b63a84
@@ -50,6 +50,8 @@ typedef struct {
b63a84
 /* make local functions really local */
b63a84
 #define snd_pcm_plugin_init \
b63a84
 	snd1_pcm_plugin_init
b63a84
+#define snd_pcm_plugin_may_wait_for_avail_min \
b63a84
+	snd1_pcm_plugin_may_wait_for_avail_min
b63a84
 #define snd_pcm_plugin_fast_ops \
b63a84
 	snd1_pcm_plugin_fast_ops
b63a84
 #define snd_pcm_plugin_undo_read_generic \
b63a84
@@ -64,6 +66,7 @@ typedef struct {
b63a84
 void snd_pcm_plugin_init(snd_pcm_plugin_t *plugin);
b63a84
 snd_pcm_sframes_t snd_pcm_plugin_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames);
b63a84
 snd_pcm_sframes_t snd_pcm_plugin_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames);
b63a84
+int snd_pcm_plugin_may_wait_for_avail_min(snd_pcm_t *pcm, snd_pcm_uframes_t avail);
b63a84
 
b63a84
 extern const snd_pcm_fast_ops_t snd_pcm_plugin_fast_ops;
b63a84
 
b63a84
diff --git a/src/pcm/pcm_rate.c b/src/pcm/pcm_rate.c
b63a84
index 61cf979..cbb7618 100644
b63a84
--- a/src/pcm/pcm_rate.c
b63a84
+++ b/src/pcm/pcm_rate.c
b63a84
@@ -1213,7 +1213,7 @@ static const snd_pcm_fast_ops_t snd_pcm_rate_fast_ops = {
b63a84
 	.poll_descriptors_count = snd_pcm_generic_poll_descriptors_count,
b63a84
 	.poll_descriptors = snd_pcm_generic_poll_descriptors,
b63a84
 	.poll_revents = snd_pcm_rate_poll_revents,
b63a84
-	.may_wait_for_avail_min = snd_pcm_generic_may_wait_for_avail_min,
b63a84
+	.may_wait_for_avail_min = snd_pcm_plugin_may_wait_for_avail_min,
b63a84
 };
b63a84
 
b63a84
 static const snd_pcm_ops_t snd_pcm_rate_ops = {
b63a84
-- 
b63a84
2.9.3
b63a84
b63a84
b63a84
From 6f7eaf92e7de73eb32bd97bad83a14fcb0f408f7 Mon Sep 17 00:00:00 2001
b63a84
From: Takashi Sakamoto <o-takashi@sakamocchi.jp>
b63a84
Date: Wed, 30 Nov 2016 00:44:32 +0900
b63a84
Subject: [PATCH 08/37] topology: fix unused-const-variable warning
b63a84
MIME-Version: 1.0
b63a84
Content-Type: text/plain; charset=UTF-8
b63a84
Content-Transfer-Encoding: 8bit
b63a84
b63a84
Last year, unused static const variable was added, then compiler generates
b63a84
a below warning.
b63a84
b63a84
dapm.c:43:30: warning: ‘widget_control_map’ defined but not used [-Wunused-const-variable=]
b63a84
 static const struct map_elem widget_control_map[] = {
b63a84
                              ^~~~~~~~~~~~~~~~~~
b63a84
b63a84
This commit removes it.
b63a84
b63a84
Fixes: 01a0e1a1c219 ("topology: Add DAPM object parser")
b63a84
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
b63a84
Acked-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
b63a84
Signed-off-by: Takashi Iwai <tiwai@suse.de>
b63a84
---
b63a84
 src/topology/dapm.c | 8 --------
b63a84
 1 file changed, 8 deletions(-)
b63a84
b63a84
diff --git a/src/topology/dapm.c b/src/topology/dapm.c
b63a84
index e830751..8c585a7 100644
b63a84
--- a/src/topology/dapm.c
b63a84
+++ b/src/topology/dapm.c
b63a84
@@ -39,14 +39,6 @@ static const struct map_elem widget_map[] = {
b63a84
 	{"dai_link", SND_SOC_TPLG_DAPM_DAI_LINK},
b63a84
 };
b63a84
 
b63a84
-/* mapping of widget kcontrol text names to types */
b63a84
-static const struct map_elem widget_control_map[] = {
b63a84
-	{"volsw", SND_SOC_TPLG_DAPM_CTL_VOLSW},
b63a84
-	{"enum_double", SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE},
b63a84
-	{"enum_virt", SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT},
b63a84
-	{"enum_value", SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE},
b63a84
-};
b63a84
-
b63a84
 static int lookup_widget(const char *w)
b63a84
 {
b63a84
 	unsigned int i;
b63a84
-- 
b63a84
2.9.3
b63a84
b63a84
b63a84
From 1eddf1f918845d1e6cbcac5516319b20cad80f2f Mon Sep 17 00:00:00 2001
b63a84
From: Adam Goode <agoode@google.com>
b63a84
Date: Tue, 3 Jan 2017 08:33:42 -0500
b63a84
Subject: [PATCH 09/37] seq: improve documentation about new get pid/card
b63a84
 functions
b63a84
b63a84
Document the technique for determining if the running kernel supports
b63a84
the new snd_seq_client_info_get_pid and snd_seq_client_info_get_card
b63a84
functions. Also add a little information about how to use these
b63a84
functions and add some cross references.
b63a84
b63a84
Signed-off-by: Adam Goode <agoode@google.com>
b63a84
Signed-off-by: Takashi Iwai <tiwai@suse.de>
b63a84
---
b63a84
 src/seq/seq.c | 44 ++++++++++++++++++++++++++++++++++++++++++--
b63a84
 1 file changed, 42 insertions(+), 2 deletions(-)
b63a84
b63a84
diff --git a/src/seq/seq.c b/src/seq/seq.c
b63a84
index 9279830..b206e2f 100644
b63a84
--- a/src/seq/seq.c
b63a84
+++ b/src/seq/seq.c
b63a84
@@ -1530,7 +1530,25 @@ int snd_seq_client_info_get_error_bounce(const snd_seq_client_info_t *info)
b63a84
  * \param info client_info container
b63a84
  * \return card number or -1 if value is not available.
b63a84
  *
b63a84
- * Only available for SND_SEQ_KERNEL_CLIENT clients.
b63a84
+ * Only available for #SND_SEQ_KERNEL_CLIENT clients.
b63a84
+ *
b63a84
+ * The card number can be used to query state about the hardware
b63a84
+ * device providing this client, by concatenating "hw:CARD="
b63a84
+ * with the card number and using it as the name parameter
b63a84
+ * to #snd_ctl_open().
b63a84
+ *
b63a84
+ * \note
b63a84
+ * The return value of -1 is returned for two different conditions: when the
b63a84
+ * running kernel does not support this operation, and when the client
b63a84
+ * does not have a hardware card attached. See
b63a84
+ * #snd_seq_client_info_get_pid() for a way to determine if the
b63a84
+ * currently running kernel has support for this operation.
b63a84
+ *
b63a84
+ * \sa snd_seq_client_info_get_pid(),
b63a84
+ *     snd_card_get_name(),
b63a84
+ *     snd_card_get_longname(),
b63a84
+ *     snd_ctl_open(),
b63a84
+ *     snd_ctl_card_info()
b63a84
  */
b63a84
 int snd_seq_client_info_get_card(const snd_seq_client_info_t *info)
b63a84
 {
b63a84
@@ -1543,7 +1561,29 @@ int snd_seq_client_info_get_card(const snd_seq_client_info_t *info)
b63a84
  * \param info client_info container
b63a84
  * \return pid or -1 if value is not available.
b63a84
  *
b63a84
- * Only available for SND_SEQ_USER_CLIENT clients.
b63a84
+ * Only available for #SND_SEQ_USER_CLIENT clients.
b63a84
+ *
b63a84
+ * \note
b63a84
+ * The functionality for getting a client's PID and getting a
b63a84
+ * client's card was added to the kernel at the same time, so you can
b63a84
+ * use this function to determine if the running kernel
b63a84
+ * supports reporting these values. If your own client has a valid
b63a84
+ * PID as reported by this function, then the running kernel supports
b63a84
+ * both #snd_seq_client_info_get_card() and #snd_seq_client_info_get_pid().
b63a84
+ *
b63a84
+ * \note
b63a84
+ * Example code for determining kernel support:
b63a84
+ * \code
b63a84
+ *   int is_get_card_or_pid_supported(snd_seq_t *seq)
b63a84
+ *   {
b63a84
+ *   	snd_seq_client_info_t *my_client_info;
b63a84
+ *   	snd_seq_client_info_alloca(&my_client_info);
b63a84
+ *   	snd_seq_get_client_info(seq, my_client_info);
b63a84
+ *   	return snd_seq_client_info_get_pid(my_client_info) != -1;
b63a84
+ *   }
b63a84
+ * \endcode
b63a84
+ *
b63a84
+ * \sa snd_seq_client_info_get_card()
b63a84
  */
b63a84
 int snd_seq_client_info_get_pid(const snd_seq_client_info_t *info)
b63a84
 {
b63a84
-- 
b63a84
2.9.3
b63a84
b63a84
b63a84
From 3f0dc404f16af58d20b4489b0daafcf87555dfb7 Mon Sep 17 00:00:00 2001
b63a84
From: Mounesh Sutar <sutar.mounesh@gmail.com>
b63a84
Date: Tue, 10 Jan 2017 12:03:17 +0530
b63a84
Subject: [PATCH 10/37] pcm: direct: returning semop error code for semaphore
b63a84
 up/down failures
b63a84
b63a84
Signed-off-by: Mounesh Sutar <sutar.mounesh@gmail.com>
b63a84
Signed-off-by: Takashi Iwai <tiwai@suse.de>
b63a84
---
b63a84
 src/pcm/pcm_direct.h | 10 ++++++++--
b63a84
 1 file changed, 8 insertions(+), 2 deletions(-)
b63a84
b63a84
diff --git a/src/pcm/pcm_direct.h b/src/pcm/pcm_direct.h
b63a84
index 91e816c..aee38c5 100644
b63a84
--- a/src/pcm/pcm_direct.h
b63a84
+++ b/src/pcm/pcm_direct.h
b63a84
@@ -263,7 +263,10 @@ static inline int snd_pcm_direct_semaphore_down(snd_pcm_direct_t *dmix, int sem_
b63a84
 {
b63a84
 	struct sembuf op[2] = { { sem_num, 0, 0 }, { sem_num, 1, SEM_UNDO } };
b63a84
 	int err = semop(dmix->semid, op, 2);
b63a84
-	if (err == 0) dmix->locked[sem_num]++;
b63a84
+	if (err == 0)
b63a84
+		dmix->locked[sem_num]++;
b63a84
+	else if (err == -1)
b63a84
+		err = -errno;
b63a84
 	return err;
b63a84
 }
b63a84
 
b63a84
@@ -271,7 +274,10 @@ static inline int snd_pcm_direct_semaphore_up(snd_pcm_direct_t *dmix, int sem_nu
b63a84
 {
b63a84
 	struct sembuf op = { sem_num, -1, SEM_UNDO | IPC_NOWAIT };
b63a84
 	int err = semop(dmix->semid, &op, 1);
b63a84
-	if (err == 0) dmix->locked[sem_num]--;
b63a84
+	if (err == 0)
b63a84
+		dmix->locked[sem_num]--;
b63a84
+	else if (err == -1)
b63a84
+		err = -errno;
b63a84
 	return err;
b63a84
 }
b63a84
 
b63a84
-- 
b63a84
2.9.3
b63a84
b63a84
b63a84
From 1a9bd0f0448106b917ae7f7bedccfcbf6ce84802 Mon Sep 17 00:00:00 2001
b63a84
From: Andreas Pape <apape@de.adit-jv.com>
b63a84
Date: Tue, 10 Jan 2017 12:03:36 +0530
b63a84
Subject: [PATCH 11/37] pcm: direct: Fix for sync issue on xrun recover
b63a84
b63a84
If using very short periods, DSHARE/DSNOOP/DMIX may report underruns while in
b63a84
status 'prepared'. This prohibits correct recovery. Now slave xrun conditions
b63a84
for DSHARE/DSNOOP/DMIX are being handled properly.
b63a84
b63a84
Signed-off-by: Andreas Pape <apape@de.adit-jv.com>
b63a84
Signed-off-by: Joshua Frkuska <joshua_frkuska@mentor.com>
b63a84
Signed-off-by: Mounesh Sutar <mounesh_sutar@mentor.com>
b63a84
Signed-off-by: Takashi Iwai <tiwai@suse.de>
b63a84
---
b63a84
 src/pcm/pcm_direct.c | 102 +++++++++++++++++++++++++++++++++++++++++++++++++++
b63a84
 src/pcm/pcm_direct.h |   5 ++-
b63a84
 src/pcm/pcm_dmix.c   |  27 +++++++++++---
b63a84
 src/pcm/pcm_dshare.c |  29 +++++++++++----
b63a84
 src/pcm/pcm_dsnoop.c |  15 +++++++-
b63a84
 5 files changed, 162 insertions(+), 16 deletions(-)
b63a84
b63a84
diff --git a/src/pcm/pcm_direct.c b/src/pcm/pcm_direct.c
b63a84
index 0770abc..a512dd2 100644
b63a84
--- a/src/pcm/pcm_direct.c
b63a84
+++ b/src/pcm/pcm_direct.c
b63a84
@@ -550,6 +550,101 @@ int snd_pcm_direct_timer_stop(snd_pcm_direct_t *dmix)
b63a84
 	return 0;
b63a84
 }
b63a84
 
b63a84
+/*
b63a84
+ * Recover slave on XRUN.
b63a84
+ * Even if direct plugins disable xrun detection, there might be an xrun
b63a84
+ * raised directly by some drivers.
b63a84
+ * The first client recovers slave pcm.
b63a84
+ * Each client needs to execute sw xrun handling afterwards
b63a84
+ */
b63a84
+int snd_pcm_direct_slave_recover(snd_pcm_direct_t *direct)
b63a84
+{
b63a84
+	int ret;
b63a84
+	int semerr;
b63a84
+
b63a84
+	semerr = snd_pcm_direct_semaphore_down(direct,
b63a84
+						   DIRECT_IPC_SEM_CLIENT);
b63a84
+	if (semerr < 0) {
b63a84
+		SNDERR("SEMDOWN FAILED with err %d", semerr);
b63a84
+		return semerr;
b63a84
+	}
b63a84
+
b63a84
+	if (snd_pcm_state(direct->spcm) != SND_PCM_STATE_XRUN) {
b63a84
+		/* ignore... someone else already did recovery */
b63a84
+		semerr = snd_pcm_direct_semaphore_up(direct,
b63a84
+						     DIRECT_IPC_SEM_CLIENT);
b63a84
+		if (semerr < 0) {
b63a84
+			SNDERR("SEMUP FAILED with err %d", semerr);
b63a84
+			return semerr;
b63a84
+		}
b63a84
+		return 0;
b63a84
+	}
b63a84
+
b63a84
+	ret = snd_pcm_prepare(direct->spcm);
b63a84
+	if (ret < 0) {
b63a84
+		SNDERR("recover: unable to prepare slave");
b63a84
+		semerr = snd_pcm_direct_semaphore_up(direct,
b63a84
+						     DIRECT_IPC_SEM_CLIENT);
b63a84
+		if (semerr < 0) {
b63a84
+			SNDERR("SEMUP FAILED with err %d", semerr);
b63a84
+			return semerr;
b63a84
+		}
b63a84
+		return ret;
b63a84
+	}
b63a84
+
b63a84
+	if (direct->type == SND_PCM_TYPE_DSHARE) {
b63a84
+		const snd_pcm_channel_area_t *dst_areas;
b63a84
+		dst_areas = snd_pcm_mmap_areas(direct->spcm);
b63a84
+		snd_pcm_areas_silence(dst_areas, 0, direct->spcm->channels,
b63a84
+				      direct->spcm->buffer_size,
b63a84
+				      direct->spcm->format);
b63a84
+	}
b63a84
+
b63a84
+	ret = snd_pcm_start(direct->spcm);
b63a84
+	if (ret < 0) {
b63a84
+		SNDERR("recover: unable to start slave");
b63a84
+		semerr = snd_pcm_direct_semaphore_up(direct,
b63a84
+						     DIRECT_IPC_SEM_CLIENT);
b63a84
+		if (semerr < 0) {
b63a84
+			SNDERR("SEMUP FAILED with err %d", semerr);
b63a84
+			return semerr;
b63a84
+		}
b63a84
+		return ret;
b63a84
+	}
b63a84
+	direct->shmptr->recoveries++;
b63a84
+	semerr = snd_pcm_direct_semaphore_up(direct,
b63a84
+						 DIRECT_IPC_SEM_CLIENT);
b63a84
+	if (semerr < 0) {
b63a84
+		SNDERR("SEMUP FAILED with err %d", semerr);
b63a84
+		return semerr;
b63a84
+	}
b63a84
+	return 0;
b63a84
+}
b63a84
+
b63a84
+/*
b63a84
+ * enter xrun state, if slave xrun occurred
b63a84
+ * @return: 0 - no xrun >0: xrun happened
b63a84
+ */
b63a84
+int snd_pcm_direct_client_chk_xrun(snd_pcm_direct_t *direct, snd_pcm_t *pcm)
b63a84
+{
b63a84
+	if (direct->shmptr->recoveries != direct->recoveries) {
b63a84
+		/* no matter how many xruns we missed -
b63a84
+		 * so don't increment but just update to actual counter
b63a84
+		 */
b63a84
+		direct->recoveries = direct->shmptr->recoveries;
b63a84
+		pcm->fast_ops->drop(pcm);
b63a84
+		/* trigger_tstamp update is missing in drop callbacks */
b63a84
+		gettimestamp(&direct->trigger_tstamp, pcm->tstamp_type);
b63a84
+		/* no timer clear:
b63a84
+		 * if slave already entered xrun again the event is lost.
b63a84
+		 * snd_pcm_direct_clear_timer_queue(direct);
b63a84
+		 */
b63a84
+		direct->state = SND_PCM_STATE_XRUN;
b63a84
+		return 1;
b63a84
+	}
b63a84
+	return 0;
b63a84
+}
b63a84
+
b63a84
 int snd_pcm_direct_poll_revents(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int nfds, unsigned short *revents)
b63a84
 {
b63a84
 	snd_pcm_direct_t *dmix = pcm->private_data;
b63a84
@@ -572,6 +667,12 @@ int snd_pcm_direct_poll_revents(snd_pcm_t *pcm, struct pollfd *pfds, unsigned in
b63a84
 	}
b63a84
 	switch (snd_pcm_state(dmix->spcm)) {
b63a84
 	case SND_PCM_STATE_XRUN:
b63a84
+		/* recover slave and update client state to xrun
b63a84
+		 * before returning POLLERR
b63a84
+		 */
b63a84
+		snd_pcm_direct_slave_recover(dmix);
b63a84
+		snd_pcm_direct_client_chk_xrun(dmix, pcm);
b63a84
+		/* fallthrough */
b63a84
 	case SND_PCM_STATE_SUSPENDED:
b63a84
 	case SND_PCM_STATE_SETUP:
b63a84
 		events |= POLLERR;
b63a84
@@ -1382,6 +1483,7 @@ int snd_pcm_direct_open_secondary_client(snd_pcm_t **spcmp, snd_pcm_direct_t *dm
b63a84
 	dmix->slave_buffer_size = spcm->buffer_size;
b63a84
 	dmix->slave_period_size = dmix->shmptr->s.period_size;
b63a84
 	dmix->slave_boundary = spcm->boundary;
b63a84
+	dmix->recoveries = dmix->shmptr->recoveries;
b63a84
 
b63a84
 	ret = snd_pcm_mmap(spcm);
b63a84
 	if (ret < 0) {
b63a84
diff --git a/src/pcm/pcm_direct.h b/src/pcm/pcm_direct.h
b63a84
index aee38c5..d48f6b4 100644
b63a84
--- a/src/pcm/pcm_direct.h
b63a84
+++ b/src/pcm/pcm_direct.h
b63a84
@@ -66,6 +66,7 @@ typedef struct {
b63a84
 	char socket_name[256];			/* name of communication socket */
b63a84
 	snd_pcm_type_t type;			/* PCM type (currently only hw) */
b63a84
 	int use_server;
b63a84
+	unsigned int recoveries;		/* no of executed recoveries on slave*/
b63a84
 	struct {
b63a84
 		unsigned int format;
b63a84
 		snd_interval_t rate;
b63a84
@@ -157,6 +158,7 @@ struct snd_pcm_direct {
b63a84
 	int var_periodsize;		/* allow variable period size if max_periods is != -1*/
b63a84
 	unsigned int channels;		/* client's channels */
b63a84
 	unsigned int *bindings;
b63a84
+	unsigned int recoveries;	/* mirror of executed recoveries on slave */
b63a84
 	union {
b63a84
 		struct {
b63a84
 			int shmid_sum;			/* IPC global sum ring buffer memory identification */
b63a84
@@ -324,7 +326,8 @@ int snd_pcm_direct_open_secondary_client(snd_pcm_t **spcmp, snd_pcm_direct_t *dm
b63a84
 snd_pcm_chmap_query_t **snd_pcm_direct_query_chmaps(snd_pcm_t *pcm);
b63a84
 snd_pcm_chmap_t *snd_pcm_direct_get_chmap(snd_pcm_t *pcm);
b63a84
 int snd_pcm_direct_set_chmap(snd_pcm_t *pcm, const snd_pcm_chmap_t *map);
b63a84
-
b63a84
+int snd_pcm_direct_slave_recover(snd_pcm_direct_t *direct);
b63a84
+int snd_pcm_direct_client_chk_xrun(snd_pcm_direct_t *direct, snd_pcm_t *pcm);
b63a84
 int snd_timer_async(snd_timer_t *timer, int sig, pid_t pid);
b63a84
 struct timespec snd_pcm_hw_fast_tstamp(snd_pcm_t *pcm);
b63a84
 
b63a84
diff --git a/src/pcm/pcm_dmix.c b/src/pcm/pcm_dmix.c
b63a84
index 0ab7323..f72ee67 100644
b63a84
--- a/src/pcm/pcm_dmix.c
b63a84
+++ b/src/pcm/pcm_dmix.c
b63a84
@@ -434,15 +434,21 @@ static int snd_pcm_dmix_sync_ptr0(snd_pcm_t *pcm, snd_pcm_uframes_t slave_hw_ptr
b63a84
 static int snd_pcm_dmix_sync_ptr(snd_pcm_t *pcm)
b63a84
 {
b63a84
 	snd_pcm_direct_t *dmix = pcm->private_data;
b63a84
+	int err;
b63a84
 
b63a84
 	switch (snd_pcm_state(dmix->spcm)) {
b63a84
 	case SND_PCM_STATE_DISCONNECTED:
b63a84
 		dmix->state = SND_PCM_STATE_DISCONNECTED;
b63a84
 		return -ENODEV;
b63a84
+	case SND_PCM_STATE_XRUN:
b63a84
+		if ((err = snd_pcm_direct_slave_recover(dmix)) < 0)
b63a84
+			return err;
b63a84
+		break;
b63a84
 	default:
b63a84
 		break;
b63a84
 	}
b63a84
-
b63a84
+	if (snd_pcm_direct_client_chk_xrun(dmix, pcm))
b63a84
+		return -EPIPE;
b63a84
 	if (dmix->slowptr)
b63a84
 		snd_pcm_hwsync(dmix->spcm);
b63a84
 
b63a84
@@ -828,12 +834,16 @@ static snd_pcm_sframes_t snd_pcm_dmix_mmap_commit(snd_pcm_t *pcm,
b63a84
 
b63a84
 	switch (snd_pcm_state(dmix->spcm)) {
b63a84
 	case SND_PCM_STATE_XRUN:
b63a84
-		return -EPIPE;
b63a84
+		if ((err = snd_pcm_direct_slave_recover(dmix)) < 0)
b63a84
+			return err;
b63a84
+		break;
b63a84
 	case SND_PCM_STATE_SUSPENDED:
b63a84
 		return -ESTRPIPE;
b63a84
 	default:
b63a84
 		break;
b63a84
 	}
b63a84
+	if (snd_pcm_direct_client_chk_xrun(dmix, pcm))
b63a84
+		return -EPIPE;
b63a84
 	if (! size)
b63a84
 		return 0;
b63a84
 	snd_pcm_mmap_appl_forward(pcm, size);
b63a84
@@ -841,8 +851,10 @@ static snd_pcm_sframes_t snd_pcm_dmix_mmap_commit(snd_pcm_t *pcm,
b63a84
 		if ((err = snd_pcm_dmix_start_timer(pcm, dmix)) < 0)
b63a84
 			return err;
b63a84
 	} else if (dmix->state == SND_PCM_STATE_RUNNING ||
b63a84
-		   dmix->state == SND_PCM_STATE_DRAINING)
b63a84
-		snd_pcm_dmix_sync_ptr(pcm);
b63a84
+		   dmix->state == SND_PCM_STATE_DRAINING) {
b63a84
+		if ((err = snd_pcm_dmix_sync_ptr(pcm)) < 0)
b63a84
+			return err;
b63a84
+	}
b63a84
 	if (dmix->state == SND_PCM_STATE_RUNNING ||
b63a84
 	    dmix->state == SND_PCM_STATE_DRAINING) {
b63a84
 		/* ok, we commit the changes after the validation of area */
b63a84
@@ -858,10 +870,13 @@ static snd_pcm_sframes_t snd_pcm_dmix_mmap_commit(snd_pcm_t *pcm,
b63a84
 static snd_pcm_sframes_t snd_pcm_dmix_avail_update(snd_pcm_t *pcm)
b63a84
 {
b63a84
 	snd_pcm_direct_t *dmix = pcm->private_data;
b63a84
+	int err;
b63a84
 	
b63a84
 	if (dmix->state == SND_PCM_STATE_RUNNING ||
b63a84
-	    dmix->state == SND_PCM_STATE_DRAINING)
b63a84
-		snd_pcm_dmix_sync_ptr(pcm);
b63a84
+	    dmix->state == SND_PCM_STATE_DRAINING) {
b63a84
+		if ((err = snd_pcm_dmix_sync_ptr(pcm)) < 0)
b63a84
+			return err;
b63a84
+	}
b63a84
 	return snd_pcm_mmap_playback_avail(pcm);
b63a84
 }
b63a84
 
b63a84
diff --git a/src/pcm/pcm_dshare.c b/src/pcm/pcm_dshare.c
b63a84
index a1fed5d..0d80037 100644
b63a84
--- a/src/pcm/pcm_dshare.c
b63a84
+++ b/src/pcm/pcm_dshare.c
b63a84
@@ -162,7 +162,7 @@ static int snd_pcm_dshare_sync_ptr0(snd_pcm_t *pcm, snd_pcm_uframes_t slave_hw_p
b63a84
 	snd_pcm_direct_t *dshare = pcm->private_data;
b63a84
 	snd_pcm_uframes_t old_slave_hw_ptr, avail;
b63a84
 	snd_pcm_sframes_t diff;
b63a84
-	
b63a84
+
b63a84
 	old_slave_hw_ptr = dshare->slave_hw_ptr;
b63a84
 	dshare->slave_hw_ptr = slave_hw_ptr;
b63a84
 	diff = slave_hw_ptr - old_slave_hw_ptr;
b63a84
@@ -202,15 +202,21 @@ static int snd_pcm_dshare_sync_ptr0(snd_pcm_t *pcm, snd_pcm_uframes_t slave_hw_p
b63a84
 static int snd_pcm_dshare_sync_ptr(snd_pcm_t *pcm)
b63a84
 {
b63a84
 	snd_pcm_direct_t *dshare = pcm->private_data;
b63a84
+	int err;
b63a84
 
b63a84
 	switch (snd_pcm_state(dshare->spcm)) {
b63a84
 	case SND_PCM_STATE_DISCONNECTED:
b63a84
 		dshare->state = SNDRV_PCM_STATE_DISCONNECTED;
b63a84
 		return -ENODEV;
b63a84
+	case SND_PCM_STATE_XRUN:
b63a84
+		if ((err = snd_pcm_direct_slave_recover(dshare)) < 0)
b63a84
+			return err;
b63a84
+		break;
b63a84
 	default:
b63a84
 		break;
b63a84
 	}
b63a84
-
b63a84
+	if (snd_pcm_direct_client_chk_xrun(dshare, pcm))
b63a84
+		return -EPIPE;
b63a84
 	if (dshare->slowptr)
b63a84
 		snd_pcm_hwsync(dshare->spcm);
b63a84
 
b63a84
@@ -516,12 +522,16 @@ static snd_pcm_sframes_t snd_pcm_dshare_mmap_commit(snd_pcm_t *pcm,
b63a84
 
b63a84
 	switch (snd_pcm_state(dshare->spcm)) {
b63a84
 	case SND_PCM_STATE_XRUN:
b63a84
-		return -EPIPE;
b63a84
+		if ((err = snd_pcm_direct_slave_recover(dshare)) < 0)
b63a84
+			return err;
b63a84
+		break;
b63a84
 	case SND_PCM_STATE_SUSPENDED:
b63a84
 		return -ESTRPIPE;
b63a84
 	default:
b63a84
 		break;
b63a84
 	}
b63a84
+	if (snd_pcm_direct_client_chk_xrun(dshare, pcm))
b63a84
+		return -EPIPE;
b63a84
 	if (! size)
b63a84
 		return 0;
b63a84
 	snd_pcm_mmap_appl_forward(pcm, size);
b63a84
@@ -529,8 +539,10 @@ static snd_pcm_sframes_t snd_pcm_dshare_mmap_commit(snd_pcm_t *pcm,
b63a84
 		if ((err = snd_pcm_dshare_start_timer(dshare)) < 0)
b63a84
 			return err;
b63a84
 	} else if (dshare->state == SND_PCM_STATE_RUNNING ||
b63a84
-		   dshare->state == SND_PCM_STATE_DRAINING)
b63a84
-		snd_pcm_dshare_sync_ptr(pcm);
b63a84
+		   dshare->state == SND_PCM_STATE_DRAINING) {
b63a84
+		if ((err = snd_pcm_dshare_sync_ptr(pcm)) < 0)
b63a84
+			return err;
b63a84
+	}
b63a84
 	if (dshare->state == SND_PCM_STATE_RUNNING ||
b63a84
 	    dshare->state == SND_PCM_STATE_DRAINING) {
b63a84
 		/* ok, we commit the changes after the validation of area */
b63a84
@@ -546,10 +558,13 @@ static snd_pcm_sframes_t snd_pcm_dshare_mmap_commit(snd_pcm_t *pcm,
b63a84
 static snd_pcm_sframes_t snd_pcm_dshare_avail_update(snd_pcm_t *pcm)
b63a84
 {
b63a84
 	snd_pcm_direct_t *dshare = pcm->private_data;
b63a84
+	int err;
b63a84
 	
b63a84
 	if (dshare->state == SND_PCM_STATE_RUNNING ||
b63a84
-	    dshare->state == SND_PCM_STATE_DRAINING)
b63a84
-		snd_pcm_dshare_sync_ptr(pcm);
b63a84
+	    dshare->state == SND_PCM_STATE_DRAINING) {
b63a84
+		if ((err = snd_pcm_dshare_sync_ptr(pcm)) < 0)
b63a84
+			return err;
b63a84
+	}
b63a84
 	return snd_pcm_mmap_playback_avail(pcm);
b63a84
 }
b63a84
 
b63a84
diff --git a/src/pcm/pcm_dsnoop.c b/src/pcm/pcm_dsnoop.c
b63a84
index 85f0ff4..618d469 100644
b63a84
--- a/src/pcm/pcm_dsnoop.c
b63a84
+++ b/src/pcm/pcm_dsnoop.c
b63a84
@@ -132,14 +132,21 @@ static int snd_pcm_dsnoop_sync_ptr(snd_pcm_t *pcm)
b63a84
 	snd_pcm_direct_t *dsnoop = pcm->private_data;
b63a84
 	snd_pcm_uframes_t slave_hw_ptr, old_slave_hw_ptr, avail;
b63a84
 	snd_pcm_sframes_t diff;
b63a84
-	
b63a84
+	int err;
b63a84
+
b63a84
 	switch (snd_pcm_state(dsnoop->spcm)) {
b63a84
 	case SND_PCM_STATE_DISCONNECTED:
b63a84
 		dsnoop->state = SNDRV_PCM_STATE_DISCONNECTED;
b63a84
 		return -ENODEV;
b63a84
+	case SND_PCM_STATE_XRUN:
b63a84
+		if ((err = snd_pcm_direct_slave_recover(dsnoop)) < 0)
b63a84
+			return err;
b63a84
+		break;
b63a84
 	default:
b63a84
 		break;
b63a84
 	}
b63a84
+	if (snd_pcm_direct_client_chk_xrun(dsnoop, pcm))
b63a84
+		return -EPIPE;
b63a84
 	if (dsnoop->slowptr)
b63a84
 		snd_pcm_hwsync(dsnoop->spcm);
b63a84
 	old_slave_hw_ptr = dsnoop->slave_hw_ptr;
b63a84
@@ -410,12 +417,16 @@ static snd_pcm_sframes_t snd_pcm_dsnoop_mmap_commit(snd_pcm_t *pcm,
b63a84
 
b63a84
 	switch (snd_pcm_state(dsnoop->spcm)) {
b63a84
 	case SND_PCM_STATE_XRUN:
b63a84
-		return -EPIPE;
b63a84
+		if ((err = snd_pcm_direct_slave_recover(dsnoop)) < 0)
b63a84
+			return err;
b63a84
+		break;
b63a84
 	case SND_PCM_STATE_SUSPENDED:
b63a84
 		return -ESTRPIPE;
b63a84
 	default:
b63a84
 		break;
b63a84
 	}
b63a84
+	if (snd_pcm_direct_client_chk_xrun(dsnoop, pcm))
b63a84
+		return -EPIPE;
b63a84
 	if (dsnoop->state == SND_PCM_STATE_RUNNING) {
b63a84
 		err = snd_pcm_dsnoop_sync_ptr(pcm);
b63a84
 		if (err < 0)
b63a84
-- 
b63a84
2.9.3
b63a84
b63a84
b63a84
From 789ee39727a12d6573b4d79e9cd7a375e6b8b005 Mon Sep 17 00:00:00 2001
b63a84
From: Andreas Pape <apape@de.adit-jv.com>
b63a84
Date: Tue, 10 Jan 2017 12:03:54 +0530
b63a84
Subject: [PATCH 12/37] pcm: direct: check state before enter poll on timer
b63a84
b63a84
To avoid the chances of timeout, we need to check the enter poll
b63a84
in state xrun.
b63a84
b63a84
Signed-off-by: Andreas Pape <apape@de.adit-jv.com>
b63a84
Signed-off-by: Mounesh Sutar <mounesh_sutar@mentor.com>
b63a84
Signed-off-by: Takashi Iwai <tiwai@suse.de>
b63a84
---
b63a84
 src/pcm/pcm_direct.c | 40 ++++++++++++++++++++++++++++++++++++++++
b63a84
 src/pcm/pcm_direct.h |  2 ++
b63a84
 src/pcm/pcm_dmix.c   |  9 +++++++--
b63a84
 src/pcm/pcm_dshare.c |  9 +++++++--
b63a84
 src/pcm/pcm_dsnoop.c |  9 +++++++--
b63a84
 5 files changed, 63 insertions(+), 6 deletions(-)
b63a84
b63a84
diff --git a/src/pcm/pcm_direct.c b/src/pcm/pcm_direct.c
b63a84
index a512dd2..f4d7c3f 100644
b63a84
--- a/src/pcm/pcm_direct.c
b63a84
+++ b/src/pcm/pcm_direct.c
b63a84
@@ -645,6 +645,46 @@ int snd_pcm_direct_client_chk_xrun(snd_pcm_direct_t *direct, snd_pcm_t *pcm)
b63a84
 	return 0;
b63a84
 }
b63a84
 
b63a84
+/*
b63a84
+ * This is the only operation guaranteed to be called before entering poll().
b63a84
+ * Direct plugins use fd of snd_timer to poll on, these timers do NOT check
b63a84
+ * state of substream in kernel by intention.
b63a84
+ * Only the enter to xrun might be notified once (SND_TIMER_EVENT_MSTOP).
b63a84
+ * If xrun event was not correctly handled or was ignored it will never be
b63a84
+ * evaluated again afterwards.
b63a84
+ * This will result in snd_pcm_wait() always returning timeout.
b63a84
+ * In contrast poll() on pcm hardware checks ALSA state and will immediately
b63a84
+ * return POLLERR on XRUN.
b63a84
+ *
b63a84
+ * To prevent timeout and applications endlessly spinning without xrun
b63a84
+ * detected we add a state check here which may trigger the xrun sequence.
b63a84
+ *
b63a84
+ * return count of filled descriptors or negative error code
b63a84
+ */
b63a84
+int snd_pcm_direct_poll_descriptors(snd_pcm_t *pcm, struct pollfd *pfds,
b63a84
+				    unsigned int space)
b63a84
+{
b63a84
+	if (pcm->poll_fd < 0) {
b63a84
+		SNDMSG("poll_fd < 0");
b63a84
+		return -EIO;
b63a84
+	}
b63a84
+	if (space >= 1 && pfds) {
b63a84
+		pfds->fd = pcm->poll_fd;
b63a84
+		pfds->events = pcm->poll_events | POLLERR | POLLNVAL;
b63a84
+	} else {
b63a84
+		return 0;
b63a84
+	}
b63a84
+
b63a84
+	/* this will also evaluate slave state and enter xrun if necessary */
b63a84
+	switch (snd_pcm_state(pcm)) {
b63a84
+	case SND_PCM_STATE_XRUN:
b63a84
+		return -EPIPE;
b63a84
+	default:
b63a84
+		break;
b63a84
+	}
b63a84
+	return 1;
b63a84
+}
b63a84
+
b63a84
 int snd_pcm_direct_poll_revents(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int nfds, unsigned short *revents)
b63a84
 {
b63a84
 	snd_pcm_direct_t *dmix = pcm->private_data;
b63a84
diff --git a/src/pcm/pcm_direct.h b/src/pcm/pcm_direct.h
b63a84
index d48f6b4..66107ec 100644
b63a84
--- a/src/pcm/pcm_direct.h
b63a84
+++ b/src/pcm/pcm_direct.h
b63a84
@@ -307,6 +307,8 @@ int snd_pcm_direct_parse_bindings(snd_pcm_direct_t *dmix,
b63a84
 				  snd_config_t *cfg);
b63a84
 int snd_pcm_direct_nonblock(snd_pcm_t *pcm, int nonblock);
b63a84
 int snd_pcm_direct_async(snd_pcm_t *pcm, int sig, pid_t pid);
b63a84
+int snd_pcm_direct_poll_descriptors(snd_pcm_t *pcm, struct pollfd *pfds,
b63a84
+				    unsigned int space);
b63a84
 int snd_pcm_direct_poll_revents(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int nfds, unsigned short *revents);
b63a84
 int snd_pcm_direct_info(snd_pcm_t *pcm, snd_pcm_info_t * info);
b63a84
 int snd_pcm_direct_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params);
b63a84
diff --git a/src/pcm/pcm_dmix.c b/src/pcm/pcm_dmix.c
b63a84
index f72ee67..6664210 100644
b63a84
--- a/src/pcm/pcm_dmix.c
b63a84
+++ b/src/pcm/pcm_dmix.c
b63a84
@@ -462,17 +462,22 @@ static int snd_pcm_dmix_sync_ptr(snd_pcm_t *pcm)
b63a84
 static snd_pcm_state_t snd_pcm_dmix_state(snd_pcm_t *pcm)
b63a84
 {
b63a84
 	snd_pcm_direct_t *dmix = pcm->private_data;
b63a84
+	int err;
b63a84
 	snd_pcm_state_t state;
b63a84
 	state = snd_pcm_state(dmix->spcm);
b63a84
 	switch (state) {
b63a84
-	case SND_PCM_STATE_XRUN:
b63a84
 	case SND_PCM_STATE_SUSPENDED:
b63a84
 	case SND_PCM_STATE_DISCONNECTED:
b63a84
 		dmix->state = state;
b63a84
 		return state;
b63a84
+	case SND_PCM_STATE_XRUN:
b63a84
+		if ((err = snd_pcm_direct_slave_recover(dmix)) < 0)
b63a84
+			return err;
b63a84
+		break;
b63a84
 	default:
b63a84
 		break;
b63a84
 	}
b63a84
+	snd_pcm_direct_client_chk_xrun(dmix, pcm);
b63a84
 	if (dmix->state == STATE_RUN_PENDING)
b63a84
 		return SNDRV_PCM_STATE_RUNNING;
b63a84
 	return dmix->state;
b63a84
@@ -968,7 +973,7 @@ static const snd_pcm_fast_ops_t snd_pcm_dmix_fast_ops = {
b63a84
 	.avail_update = snd_pcm_dmix_avail_update,
b63a84
 	.mmap_commit = snd_pcm_dmix_mmap_commit,
b63a84
 	.htimestamp = snd_pcm_dmix_htimestamp,
b63a84
-	.poll_descriptors = NULL,
b63a84
+	.poll_descriptors = snd_pcm_direct_poll_descriptors,
b63a84
 	.poll_descriptors_count = NULL,
b63a84
 	.poll_revents = snd_pcm_dmix_poll_revents,
b63a84
 };
b63a84
diff --git a/src/pcm/pcm_dshare.c b/src/pcm/pcm_dshare.c
b63a84
index 0d80037..fdc95e3 100644
b63a84
--- a/src/pcm/pcm_dshare.c
b63a84
+++ b/src/pcm/pcm_dshare.c
b63a84
@@ -255,17 +255,22 @@ static int snd_pcm_dshare_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
b63a84
 static snd_pcm_state_t snd_pcm_dshare_state(snd_pcm_t *pcm)
b63a84
 {
b63a84
 	snd_pcm_direct_t *dshare = pcm->private_data;
b63a84
+	int err;
b63a84
 	snd_pcm_state_t state;
b63a84
 	state = snd_pcm_state(dshare->spcm);
b63a84
 	switch (state) {
b63a84
-	case SND_PCM_STATE_XRUN:
b63a84
 	case SND_PCM_STATE_SUSPENDED:
b63a84
 	case SND_PCM_STATE_DISCONNECTED:
b63a84
 		dshare->state = state;
b63a84
 		return state;
b63a84
+	case SND_PCM_STATE_XRUN:
b63a84
+		if ((err = snd_pcm_direct_slave_recover(dshare)) < 0)
b63a84
+			return err;
b63a84
+		break;
b63a84
 	default:
b63a84
 		break;
b63a84
 	}
b63a84
+	snd_pcm_direct_client_chk_xrun(dshare, pcm);
b63a84
 	if (dshare->state == STATE_RUN_PENDING)
b63a84
 		return SNDRV_PCM_STATE_RUNNING;
b63a84
 	return dshare->state;
b63a84
@@ -646,7 +651,7 @@ static const snd_pcm_fast_ops_t snd_pcm_dshare_fast_ops = {
b63a84
 	.avail_update = snd_pcm_dshare_avail_update,
b63a84
 	.mmap_commit = snd_pcm_dshare_mmap_commit,
b63a84
 	.htimestamp = snd_pcm_dshare_htimestamp,
b63a84
-	.poll_descriptors = NULL,
b63a84
+	.poll_descriptors = snd_pcm_direct_poll_descriptors,
b63a84
 	.poll_descriptors_count = NULL,
b63a84
 	.poll_revents = snd_pcm_direct_poll_revents,
b63a84
 };
b63a84
diff --git a/src/pcm/pcm_dsnoop.c b/src/pcm/pcm_dsnoop.c
b63a84
index 618d469..a148771 100644
b63a84
--- a/src/pcm/pcm_dsnoop.c
b63a84
+++ b/src/pcm/pcm_dsnoop.c
b63a84
@@ -208,17 +208,22 @@ static int snd_pcm_dsnoop_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
b63a84
 static snd_pcm_state_t snd_pcm_dsnoop_state(snd_pcm_t *pcm)
b63a84
 {
b63a84
 	snd_pcm_direct_t *dsnoop = pcm->private_data;
b63a84
+	int err;
b63a84
 	snd_pcm_state_t state;
b63a84
 	state = snd_pcm_state(dsnoop->spcm);
b63a84
 	switch (state) {
b63a84
-	case SND_PCM_STATE_XRUN:
b63a84
 	case SND_PCM_STATE_SUSPENDED:
b63a84
 	case SND_PCM_STATE_DISCONNECTED:
b63a84
 		dsnoop->state = state;
b63a84
 		return state;
b63a84
+	case SND_PCM_STATE_XRUN:
b63a84
+		if ((err = snd_pcm_direct_slave_recover(dsnoop)) < 0)
b63a84
+			return err;
b63a84
+		break;
b63a84
 	default:
b63a84
 		break;
b63a84
 	}
b63a84
+	snd_pcm_direct_client_chk_xrun(dsnoop, pcm);
b63a84
 	return dsnoop->state;
b63a84
 }
b63a84
 
b63a84
@@ -531,7 +536,7 @@ static const snd_pcm_fast_ops_t snd_pcm_dsnoop_fast_ops = {
b63a84
 	.avail_update = snd_pcm_dsnoop_avail_update,
b63a84
 	.mmap_commit = snd_pcm_dsnoop_mmap_commit,
b63a84
 	.htimestamp = snd_pcm_dsnoop_htimestamp,
b63a84
-	.poll_descriptors = NULL,
b63a84
+	.poll_descriptors = snd_pcm_direct_poll_descriptors,
b63a84
 	.poll_descriptors_count = NULL,
b63a84
 	.poll_revents = snd_pcm_direct_poll_revents,
b63a84
 };
b63a84
-- 
b63a84
2.9.3
b63a84
b63a84
b63a84
From 79a358ae26f74ed9b92b2190d4725325edf0c787 Mon Sep 17 00:00:00 2001
b63a84
From: Andreas Pape <apape@de.adit-jv.com>
b63a84
Date: Tue, 10 Jan 2017 12:04:09 +0530
b63a84
Subject: [PATCH 13/37] pcm: direct: don't return bogus buffer levels in xrun
b63a84
 state
b63a84
b63a84
Signed-off-by: Andreas Pape <apape@de.adit-jv.com>
b63a84
Signed-off-by: Mounesh Sutar <mounesh_sutar@mentor.com>
b63a84
Signed-off-by: Takashi Iwai <tiwai@suse.de>
b63a84
---
b63a84
 src/pcm/pcm_dmix.c   | 3 +++
b63a84
 src/pcm/pcm_dshare.c | 3 +++
b63a84
 src/pcm/pcm_dsnoop.c | 3 +++
b63a84
 3 files changed, 9 insertions(+)
b63a84
b63a84
diff --git a/src/pcm/pcm_dmix.c b/src/pcm/pcm_dmix.c
b63a84
index 6664210..2ef6159 100644
b63a84
--- a/src/pcm/pcm_dmix.c
b63a84
+++ b/src/pcm/pcm_dmix.c
b63a84
@@ -882,6 +882,9 @@ static snd_pcm_sframes_t snd_pcm_dmix_avail_update(snd_pcm_t *pcm)
b63a84
 		if ((err = snd_pcm_dmix_sync_ptr(pcm)) < 0)
b63a84
 			return err;
b63a84
 	}
b63a84
+	if (dmix->state == SND_PCM_STATE_XRUN)
b63a84
+		return -EPIPE;
b63a84
+
b63a84
 	return snd_pcm_mmap_playback_avail(pcm);
b63a84
 }
b63a84
 
b63a84
diff --git a/src/pcm/pcm_dshare.c b/src/pcm/pcm_dshare.c
b63a84
index fdc95e3..331f799 100644
b63a84
--- a/src/pcm/pcm_dshare.c
b63a84
+++ b/src/pcm/pcm_dshare.c
b63a84
@@ -570,6 +570,9 @@ static snd_pcm_sframes_t snd_pcm_dshare_avail_update(snd_pcm_t *pcm)
b63a84
 		if ((err = snd_pcm_dshare_sync_ptr(pcm)) < 0)
b63a84
 			return err;
b63a84
 	}
b63a84
+	if (dshare->state == SND_PCM_STATE_XRUN)
b63a84
+		return -EPIPE;
b63a84
+
b63a84
 	return snd_pcm_mmap_playback_avail(pcm);
b63a84
 }
b63a84
 
b63a84
diff --git a/src/pcm/pcm_dsnoop.c b/src/pcm/pcm_dsnoop.c
b63a84
index a148771..539b671 100644
b63a84
--- a/src/pcm/pcm_dsnoop.c
b63a84
+++ b/src/pcm/pcm_dsnoop.c
b63a84
@@ -454,6 +454,9 @@ static snd_pcm_sframes_t snd_pcm_dsnoop_avail_update(snd_pcm_t *pcm)
b63a84
 		if (err < 0)
b63a84
 			return err;
b63a84
 	}
b63a84
+	if (dsnoop->state == SND_PCM_STATE_XRUN)
b63a84
+		return -EPIPE;
b63a84
+
b63a84
 	return snd_pcm_mmap_capture_avail(pcm);
b63a84
 }
b63a84
 
b63a84
-- 
b63a84
2.9.3
b63a84
b63a84
b63a84
From 360c976aaa051809c34cb412ffa52380baeaabee Mon Sep 17 00:00:00 2001
b63a84
From: Vinod Koul <vinod.koul@intel.com>
b63a84
Date: Thu, 12 Jan 2017 14:50:28 +0530
b63a84
Subject: [PATCH 14/37] conf/ucm: broxton: add broxton-rt298 conf files
b63a84
b63a84
This adds the UCM conf files for broxton enabling with rt298 codec on
b63a84
I2S audio, HDMI and DMIC ports.
b63a84
b63a84
Signed-off-by: Nishit Sharma <nishitx.sharma@intel.com>
b63a84
Signed-off-by: G Kranthi <gudishax.kranthikumar@intel.com>
b63a84
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
b63a84
Signed-off-by: Takashi Iwai <tiwai@suse.de>
b63a84
---
b63a84
 configure.ac                                  |   1 +
b63a84
 src/conf/ucm/Makefile.am                      |   2 +-
b63a84
 src/conf/ucm/broxton-rt298/Hdmi1              |  22 +++++
b63a84
 src/conf/ucm/broxton-rt298/Hdmi2              |  14 +++
b63a84
 src/conf/ucm/broxton-rt298/HiFi               | 129 ++++++++++++++++++++++++++
b63a84
 src/conf/ucm/broxton-rt298/Makefile.am        |   4 +
b63a84
 src/conf/ucm/broxton-rt298/broxton-rt298.conf |  58 ++++++++++++
b63a84
 7 files changed, 229 insertions(+), 1 deletion(-)
b63a84
 create mode 100644 src/conf/ucm/broxton-rt298/Hdmi1
b63a84
 create mode 100644 src/conf/ucm/broxton-rt298/Hdmi2
b63a84
 create mode 100644 src/conf/ucm/broxton-rt298/HiFi
b63a84
 create mode 100644 src/conf/ucm/broxton-rt298/Makefile.am
b63a84
 create mode 100644 src/conf/ucm/broxton-rt298/broxton-rt298.conf
b63a84
b63a84
diff --git a/configure.ac b/configure.ac
b63a84
index 71bd852..d645ab6 100644
b63a84
--- a/configure.ac
b63a84
+++ b/configure.ac
b63a84
@@ -684,6 +684,7 @@ AC_OUTPUT(Makefile doc/Makefile doc/pictures/Makefile doc/doxygen.cfg \
b63a84
 	  src/conf/topology/bxtrt298/Makefile \
b63a84
 	  alsalisp/Makefile aserver/Makefile \
b63a84
 	  test/Makefile test/lsb/Makefile \
b63a84
+	  src/conf/ucm/broxton-rt298/Makefile \
b63a84
 	  utils/Makefile utils/alsa-lib.spec utils/alsa.pc)
b63a84
 
b63a84
 dnl Create asoundlib.h dynamically according to configure options
b63a84
diff --git a/src/conf/ucm/Makefile.am b/src/conf/ucm/Makefile.am
b63a84
index a11d324..ea9b385 100644
b63a84
--- a/src/conf/ucm/Makefile.am
b63a84
+++ b/src/conf/ucm/Makefile.am
b63a84
@@ -1 +1 @@
b63a84
-SUBDIRS=DAISY-I2S PandaBoard PandaBoardES SDP4430 tegraalc5632 PAZ00 GoogleNyan broadwell-rt286 skylake-rt286 VEYRON-I2S chtrt5645 DB410c
b63a84
+SUBDIRS=DAISY-I2S PandaBoard PandaBoardES SDP4430 tegraalc5632 PAZ00 GoogleNyan broadwell-rt286 skylake-rt286 VEYRON-I2S chtrt5645 DB410c broxton-rt298
b63a84
diff --git a/src/conf/ucm/broxton-rt298/Hdmi1 b/src/conf/ucm/broxton-rt298/Hdmi1
b63a84
new file mode 100644
b63a84
index 0000000..48514f4
b63a84
--- /dev/null
b63a84
+++ b/src/conf/ucm/broxton-rt298/Hdmi1
b63a84
@@ -0,0 +1,22 @@
b63a84
+# Usecase for device HDMI1/Display Port stereo playback on Intel SKYLAKE/KABYLAKE platforms
b63a84
+# For Audio in I2S mode
b63a84
+
b63a84
+SectionDevice."Hdmi1" {
b63a84
+        Comment "HDMI/Display Port 1 Stereo"
b63a84
+
b63a84
+        EnableSequence [
b63a84
+                exec "echo Hdmi1 EnableSequnece"
b63a84
+        ]
b63a84
+
b63a84
+        DisableSequence [
b63a84
+                exec "echo Hdmi1 DisableSequnece"
b63a84
+        ]
b63a84
+
b63a84
+        Value {
b63a84
+                PlaybackPCM "hw:broxtonrt298,4"
b63a84
+                PlaybackChannels "2"
b63a84
+                PlaybackPriority "3"
b63a84
+                JackControl "HDMI/DP, pcm=4 Jack"
b63a84
+        }
b63a84
+}
b63a84
+
b63a84
diff --git a/src/conf/ucm/broxton-rt298/Hdmi2 b/src/conf/ucm/broxton-rt298/Hdmi2
b63a84
new file mode 100644
b63a84
index 0000000..764f8b9
b63a84
--- /dev/null
b63a84
+++ b/src/conf/ucm/broxton-rt298/Hdmi2
b63a84
@@ -0,0 +1,14 @@
b63a84
+# Usecase for device HDMI2/Display Port stereo playback on Intel Broxton platforms
b63a84
+# For Audio in I2S mode
b63a84
+
b63a84
+SectionDevice."Hdmi2" {
b63a84
+        Comment "HDMI/Display Port 2 Stereo"
b63a84
+
b63a84
+        Value {
b63a84
+                PlaybackPCM "hw:broxtonrt298,5"
b63a84
+                PlaybackChannels "2"
b63a84
+                PlaybackPriority "4"
b63a84
+                JackControl "HDMI/DP, pcm=5 Jack"
b63a84
+        }
b63a84
+}
b63a84
+
b63a84
diff --git a/src/conf/ucm/broxton-rt298/HiFi b/src/conf/ucm/broxton-rt298/HiFi
b63a84
new file mode 100644
b63a84
index 0000000..2e2d6fe
b63a84
--- /dev/null
b63a84
+++ b/src/conf/ucm/broxton-rt298/HiFi
b63a84
@@ -0,0 +1,129 @@
b63a84
+# Usecase for stereo playback Speaker and Headset, Recording on DMIC and Headset MIC.
b63a84
+# For Audio in I2S mode on Intel Broxton platforms
b63a84
+
b63a84
+SectionVerb {
b63a84
+
b63a84
+	EnableSequence [
b63a84
+		cdev "hw:broxtonrt298"
b63a84
+		cset "name='media0_out mo dmic01_hifi_in mi Switch' 1"
b63a84
+	]
b63a84
+
b63a84
+	DisableSequence [
b63a84
+		cdev "hw:broxtonrt298"
b63a84
+	]
b63a84
+
b63a84
+	Value {
b63a84
+		TQ "HiFi"
b63a84
+		CapturePCM "hw:broxtonrt298,1"
b63a84
+		PlaybackPCM "hw:broxtonrt298,0"
b63a84
+	}
b63a84
+}
b63a84
+
b63a84
+SectionDevice."dmiccap" {
b63a84
+	Comment "DMIC Stereo"
b63a84
+
b63a84
+	ConflictingDevice [
b63a84
+		"Headset"
b63a84
+	]
b63a84
+
b63a84
+	EnableSequence [
b63a84
+
b63a84
+		cdev "hw:broxtonrt298"
b63a84
+		exec "echo broxtonrt298 dmiccap called"
b63a84
+		cset "name='media0_out mo dmic01_hifi_in mi Switch' 1"
b63a84
+		cset "name='media0_out mo codec0_in mi Switch' 0"
b63a84
+		cset "name='Mic Jack Switch' 0"
b63a84
+
b63a84
+	]
b63a84
+
b63a84
+	DisableSequence [
b63a84
+		cdev "hw:broxtonrt298"
b63a84
+		cset "name='media0_out mo codec0_in mi Switch' 1"
b63a84
+		cset "name='media0_out mo dmic01_hifi_in mi Switch' 0"
b63a84
+		cset "name='Mic Jack Switch' 1"
b63a84
+		cset "name='ADC 0 Mux' 0"
b63a84
+	]
b63a84
+	Value {
b63a84
+		CaptureChannels "2"
b63a84
+		CapturePriority "2"
b63a84
+	}
b63a84
+}
b63a84
+
b63a84
+SectionDevice."Headphones" {
b63a84
+	Comment "Headphones"
b63a84
+
b63a84
+	ConflictingDevice [
b63a84
+		"Speaker"
b63a84
+	]
b63a84
+	EnableSequence [
b63a84
+		cdev "hw:broxtonrt298"
b63a84
+		exec "echo broxtonrt298 Headphone called"
b63a84
+		cset "name='HPO L Switch' 1"
b63a84
+		cset "name='HPO R Switch' 1"
b63a84
+		cset "name='Headphone Jack Switch' 1"
b63a84
+		cset "name='Speaker Playback Switch' 0,0"
b63a84
+	]
b63a84
+
b63a84
+	DisableSequence [
b63a84
+		cdev "hw:broxtonrt298"
b63a84
+	]
b63a84
+	Value {
b63a84
+		PlaybackChannels "2"
b63a84
+		PlaybackPriority "1"
b63a84
+		JackControl "Headphone Jack"
b63a84
+		JackHWMute "Speaker"
b63a84
+	}
b63a84
+}
b63a84
+
b63a84
+SectionDevice."Speaker" {
b63a84
+	Comment "Speaker"
b63a84
+
b63a84
+	ConflictingDevice [
b63a84
+		"Headphones"
b63a84
+	]
b63a84
+	EnableSequence [
b63a84
+		cdev "hw:broxtonrt298"
b63a84
+		exec "echo broxtonrt298 speaker called"
b63a84
+		cset "name='SPO Switch' 1"
b63a84
+		cset "name='Speaker Playback Switch' 1,1"
b63a84
+		cset "name='Speaker Switch' 1"
b63a84
+		cset "name='HPO L Switch' 0"
b63a84
+		cset "name='HPO R Switch' 0"
b63a84
+	]
b63a84
+
b63a84
+	DisableSequence [
b63a84
+	]
b63a84
+	Value {
b63a84
+		PlaybackChannels "2"
b63a84
+		PlaybackPriority "1"
b63a84
+		JackHWMute "Headphones"
b63a84
+	}
b63a84
+}
b63a84
+
b63a84
+SectionDevice."Headset" {
b63a84
+	Comment "Headset Mic"
b63a84
+
b63a84
+	ConflictingDevice [
b63a84
+		"dmiccap"
b63a84
+	]
b63a84
+	EnableSequence [
b63a84
+		cdev "hw:broxtonrt298"
b63a84
+		exec "echo broxtonrt298 Headset called"
b63a84
+		cset "name='media0_out mo codec0_in mi Switch' 1"
b63a84
+		cset "name='ADC0 Capture Volume' 105,105"
b63a84
+		cset "name='ADC 0 Mux' 0"
b63a84
+		cset "name='Mic Jack Switch' 1"
b63a84
+		cset "name='media0_out mo dmic01_hifi_in mi Switch' 0"
b63a84
+	]
b63a84
+
b63a84
+	DisableSequence [
b63a84
+		cdev "hw:broxtonrt298"
b63a84
+		cset "name='media0_out mo dmic01_hifi_in mi Switch' 1"
b63a84
+		cset "name='media0_out mo codec0_in mi Switch' 0"
b63a84
+	]
b63a84
+	Value {
b63a84
+		CaptureChannels "2"
b63a84
+		CapturePriority "2"
b63a84
+		JackControl "Mic Jack"
b63a84
+	}
b63a84
+}
b63a84
diff --git a/src/conf/ucm/broxton-rt298/Makefile.am b/src/conf/ucm/broxton-rt298/Makefile.am
b63a84
new file mode 100644
b63a84
index 0000000..80f480e
b63a84
--- /dev/null
b63a84
+++ b/src/conf/ucm/broxton-rt298/Makefile.am
b63a84
@@ -0,0 +1,4 @@
b63a84
+alsaconfigdir = @ALSA_CONFIG_DIR@
b63a84
+ucmdir = $(alsaconfigdir)/ucm/broxton-rt298
b63a84
+ucm_DATA = broxton-rt298.conf HiFi Hdmi1 Hdmi2
b63a84
+EXTRA_DIST = $(ucm_DATA)
b63a84
diff --git a/src/conf/ucm/broxton-rt298/broxton-rt298.conf b/src/conf/ucm/broxton-rt298/broxton-rt298.conf
b63a84
new file mode 100644
b63a84
index 0000000..3f3d0be
b63a84
--- /dev/null
b63a84
+++ b/src/conf/ucm/broxton-rt298/broxton-rt298.conf
b63a84
@@ -0,0 +1,58 @@
b63a84
+# UCM for Intel Broxton platforms
b63a84
+# For Audio in I2S mode
b63a84
+
b63a84
+SectionUseCase."HiFi" {
b63a84
+	File "HiFi"
b63a84
+	Comment "Play and record HiFi quality Music"
b63a84
+}
b63a84
+
b63a84
+SectionUseCase."Hdmi1" {
b63a84
+        File "Hdmi1"
b63a84
+        Comment "Play on Hdmi/DP 1"
b63a84
+}
b63a84
+
b63a84
+SectionUseCase."Hdmi2" {
b63a84
+        File "Hdmi2"
b63a84
+        Comment "Play on Hdmi/DP 2"
b63a84
+}
b63a84
+
b63a84
+ValueDefaults {
b63a84
+	PlaybackCTL "hw:broxtonrt298"
b63a84
+	CaptureCTL "hw:broxtonrt298"
b63a84
+	CaptureChannels "2"
b63a84
+	CapturePriority "2"
b63a84
+}
b63a84
+
b63a84
+SectionDefaults [
b63a84
+	cdev "hw:broxtonrt298"
b63a84
+	exec "echo broxtonrt298 CONF Defaults"
b63a84
+	cset "name='Headphone Jack Switch' 1"
b63a84
+	cset "name='Speaker Switch' 1"
b63a84
+	cset "name='Speaker Playback Switch' 0,0"
b63a84
+	cset "name='Front DAC Switch' 1"
b63a84
+	cset "name='Front RECMIX Switch' 0"
b63a84
+	cset "name='Mic Jack Switch' 1"
b63a84
+	cset "name='ADC 0 Mux' 2"
b63a84
+	cset "name='ADC 1 Mux' 0"
b63a84
+	cset "name='DAC0 Playback Volume' 100,100"
b63a84
+	cset "name='HPO L Switch' 0"
b63a84
+	cset "name='HPO Mux' 0"
b63a84
+	cset "name='HPO R Switch' 0"
b63a84
+	cset "name='Pin 5 Mux' 1"
b63a84
+	cset "name='Pin 6 Mux' 2"
b63a84
+	cset "name='Pin 7 Mux' 3"
b63a84
+	cset "name='RECMIX Beep Switch' 0"
b63a84
+	cset "name='RECMIX Line1 Switch' 0"
b63a84
+	cset "name='RECMIX Mic1 Switch' 0"
b63a84
+	cset "name='SPK Mux' 0"
b63a84
+	cset "name='SPO Switch' 1"
b63a84
+	cset "name='codec0_out mo codec0_in mi Switch' 0"
b63a84
+	cset "name='codec0_out mo dmic01_hifi_in mi Switch' 0"
b63a84
+	cset "name='codec0_out mo media0_in mi Switch' 1"
b63a84
+	cset "name='codec1_out mo codec0_in mi Switch' 0"
b63a84
+	cset "name='codec1_out mo dmic01_hifi_in mi Switch' 0"
b63a84
+	cset "name='codec1_out mo media0_in mi Switch' 0"
b63a84
+	cset "name='media0_out mo codec0_in mi Switch' 1"
b63a84
+	cset "name='media0_out mo dmic01_hifi_in mi Switch' 1"
b63a84
+	cset "name='media0_out mo media0_in mi Switch' 0"
b63a84
+]
b63a84
-- 
b63a84
2.9.3
b63a84
b63a84
b63a84
From 24e63b75275e9c923c336b8dba3919b980e8f234 Mon Sep 17 00:00:00 2001
b63a84
From: Takashi Iwai <tiwai@suse.de>
b63a84
Date: Mon, 16 Jan 2017 16:21:52 +0100
b63a84
Subject: [PATCH 15/37] pcm: direct: Fix deadlock in poll_descriptors
b63a84
b63a84
The recent change in PCM direct plugins to check XRUN in
b63a84
poll_descriptors callback caused a regression; as consequence, the
b63a84
whole playback hangs up.
b63a84
b63a84
The culprit is a mutex dead lock by the call in snd_pcm_state() inside
b63a84
the new snd_pcm_direct_poll_descriptors().  The poll_descriptors code
b63a84
path is protected with pcm mutex, thus an unlocked version
b63a84
(__snd_pcm_state()) has to be used inside the callback instead.
b63a84
b63a84
Fixes: 789ee39727a1 ("pcm: direct: check state before enter poll on timer")
b63a84
Signed-off-by: Takashi Iwai <tiwai@suse.de>
b63a84
---
b63a84
 src/pcm/pcm_direct.c | 3 ++-
b63a84
 1 file changed, 2 insertions(+), 1 deletion(-)
b63a84
b63a84
diff --git a/src/pcm/pcm_direct.c b/src/pcm/pcm_direct.c
b63a84
index f4d7c3f..e4bef78 100644
b63a84
--- a/src/pcm/pcm_direct.c
b63a84
+++ b/src/pcm/pcm_direct.c
b63a84
@@ -676,7 +676,8 @@ int snd_pcm_direct_poll_descriptors(snd_pcm_t *pcm, struct pollfd *pfds,
b63a84
 	}
b63a84
 
b63a84
 	/* this will also evaluate slave state and enter xrun if necessary */
b63a84
-	switch (snd_pcm_state(pcm)) {
b63a84
+	/* using __snd_pcm_state() since this function is called inside lock */
b63a84
+	switch (__snd_pcm_state(pcm)) {
b63a84
 	case SND_PCM_STATE_XRUN:
b63a84
 		return -EPIPE;
b63a84
 	default:
b63a84
-- 
b63a84
2.9.3
b63a84
b63a84
b63a84
From 2b9b3f013467765219c8ab8a50943d3c7db68f75 Mon Sep 17 00:00:00 2001
b63a84
From: Mengdong Lin <mengdong.lin@linux.intel.com>
b63a84
Date: Wed, 18 Jan 2017 11:52:35 +0800
b63a84
Subject: [PATCH 16/37] ucm: Assure the user input card name not to exceed max
b63a84
 size of card long name
b63a84
b63a84
Users can load a card's UCM configuration file by giving the card short
b63a84
name or long name, which should not exceed the maximum card long name
b63a84
defined by the kernel. The kernel uses an 80-character buffer to store
b63a84
the card long name.
b63a84
b63a84
Signed-off-by: Mengdong Lin <mengdong.lin@linux.intel.com>
b63a84
Signed-off-by: Takashi Iwai <tiwai@suse.de>
b63a84
---
b63a84
 src/ucm/parser.c    | 6 ++++++
b63a84
 src/ucm/ucm_local.h | 1 +
b63a84
 2 files changed, 7 insertions(+)
b63a84
b63a84
diff --git a/src/ucm/parser.c b/src/ucm/parser.c
b63a84
index f520abc..f61201a 100644
b63a84
--- a/src/ucm/parser.c
b63a84
+++ b/src/ucm/parser.c
b63a84
@@ -1335,6 +1335,12 @@ static int load_master_config(const char *card_name, snd_config_t **cfg)
b63a84
 	char *env = getenv(ALSA_CONFIG_UCM_VAR);
b63a84
 	int err;
b63a84
 
b63a84
+	if (strnlen(card_name, MAX_CARD_LONG_NAME) == MAX_CARD_LONG_NAME) {
b63a84
+		uc_error("error: invalid card name %s (at most %d chars)\n",
b63a84
+			 card_name, MAX_CARD_LONG_NAME - 1);
b63a84
+		return -EINVAL;
b63a84
+	}
b63a84
+
b63a84
 	snprintf(filename, sizeof(filename)-1,
b63a84
 		"%s/%s/%s.conf", env ? env : ALSA_USE_CASE_DIR,
b63a84
 		card_name, card_name);
b63a84
diff --git a/src/ucm/ucm_local.h b/src/ucm/ucm_local.h
b63a84
index 6d3302f..e41aafa 100644
b63a84
--- a/src/ucm/ucm_local.h
b63a84
+++ b/src/ucm/ucm_local.h
b63a84
@@ -41,6 +41,7 @@
b63a84
 #include "use-case.h"
b63a84
 
b63a84
 #define MAX_FILE		256
b63a84
+#define MAX_CARD_LONG_NAME	80
b63a84
 #define ALSA_USE_CASE_DIR	ALSA_CONFIG_DIR "/ucm"
b63a84
 
b63a84
 #define SEQUENCE_ELEMENT_TYPE_CDEV	1
b63a84
-- 
b63a84
2.9.3
b63a84
b63a84
b63a84
From 4b9297e65f541f1a6c1b4a036f66936b9cafe030 Mon Sep 17 00:00:00 2001
b63a84
From: Mengdong Lin <mengdong.lin@linux.intel.com>
b63a84
Date: Wed, 18 Jan 2017 11:53:35 +0800
b63a84
Subject: [PATCH 17/37] ucm: Load device-specific configuration file based on
b63a84
 the card long name
b63a84
b63a84
Intel DSP platform drivers are used by many different devices. For user
b63a84
space to differentiate them, ASoC machine drivers may use the DMI info
b63a84
(vendor-product-version-board) as card long name. Possible card long names
b63a84
are:
b63a84
DellInc.-XPS139343-01-0310JH
b63a84
ASUSTeKCOMPUTERINC.-T100TA-1.0-T100TA
b63a84
Circuitco-MinnowboardMaxD0PLATFORM-D0-MinnowBoardMAX
b63a84
...
b63a84
b63a84
If we want to define a device-specific UCM config file for a card, we
b63a84
need to use the card long name as the name of both the directory that
b63a84
contains the UCM config file and the UCM config file itself, like
b63a84
longname/longname.conf
b63a84
b63a84
When being asked to load configuration file of a card, UCM will try to
b63a84
find the card in the local machine and get its long name. If the card
b63a84
long name is available, try to load the file longname/longname.conf to
b63a84
get the best device-specific configuration; if this file is not available,
b63a84
fall back to load the default configuration file shortname/shortname.conf
b63a84
as before.
b63a84
b63a84
This update is backward compatible, because if ASoC machine drivers don't
b63a84
explicity use DMI or other means to set the card long name, ASoC core
b63a84
will use the card short name as the long name. And so UCM will load the
b63a84
config file that matches both the card short name and the long name.
b63a84
b63a84
Signed-off-by: Mengdong Lin <mengdong.lin@linux.intel.com>
b63a84
Signed-off-by: Takashi Iwai <tiwai@suse.de>
b63a84
---
b63a84
 src/ucm/parser.c    | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++---
b63a84
 src/ucm/ucm_local.h |  2 ++
b63a84
 2 files changed, 97 insertions(+), 4 deletions(-)
b63a84
b63a84
diff --git a/src/ucm/parser.c b/src/ucm/parser.c
b63a84
index f61201a..798bf48 100644
b63a84
--- a/src/ucm/parser.c
b63a84
+++ b/src/ucm/parser.c
b63a84
@@ -56,6 +56,9 @@ static const char * const component_dir[] = {
b63a84
 	NULL,		/* terminator */
b63a84
 };
b63a84
 
b63a84
+static int filename_filter(const struct dirent *dirent);
b63a84
+static int is_component_directory(const char *dir);
b63a84
+
b63a84
 static int parse_sequence(snd_use_case_mgr_t *uc_mgr,
b63a84
 			  struct list_head *base,
b63a84
 			  snd_config_t *cfg);
b63a84
@@ -1329,6 +1332,66 @@ static int parse_master_file(snd_use_case_mgr_t *uc_mgr, snd_config_t *cfg)
b63a84
 	return 0;
b63a84
 }
b63a84
 
b63a84
+/* find the card in the local machine and store the card long name */
b63a84
+static int get_card_long_name(snd_use_case_mgr_t *mgr)
b63a84
+{
b63a84
+	const char *card_name = mgr->card_name;
b63a84
+	snd_ctl_t *handle;
b63a84
+	int card, err;
b63a84
+	snd_ctl_card_info_t *info;
b63a84
+	const char *_name, *_long_name;
b63a84
+
b63a84
+	snd_ctl_card_info_alloca(&info;;
b63a84
+
b63a84
+	card = -1;
b63a84
+	if (snd_card_next(&card) < 0 || card < 0) {
b63a84
+		uc_error("no soundcards found...");
b63a84
+		return -1;
b63a84
+	}
b63a84
+
b63a84
+	while (card >= 0) {
b63a84
+		char name[32];
b63a84
+
b63a84
+		sprintf(name, "hw:%d", card);
b63a84
+		err = snd_ctl_open(&handle, name, 0);
b63a84
+		if (err < 0) {
b63a84
+			uc_error("control open (%i): %s", card,
b63a84
+				 snd_strerror(err));
b63a84
+			goto next_card;
b63a84
+		}
b63a84
+
b63a84
+		err = snd_ctl_card_info(handle, info);
b63a84
+		if (err < 0) {
b63a84
+			uc_error("control hardware info (%i): %s", card,
b63a84
+				 snd_strerror(err));
b63a84
+			snd_ctl_close(handle);
b63a84
+			goto next_card;
b63a84
+		}
b63a84
+
b63a84
+		/* Find the local card by comparing the given name with the
b63a84
+		 * card short name and long name. The given card name may be
b63a84
+		 * either a short name or long name, because users may open
b63a84
+		 * the card by either of the two names.
b63a84
+		 */
b63a84
+		_name = snd_ctl_card_info_get_name(info);
b63a84
+		_long_name = snd_ctl_card_info_get_longname(info);
b63a84
+		if (!strcmp(card_name, _name)
b63a84
+		    || !strcmp(card_name, _long_name)) {
b63a84
+			strcpy(mgr->card_long_name, _long_name);
b63a84
+			snd_ctl_close(handle);
b63a84
+			return 0;
b63a84
+		}
b63a84
+
b63a84
+		snd_ctl_close(handle);
b63a84
+next_card:
b63a84
+		if (snd_card_next(&card) < 0) {
b63a84
+			uc_error("snd_card_next");
b63a84
+			break;
b63a84
+		}
b63a84
+	}
b63a84
+
b63a84
+	return -1;
b63a84
+}
b63a84
 static int load_master_config(const char *card_name, snd_config_t **cfg)
b63a84
 {
b63a84
 	char filename[MAX_FILE];
b63a84
@@ -1356,15 +1419,43 @@ static int load_master_config(const char *card_name, snd_config_t **cfg)
b63a84
 	return 0;
b63a84
 }
b63a84
 
b63a84
-/* load master use case file for sound card */
b63a84
+/* load master use case file for sound card
b63a84
+ *
b63a84
+ * The same ASoC machine driver can be shared by many different devices.
b63a84
+ * For user space to differentiate them and get the best device-specific
b63a84
+ * configuration, ASoC machine drivers may use the DMI info
b63a84
+ * (vendor-product-version-board) as the card long name. And user space can
b63a84
+ * define configuration files like longnamei/longname.conf for a specific device.
b63a84
+ *
b63a84
+ * This function will try to find the card in the local machine and get its
b63a84
+ * long name, then load the file longname/longname.conf to get the best
b63a84
+ * device-specific configuration. If the card is not found in the local
b63a84
+ * machine or the device-specific file is not available, fall back to load
b63a84
+ * the default configuration file name/name.conf.
b63a84
+ */
b63a84
 int uc_mgr_import_master_config(snd_use_case_mgr_t *uc_mgr)
b63a84
 {
b63a84
 	snd_config_t *cfg;
b63a84
 	int err;
b63a84
 
b63a84
-	err = load_master_config(uc_mgr->card_name, &cfg;;
b63a84
-	if (err < 0)
b63a84
-		return err;
b63a84
+	err = get_card_long_name(uc_mgr);
b63a84
+	if (err == 0)	/* load file that maches the card long name */
b63a84
+		err = load_master_config(uc_mgr->card_long_name, &cfg;;
b63a84
+
b63a84
+	if (err == 0) {
b63a84
+		/* got device-specific file that matches the card long name */
b63a84
+		strcpy(uc_mgr->conf_file_name, uc_mgr->card_long_name);
b63a84
+	} else {
b63a84
+		/* Fall back to the file that maches the given card name,
b63a84
+		 * either short name or long name (users may open a card by
b63a84
+		 * its name or long name).
b63a84
+		 */
b63a84
+		err = load_master_config(uc_mgr->card_name, &cfg;;
b63a84
+		if (err < 0)
b63a84
+			return err;
b63a84
+		strcpy(uc_mgr->conf_file_name, uc_mgr->card_name);
b63a84
+	}
b63a84
+
b63a84
 	err = parse_master_file(uc_mgr, cfg);
b63a84
 	snd_config_delete(cfg);
b63a84
 	if (err < 0)
b63a84
diff --git a/src/ucm/ucm_local.h b/src/ucm/ucm_local.h
b63a84
index e41aafa..299a5b9 100644
b63a84
--- a/src/ucm/ucm_local.h
b63a84
+++ b/src/ucm/ucm_local.h
b63a84
@@ -191,6 +191,8 @@ struct use_case_verb {
b63a84
  */
b63a84
 struct snd_use_case_mgr {
b63a84
 	char *card_name;
b63a84
+	char card_long_name[MAX_CARD_LONG_NAME];
b63a84
+	char conf_file_name[MAX_CARD_LONG_NAME];
b63a84
 	char *comment;
b63a84
 
b63a84
 	/* use case verb, devices and modifier configs parsed from files */
b63a84
-- 
b63a84
2.9.3
b63a84
b63a84
b63a84
From e93d93a8cd37f94f119aba72ca05d7f92b648bcc Mon Sep 17 00:00:00 2001
b63a84
From: Mengdong Lin <mengdong.lin@linux.intel.com>
b63a84
Date: Wed, 18 Jan 2017 11:53:42 +0800
b63a84
Subject: [PATCH 18/37] ucm: Add command 'get _file' to get the config file
b63a84
 name of the opened card
b63a84
b63a84
After opening a card, this command can show the name of the actually
b63a84
loaded configuration file, either matches the card name or card long name.
b63a84
So developers can check if there is a device-sepcific configuration file
b63a84
available for a given card.
b63a84
b63a84
Signed-off-by: Mengdong Lin <mengdong.lin@linux.intel.com>
b63a84
Signed-off-by: Takashi Iwai <tiwai@suse.de>
b63a84
---
b63a84
 include/use-case.h |  1 +
b63a84
 src/ucm/main.c     | 14 ++++++++++++++
b63a84
 2 files changed, 15 insertions(+)
b63a84
b63a84
diff --git a/include/use-case.h b/include/use-case.h
b63a84
index 8911645..ae22bde 100644
b63a84
--- a/include/use-case.h
b63a84
+++ b/include/use-case.h
b63a84
@@ -230,6 +230,7 @@ int snd_use_case_get_list(snd_use_case_mgr_t *uc_mgr,
b63a84
  * Known identifiers:
b63a84
  *   - NULL 		- return current card
b63a84
  *   - _verb		- return current verb
b63a84
+ *   - _file		- return configuration file loaded for current card
b63a84
  *
b63a84
  *   - [=]{NAME}[/[{modifier}|{/device}][/{verb}]]
b63a84
  *                      - value identifier {NAME}
b63a84
diff --git a/src/ucm/main.c b/src/ucm/main.c
b63a84
index 38a5e81..2d33886 100644
b63a84
--- a/src/ucm/main.c
b63a84
+++ b/src/ucm/main.c
b63a84
@@ -1528,6 +1528,20 @@ int snd_use_case_get(snd_use_case_mgr_t *uc_mgr,
b63a84
                         goto __end;
b63a84
                 }
b63a84
 	        err = 0;
b63a84
+	} else if (strcmp(identifier, "_file") == 0) {
b63a84
+		/* get the conf file name of the opened card */
b63a84
+		if ((uc_mgr->card_name == NULL)
b63a84
+		    || (uc_mgr->conf_file_name[0] == '\0')) {
b63a84
+			err = -ENOENT;
b63a84
+			goto __end;
b63a84
+		}
b63a84
+		*value = strndup(uc_mgr->conf_file_name, MAX_FILE);
b63a84
+		if (*value == NULL) {
b63a84
+			err = -ENOMEM;
b63a84
+			goto __end;
b63a84
+		}
b63a84
+		err = 0;
b63a84
+
b63a84
 	} else if (identifier[0] == '_') {
b63a84
 		err = -ENOENT;
b63a84
 		goto __end;
b63a84
-- 
b63a84
2.9.3
b63a84
b63a84
b63a84
From ec40aafa4374f2388876702513c4b3eee2e2235f Mon Sep 17 00:00:00 2001
b63a84
From: Liam Girdwood <liam.r.girdwood@linux.intel.com>
b63a84
Date: Tue, 24 Jan 2017 14:59:08 +0000
b63a84
Subject: [PATCH 19/37] topology: Fix incorrect license in source comments.
b63a84
b63a84
The topology source files had the wrong licence specified in the
b63a84
comments when initially upstreamed. The topology source files are all
b63a84
licensed under the LGPL-2.1 and not the GPLv2.
b63a84
b63a84
All earlier versions of the alsa-lib topology source files must be
b63a84
considered LGPL-2.1 like the other source files in alsa-lib and also
b63a84
as specified in the alsa-lib COPYING file.
b63a84
b63a84
Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
b63a84
Signed-off-by: Takashi Iwai <tiwai@suse.de>
b63a84
---
b63a84
 src/topology/builder.c | 17 +++++++++--------
b63a84
 src/topology/channel.c | 17 +++++++++--------
b63a84
 src/topology/ctl.c     | 17 +++++++++--------
b63a84
 src/topology/dapm.c    | 17 +++++++++--------
b63a84
 src/topology/data.c    | 17 +++++++++--------
b63a84
 src/topology/elem.c    | 17 +++++++++--------
b63a84
 src/topology/ops.c     | 17 +++++++++--------
b63a84
 src/topology/parser.c  | 17 +++++++++--------
b63a84
 src/topology/pcm.c     | 17 +++++++++--------
b63a84
 src/topology/text.c    | 17 +++++++++--------
b63a84
 10 files changed, 90 insertions(+), 80 deletions(-)
b63a84
b63a84
diff --git a/src/topology/builder.c b/src/topology/builder.c
b63a84
index 20fa925..dcd9e2a 100644
b63a84
--- a/src/topology/builder.c
b63a84
+++ b/src/topology/builder.c
b63a84
@@ -2,14 +2,15 @@
b63a84
   Copyright(c) 2014-2015 Intel Corporation
b63a84
   All rights reserved.
b63a84
 
b63a84
-  This program is free software; you can redistribute it and/or modify
b63a84
-  it under the terms of version 2 of the GNU General Public License as
b63a84
-  published by the Free Software Foundation.
b63a84
-
b63a84
-  This program is distributed in the hope that it will be useful, but
b63a84
-  WITHOUT ANY WARRANTY; without even the implied warranty of
b63a84
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
b63a84
-  General Public License for more details.
b63a84
+  This library is free software; you can redistribute it and/or modify
b63a84
+  it under the terms of the GNU Lesser General Public License as
b63a84
+  published by the Free Software Foundation; either version 2.1 of
b63a84
+  the License, or (at your option) any later version.
b63a84
+
b63a84
+  This program is distributed in the hope that it will be useful,
b63a84
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
b63a84
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
b63a84
+  GNU Lesser General Public License for more details.
b63a84
 
b63a84
   Authors: Mengdong Lin <mengdong.lin@intel.com>
b63a84
            Yao Jin <yao.jin@intel.com>
b63a84
diff --git a/src/topology/channel.c b/src/topology/channel.c
b63a84
index c2f1fea..8516b23 100644
b63a84
--- a/src/topology/channel.c
b63a84
+++ b/src/topology/channel.c
b63a84
@@ -2,14 +2,15 @@
b63a84
   Copyright(c) 2014-2015 Intel Corporation
b63a84
   All rights reserved.
b63a84
 
b63a84
-  This program is free software; you can redistribute it and/or modify
b63a84
-  it under the terms of version 2 of the GNU General Public License as
b63a84
-  published by the Free Software Foundation.
b63a84
-
b63a84
-  This program is distributed in the hope that it will be useful, but
b63a84
-  WITHOUT ANY WARRANTY; without even the implied warranty of
b63a84
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
b63a84
-  General Public License for more details.
b63a84
+  This library is free software; you can redistribute it and/or modify
b63a84
+  it under the terms of the GNU Lesser General Public License as
b63a84
+  published by the Free Software Foundation; either version 2.1 of
b63a84
+  the License, or (at your option) any later version.
b63a84
+
b63a84
+  This program is distributed in the hope that it will be useful,
b63a84
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
b63a84
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
b63a84
+  GNU Lesser General Public License for more details.
b63a84
 
b63a84
   Authors: Mengdong Lin <mengdong.lin@intel.com>
b63a84
            Yao Jin <yao.jin@intel.com>
b63a84
diff --git a/src/topology/ctl.c b/src/topology/ctl.c
b63a84
index 907a97f..1da3d18 100644
b63a84
--- a/src/topology/ctl.c
b63a84
+++ b/src/topology/ctl.c
b63a84
@@ -2,14 +2,15 @@
b63a84
   Copyright(c) 2014-2015 Intel Corporation
b63a84
   All rights reserved.
b63a84
 
b63a84
-  This program is free software; you can redistribute it and/or modify
b63a84
-  it under the terms of version 2 of the GNU General Public License as
b63a84
-  published by the Free Software Foundation.
b63a84
-
b63a84
-  This program is distributed in the hope that it will be useful, but
b63a84
-  WITHOUT ANY WARRANTY; without even the implied warranty of
b63a84
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
b63a84
-  General Public License for more details.
b63a84
+  This library is free software; you can redistribute it and/or modify
b63a84
+  it under the terms of the GNU Lesser General Public License as
b63a84
+  published by the Free Software Foundation; either version 2.1 of
b63a84
+  the License, or (at your option) any later version.
b63a84
+
b63a84
+  This program is distributed in the hope that it will be useful,
b63a84
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
b63a84
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
b63a84
+  GNU Lesser General Public License for more details.
b63a84
 
b63a84
   Authors: Mengdong Lin <mengdong.lin@intel.com>
b63a84
            Yao Jin <yao.jin@intel.com>
b63a84
diff --git a/src/topology/dapm.c b/src/topology/dapm.c
b63a84
index 8c585a7..eef72bb 100644
b63a84
--- a/src/topology/dapm.c
b63a84
+++ b/src/topology/dapm.c
b63a84
@@ -2,14 +2,15 @@
b63a84
   Copyright(c) 2014-2015 Intel Corporation
b63a84
   All rights reserved.
b63a84
 
b63a84
-  This program is free software; you can redistribute it and/or modify
b63a84
-  it under the terms of version 2 of the GNU General Public License as
b63a84
-  published by the Free Software Foundation.
b63a84
-
b63a84
-  This program is distributed in the hope that it will be useful, but
b63a84
-  WITHOUT ANY WARRANTY; without even the implied warranty of
b63a84
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
b63a84
-  General Public License for more details.
b63a84
+  This library is free software; you can redistribute it and/or modify
b63a84
+  it under the terms of the GNU Lesser General Public License as
b63a84
+  published by the Free Software Foundation; either version 2.1 of
b63a84
+  the License, or (at your option) any later version.
b63a84
+
b63a84
+  This program is distributed in the hope that it will be useful,
b63a84
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
b63a84
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
b63a84
+  GNU Lesser General Public License for more details.
b63a84
 
b63a84
   Authors: Mengdong Lin <mengdong.lin@intel.com>
b63a84
            Yao Jin <yao.jin@intel.com>
b63a84
diff --git a/src/topology/data.c b/src/topology/data.c
b63a84
index 0d5c430..e2aa38c 100644
b63a84
--- a/src/topology/data.c
b63a84
+++ b/src/topology/data.c
b63a84
@@ -2,14 +2,15 @@
b63a84
   Copyright(c) 2014-2015 Intel Corporation
b63a84
   All rights reserved.
b63a84
 
b63a84
-  This program is free software; you can redistribute it and/or modify
b63a84
-  it under the terms of version 2 of the GNU General Public License as
b63a84
-  published by the Free Software Foundation.
b63a84
-
b63a84
-  This program is distributed in the hope that it will be useful, but
b63a84
-  WITHOUT ANY WARRANTY; without even the implied warranty of
b63a84
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
b63a84
-  General Public License for more details.
b63a84
+  This library is free software; you can redistribute it and/or modify
b63a84
+  it under the terms of the GNU Lesser General Public License as
b63a84
+  published by the Free Software Foundation; either version 2.1 of
b63a84
+  the License, or (at your option) any later version.
b63a84
+
b63a84
+  This program is distributed in the hope that it will be useful,
b63a84
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
b63a84
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
b63a84
+  GNU Lesser General Public License for more details.
b63a84
 
b63a84
   Authors: Mengdong Lin <mengdong.lin@intel.com>
b63a84
            Yao Jin <yao.jin@intel.com>
b63a84
diff --git a/src/topology/elem.c b/src/topology/elem.c
b63a84
index db26483..efcf3e9 100644
b63a84
--- a/src/topology/elem.c
b63a84
+++ b/src/topology/elem.c
b63a84
@@ -2,14 +2,15 @@
b63a84
   Copyright(c) 2014-2015 Intel Corporation
b63a84
   All rights reserved.
b63a84
 
b63a84
-  This program is free software; you can redistribute it and/or modify
b63a84
-  it under the terms of version 2 of the GNU General Public License as
b63a84
-  published by the Free Software Foundation.
b63a84
-
b63a84
-  This program is distributed in the hope that it will be useful, but
b63a84
-  WITHOUT ANY WARRANTY; without even the implied warranty of
b63a84
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
b63a84
-  General Public License for more details.
b63a84
+  This library is free software; you can redistribute it and/or modify
b63a84
+  it under the terms of the GNU Lesser General Public License as
b63a84
+  published by the Free Software Foundation; either version 2.1 of
b63a84
+  the License, or (at your option) any later version.
b63a84
+
b63a84
+  This program is distributed in the hope that it will be useful,
b63a84
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
b63a84
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
b63a84
+  GNU Lesser General Public License for more details.
b63a84
 
b63a84
   Authors: Mengdong Lin <mengdong.lin@intel.com>
b63a84
            Yao Jin <yao.jin@intel.com>
b63a84
diff --git a/src/topology/ops.c b/src/topology/ops.c
b63a84
index 1b5c1e2..6f8dc1f 100644
b63a84
--- a/src/topology/ops.c
b63a84
+++ b/src/topology/ops.c
b63a84
@@ -2,14 +2,15 @@
b63a84
   Copyright(c) 2014-2015 Intel Corporation
b63a84
   All rights reserved.
b63a84
 
b63a84
-  This program is free software; you can redistribute it and/or modify
b63a84
-  it under the terms of version 2 of the GNU General Public License as
b63a84
-  published by the Free Software Foundation.
b63a84
-
b63a84
-  This program is distributed in the hope that it will be useful, but
b63a84
-  WITHOUT ANY WARRANTY; without even the implied warranty of
b63a84
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
b63a84
-  General Public License for more details.
b63a84
+  This library is free software; you can redistribute it and/or modify
b63a84
+  it under the terms of the GNU Lesser General Public License as
b63a84
+  published by the Free Software Foundation; either version 2.1 of
b63a84
+  the License, or (at your option) any later version.
b63a84
+
b63a84
+  This program is distributed in the hope that it will be useful,
b63a84
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
b63a84
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
b63a84
+  GNU Lesser General Public License for more details.
b63a84
 
b63a84
   Authors: Mengdong Lin <mengdong.lin@intel.com>
b63a84
            Yao Jin <yao.jin@intel.com>
b63a84
diff --git a/src/topology/parser.c b/src/topology/parser.c
b63a84
index c5f9757..cfc20e0 100644
b63a84
--- a/src/topology/parser.c
b63a84
+++ b/src/topology/parser.c
b63a84
@@ -2,14 +2,15 @@
b63a84
   Copyright(c) 2014-2015 Intel Corporation
b63a84
   All rights reserved.
b63a84
 
b63a84
-  This program is free software; you can redistribute it and/or modify
b63a84
-  it under the terms of version 2 of the GNU General Public License as
b63a84
-  published by the Free Software Foundation.
b63a84
-
b63a84
-  This program is distributed in the hope that it will be useful, but
b63a84
-  WITHOUT ANY WARRANTY; without even the implied warranty of
b63a84
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
b63a84
-  General Public License for more details.
b63a84
+  This library is free software; you can redistribute it and/or modify
b63a84
+  it under the terms of the GNU Lesser General Public License as
b63a84
+  published by the Free Software Foundation; either version 2.1 of
b63a84
+  the License, or (at your option) any later version.
b63a84
+
b63a84
+  This program is distributed in the hope that it will be useful,
b63a84
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
b63a84
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
b63a84
+  GNU Lesser General Public License for more details.
b63a84
 
b63a84
   Authors: Mengdong Lin <mengdong.lin@intel.com>
b63a84
            Yao Jin <yao.jin@intel.com>
b63a84
diff --git a/src/topology/pcm.c b/src/topology/pcm.c
b63a84
index 8f8a703..5568d57 100644
b63a84
--- a/src/topology/pcm.c
b63a84
+++ b/src/topology/pcm.c
b63a84
@@ -2,14 +2,15 @@
b63a84
   Copyright(c) 2014-2015 Intel Corporation
b63a84
   All rights reserved.
b63a84
 
b63a84
-  This program is free software; you can redistribute it and/or modify
b63a84
-  it under the terms of version 2 of the GNU General Public License as
b63a84
-  published by the Free Software Foundation.
b63a84
-
b63a84
-  This program is distributed in the hope that it will be useful, but
b63a84
-  WITHOUT ANY WARRANTY; without even the implied warranty of
b63a84
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
b63a84
-  General Public License for more details.
b63a84
+  This library is free software; you can redistribute it and/or modify
b63a84
+  it under the terms of the GNU Lesser General Public License as
b63a84
+  published by the Free Software Foundation; either version 2.1 of
b63a84
+  the License, or (at your option) any later version.
b63a84
+
b63a84
+  This program is distributed in the hope that it will be useful,
b63a84
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
b63a84
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
b63a84
+  GNU Lesser General Public License for more details.
b63a84
 
b63a84
   Authors: Mengdong Lin <mengdong.lin@intel.com>
b63a84
            Yao Jin <yao.jin@intel.com>
b63a84
diff --git a/src/topology/text.c b/src/topology/text.c
b63a84
index 303fbeb..cba6887 100644
b63a84
--- a/src/topology/text.c
b63a84
+++ b/src/topology/text.c
b63a84
@@ -2,14 +2,15 @@
b63a84
   Copyright(c) 2014-2015 Intel Corporation
b63a84
   All rights reserved.
b63a84
 
b63a84
-  This program is free software; you can redistribute it and/or modify
b63a84
-  it under the terms of version 2 of the GNU General Public License as
b63a84
-  published by the Free Software Foundation.
b63a84
-
b63a84
-  This program is distributed in the hope that it will be useful, but
b63a84
-  WITHOUT ANY WARRANTY; without even the implied warranty of
b63a84
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
b63a84
-  General Public License for more details.
b63a84
+  This library is free software; you can redistribute it and/or modify
b63a84
+  it under the terms of the GNU Lesser General Public License as
b63a84
+  published by the Free Software Foundation; either version 2.1 of
b63a84
+  the License, or (at your option) any later version.
b63a84
+
b63a84
+  This program is distributed in the hope that it will be useful,
b63a84
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
b63a84
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
b63a84
+  GNU Lesser General Public License for more details.
b63a84
 
b63a84
   Authors: Mengdong Lin <mengdong.lin@intel.com>
b63a84
            Yao Jin <yao.jin@intel.com>
b63a84
-- 
b63a84
2.9.3
b63a84
b63a84
b63a84
From 4dfa8f08fb834f7b087f35f9ba1746cd0c989d02 Mon Sep 17 00:00:00 2001
b63a84
From: Manohar Narkhede <Manohar.Narkhede@imgtec.com>
b63a84
Date: Wed, 25 Jan 2017 22:14:15 +0100
b63a84
Subject: [PATCH 20/37] conf/cards: add support for pistachio-card.
b63a84
b63a84
The data sheet of the chip and technical reference manual can be found at https://docs.creatordev.io/ci40/guides/hardwaredocs/cXT200_datasheet2.pdf
b63a84
and https://docs.creatordev.io/ci40/guides/hardwaredocs/MIPS_Creator_cXT200_Technical_Reference_Manual_1.0.112.pdf.
b63a84
b63a84
The additional information about the cards can be found in src/conf/cards/pistachio-card.conf file.
b63a84
b63a84
Signed-off-by: Manohar Narkhede <Manohar.Narkhede@imgtec.com>
b63a84
Signed-off-by: Takashi Iwai <tiwai@suse.de>
b63a84
---
b63a84
 src/conf/cards/Makefile.am         |  1 +
b63a84
 src/conf/cards/aliases.conf        |  1 +
b63a84
 src/conf/cards/pistachio-card.conf | 58 ++++++++++++++++++++++++++++++++++++++
b63a84
 3 files changed, 60 insertions(+)
b63a84
 create mode 100644 src/conf/cards/pistachio-card.conf
b63a84
b63a84
diff --git a/src/conf/cards/Makefile.am b/src/conf/cards/Makefile.am
b63a84
index 008d399..60b5309 100644
b63a84
--- a/src/conf/cards/Makefile.am
b63a84
+++ b/src/conf/cards/Makefile.am
b63a84
@@ -39,6 +39,7 @@ cfg_files = aliases.conf \
b63a84
 	Maestro3.conf \
b63a84
 	NFORCE.conf \
b63a84
 	PC-Speaker.conf \
b63a84
+	pistachio-card.conf \
b63a84
 	PMac.conf \
b63a84
 	PMacToonie.conf \
b63a84
 	PS3.conf \
b63a84
diff --git a/src/conf/cards/aliases.conf b/src/conf/cards/aliases.conf
b63a84
index 4a92fb2..60f9d26 100644
b63a84
--- a/src/conf/cards/aliases.conf
b63a84
+++ b/src/conf/cards/aliases.conf
b63a84
@@ -55,6 +55,7 @@ AV100 cards.CMI8788
b63a84
 AV200 cards.CMI8788
b63a84
 CMI8786 cards.CMI8788
b63a84
 CMI8787 cards.CMI8788
b63a84
+pistachio cards.pistachio-card
b63a84
 
b63a84
 <confdir:pcm/default.conf>
b63a84
 <confdir:pcm/dmix.conf>
b63a84
diff --git a/src/conf/cards/pistachio-card.conf b/src/conf/cards/pistachio-card.conf
b63a84
new file mode 100644
b63a84
index 0000000..59cd920
b63a84
--- /dev/null
b63a84
+++ b/src/conf/cards/pistachio-card.conf
b63a84
@@ -0,0 +1,58 @@
b63a84
+#
b63a84
+# Configuration for the pistachio chip.
b63a84
+#
b63a84
+# The data sheet of the chip and technical reference manual can be 
b63a84
+found at 
b63a84
+https://docs.creatordev.io/ci40/guides/hardwaredocs/cXT200_datasheet2.p
b63a84
+df # and 
b63a84
+https://docs.creatordev.io/ci40/guides/hardwaredocs/MIPS_Creator_cXT200_Technical_Reference_Manual_1.0.112.pdf.
b63a84
+#
b63a84
+# The list of hardware devices is as per below:
b63a84
+#
b63a84
+#  root@OpenWrt:/# arecord -l
b63a84
+# **** List of CAPTURE Hardware Devices **** card 0: pistachiocard [pistachio-card], device 1: pistachio-spdif-in snd-soc-dummy-dai-1 []
b63a84
+#   Subdevices: 1/1
b63a84
+#   Subdevice #0: subdevice #0
b63a84
+# card 0: pistachiocard [pistachio-card], device 4: pistachio-i2s-in-0 snd-soc-dummy-dai-4 []
b63a84
+#   Subdevices: 1/1
b63a84
+#   Subdevice #0: subdevice #0
b63a84
+#
b63a84
+# root@OpenWrt:/# aplay -l
b63a84
+# **** List of PLAYBACK Hardware Devices **** card 0: pistachiocard [pistachio-card], device 0: pistachio-spdif-out snd-soc-dummy-dai-0 []
b63a84
+#   Subdevices: 1/1
b63a84
+#   Subdevice #0: subdevice #0
b63a84
+# card 0: pistachiocard [pistachio-card], device 2: pistachio-parallel-out pistachio_internal_dac-2 []
b63a84
+#   Subdevices: 1/1
b63a84
+#   Subdevice #0: subdevice #0
b63a84
+# card 0: pistachiocard [pistachio-card], device 3: pistachio-i2s-out snd-soc-dummy-dai-3 []
b63a84
+#   Subdevices: 1/1
b63a84
+#   Subdevice #0: subdevice #0
b63a84
+#
b63a84
+
b63a84
+pistachio-card.pcm.default{
b63a84
+        @args [ CARD ]
b63a84
+        @args.CARD {
b63a84
+                type string
b63a84
+                default "pistachio"
b63a84
+        }
b63a84
+        @args.DEVICE {
b63a84
+                type integer
b63a84
+                default 2
b63a84
+        }
b63a84
+
b63a84
+        type asym
b63a84
+        capture.pcm {
b63a84
+                type multi
b63a84
+                slaves.a.pcm "hw:0,4"
b63a84
+                slaves.a.channels 12
b63a84
+                bindings.0.slave a
b63a84
+                bindings.0.channel 4
b63a84
+                bindings.1.slave a
b63a84
+                bindings.1.channel 5
b63a84
+        }
b63a84
+
b63a84
+        playback.pcm {
b63a84
+                type hw
b63a84
+                card $CARD
b63a84
+                device $DEVICE
b63a84
+
b63a84
-- 
b63a84
2.9.3
b63a84
b63a84
b63a84
From e1143dd9ba350eb19d13d4e298eeb55179712a1e Mon Sep 17 00:00:00 2001
b63a84
From: Takashi Iwai <tiwai@suse.de>
b63a84
Date: Fri, 27 Jan 2017 12:01:51 +0100
b63a84
Subject: [PATCH 21/37] pcm: multi: Drop the fixed slave_map[] in
b63a84
 snd_pcm_multi_open()
b63a84
MIME-Version: 1.0
b63a84
Content-Type: text/plain; charset=UTF-8
b63a84
Content-Transfer-Encoding: 8bit
b63a84
b63a84
slave_map[] in snd_pcm_multi_open() is a fixed size array and
b63a84
obviously we have no overflow check, and eventually the program gets
b63a84
an error when more than 64 channels are used.
b63a84
b63a84
Although we can modify the code to allocate the array dynamically, it
b63a84
turned out that we can drop the whole slave_map[] thingy in this
b63a84
function when looking at the code closely.  In the past, it was used
b63a84
to identify the one-to-many mapping.  But the check was dropped, and
b63a84
now it's nothing more than a sanity check.
b63a84
b63a84
Reported-by: Jörg Müller <joerg.mueller7744@gmail.com>
b63a84
Signed-off-by: Takashi Iwai <tiwai@suse.de>
b63a84
---
b63a84
 src/pcm/pcm_multi.c | 3 ---
b63a84
 1 file changed, 3 deletions(-)
b63a84
b63a84
diff --git a/src/pcm/pcm_multi.c b/src/pcm/pcm_multi.c
b63a84
index c4b1fba..9e4be71 100644
b63a84
--- a/src/pcm/pcm_multi.c
b63a84
+++ b/src/pcm/pcm_multi.c
b63a84
@@ -1015,7 +1015,6 @@ int snd_pcm_multi_open(snd_pcm_t **pcmp, const char *name,
b63a84
 	snd_pcm_multi_t *multi;
b63a84
 	unsigned int i;
b63a84
 	snd_pcm_stream_t stream;
b63a84
-	char slave_map[64][64] = { { 0 } };
b63a84
 	int err;
b63a84
 
b63a84
 	assert(pcmp);
b63a84
@@ -1059,8 +1058,6 @@ int snd_pcm_multi_open(snd_pcm_t **pcmp, const char *name,
b63a84
 		bind->slave_channel = schannels[i];
b63a84
 		if (sidxs[i] < 0)
b63a84
 			continue;
b63a84
-		assert(!slave_map[sidxs[i]][schannels[i]]);
b63a84
-		slave_map[sidxs[i]][schannels[i]] = 1;
b63a84
 	}
b63a84
 	multi->channels_count = channels_count;
b63a84
 
b63a84
-- 
b63a84
2.9.3
b63a84
b63a84
b63a84
From 53dc36f1f465e2a1f9ed37906a7f16a438f941e4 Mon Sep 17 00:00:00 2001
b63a84
From: Takashi Iwai <tiwai@suse.de>
b63a84
Date: Tue, 7 Feb 2017 14:25:17 +0100
b63a84
Subject: [PATCH 22/37] conf: Add card config for Intel HDMI/DP LPE audio
b63a84
b63a84
It's a playback-only device with a single PCM dedicated for HDMI/DP
b63a84
output.  The dmix is working with the latest driver code, so enable it
b63a84
for default, while providing the hdmi PCM dev for the accesses with
b63a84
AES bits.
b63a84
b63a84
Signed-off-by: Takashi Iwai <tiwai@suse.de>
b63a84
---
b63a84
 src/conf/cards/HdmiLpeAudio.conf | 85 ++++++++++++++++++++++++++++++++++++++++
b63a84
 src/conf/cards/Makefile.am       |  1 +
b63a84
 2 files changed, 86 insertions(+)
b63a84
 create mode 100644 src/conf/cards/HdmiLpeAudio.conf
b63a84
b63a84
diff --git a/src/conf/cards/HdmiLpeAudio.conf b/src/conf/cards/HdmiLpeAudio.conf
b63a84
new file mode 100644
b63a84
index 0000000..f5836c0
b63a84
--- /dev/null
b63a84
+++ b/src/conf/cards/HdmiLpeAudio.conf
b63a84
@@ -0,0 +1,85 @@
b63a84
+#
b63a84
+# Configuration for the Intel HDMI/DP LPE audio
b63a84
+#
b63a84
+
b63a84
+<confdir:pcm/front.conf>
b63a84
+
b63a84
+HdmiLpeAudio.pcm.front.0 {
b63a84
+	@args [ CARD ]
b63a84
+	@args.CARD {
b63a84
+		type string
b63a84
+	}
b63a84
+	type softvol
b63a84
+	slave.pcm {
b63a84
+		type hw
b63a84
+		card $CARD
b63a84
+	}
b63a84
+	control {
b63a84
+		name "PCM Playback Volume"
b63a84
+		card $CARD
b63a84
+	}
b63a84
+}
b63a84
+
b63a84
+# default with dmix+softvol
b63a84
+HdmiLpeAudio.pcm.default {
b63a84
+	@args [ CARD ]
b63a84
+	@args.CARD {
b63a84
+		type string
b63a84
+	}
b63a84
+	type plug
b63a84
+	slave.pcm {
b63a84
+		type softvol
b63a84
+		slave.pcm {
b63a84
+			@func concat
b63a84
+			strings [ "dmix:" $CARD ]
b63a84
+		}
b63a84
+		control {
b63a84
+			name "PCM Playback Volume"
b63a84
+			card $CARD
b63a84
+		}
b63a84
+	}
b63a84
+}
b63a84
+
b63a84
+<confdir:pcm/surround40.conf>
b63a84
+<confdir:pcm/surround21.conf>
b63a84
+<confdir:pcm/surround41.conf>
b63a84
+<confdir:pcm/surround50.conf>
b63a84
+<confdir:pcm/surround51.conf>
b63a84
+
b63a84
+<confdir:pcm/hdmi.conf>
b63a84
+
b63a84
+HdmiLpeAudio.pcm.hdmi.0 {
b63a84
+	@args [ CARD AES0 AES1 AES2 AES3 ]
b63a84
+	@args.CARD {
b63a84
+		type string
b63a84
+	}
b63a84
+	@args.AES0 {
b63a84
+		type integer
b63a84
+	}
b63a84
+	@args.AES1 {
b63a84
+		type integer
b63a84
+	}
b63a84
+	@args.AES2 {
b63a84
+		type integer
b63a84
+	}
b63a84
+	@args.AES3 {
b63a84
+		type integer
b63a84
+	}
b63a84
+	type hooks
b63a84
+	slave.pcm {
b63a84
+		type hw
b63a84
+		card $CARD
b63a84
+	}
b63a84
+	hooks.0 {
b63a84
+		type ctl_elems
b63a84
+		hook_args [
b63a84
+			{
b63a84
+				interface PCM
b63a84
+				name "IEC958 Playback Default"
b63a84
+				lock true
b63a84
+				preserve true
b63a84
+				value [ $AES0 $AES1 $AES2 $AES3 ]
b63a84
+			}
b63a84
+		]
b63a84
+	}
b63a84
+}
b63a84
diff --git a/src/conf/cards/Makefile.am b/src/conf/cards/Makefile.am
b63a84
index 60b5309..e8b530e 100644
b63a84
--- a/src/conf/cards/Makefile.am
b63a84
+++ b/src/conf/cards/Makefile.am
b63a84
@@ -30,6 +30,7 @@ cfg_files = aliases.conf \
b63a84
 	FireWave.conf \
b63a84
 	GUS.conf \
b63a84
 	HDA-Intel.conf \
b63a84
+	HdmiLpeAudio.conf \
b63a84
 	ICE1712.conf \
b63a84
 	ICE1724.conf \
b63a84
 	ICH.conf \
b63a84
-- 
b63a84
2.9.3
b63a84
b63a84
b63a84
From b5a2c06f6c5d69fc71ef648af95a044ee1dc25d0 Mon Sep 17 00:00:00 2001
b63a84
From: Takashi Iwai <tiwai@suse.de>
b63a84
Date: Thu, 9 Feb 2017 17:23:22 +0100
b63a84
Subject: [PATCH 23/37] pcm: Avoid lock for snd_pcm_nonblock()
b63a84
b63a84
snd_pcm_nonblock() is called as snd_pcm_abort().  Since
b63a84
snd_pcm_abort() is called often from a signal handler to clean things
b63a84
up (e.g. aplay does it), we may face a deadlock if the signal is
b63a84
raised during the locked operation.
b63a84
b63a84
There can be some way to check the deadlock state, but they would cost
b63a84
much.  Since the race condition of snd_pcm_nonblock() is quite small,
b63a84
let's just drop the locking inside snd_pcm_nonblock() as a
b63a84
workaround.
b63a84
b63a84
Signed-off-by: Takashi Iwai <tiwai@suse.de>
b63a84
---
b63a84
 src/pcm/pcm.c | 7 +++++--
b63a84
 1 file changed, 5 insertions(+), 2 deletions(-)
b63a84
b63a84
diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c
b63a84
index 0cf740f..c136d55 100644
b63a84
--- a/src/pcm/pcm.c
b63a84
+++ b/src/pcm/pcm.c
b63a84
@@ -759,7 +759,10 @@ int snd_pcm_nonblock(snd_pcm_t *pcm, int nonblock)
b63a84
 	int err = 0;
b63a84
 
b63a84
 	assert(pcm);
b63a84
-	__snd_pcm_lock(pcm); /* forced lock due to pcm field change */
b63a84
+	/* FIXME: __snd_pcm_lock() call below is commented out because of the
b63a84
+	 * the possible deadlock in signal handler calling snd_pcm_abort()
b63a84
+	 */
b63a84
+	/* __snd_pcm_lock(pcm); */ /* forced lock due to pcm field change */
b63a84
 	if ((err = pcm->ops->nonblock(pcm->op_arg, nonblock)) < 0)
b63a84
 		goto unlock;
b63a84
 	if (nonblock == 2) {
b63a84
@@ -775,7 +778,7 @@ int snd_pcm_nonblock(snd_pcm_t *pcm, int nonblock)
b63a84
 			pcm->mode &= ~SND_PCM_NONBLOCK;
b63a84
 	}
b63a84
  unlock:
b63a84
-	__snd_pcm_unlock(pcm);
b63a84
+	/* __snd_pcm_unlock(pcm); */ /* FIXME: see above */
b63a84
 	return err;
b63a84
 }
b63a84
 
b63a84
-- 
b63a84
2.9.3
b63a84
b63a84
b63a84
From e31a3273df6eb619e35d10bf6a0fc0fded91d559 Mon Sep 17 00:00:00 2001
b63a84
From: Takashi Iwai <tiwai@suse.de>
b63a84
Date: Thu, 9 Feb 2017 17:29:21 +0100
b63a84
Subject: [PATCH 24/37] pcm: Disable locking in async mode
b63a84
b63a84
When PCM is operated in async mode and an async handler calls some PCM
b63a84
functions with lock during other PCM operations, we may hit a
b63a84
deadlock.
b63a84
b63a84
Although async mode is rarely used, it's still a possible use case.
b63a84
Disable the locking when the stream is opened in async mode or it's
b63a84
set to async mode via snd_pcm_async().
b63a84
b63a84
Signed-off-by: Takashi Iwai <tiwai@suse.de>
b63a84
---
b63a84
 src/pcm/pcm.c | 7 ++++++-
b63a84
 1 file changed, 6 insertions(+), 1 deletion(-)
b63a84
b63a84
diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c
b63a84
index c136d55..493e903 100644
b63a84
--- a/src/pcm/pcm.c
b63a84
+++ b/src/pcm/pcm.c
b63a84
@@ -799,6 +799,8 @@ int snd_pcm_async(snd_pcm_t *pcm, int sig, pid_t pid)
b63a84
 		sig = SIGIO;
b63a84
 	if (pid == 0)
b63a84
 		pid = getpid();
b63a84
+	/* async handler may lead to a deadlock; suppose no multi thread */
b63a84
+	pcm->lock_enabled = 0;
b63a84
 	return pcm->ops->async(pcm->op_arg, sig, pid);
b63a84
 }
b63a84
 #endif
b63a84
@@ -2597,7 +2599,10 @@ int snd_pcm_new(snd_pcm_t **pcmp, snd_pcm_type_t type, const char *name,
b63a84
 	 * each plugin may suppress this in its open call
b63a84
 	 */
b63a84
 	pcm->need_lock = 1;
b63a84
-	{
b63a84
+	if (mode & SND_PCM_ASYNC) {
b63a84
+		/* async handler may lead to a deadlock; suppose no MT */
b63a84
+		pcm->lock_enabled = 0;
b63a84
+	} else {
b63a84
 		/* set lock_enabled field depending on $LIBASOUND_THREAD_SAFE */
b63a84
 		static int do_lock_enable = -1; /* uninitialized */
b63a84
 
b63a84
-- 
b63a84
2.9.3
b63a84
b63a84
b63a84
From 22eca6468b4aea47c783770ec0739d1e13bf3bfc Mon Sep 17 00:00:00 2001
b63a84
From: Takashi Iwai <tiwai@suse.de>
b63a84
Date: Fri, 10 Feb 2017 12:16:12 +0100
b63a84
Subject: [PATCH 25/37] pcm: dmix: Allow disabling x86 optimizations
b63a84
b63a84
The dmix plugin has some optimized implementations for x86 using the
b63a84
direct memory accesses, which was rather the original version, in
b63a84
addition to the "generic" implementation using the semaphore
b63a84
blocking.  The x86 implementation relies on the memory coherency *and*
b63a84
the fast read/write on it.
b63a84
b63a84
For other architectures, this has been always disabled just because of
b63a84
memory coherency.  But, the recent LPE audio development revealed
b63a84
that, even on x86 platforms, the read/write performance might become
b63a84
extremely bad when the buffer is marked as uncached.  Some drivers
b63a84
already know the buffer is uncached, we need to switch to the generic
b63a84
mode in such a case.
b63a84
b63a84
This patch introduces yet another flag to dmix configuration,
b63a84
direct_memory_access, that indicates whether the x86-specific
b63a84
optimization can be used or not.  Each driver can set the flag in its
b63a84
cards config namespace, and the default dmix config refers to it.
b63a84
b63a84
As of this patch, only HDMI LPE Audio driver sets it.
b63a84
b63a84
Signed-off-by: Takashi Iwai <tiwai@suse.de>
b63a84
---
b63a84
 src/conf/cards/HdmiLpeAudio.conf |  3 +++
b63a84
 src/conf/pcm/dmix.conf           | 15 +++++++++++++++
b63a84
 src/pcm/pcm_direct.c             |  8 ++++++++
b63a84
 src/pcm/pcm_direct.h             |  2 ++
b63a84
 src/pcm/pcm_dmix.c               |  1 +
b63a84
 src/pcm/pcm_dmix_i386.c          |  5 +++++
b63a84
 src/pcm/pcm_dmix_x86_64.c        |  5 +++++
b63a84
 7 files changed, 39 insertions(+)
b63a84
b63a84
diff --git a/src/conf/cards/HdmiLpeAudio.conf b/src/conf/cards/HdmiLpeAudio.conf
b63a84
index f5836c0..61bdfea 100644
b63a84
--- a/src/conf/cards/HdmiLpeAudio.conf
b63a84
+++ b/src/conf/cards/HdmiLpeAudio.conf
b63a84
@@ -20,6 +20,9 @@ HdmiLpeAudio.pcm.front.0 {
b63a84
 	}
b63a84
 }
b63a84
 
b63a84
+# uncached memory reads have a high penalty
b63a84
+HdmiLpeAudio.dmix.direct_memory_access false
b63a84
+
b63a84
 # default with dmix+softvol
b63a84
 HdmiLpeAudio.pcm.default {
b63a84
 	@args [ CARD ]
b63a84
diff --git a/src/conf/pcm/dmix.conf b/src/conf/pcm/dmix.conf
b63a84
index 7d0aa01..2d3b329 100644
b63a84
--- a/src/conf/pcm/dmix.conf
b63a84
+++ b/src/conf/pcm/dmix.conf
b63a84
@@ -49,6 +49,21 @@ pcm.!dmix {
b63a84
 		@func refer
b63a84
 		name defaults.pcm.ipc_perm
b63a84
 	}
b63a84
+	direct_memory_access {
b63a84
+		@func refer
b63a84
+		name {
b63a84
+			@func concat
b63a84
+			strings [
b63a84
+				"cards."
b63a84
+				{
b63a84
+					@func card_driver
b63a84
+					card $CARD
b63a84
+				}
b63a84
+				".dmix.direct_memory_access"
b63a84
+			]
b63a84
+		}
b63a84
+		default true
b63a84
+	}
b63a84
 	slave {
b63a84
 		pcm {
b63a84
 			type hw
b63a84
diff --git a/src/pcm/pcm_direct.c b/src/pcm/pcm_direct.c
b63a84
index e4bef78..364191b 100644
b63a84
--- a/src/pcm/pcm_direct.c
b63a84
+++ b/src/pcm/pcm_direct.c
b63a84
@@ -1861,6 +1861,7 @@ int snd_pcm_direct_parse_open_conf(snd_config_t *root, snd_config_t *conf,
b63a84
 	rec->slowptr = 1;
b63a84
 	rec->max_periods = 0;
b63a84
 	rec->var_periodsize = 1;
b63a84
+	rec->direct_memory_access = 1;
b63a84
 
b63a84
 	/* read defaults */
b63a84
 	if (snd_config_search(root, "defaults.pcm.dmix_max_periods", &n) >= 0) {
b63a84
@@ -1974,6 +1975,13 @@ int snd_pcm_direct_parse_open_conf(snd_config_t *root, snd_config_t *conf,
b63a84
 			rec->var_periodsize = err;
b63a84
 			continue;
b63a84
 		}
b63a84
+		if (strcmp(id, "direct_memory_access") == 0) {
b63a84
+			err = snd_config_get_bool(n);
b63a84
+			if (err < 0)
b63a84
+				return err;
b63a84
+			rec->direct_memory_access = err;
b63a84
+			continue;
b63a84
+		}
b63a84
 		SNDERR("Unknown field %s", id);
b63a84
 		return -EINVAL;
b63a84
 	}
b63a84
diff --git a/src/pcm/pcm_direct.h b/src/pcm/pcm_direct.h
b63a84
index 66107ec..fba55fd 100644
b63a84
--- a/src/pcm/pcm_direct.h
b63a84
+++ b/src/pcm/pcm_direct.h
b63a84
@@ -159,6 +159,7 @@ struct snd_pcm_direct {
b63a84
 	unsigned int channels;		/* client's channels */
b63a84
 	unsigned int *bindings;
b63a84
 	unsigned int recoveries;	/* mirror of executed recoveries on slave */
b63a84
+	int direct_memory_access;	/* use arch-optimized buffer RW */
b63a84
 	union {
b63a84
 		struct {
b63a84
 			int shmid_sum;			/* IPC global sum ring buffer memory identification */
b63a84
@@ -340,6 +341,7 @@ struct snd_pcm_direct_open_conf {
b63a84
 	int slowptr;
b63a84
 	int max_periods;
b63a84
 	int var_periodsize;
b63a84
+	int direct_memory_access;
b63a84
 	snd_config_t *slave;
b63a84
 	snd_config_t *bindings;
b63a84
 };
b63a84
diff --git a/src/pcm/pcm_dmix.c b/src/pcm/pcm_dmix.c
b63a84
index 2ef6159..dd0356e 100644
b63a84
--- a/src/pcm/pcm_dmix.c
b63a84
+++ b/src/pcm/pcm_dmix.c
b63a84
@@ -1065,6 +1065,7 @@ int snd_pcm_dmix_open(snd_pcm_t **pcmp, const char *name,
b63a84
 	dmix->max_periods = opts->max_periods;
b63a84
 	dmix->var_periodsize = opts->var_periodsize;
b63a84
 	dmix->sync_ptr = snd_pcm_dmix_sync_ptr;
b63a84
+	dmix->direct_memory_access = opts->direct_memory_access;
b63a84
 
b63a84
  retry:
b63a84
 	if (first_instance) {
b63a84
diff --git a/src/pcm/pcm_dmix_i386.c b/src/pcm/pcm_dmix_i386.c
b63a84
index dcc6b9a..1ab983a 100644
b63a84
--- a/src/pcm/pcm_dmix_i386.c
b63a84
+++ b/src/pcm/pcm_dmix_i386.c
b63a84
@@ -87,6 +87,11 @@ static void mix_select_callbacks(snd_pcm_direct_t *dmix)
b63a84
 {
b63a84
 	static int smp = 0, mmx = 0, cmov = 0;
b63a84
 
b63a84
+	if (!dmix->direct_memory_access) {
b63a84
+		generic_mix_select_callbacks(dmix);
b63a84
+		return;
b63a84
+	}
b63a84
+
b63a84
 	if (!((1ULL<< dmix->shmptr->s.format) & i386_dmix_supported_format)) {
b63a84
 		generic_mix_select_callbacks(dmix);
b63a84
 		return;
b63a84
diff --git a/src/pcm/pcm_dmix_x86_64.c b/src/pcm/pcm_dmix_x86_64.c
b63a84
index 831046d..34c40d4 100644
b63a84
--- a/src/pcm/pcm_dmix_x86_64.c
b63a84
+++ b/src/pcm/pcm_dmix_x86_64.c
b63a84
@@ -70,6 +70,11 @@ static void mix_select_callbacks(snd_pcm_direct_t *dmix)
b63a84
 {
b63a84
 	static int smp = 0;
b63a84
 	
b63a84
+	if (!dmix->direct_memory_access) {
b63a84
+		generic_mix_select_callbacks(dmix);
b63a84
+		return;
b63a84
+	}
b63a84
+
b63a84
 	if (!((1ULL<< dmix->shmptr->s.format) & x86_64_dmix_supported_format)) {
b63a84
 		generic_mix_select_callbacks(dmix);
b63a84
 		return;
b63a84
-- 
b63a84
2.9.3
b63a84
b63a84
b63a84
From df7694d80cdd7d273b34ead6841b9f32f5991966 Mon Sep 17 00:00:00 2001
b63a84
From: Timo Wischer <twischer@de.adit-jv.com>
b63a84
Date: Fri, 17 Feb 2017 12:45:36 +0530
b63a84
Subject: [PATCH 26/37] pcm: dmix_rewind corrupts application pointer fix
b63a84
b63a84
sometimes pulseaudio stops with the following assertion in libasound.so:
b63a84
alsa-lib-1.0.29/src/pcm/pcm.c:2761:
b63a84
snd_pcm_area_copy: Assertion `dst < src || dst >= src + bytes' failed.
b63a84
Application pointer is handled properly, in cases of rewind operations.
b63a84
b63a84
Signed-off-by: Timo Wischer <twischer@de.adit-jv.com>
b63a84
Signed-off-by: Ravikiran Polepalli <ravikiran_polepalli@mentor.com>
b63a84
Signed-off-by: Mikhail Durnev <mikhail_durnev@mentor.com>
b63a84
Signed-off-by: Mounesh Sutar <sutar.mounesh@gmail.com>
b63a84
Signed-off-by: Takashi Iwai <tiwai@suse.de>
b63a84
---
b63a84
 src/pcm/pcm_dmix.c | 33 +++++++++++++++++++++++----------
b63a84
 1 file changed, 23 insertions(+), 10 deletions(-)
b63a84
b63a84
diff --git a/src/pcm/pcm_dmix.c b/src/pcm/pcm_dmix.c
b63a84
index dd0356e..46142e5 100644
b63a84
--- a/src/pcm/pcm_dmix.c
b63a84
+++ b/src/pcm/pcm_dmix.c
b63a84
@@ -706,7 +706,7 @@ static snd_pcm_sframes_t snd_pcm_dmix_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t f
b63a84
 {
b63a84
 	snd_pcm_direct_t *dmix = pcm->private_data;
b63a84
 	snd_pcm_uframes_t slave_appl_ptr, slave_size;
b63a84
-	snd_pcm_uframes_t appl_ptr, size, transfer, result;
b63a84
+	snd_pcm_uframes_t appl_ptr, size, transfer, result, frames_to_remix;
b63a84
 	int err;
b63a84
 	const snd_pcm_channel_area_t *src_areas, *dst_areas;
b63a84
 
b63a84
@@ -717,6 +717,13 @@ static snd_pcm_sframes_t snd_pcm_dmix_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t f
b63a84
 			return err;
b63a84
 	}
b63a84
 
b63a84
+	/* (appl_ptr - last_appl_ptr) indicates the frames which are not
b63a84
+	 * already mixed
b63a84
+	 * (last_appl_ptr - hw_ptr)  indicates the frames which are already
b63a84
+	 * mixed but not played yet.
b63a84
+	 * So they can be remixed.
b63a84
+	 */
b63a84
+
b63a84
 	if (dmix->last_appl_ptr < dmix->appl_ptr)
b63a84
 		size = dmix->appl_ptr - dmix->last_appl_ptr;
b63a84
 	else
b63a84
@@ -729,6 +736,9 @@ static snd_pcm_sframes_t snd_pcm_dmix_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t f
b63a84
 		return size;
b63a84
 	result = size;
b63a84
 
b63a84
+	/* Always at this point last_appl_ptr == appl_ptr
b63a84
+	 * So (appl_ptr - hw_ptr) indicates the frames which can be remixed
b63a84
+	 */
b63a84
 	if (dmix->hw_ptr < dmix->appl_ptr)
b63a84
 		size = dmix->appl_ptr - dmix->hw_ptr;
b63a84
 	else
b63a84
@@ -741,9 +751,12 @@ static snd_pcm_sframes_t snd_pcm_dmix_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t f
b63a84
 		slave_size = dmix->slave_appl_ptr + (pcm->boundary - dmix->slave_hw_ptr);
b63a84
 	if (slave_size < size)
b63a84
 		size = slave_size;
b63a84
-	frames -= size;
b63a84
-	result += size;
b63a84
-		
b63a84
+
b63a84
+	/* frames which should be remixed will be saved
b63a84
+	 * to also backward the appl pointer on success
b63a84
+	 */
b63a84
+	frames_to_remix = size;
b63a84
+
b63a84
 	/* add sample areas here */
b63a84
 	src_areas = snd_pcm_mmap_areas(pcm);
b63a84
 	dst_areas = snd_pcm_mmap_areas(dmix->spcm);
b63a84
@@ -769,15 +782,15 @@ static snd_pcm_sframes_t snd_pcm_dmix_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t f
b63a84
 		appl_ptr += transfer;
b63a84
 		appl_ptr %= pcm->buffer_size;
b63a84
 	}
b63a84
-	dmix->last_appl_ptr -= frames;
b63a84
-	dmix->last_appl_ptr %= pcm->boundary;
b63a84
-	dmix->slave_appl_ptr -= frames;
b63a84
-	dmix->slave_appl_ptr %= dmix->slave_boundary;
b63a84
 	dmix_up_sem(dmix);
b63a84
 
b63a84
-	snd_pcm_mmap_appl_backward(pcm, frames);
b63a84
+	snd_pcm_mmap_appl_backward(pcm, frames_to_remix);
b63a84
+	result += frames_to_remix;
b63a84
+	/* At this point last_appl_ptr and appl_ptr has to indicate the
b63a84
+	 * position of the first not mixed frame
b63a84
+	 */
b63a84
 
b63a84
-	return result + frames;
b63a84
+	return result;
b63a84
 }
b63a84
 
b63a84
 static snd_pcm_sframes_t snd_pcm_dmix_forwardable(snd_pcm_t *pcm)
b63a84
-- 
b63a84
2.9.3
b63a84
b63a84
b63a84
From 9219034301a3bf3d8de57ac5672bbc1c53f18049 Mon Sep 17 00:00:00 2001
b63a84
From: Andreas Pape <apape@de.adit-jv.com>
b63a84
Date: Fri, 17 Feb 2017 12:45:56 +0530
b63a84
Subject: [PATCH 27/37] pcm: direct: fix race on clearing timer events
b63a84
b63a84
snd_timer handling is racy: plugins clear timer queue if avail_min
b63a84
is not reached to force a sleep on timer. The race can happen if
b63a84
the expected event arrives in between the avail check and the
b63a84
clearing of pending events. If this race happens, the user will
b63a84
unnecessarily wait for one more timer event. On low latency/realtime
b63a84
streams this can lead to xruns and must be avoided.
b63a84
b63a84
As a fix we recheck avail after having cleared poll events.
b63a84
b63a84
Signed-off-by: Andreas Pape <apape@de.adit-jv.com>
b63a84
Signed-off-by: Jiada Wang <jiada_wang@mentor.com>
b63a84
Signed-off-by: Mounesh Sutar <sutar.mounesh@gmail.com>
b63a84
Signed-off-by: Takashi Iwai <tiwai@suse.de>
b63a84
---
b63a84
 src/pcm/pcm_direct.c | 23 +++++++++++++++++++----
b63a84
 src/pcm/pcm_direct.h |  2 +-
b63a84
 2 files changed, 20 insertions(+), 5 deletions(-)
b63a84
b63a84
diff --git a/src/pcm/pcm_direct.c b/src/pcm/pcm_direct.c
b63a84
index 364191b..8a75c42 100644
b63a84
--- a/src/pcm/pcm_direct.c
b63a84
+++ b/src/pcm/pcm_direct.c
b63a84
@@ -515,10 +515,12 @@ int snd_pcm_direct_async(snd_pcm_t *pcm, int sig, pid_t pid)
b63a84
 }
b63a84
 
b63a84
 /* empty the timer read queue */
b63a84
-void snd_pcm_direct_clear_timer_queue(snd_pcm_direct_t *dmix)
b63a84
+int snd_pcm_direct_clear_timer_queue(snd_pcm_direct_t *dmix)
b63a84
 {
b63a84
+	int changed = 0;
b63a84
 	if (dmix->timer_need_poll) {
b63a84
 		while (poll(&dmix->timer_fd, 1, 0) > 0) {
b63a84
+			changed++;
b63a84
 			/* we don't need the value */
b63a84
 			if (dmix->tread) {
b63a84
 				snd_timer_tread_t rbuf[4];
b63a84
@@ -533,15 +535,17 @@ void snd_pcm_direct_clear_timer_queue(snd_pcm_direct_t *dmix)
b63a84
 			snd_timer_tread_t rbuf[4];
b63a84
 			int len;
b63a84
 			while ((len = snd_timer_read(dmix->timer, rbuf,
b63a84
-						     sizeof(rbuf))) > 0 &&
b63a84
+						     sizeof(rbuf))) > 0
b63a84
+						     && (++changed) &&
b63a84
 			       len != sizeof(rbuf[0]))
b63a84
 				;
b63a84
 		} else {
b63a84
 			snd_timer_read_t rbuf;
b63a84
 			while (snd_timer_read(dmix->timer, &rbuf, sizeof(rbuf)) > 0)
b63a84
-				;
b63a84
+				changed++;
b63a84
 		}
b63a84
 	}
b63a84
+	return changed;
b63a84
 }
b63a84
 
b63a84
 int snd_pcm_direct_timer_stop(snd_pcm_direct_t *dmix)
b63a84
@@ -693,6 +697,8 @@ int snd_pcm_direct_poll_revents(snd_pcm_t *pcm, struct pollfd *pfds, unsigned in
b63a84
 	int empty = 0;
b63a84
 
b63a84
 	assert(pfds && nfds == 1 && revents);
b63a84
+
b63a84
+timer_changed:
b63a84
 	events = pfds[0].revents;
b63a84
 	if (events & POLLIN) {
b63a84
 		snd_pcm_uframes_t avail;
b63a84
@@ -720,7 +726,16 @@ int snd_pcm_direct_poll_revents(snd_pcm_t *pcm, struct pollfd *pfds, unsigned in
b63a84
 		break;
b63a84
 	default:
b63a84
 		if (empty) {
b63a84
-			snd_pcm_direct_clear_timer_queue(dmix);
b63a84
+			/* here we have a race condition:
b63a84
+			 * if period event arrived after the avail_update call
b63a84
+			 * above we might clear this event with the following
b63a84
+			 * clear_timer_queue.
b63a84
+			 * There is no way to do this in atomic manner, so we
b63a84
+			 * need to recheck avail_update if we successfully
b63a84
+			 * cleared a poll event.
b63a84
+			 */
b63a84
+			if (snd_pcm_direct_clear_timer_queue(dmix))
b63a84
+				goto timer_changed;
b63a84
 			events &= ~(POLLOUT|POLLIN);
b63a84
 			/* additional check */
b63a84
 			switch (__snd_pcm_state(pcm)) {
b63a84
diff --git a/src/pcm/pcm_direct.h b/src/pcm/pcm_direct.h
b63a84
index fba55fd..24e85f0 100644
b63a84
--- a/src/pcm/pcm_direct.h
b63a84
+++ b/src/pcm/pcm_direct.h
b63a84
@@ -322,7 +322,7 @@ int snd_pcm_direct_munmap(snd_pcm_t *pcm);
b63a84
 int snd_pcm_direct_prepare(snd_pcm_t *pcm);
b63a84
 int snd_pcm_direct_resume(snd_pcm_t *pcm);
b63a84
 int snd_pcm_direct_timer_stop(snd_pcm_direct_t *dmix);
b63a84
-void snd_pcm_direct_clear_timer_queue(snd_pcm_direct_t *dmix);
b63a84
+int snd_pcm_direct_clear_timer_queue(snd_pcm_direct_t *dmix);
b63a84
 int snd_pcm_direct_set_timer_params(snd_pcm_direct_t *dmix);
b63a84
 int snd_pcm_direct_open_secondary_client(snd_pcm_t **spcmp, snd_pcm_direct_t *dmix, const char *client_name);
b63a84
 
b63a84
-- 
b63a84
2.9.3
b63a84
b63a84
b63a84
From fe65b00f337dd08f8c14d54b0ce6b516424d78e8 Mon Sep 17 00:00:00 2001
b63a84
From: Timo Wischer <twischer@de.adit-jv.com>
b63a84
Date: Fri, 17 Feb 2017 12:47:17 +0530
b63a84
Subject: [PATCH 28/37] pcm: file: Enable file writing for capture path
b63a84
b63a84
This commit reverts parts of commit 4081be0b87ab9fa53a8906e66bc240f18a7a9a54,
b63a84
because it is realy useful to use the file plugin in a capture path for
b63a84
debugging. Also it fixes the truncate issue mentioned in above commit.
b63a84
b63a84
Additionally following MMAP access issue is considered:
b63a84
$ arecord -D teeraw -M -d5 arecord.wav
b63a84
Recording WAVE 'arecord.wav' : Unsigned 8 bit, Rate 8000 Hz, Mono
b63a84
ALSA lib pcm/pcm_file.c:358:(snd_pcm_file_write_bytes)
b63a84
write failed: Bad file descriptor
b63a84
ALSA lib pcm/pcm_file.c:358:(snd_pcm_file_write_bytes)
b63a84
write failed: Bad file descriptor
b63a84
arecord: pcm/pcm_file.c:397: snd_pcm_file_add_frames:
b63a84
Assertion `file->wbuf_used_bytes < file->wbuf_size_bytes' failed.
b63a84
Aborted by signal Aborted...
b63a84
b63a84
Signed-off-by: Timo Wischer <twischer@de.adit-jv.com>
b63a84
Signed-off-by: Mounesh Sutar <sutar.mounesh@gmail.com>
b63a84
Signed-off-by: Takashi Iwai <tiwai@suse.de>
b63a84
---
b63a84
 src/pcm/pcm_file.c | 12 ++++++++++--
b63a84
 1 file changed, 10 insertions(+), 2 deletions(-)
b63a84
b63a84
diff --git a/src/pcm/pcm_file.c b/src/pcm/pcm_file.c
b63a84
index 6d119d6..0363f84 100644
b63a84
--- a/src/pcm/pcm_file.c
b63a84
+++ b/src/pcm/pcm_file.c
b63a84
@@ -544,6 +544,7 @@ static snd_pcm_sframes_t snd_pcm_file_writen(snd_pcm_t *pcm, void **bufs, snd_pc
b63a84
 static snd_pcm_sframes_t snd_pcm_file_readi(snd_pcm_t *pcm, void *buffer, snd_pcm_uframes_t size)
b63a84
 {
b63a84
 	snd_pcm_file_t *file = pcm->private_data;
b63a84
+	snd_pcm_channel_area_t areas[pcm->channels];
b63a84
 	snd_pcm_sframes_t n;
b63a84
 
b63a84
 	n = _snd_pcm_readi(file->gen.slave, buffer, size);
b63a84
@@ -555,8 +556,10 @@ static snd_pcm_sframes_t snd_pcm_file_readi(snd_pcm_t *pcm, void *buffer, snd_pc
b63a84
 		__snd_pcm_unlock(pcm);
b63a84
 		if (n < 0)
b63a84
 			return n;
b63a84
-		return n * 8 / pcm->frame_bits;
b63a84
+		n = n * 8 / pcm->frame_bits;
b63a84
 	}
b63a84
+	snd_pcm_areas_from_buf(pcm, areas, buffer);
b63a84
+	snd_pcm_file_add_frames(pcm, areas, 0, n);
b63a84
 	return n;
b63a84
 }
b63a84
 
b63a84
@@ -564,6 +567,7 @@ static snd_pcm_sframes_t snd_pcm_file_readi(snd_pcm_t *pcm, void *buffer, snd_pc
b63a84
 static snd_pcm_sframes_t snd_pcm_file_readn(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size)
b63a84
 {
b63a84
 	snd_pcm_file_t *file = pcm->private_data;
b63a84
+	snd_pcm_channel_area_t areas[pcm->channels];
b63a84
 	snd_pcm_sframes_t n;
b63a84
 
b63a84
 	if (file->ifd >= 0) {
b63a84
@@ -572,6 +576,10 @@ static snd_pcm_sframes_t snd_pcm_file_readn(snd_pcm_t *pcm, void **bufs, snd_pcm
b63a84
 	}
b63a84
 
b63a84
 	n = _snd_pcm_readn(file->gen.slave, bufs, size);
b63a84
+	if (n > 0) {
b63a84
+		snd_pcm_areas_from_bufs(pcm, areas, bufs);
b63a84
+		snd_pcm_file_add_frames(pcm, areas, 0, n);
b63a84
+	}
b63a84
 	return n;
b63a84
 }
b63a84
 
b63a84
@@ -635,7 +643,7 @@ static int snd_pcm_file_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params)
b63a84
 		a->first = slave->sample_bits * channel;
b63a84
 		a->step = slave->frame_bits;
b63a84
 	}
b63a84
-	if ((file->fd < 0) && (pcm->stream == SND_PCM_STREAM_PLAYBACK)) {
b63a84
+	if (file->fd < 0) {
b63a84
 		err = snd_pcm_file_open_output_file(file);
b63a84
 		if (err < 0) {
b63a84
 			SYSERR("failed opening output file %s", file->fname);
b63a84
-- 
b63a84
2.9.3
b63a84
b63a84
b63a84
From a50496346f39e91ecd42cb09bc5c95321131be55 Mon Sep 17 00:00:00 2001
b63a84
From: Andreas Pape <apape@de.adit-jv.com>
b63a84
Date: Fri, 17 Feb 2017 12:47:36 +0530
b63a84
Subject: [PATCH 29/37] pcm: status dump fix timestamp formatting
b63a84
b63a84
nanosecond part formatted with %06 will give incorrect/confusing results:
b63a84
b63a84
trigger_time: 154.9748287
b63a84
trigger_time: 154.60109090
b63a84
trigger_time: 154.110425257
b63a84
b63a84
time seems to run backwards...
b63a84
b63a84
This patch converts to us before printing
b63a84
which gives the correct/expected result:
b63a84
b63a84
trigger_time: 154.009748
b63a84
trigger_time: 154.060109
b63a84
trigger_time: 154.110425
b63a84
b63a84
Signed-off-by: Andreas Pape <apape@de.adit-jv.com>
b63a84
Signed-off-by: Mounesh Sutar <sutar.mounesh@gmail.com>
b63a84
Signed-off-by: Takashi Iwai <tiwai@suse.de>
b63a84
---
b63a84
 src/pcm/pcm.c | 5 +++--
b63a84
 1 file changed, 3 insertions(+), 2 deletions(-)
b63a84
b63a84
diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c
b63a84
index 493e903..a16fd86 100644
b63a84
--- a/src/pcm/pcm.c
b63a84
+++ b/src/pcm/pcm.c
b63a84
@@ -2194,9 +2194,10 @@ int snd_pcm_status_dump(snd_pcm_status_t *status, snd_output_t *out)
b63a84
 	assert(status);
b63a84
 	snd_output_printf(out, "  state       : %s\n", snd_pcm_state_name((snd_pcm_state_t) status->state));
b63a84
 	snd_output_printf(out, "  trigger_time: %ld.%06ld\n",
b63a84
-		status->trigger_tstamp.tv_sec, status->trigger_tstamp.tv_nsec);
b63a84
+			  status->trigger_tstamp.tv_sec,
b63a84
+			  status->trigger_tstamp.tv_nsec / 1000);
b63a84
 	snd_output_printf(out, "  tstamp      : %ld.%06ld\n",
b63a84
-		status->tstamp.tv_sec, status->tstamp.tv_nsec);
b63a84
+		status->tstamp.tv_sec, status->tstamp.tv_nsec / 1000);
b63a84
 	snd_output_printf(out, "  delay       : %ld\n", (long)status->delay);
b63a84
 	snd_output_printf(out, "  avail       : %ld\n", (long)status->avail);
b63a84
 	snd_output_printf(out, "  avail_max   : %ld\n", (long)status->avail_max);
b63a84
-- 
b63a84
2.9.3
b63a84
b63a84
b63a84
From fbb957138135e09ed9fd0180dcad549aad815465 Mon Sep 17 00:00:00 2001
b63a84
From: Awais Belal <awais_belal@mentor.com>
b63a84
Date: Fri, 17 Feb 2017 12:47:49 +0530
b63a84
Subject: [PATCH 30/37] pcm: extplug: refinement of masks in extplug
b63a84
b63a84
It should be possible to use empty mask format with extplug.
b63a84
The refinement of mask via extplug is now modified,
b63a84
to accept empty masks as well to work properly.
b63a84
b63a84
Signed-off-by: Awais Belal <awais_belal@mentor.com>
b63a84
Signed-off-by: Mounesh Sutar <sutar.mounesh@gmail.com>
b63a84
Signed-off-by: Takashi Iwai <tiwai@suse.de>
b63a84
---
b63a84
 src/pcm/pcm_extplug.c | 2 ++
b63a84
 1 file changed, 2 insertions(+)
b63a84
b63a84
diff --git a/src/pcm/pcm_extplug.c b/src/pcm/pcm_extplug.c
b63a84
index a04f826..1004f54 100644
b63a84
--- a/src/pcm/pcm_extplug.c
b63a84
+++ b/src/pcm/pcm_extplug.c
b63a84
@@ -172,6 +172,8 @@ int snd_ext_parm_mask_refine(snd_mask_t *mask, struct snd_ext_parm *parm, int ty
b63a84
 	unsigned int i;
b63a84
 
b63a84
 	parm += type;
b63a84
+	if (!parm->active)
b63a84
+		return 0;
b63a84
 	memset(&bits, 0, sizeof(bits));
b63a84
 	for (i = 0; i < parm->num_list; i++)
b63a84
 		bits.bits[parm->list[i] / 32] |= 1U << (parm->list[i] % 32);
b63a84
-- 
b63a84
2.9.3
b63a84
b63a84
b63a84
From 97be19cf6f44fc5084828114c53281dff6e365b4 Mon Sep 17 00:00:00 2001
b63a84
From: Alan Young <consult.awy@gmail.com>
b63a84
Date: Thu, 7 Apr 2016 09:15:04 +0100
b63a84
Subject: [PATCH 31/37] pcm: rate: Add capability to pass configuration node to
b63a84
 plugins
b63a84
b63a84
If a rate plugin uses a node (compound) instead of a plain string for
b63a84
its "converter", and that compound is not a simple string array, then
b63a84
the compound will be passed as an additional parameter to the new plugin
b63a84
open() function (SND_PCM_RATE_PLUGIN_CONF_ENTRY(XXX)). The previous
b63a84
open() function (SND_PCM_RATE_PLUGIN_ENTRY(XXX)) will be called if the
b63a84
CONF version is not found. It is up to the plugin to determine whether
b63a84
the presence of the conf parameter is mandatory.
b63a84
b63a84
Signed-off-by: Alan Young <consult.awy@gmail.com>
b63a84
Signed-off-by: Takashi Iwai <tiwai@suse.de>
b63a84
---
b63a84
 include/pcm_rate.h |  5 +++-
b63a84
 src/pcm/pcm_rate.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++------
b63a84
 2 files changed, 82 insertions(+), 10 deletions(-)
b63a84
b63a84
diff --git a/include/pcm_rate.h b/include/pcm_rate.h
b63a84
index 4d70df2..da278ac 100644
b63a84
--- a/include/pcm_rate.h
b63a84
+++ b/include/pcm_rate.h
b63a84
@@ -120,11 +120,14 @@ typedef struct snd_pcm_rate_ops {
b63a84
 typedef int (*snd_pcm_rate_open_func_t)(unsigned int version, void **objp,
b63a84
 					snd_pcm_rate_ops_t *opsp);
b63a84
 
b63a84
+typedef int (*snd_pcm_rate_open_conf_func_t)(unsigned int version, void **objp,
b63a84
+					snd_pcm_rate_ops_t *opsp, const snd_config_t *conf);
b63a84
+
b63a84
 /**
b63a84
  * Define the object entry for external PCM rate-converter plugins
b63a84
  */
b63a84
 #define SND_PCM_RATE_PLUGIN_ENTRY(name) _snd_pcm_rate_##name##_open
b63a84
-
b63a84
+#define SND_PCM_RATE_PLUGIN_CONF_ENTRY(name) _snd_pcm_rate_##name##_open_conf
b63a84
 
b63a84
 #ifndef DOC_HIDDEN
b63a84
 /* old rate_ops for protocol version 0x010001 */
b63a84
diff --git a/src/pcm/pcm_rate.c b/src/pcm/pcm_rate.c
b63a84
index cbb7618..46eb797 100644
b63a84
--- a/src/pcm/pcm_rate.c
b63a84
+++ b/src/pcm/pcm_rate.c
b63a84
@@ -1258,26 +1258,48 @@ static const char *const default_rate_plugins[] = {
b63a84
 	"speexrate", "linear", NULL
b63a84
 };
b63a84
 
b63a84
-static int rate_open_func(snd_pcm_rate_t *rate, const char *type, int verbose)
b63a84
+static int rate_open_func(snd_pcm_rate_t *rate, const char *type, const snd_config_t *converter_conf, int verbose)
b63a84
 {
b63a84
-	char open_name[64], lib_name[128], *lib = NULL;
b63a84
+	char open_name[64], open_conf_name[64], lib_name[128], *lib = NULL;
b63a84
 	snd_pcm_rate_open_func_t open_func;
b63a84
+	snd_pcm_rate_open_conf_func_t open_conf_func;
b63a84
 	int err;
b63a84
 
b63a84
 	snprintf(open_name, sizeof(open_name), "_snd_pcm_rate_%s_open", type);
b63a84
+	snprintf(open_conf_name, sizeof(open_conf_name), "_snd_pcm_rate_%s_open_conf", type);
b63a84
 	if (!is_builtin_plugin(type)) {
b63a84
 		snprintf(lib_name, sizeof(lib_name),
b63a84
 				 "%s/libasound_module_rate_%s.so", ALSA_PLUGIN_DIR, type);
b63a84
 		lib = lib_name;
b63a84
 	}
b63a84
+
b63a84
+	rate->rate_min = SND_PCM_PLUGIN_RATE_MIN;
b63a84
+	rate->rate_max = SND_PCM_PLUGIN_RATE_MAX;
b63a84
+	rate->plugin_version = SND_PCM_RATE_PLUGIN_VERSION;
b63a84
+
b63a84
+	open_conf_func = snd_dlobj_cache_get(lib, open_conf_name, NULL, verbose && converter_conf != NULL);
b63a84
+	if (open_conf_func) {
b63a84
+		err = open_conf_func(SND_PCM_RATE_PLUGIN_VERSION,
b63a84
+				     &rate->obj, &rate->ops, converter_conf);
b63a84
+		if (!err) {
b63a84
+			rate->plugin_version = rate->ops.version;
b63a84
+			if (rate->ops.get_supported_rates)
b63a84
+				rate->ops.get_supported_rates(rate->obj,
b63a84
+							      &rate->rate_min,
b63a84
+							      &rate->rate_max);
b63a84
+			rate->open_func = open_conf_func;
b63a84
+			return 0;
b63a84
+		} else {
b63a84
+			snd_dlobj_cache_put(open_conf_func);
b63a84
+			return err;
b63a84
+		}
b63a84
+	}
b63a84
+
b63a84
 	open_func = snd_dlobj_cache_get(lib, open_name, NULL, verbose);
b63a84
 	if (!open_func)
b63a84
 		return -ENOENT;
b63a84
 
b63a84
 	rate->open_func = open_func;
b63a84
-	rate->rate_min = SND_PCM_PLUGIN_RATE_MIN;
b63a84
-	rate->rate_max = SND_PCM_PLUGIN_RATE_MAX;
b63a84
-	rate->plugin_version = SND_PCM_RATE_PLUGIN_VERSION;
b63a84
 
b63a84
 	err = open_func(SND_PCM_RATE_PLUGIN_VERSION, &rate->obj, &rate->ops);
b63a84
 	if (!err) {
b63a84
@@ -1301,6 +1323,30 @@ static int rate_open_func(snd_pcm_rate_t *rate, const char *type, int verbose)
b63a84
 }
b63a84
 #endif
b63a84
 
b63a84
+/*
b63a84
+ * If the conf is an array of alternatives then the id of
b63a84
+ * the first element will be "0" (or maybe NULL). Otherwise assume it is
b63a84
+ * a structure.
b63a84
+ */
b63a84
+static int is_string_array(const snd_config_t *conf)
b63a84
+{
b63a84
+	snd_config_iterator_t i;
b63a84
+
b63a84
+	if (snd_config_get_type(conf) != SND_CONFIG_TYPE_COMPOUND)
b63a84
+		return 0;
b63a84
+
b63a84
+	i = snd_config_iterator_first(conf);
b63a84
+	if (i && i != snd_config_iterator_end(conf)) {
b63a84
+		snd_config_t *n = snd_config_iterator_entry(i);
b63a84
+		const char *id;
b63a84
+		snd_config_get_id(n, &id;;
b63a84
+		if (id && strcmp(id, "0") != 0)
b63a84
+			return 0;
b63a84
+	}
b63a84
+
b63a84
+	return 1;
b63a84
+}
b63a84
+
b63a84
 /**
b63a84
  * \brief Creates a new rate PCM
b63a84
  * \param pcmp Returns created PCM handle
b63a84
@@ -1353,24 +1399,42 @@ int snd_pcm_rate_open(snd_pcm_t **pcmp, const char *name,
b63a84
 	if (!converter) {
b63a84
 		const char *const *types;
b63a84
 		for (types = default_rate_plugins; *types; types++) {
b63a84
-			err = rate_open_func(rate, *types, 0);
b63a84
+			err = rate_open_func(rate, *types, NULL, 0);
b63a84
 			if (!err) {
b63a84
 				type = *types;
b63a84
 				break;
b63a84
 			}
b63a84
 		}
b63a84
 	} else if (!snd_config_get_string(converter, &type))
b63a84
-		err = rate_open_func(rate, type, 1);
b63a84
-	else if (snd_config_get_type(converter) == SND_CONFIG_TYPE_COMPOUND) {
b63a84
+		err = rate_open_func(rate, type, NULL, 1);
b63a84
+	else if (is_string_array(converter)) {
b63a84
 		snd_config_iterator_t i, next;
b63a84
 		snd_config_for_each(i, next, converter) {
b63a84
 			snd_config_t *n = snd_config_iterator_entry(i);
b63a84
 			if (snd_config_get_string(n, &type) < 0)
b63a84
 				break;
b63a84
-			err = rate_open_func(rate, type, 0);
b63a84
+			err = rate_open_func(rate, type, NULL, 0);
b63a84
 			if (!err)
b63a84
 				break;
b63a84
 		}
b63a84
+	} else if (snd_config_get_type(converter) == SND_CONFIG_TYPE_COMPOUND) {
b63a84
+		snd_config_iterator_t i, next;
b63a84
+		snd_config_for_each(i, next, converter) {
b63a84
+			snd_config_t *n = snd_config_iterator_entry(i);
b63a84
+			const char *id;
b63a84
+			snd_config_get_id(n, &id;;
b63a84
+			if (strcmp(id, "name") != 0)
b63a84
+				continue;
b63a84
+			snd_config_get_string(n, &type);
b63a84
+			break;
b63a84
+		}
b63a84
+		if (!type) {
b63a84
+			SNDERR("No name given for rate converter");
b63a84
+			snd_pcm_free(pcm);
b63a84
+			free(rate);
b63a84
+			return -EINVAL;
b63a84
+		}
b63a84
+		err = rate_open_func(rate, type, converter, 1);
b63a84
 	} else {
b63a84
 		SNDERR("Invalid type for rate converter");
b63a84
 		snd_pcm_free(pcm);
b63a84
@@ -1439,6 +1503,11 @@ pcm.name {
b63a84
 	converter [ STR1 STR2 ... ]	# optional
b63a84
 				# Converter type, default is taken from
b63a84
 				# defaults.pcm.rate_converter
b63a84
+	# or
b63a84
+	converter {		# optional
b63a84
+		name STR	# Convertor type
b63a84
+		xxx yyy		# optional convertor-specific configuration
b63a84
+	}
b63a84
 }
b63a84
 \endcode
b63a84
 
b63a84
-- 
b63a84
2.9.3
b63a84
b63a84
b63a84
From 3bad0a21b4d13d8d10691f382c836897fa7a7cb9 Mon Sep 17 00:00:00 2001
b63a84
From: Breno Leitao <leitao@debian.org>
b63a84
Date: Wed, 22 Feb 2017 16:45:00 -0300
b63a84
Subject: [PATCH 32/37] Drop ppc64-specific workaround for versioned symbols
b63a84
b63a84
Currently aserver fails to build when using parameter
b63a84
--without-versioned, due to an workaround for ppc64
b63a84
(06221f86d207cb33ddd4867ca5301eeb247c4400).  This workaround is
b63a84
not required anymore on the ppc64 ABI v2, and, in fact is breaking the
b63a84
compilation. Reverting this commit
b63a84
b63a84
Signed-off-by: Breno Leitao <leitao@debian.org>
b63a84
Signed-off-by: Takashi Iwai <tiwai@suse.de>
b63a84
---
b63a84
 include/alsa-symbols.h | 17 -----------------
b63a84
 1 file changed, 17 deletions(-)
b63a84
b63a84
diff --git a/include/alsa-symbols.h b/include/alsa-symbols.h
b63a84
index 51cb982..eeacfdb 100644
b63a84
--- a/include/alsa-symbols.h
b63a84
+++ b/include/alsa-symbols.h
b63a84
@@ -29,19 +29,10 @@
b63a84
 #define INTERNAL_CONCAT2_2(Pre, Post) Pre##Post
b63a84
 #define INTERNAL(Name) INTERNAL_CONCAT2_2(__, Name)
b63a84
 
b63a84
-#ifdef __powerpc64__
b63a84
-# define symbol_version(real, name, version) 			\
b63a84
-	__asm__ (".symver " ASM_NAME(#real) "," ASM_NAME(#name) "@" #version);	\
b63a84
-	__asm__ (".symver ." ASM_NAME(#real) ",." ASM_NAME(#name) "@" #version)
b63a84
-# define default_symbol_version(real, name, version) 		\
b63a84
-	__asm__ (".symver " ASM_NAME(#real) "," ASM_NAME(#name) "@@" #version);	\
b63a84
-	__asm__ (".symver ." ASM_NAME(#real) ",." ASM_NAME(#name) "@@" #version)
b63a84
-#else
b63a84
 # define symbol_version(real, name, version) \
b63a84
 	__asm__ (".symver " ASM_NAME(#real) "," ASM_NAME(#name) "@" #version)
b63a84
 # define default_symbol_version(real, name, version) \
b63a84
 	__asm__ (".symver " ASM_NAME(#real) "," ASM_NAME(#name) "@@" #version)
b63a84
-#endif
b63a84
 
b63a84
 #ifdef USE_VERSIONED_SYMBOLS
b63a84
 #define use_symbol_version(real, name, version) \
b63a84
@@ -50,13 +41,6 @@
b63a84
 		default_symbol_version(real, name, version)
b63a84
 #else
b63a84
 #define use_symbol_version(real, name, version) /* nothing */
b63a84
-#ifdef __powerpc64__
b63a84
-#define use_default_symbol_version(real, name, version) \
b63a84
-	__asm__ (".weak " ASM_NAME(#name)); 			\
b63a84
-	__asm__ (".weak ." ASM_NAME(#name)); 			\
b63a84
-	__asm__ (".set " ASM_NAME(#name) "," ASM_NAME(#real));		\
b63a84
-	__asm__ (".set ." ASM_NAME(#name) ",." ASM_NAME(#real))
b63a84
-#else
b63a84
 #if defined(__alpha__) || defined(__mips__)
b63a84
 #define use_default_symbol_version(real, name, version) \
b63a84
         __asm__ (".weak " ASM_NAME(#name)); \
b63a84
@@ -67,6 +51,5 @@
b63a84
 	__asm__ (".set " ASM_NAME(#name) "," ASM_NAME(#real))
b63a84
 #endif
b63a84
 #endif
b63a84
-#endif
b63a84
 
b63a84
 #endif /* __ALSA_SYMBOLS_H */
b63a84
-- 
b63a84
2.9.3
b63a84
b63a84
b63a84
From b0e4652881f883023d2b190cf3897b7494d8d0ed Mon Sep 17 00:00:00 2001
b63a84
From: Jaroslav Kysela <perex@perex.cz>
b63a84
Date: Mon, 27 Feb 2017 09:25:24 +0100
b63a84
Subject: [PATCH 33/37] pcm_plugin: unify the snd_pcm_mmap_begin result value
b63a84
 checking
b63a84
b63a84
---
b63a84
 src/pcm/pcm_plugin.c | 26 +++++++++++++++++++-------
b63a84
 1 file changed, 19 insertions(+), 7 deletions(-)
b63a84
b63a84
diff --git a/src/pcm/pcm_plugin.c b/src/pcm/pcm_plugin.c
b63a84
index ad4a102..aaea2ab 100644
b63a84
--- a/src/pcm/pcm_plugin.c
b63a84
+++ b/src/pcm/pcm_plugin.c
b63a84
@@ -251,8 +251,12 @@ static snd_pcm_sframes_t snd_pcm_plugin_write_areas(snd_pcm_t *pcm,
b63a84
 		snd_pcm_uframes_t slave_offset;
b63a84
 		snd_pcm_uframes_t slave_frames = ULONG_MAX;
b63a84
 		
b63a84
-		err = snd_pcm_mmap_begin(slave, &slave_areas, &slave_offset, &slave_frames);
b63a84
-		if (err < 0 || slave_frames == 0)
b63a84
+		result = snd_pcm_mmap_begin(slave, &slave_areas, &slave_offset, &slave_frames);
b63a84
+		if (result < 0) {
b63a84
+			err = result;
b63a84
+			goto error;
b63a84
+		}
b63a84
+		if (slave_frames == 0)
b63a84
 			break;
b63a84
 		frames = plugin->write(pcm, areas, offset, frames,
b63a84
 				       slave_areas, slave_offset, &slave_frames);
b63a84
@@ -304,7 +308,11 @@ static snd_pcm_sframes_t snd_pcm_plugin_read_areas(snd_pcm_t *pcm,
b63a84
 		snd_pcm_uframes_t slave_offset;
b63a84
 		snd_pcm_uframes_t slave_frames = ULONG_MAX;
b63a84
 		
b63a84
-		snd_pcm_mmap_begin(slave, &slave_areas, &slave_offset, &slave_frames);
b63a84
+		result = snd_pcm_mmap_begin(slave, &slave_areas, &slave_offset, &slave_frames);
b63a84
+		if (result < 0) {
b63a84
+			err = result;
b63a84
+			goto error;
b63a84
+		}
b63a84
 		if (slave_frames == 0)
b63a84
 			break;
b63a84
 		frames = (plugin->read)(pcm, areas, offset, frames,
b63a84
@@ -409,9 +417,11 @@ snd_pcm_plugin_mmap_commit(snd_pcm_t *pcm,
b63a84
 		snd_pcm_uframes_t slave_frames = ULONG_MAX;
b63a84
 		snd_pcm_sframes_t result;
b63a84
 
b63a84
-		err = snd_pcm_mmap_begin(slave, &slave_areas, &slave_offset, &slave_frames);
b63a84
-		if (err < 0)
b63a84
+		result = snd_pcm_mmap_begin(slave, &slave_areas, &slave_offset, &slave_frames);
b63a84
+		if (result < 0) {
b63a84
+			err = result;
b63a84
 			goto error;
b63a84
+		}
b63a84
 		if (frames > cont)
b63a84
 			frames = cont;
b63a84
 		frames = plugin->write(pcm, areas, appl_offset, frames,
b63a84
@@ -481,9 +491,11 @@ static snd_pcm_sframes_t snd_pcm_plugin_avail_update(snd_pcm_t *pcm)
b63a84
 			snd_pcm_uframes_t slave_frames = ULONG_MAX;
b63a84
 			snd_pcm_sframes_t result;
b63a84
 
b63a84
-			err = snd_pcm_mmap_begin(slave, &slave_areas, &slave_offset, &slave_frames);
b63a84
-			if (err < 0)
b63a84
+			result = snd_pcm_mmap_begin(slave, &slave_areas, &slave_offset, &slave_frames);
b63a84
+			if (result < 0) {
b63a84
+				err = result;
b63a84
 				goto error;
b63a84
+			}
b63a84
 			if (frames > cont)
b63a84
 				frames = cont;
b63a84
 			frames = (plugin->read)(pcm, areas, hw_offset, frames,
b63a84
-- 
b63a84
2.9.3
b63a84
b63a84
b63a84
From 8a38461fac67f6542308063ba8e9887a1a2fa84e Mon Sep 17 00:00:00 2001
b63a84
From: Jaroslav Kysela <perex@perex.cz>
b63a84
Date: Mon, 27 Feb 2017 09:26:33 +0100
b63a84
Subject: [PATCH 34/37] always handle return value from snd_config_get_id()
b63a84
 (coverity)
b63a84
b63a84
---
b63a84
 src/pcm/pcm_rate.c  | 6 ++++--
b63a84
 src/topology/data.c | 4 ++--
b63a84
 2 files changed, 6 insertions(+), 4 deletions(-)
b63a84
b63a84
diff --git a/src/pcm/pcm_rate.c b/src/pcm/pcm_rate.c
b63a84
index 46eb797..f60b0ae 100644
b63a84
--- a/src/pcm/pcm_rate.c
b63a84
+++ b/src/pcm/pcm_rate.c
b63a84
@@ -1339,7 +1339,8 @@ static int is_string_array(const snd_config_t *conf)
b63a84
 	if (i && i != snd_config_iterator_end(conf)) {
b63a84
 		snd_config_t *n = snd_config_iterator_entry(i);
b63a84
 		const char *id;
b63a84
-		snd_config_get_id(n, &id;;
b63a84
+		if (snd_config_get_id(n, &id) < 0)
b63a84
+			return 0;
b63a84
 		if (id && strcmp(id, "0") != 0)
b63a84
 			return 0;
b63a84
 	}
b63a84
@@ -1422,7 +1423,8 @@ int snd_pcm_rate_open(snd_pcm_t **pcmp, const char *name,
b63a84
 		snd_config_for_each(i, next, converter) {
b63a84
 			snd_config_t *n = snd_config_iterator_entry(i);
b63a84
 			const char *id;
b63a84
-			snd_config_get_id(n, &id;;
b63a84
+			if (snd_config_get_id(n, &id) < 0)
b63a84
+				continue;
b63a84
 			if (strcmp(id, "name") != 0)
b63a84
 				continue;
b63a84
 			snd_config_get_string(n, &type);
b63a84
diff --git a/src/topology/data.c b/src/topology/data.c
b63a84
index e2aa38c..8fe2342 100644
b63a84
--- a/src/topology/data.c
b63a84
+++ b/src/topology/data.c
b63a84
@@ -653,8 +653,8 @@ static int parse_tuple_sets(snd_config_t *cfg,
b63a84
 	int err;
b63a84
 
b63a84
 	if (snd_config_get_type(cfg) != SND_CONFIG_TYPE_COMPOUND) {
b63a84
-		snd_config_get_id(cfg, &id;;
b63a84
-		SNDERR("error: compound type expected for %s", id);
b63a84
+		if (snd_config_get_id(cfg, &id) >= 0)
b63a84
+			SNDERR("error: compound type expected for %s", id);
b63a84
 		return -EINVAL;
b63a84
 	}
b63a84
 
b63a84
-- 
b63a84
2.9.3
b63a84
b63a84
b63a84
From b96f6f47852aa145645fb8626d009ec532246e55 Mon Sep 17 00:00:00 2001
b63a84
From: Jaroslav Kysela <perex@perex.cz>
b63a84
Date: Mon, 27 Feb 2017 09:29:18 +0100
b63a84
Subject: [PATCH 35/37] pcm file plugin: handle snd_pcm_mmap_begin() error path
b63a84
 in snd_pcm_file_mmap_commit()
b63a84
b63a84
---
b63a84
 src/pcm/pcm_file.c | 12 +++++++-----
b63a84
 1 file changed, 7 insertions(+), 5 deletions(-)
b63a84
b63a84
diff --git a/src/pcm/pcm_file.c b/src/pcm/pcm_file.c
b63a84
index 0363f84..8012251 100644
b63a84
--- a/src/pcm/pcm_file.c
b63a84
+++ b/src/pcm/pcm_file.c
b63a84
@@ -593,11 +593,13 @@ static snd_pcm_sframes_t snd_pcm_file_mmap_commit(snd_pcm_t *pcm,
b63a84
 	const snd_pcm_channel_area_t *areas;
b63a84
 	snd_pcm_sframes_t result;
b63a84
 
b63a84
-	snd_pcm_mmap_begin(file->gen.slave, &areas, &ofs, &siz;;
b63a84
-	assert(ofs == offset && siz == size);
b63a84
-	result = snd_pcm_mmap_commit(file->gen.slave, ofs, siz);
b63a84
-	if (result > 0)
b63a84
-		snd_pcm_file_add_frames(pcm, areas, ofs, result);
b63a84
+	result = snd_pcm_mmap_begin(file->gen.slave, &areas, &ofs, &siz;;
b63a84
+	if (result >= 0) {
b63a84
+		assert(ofs == offset && siz == size);
b63a84
+		result = snd_pcm_mmap_commit(file->gen.slave, ofs, siz);
b63a84
+		if (result > 0)
b63a84
+			snd_pcm_file_add_frames(pcm, areas, ofs, result);
b63a84
+	}
b63a84
 	return result;
b63a84
 }
b63a84
 
b63a84
-- 
b63a84
2.9.3
b63a84
b63a84
b63a84
From db0e1dcfc22fb2e408a12993cda2d604e0fb10f8 Mon Sep 17 00:00:00 2001
b63a84
From: Jaroslav Kysela <perex@perex.cz>
b63a84
Date: Mon, 27 Feb 2017 09:46:18 +0100
b63a84
Subject: [PATCH 36/37] topology: coverity - remove dead code
b63a84
b63a84
---
b63a84
 src/topology/ctl.c  |  5 ++---
b63a84
 src/topology/data.c |  2 +-
b63a84
 src/topology/pcm.c  | 17 +++++++----------
b63a84
 3 files changed, 10 insertions(+), 14 deletions(-)
b63a84
b63a84
diff --git a/src/topology/ctl.c b/src/topology/ctl.c
b63a84
index 1da3d18..c026c2a 100644
b63a84
--- a/src/topology/ctl.c
b63a84
+++ b/src/topology/ctl.c
b63a84
@@ -173,7 +173,7 @@ static int tplg_build_enum_control(snd_tplg_t *tplg,
b63a84
 {
b63a84
 	struct tplg_ref *ref;
b63a84
 	struct list_head *base, *pos;
b63a84
-	int err = 0;
b63a84
+	int err;
b63a84
 
b63a84
 	base = &elem->ref_list;
b63a84
 
b63a84
@@ -198,8 +198,7 @@ static int tplg_build_enum_control(snd_tplg_t *tplg,
b63a84
 			SNDERR("error: cannot find '%s' referenced by"
b63a84
 				" control '%s'\n", ref->id, elem->id);
b63a84
 			return -EINVAL;
b63a84
-		} else if (err < 0)
b63a84
-			return err;
b63a84
+		}
b63a84
 	}
b63a84
 
b63a84
 	return 0;
b63a84
diff --git a/src/topology/data.c b/src/topology/data.c
b63a84
index 8fe2342..31e4ee1 100644
b63a84
--- a/src/topology/data.c
b63a84
+++ b/src/topology/data.c
b63a84
@@ -917,7 +917,7 @@ int tplg_build_manifest_data(snd_tplg_t *tplg)
b63a84
 	list_for_each(pos, base) {
b63a84
 
b63a84
 		ref = list_entry(pos, struct tplg_ref, list);
b63a84
-		if (ref->id == NULL || ref->elem)
b63a84
+		if (ref->elem)
b63a84
 			continue;
b63a84
 
b63a84
 		if (ref->type == SND_TPLG_TYPE_DATA) {
b63a84
diff --git a/src/topology/pcm.c b/src/topology/pcm.c
b63a84
index 5568d57..50a373a 100644
b63a84
--- a/src/topology/pcm.c
b63a84
+++ b/src/topology/pcm.c
b63a84
@@ -79,8 +79,8 @@ static int build_pcm(snd_tplg_t *tplg, struct tplg_elem *elem)
b63a84
 	int err;
b63a84
 
b63a84
 	err = tplg_build_stream_caps(tplg, elem->id, elem->pcm->caps);
b63a84
-		if (err < 0)
b63a84
-			return err;
b63a84
+	if (err < 0)
b63a84
+		return err;
b63a84
 
b63a84
 	/* merge private data from the referenced data elements */
b63a84
 	base = &elem->ref_list;
b63a84
@@ -96,8 +96,7 @@ static int build_pcm(snd_tplg_t *tplg, struct tplg_elem *elem)
b63a84
 			SNDERR("error: cannot find '%s' referenced by"
b63a84
 				" PCM '%s'\n", ref->id, elem->id);
b63a84
 			return -EINVAL;
b63a84
-		} else if (err < 0)
b63a84
-			return err;
b63a84
+		}
b63a84
 	}
b63a84
 
b63a84
 	return 0;
b63a84
@@ -1208,12 +1207,10 @@ int tplg_add_link_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t)
b63a84
 
b63a84
 	/* ID and names */
b63a84
 	link->id = link_tpl->id;
b63a84
-	if (link->name)
b63a84
-		elem_copy_text(link->name, link_tpl->name,
b63a84
-			       SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
b63a84
-	if (link->stream_name)
b63a84
-		elem_copy_text(link->stream_name, link_tpl->stream_name,
b63a84
-			       SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
b63a84
+	elem_copy_text(link->name, link_tpl->name,
b63a84
+		       SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
b63a84
+	elem_copy_text(link->stream_name, link_tpl->stream_name,
b63a84
+		       SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
b63a84
 
b63a84
 	/* stream configs */
b63a84
 	if (link_tpl->num_streams > SND_SOC_TPLG_STREAM_CONFIG_MAX)
b63a84
-- 
b63a84
2.9.3
b63a84
b63a84
b63a84
From ad188bbf7813eab6f42dcdf617aa947107118857 Mon Sep 17 00:00:00 2001
b63a84
From: Jaroslav Kysela <perex@perex.cz>
b63a84
Date: Mon, 27 Feb 2017 09:53:26 +0100
b63a84
Subject: [PATCH 37/37] ucm parser: fix possible string overflow in
b63a84
 uc_mgr_import_master_config()
b63a84
b63a84
---
b63a84
 src/ucm/parser.c | 3 ++-
b63a84
 1 file changed, 2 insertions(+), 1 deletion(-)
b63a84
b63a84
diff --git a/src/ucm/parser.c b/src/ucm/parser.c
b63a84
index 798bf48..b79b92d 100644
b63a84
--- a/src/ucm/parser.c
b63a84
+++ b/src/ucm/parser.c
b63a84
@@ -1453,7 +1453,8 @@ int uc_mgr_import_master_config(snd_use_case_mgr_t *uc_mgr)
b63a84
 		err = load_master_config(uc_mgr->card_name, &cfg;;
b63a84
 		if (err < 0)
b63a84
 			return err;
b63a84
-		strcpy(uc_mgr->conf_file_name, uc_mgr->card_name);
b63a84
+		strncpy(uc_mgr->conf_file_name, uc_mgr->card_name, MAX_CARD_LONG_NAME);
b63a84
+		uc_mgr->conf_file_name[MAX_CARD_LONG_NAME-1] = '\0';
b63a84
 	}
b63a84
 
b63a84
 	err = parse_master_file(uc_mgr, cfg);
b63a84
-- 
b63a84
2.9.3
b63a84