diff --git a/.alsa-lib.metadata b/.alsa-lib.metadata
index de4b8b4..0e23661 100644
--- a/.alsa-lib.metadata
+++ b/.alsa-lib.metadata
@@ -1 +1 @@
-09f7e9b2d88287e04a4bb0d56e0cbc9018e524ec SOURCES/alsa-lib-1.1.1.tar.bz2
+8ef0b9725296ac8f24e06f20196f5b2b62ab27a9 SOURCES/alsa-lib-1.1.3.tar.bz2
diff --git a/.gitignore b/.gitignore
index 07630c5..93e2d4a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1 @@
-SOURCES/alsa-lib-1.1.1.tar.bz2
+SOURCES/alsa-lib-1.1.3.tar.bz2
diff --git a/SOURCES/alsa-lib-1.0.16-no-dox-date.patch b/SOURCES/alsa-lib-1.0.16-no-dox-date.patch
deleted file mode 100644
index 2669115..0000000
--- a/SOURCES/alsa-lib-1.0.16-no-dox-date.patch
+++ /dev/null
@@ -1,17 +0,0 @@
---- alsa-lib-1.0.16/doc/no_date_footer.html	1969-12-31 16:00:00.000000000 -0800
-+++ alsa-lib-1.0.16-dox/doc/no_date_footer.html	2008-04-03 17:52:52.000000000 -0700
-@@ -0,0 +1,6 @@
-+<hr size="1"><address style="text-align: right;"><small>
-+Generated for $projectname by&nbsp;<a href="http://www.doxygen.org/
-+index.html"><img src="doxygen.png" alt="doxygen" align="middle" border="0"></a>
-+$doxygenversion</small></address>
-+</body>
-+</html>
---- alsa-lib-1.0.16/doc/doxygen.cfg.in	2008-02-05 01:23:44.000000000 -0800
-+++ alsa-lib-1.0.16-dox/doc/doxygen.cfg.in	2008-04-03 17:58:01.000000000 -0700
-@@ -117,3 +117,5 @@
- 
- #INPUT_FILTER	 = inputfilter
- #FILTER_SOURCE_FILES = YES
-+
-+HTML_FOOTER      = no_date_footer.html
diff --git a/SOURCES/alsa-lib-1.1.1-post.patch b/SOURCES/alsa-lib-1.1.1-post.patch
deleted file mode 100644
index 0227a2d..0000000
--- a/SOURCES/alsa-lib-1.1.1-post.patch
+++ /dev/null
@@ -1,6314 +0,0 @@
-From 7c424edd116e76eee6218a1e9a6ff6c4daaf2a4d Mon Sep 17 00:00:00 2001
-From: Shengjiu Wang <shengjiu.wang@freescale.com>
-Date: Wed, 6 Apr 2016 19:02:12 +0800
-Subject: [PATCH 01/34] pcm_plugin: fix appl pointer not correct when
- mmap_commit() return error
-
-When snd_pcm_mmap_commit() return error, the appl pointer is also updated.
-which cause the avail_update()'s result wrong.
-This patch move the snd_pcm_mmap_appl_forward() to the place when
-snd_pcm_mmap_commit() is successfully returned.
-
-Signed-off-by: Shengjiu Wang <shengjiu.wang@freescale.com>
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
----
- src/pcm/pcm_plugin.c | 48 ++++++++++++++++++++++++++++++++----------------
- 1 file changed, 32 insertions(+), 16 deletions(-)
-
-diff --git a/src/pcm/pcm_plugin.c b/src/pcm/pcm_plugin.c
-index d007e8c..940491d 100644
---- a/src/pcm/pcm_plugin.c
-+++ b/src/pcm/pcm_plugin.c
-@@ -279,18 +279,22 @@ static snd_pcm_sframes_t snd_pcm_plugin_write_areas(snd_pcm_t *pcm,
- 			return -EPIPE;
- 		}
- 		snd_atomic_write_begin(&plugin->watom);
--		snd_pcm_mmap_appl_forward(pcm, frames);
- 		result = snd_pcm_mmap_commit(slave, slave_offset, slave_frames);
- 		if (result > 0 && (snd_pcm_uframes_t)result != slave_frames) {
- 			snd_pcm_sframes_t res;
- 			res = plugin->undo_write(pcm, slave_areas, slave_offset + result, slave_frames, slave_frames - result);
--			if (res < 0)
-+			if (res < 0) {
-+				snd_atomic_write_end(&plugin->watom);
- 				return xfer > 0 ? (snd_pcm_sframes_t)xfer : res;
-+			}
- 			frames -= res;
- 		}
--		snd_atomic_write_end(&plugin->watom);
--		if (result <= 0)
-+		if (result <= 0) {
-+			snd_atomic_write_end(&plugin->watom);
- 			return xfer > 0 ? (snd_pcm_sframes_t)xfer : result;
-+		}
-+		snd_pcm_mmap_appl_forward(pcm, frames);
-+		snd_atomic_write_end(&plugin->watom);
- 		offset += frames;
- 		xfer += frames;
- 		size -= frames;
-@@ -325,19 +329,23 @@ static snd_pcm_sframes_t snd_pcm_plugin_read_areas(snd_pcm_t *pcm,
- 			return -EPIPE;
- 		}
- 		snd_atomic_write_begin(&plugin->watom);
--		snd_pcm_mmap_appl_forward(pcm, frames);
- 		result = snd_pcm_mmap_commit(slave, slave_offset, slave_frames);
- 		if (result > 0 && (snd_pcm_uframes_t)result != slave_frames) {
- 			snd_pcm_sframes_t res;
- 			
- 			res = plugin->undo_read(slave, areas, offset, frames, slave_frames - result);
--			if (res < 0)
-+			if (res < 0) {
-+				snd_atomic_write_end(&plugin->watom);
- 				return xfer > 0 ? (snd_pcm_sframes_t)xfer : res;
-+			}
- 			frames -= res;
- 		}
--		snd_atomic_write_end(&plugin->watom);
--		if (result <= 0)
-+		if (result <= 0) {
-+			snd_atomic_write_end(&plugin->watom);
- 			return xfer > 0 ? (snd_pcm_sframes_t)xfer : result;
-+		}
-+		snd_pcm_mmap_appl_forward(pcm, frames);
-+		snd_atomic_write_end(&plugin->watom);
- 		offset += frames;
- 		xfer += frames;
- 		size -= frames;
-@@ -423,19 +431,23 @@ snd_pcm_plugin_mmap_commit(snd_pcm_t *pcm,
- 		frames = plugin->write(pcm, areas, appl_offset, frames,
- 				       slave_areas, slave_offset, &slave_frames);
- 		snd_atomic_write_begin(&plugin->watom);
--		snd_pcm_mmap_appl_forward(pcm, frames);
- 		result = snd_pcm_mmap_commit(slave, slave_offset, slave_frames);
--		snd_atomic_write_end(&plugin->watom);
- 		if (result > 0 && (snd_pcm_uframes_t)result != slave_frames) {
- 			snd_pcm_sframes_t res;
- 			
- 			res = plugin->undo_write(pcm, slave_areas, slave_offset + result, slave_frames, slave_frames - result);
--			if (res < 0)
-+			if (res < 0) {
-+				snd_atomic_write_end(&plugin->watom);
- 				return xfer > 0 ? xfer : res;
-+			}
- 			frames -= res;
- 		}
--		if (result <= 0)
-+		if (result <= 0) {
-+			snd_atomic_write_end(&plugin->watom);
- 			return xfer > 0 ? xfer : result;
-+		}
-+		snd_pcm_mmap_appl_forward(pcm, frames);
-+		snd_atomic_write_end(&plugin->watom);
- 		if (frames == cont)
- 			appl_offset = 0;
- 		else
-@@ -490,19 +502,23 @@ static snd_pcm_sframes_t snd_pcm_plugin_avail_update(snd_pcm_t *pcm)
- 			frames = (plugin->read)(pcm, areas, hw_offset, frames,
- 					      slave_areas, slave_offset, &slave_frames);
- 			snd_atomic_write_begin(&plugin->watom);
--			snd_pcm_mmap_hw_forward(pcm, frames);
- 			result = snd_pcm_mmap_commit(slave, slave_offset, slave_frames);
--			snd_atomic_write_end(&plugin->watom);
- 			if (result > 0 && (snd_pcm_uframes_t)result != slave_frames) {
- 				snd_pcm_sframes_t res;
- 				
- 				res = plugin->undo_read(slave, areas, hw_offset, frames, slave_frames - result);
--				if (res < 0)
-+				if (res < 0) {
-+					snd_atomic_write_end(&plugin->watom);
- 					return xfer > 0 ? (snd_pcm_sframes_t)xfer : res;
-+				}
- 				frames -= res;
- 			}
--			if (result <= 0)
-+			if (result <= 0) {
-+				snd_atomic_write_end(&plugin->watom);
- 				return xfer > 0 ? (snd_pcm_sframes_t)xfer : result;
-+			}
-+			snd_pcm_mmap_hw_forward(pcm, frames);
-+			snd_atomic_write_end(&plugin->watom);
- 			if (frames == cont)
- 				hw_offset = 0;
- 			else
--- 
-2.5.5
-
-From 503a285ed60164d8c65c6ee9ba6f23631da753df Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Thu, 7 Apr 2016 16:29:41 +0200
-Subject: [PATCH 02/34] pcm: Clean up error paths in snd_pcm_plugin_*() helpers
-
-Minor code refactoring to unify the error return paths.
-
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
----
- src/pcm/pcm_plugin.c | 67 +++++++++++++++++++++++++++++++++++-----------------
- 1 file changed, 45 insertions(+), 22 deletions(-)
-
-diff --git a/src/pcm/pcm_plugin.c b/src/pcm/pcm_plugin.c
-index 940491d..8527783 100644
---- a/src/pcm/pcm_plugin.c
-+++ b/src/pcm/pcm_plugin.c
-@@ -276,7 +276,8 @@ static snd_pcm_sframes_t snd_pcm_plugin_write_areas(snd_pcm_t *pcm,
- 		if (CHECK_SANITY(slave_frames > snd_pcm_mmap_playback_avail(slave))) {
- 			SNDMSG("write overflow %ld > %ld", slave_frames,
- 			       snd_pcm_mmap_playback_avail(slave));
--			return -EPIPE;
-+			err = -EPIPE;
-+			goto error;
- 		}
- 		snd_atomic_write_begin(&plugin->watom);
- 		result = snd_pcm_mmap_commit(slave, slave_offset, slave_frames);
-@@ -284,14 +285,14 @@ static snd_pcm_sframes_t snd_pcm_plugin_write_areas(snd_pcm_t *pcm,
- 			snd_pcm_sframes_t res;
- 			res = plugin->undo_write(pcm, slave_areas, slave_offset + result, slave_frames, slave_frames - result);
- 			if (res < 0) {
--				snd_atomic_write_end(&plugin->watom);
--				return xfer > 0 ? (snd_pcm_sframes_t)xfer : res;
-+				err = res;
-+				goto error_atomic;
- 			}
- 			frames -= res;
- 		}
- 		if (result <= 0) {
--			snd_atomic_write_end(&plugin->watom);
--			return xfer > 0 ? (snd_pcm_sframes_t)xfer : result;
-+			err = result;
-+			goto error_atomic;
- 		}
- 		snd_pcm_mmap_appl_forward(pcm, frames);
- 		snd_atomic_write_end(&plugin->watom);
-@@ -300,6 +301,11 @@ static snd_pcm_sframes_t snd_pcm_plugin_write_areas(snd_pcm_t *pcm,
- 		size -= frames;
- 	}
- 	return (snd_pcm_sframes_t)xfer;
-+
-+ error_atomic:
-+	snd_atomic_write_end(&plugin->watom);
-+ error:
-+	return xfer > 0 ? (snd_pcm_sframes_t)xfer : err;
- }
- 
- static snd_pcm_sframes_t snd_pcm_plugin_read_areas(snd_pcm_t *pcm,
-@@ -311,6 +317,7 @@ static snd_pcm_sframes_t snd_pcm_plugin_read_areas(snd_pcm_t *pcm,
- 	snd_pcm_t *slave = plugin->gen.slave;
- 	snd_pcm_uframes_t xfer = 0;
- 	snd_pcm_sframes_t result;
-+	int err;
- 	
- 	while (size > 0) {
- 		snd_pcm_uframes_t frames = size;
-@@ -326,7 +333,8 @@ static snd_pcm_sframes_t snd_pcm_plugin_read_areas(snd_pcm_t *pcm,
- 		if (CHECK_SANITY(slave_frames > snd_pcm_mmap_capture_avail(slave))) {
- 			SNDMSG("read overflow %ld > %ld", slave_frames,
- 			       snd_pcm_mmap_playback_avail(slave));
--			return -EPIPE;
-+			err = -EPIPE;
-+			goto error;
- 		}
- 		snd_atomic_write_begin(&plugin->watom);
- 		result = snd_pcm_mmap_commit(slave, slave_offset, slave_frames);
-@@ -335,14 +343,14 @@ static snd_pcm_sframes_t snd_pcm_plugin_read_areas(snd_pcm_t *pcm,
- 			
- 			res = plugin->undo_read(slave, areas, offset, frames, slave_frames - result);
- 			if (res < 0) {
--				snd_atomic_write_end(&plugin->watom);
--				return xfer > 0 ? (snd_pcm_sframes_t)xfer : res;
-+				err = res;
-+				goto error_atomic;
- 			}
- 			frames -= res;
- 		}
- 		if (result <= 0) {
--			snd_atomic_write_end(&plugin->watom);
--			return xfer > 0 ? (snd_pcm_sframes_t)xfer : result;
-+			err = result;
-+			goto error_atomic;
- 		}
- 		snd_pcm_mmap_appl_forward(pcm, frames);
- 		snd_atomic_write_end(&plugin->watom);
-@@ -351,6 +359,11 @@ static snd_pcm_sframes_t snd_pcm_plugin_read_areas(snd_pcm_t *pcm,
- 		size -= frames;
- 	}
- 	return (snd_pcm_sframes_t)xfer;
-+
-+ error_atomic:
-+	snd_atomic_write_end(&plugin->watom);
-+ error:
-+	return xfer > 0 ? (snd_pcm_sframes_t)xfer : err;
- }
- 
- 
-@@ -401,6 +414,7 @@ snd_pcm_plugin_mmap_commit(snd_pcm_t *pcm,
- 	snd_pcm_uframes_t appl_offset;
- 	snd_pcm_sframes_t slave_size;
- 	snd_pcm_sframes_t xfer;
-+	int err;
- 
- 	if (pcm->stream == SND_PCM_STREAM_CAPTURE) {
- 		snd_atomic_write_begin(&plugin->watom);
-@@ -421,11 +435,10 @@ snd_pcm_plugin_mmap_commit(snd_pcm_t *pcm,
- 		snd_pcm_uframes_t slave_offset;
- 		snd_pcm_uframes_t slave_frames = ULONG_MAX;
- 		snd_pcm_sframes_t result;
--		int err;
- 
- 		err = snd_pcm_mmap_begin(slave, &slave_areas, &slave_offset, &slave_frames);
- 		if (err < 0)
--			return xfer > 0 ? xfer : err;
-+			goto error;
- 		if (frames > cont)
- 			frames = cont;
- 		frames = plugin->write(pcm, areas, appl_offset, frames,
-@@ -437,14 +450,14 @@ snd_pcm_plugin_mmap_commit(snd_pcm_t *pcm,
- 			
- 			res = plugin->undo_write(pcm, slave_areas, slave_offset + result, slave_frames, slave_frames - result);
- 			if (res < 0) {
--				snd_atomic_write_end(&plugin->watom);
--				return xfer > 0 ? xfer : res;
-+				err = res;
-+				goto error_atomic;
- 			}
- 			frames -= res;
- 		}
- 		if (result <= 0) {
--			snd_atomic_write_end(&plugin->watom);
--			return xfer > 0 ? xfer : result;
-+			err = result;
-+			goto error_atomic;
- 		}
- 		snd_pcm_mmap_appl_forward(pcm, frames);
- 		snd_atomic_write_end(&plugin->watom);
-@@ -461,6 +474,11 @@ snd_pcm_plugin_mmap_commit(snd_pcm_t *pcm,
- 		return -EPIPE;
- 	}
- 	return xfer;
-+
-+ error_atomic:
-+	snd_atomic_write_end(&plugin->watom);
-+ error:
-+	return xfer > 0 ? xfer : err;
- }
- 
- static snd_pcm_sframes_t snd_pcm_plugin_avail_update(snd_pcm_t *pcm)
-@@ -468,6 +486,7 @@ static snd_pcm_sframes_t snd_pcm_plugin_avail_update(snd_pcm_t *pcm)
- 	snd_pcm_plugin_t *plugin = pcm->private_data;
- 	snd_pcm_t *slave = plugin->gen.slave;
- 	snd_pcm_sframes_t slave_size;
-+	int err;
- 
- 	slave_size = snd_pcm_avail_update(slave);
- 	if (pcm->stream == SND_PCM_STREAM_CAPTURE &&
-@@ -492,11 +511,10 @@ static snd_pcm_sframes_t snd_pcm_plugin_avail_update(snd_pcm_t *pcm)
- 			snd_pcm_uframes_t slave_offset;
- 			snd_pcm_uframes_t slave_frames = ULONG_MAX;
- 			snd_pcm_sframes_t result;
--			int err;
- 
- 			err = snd_pcm_mmap_begin(slave, &slave_areas, &slave_offset, &slave_frames);
- 			if (err < 0)
--				return xfer > 0 ? (snd_pcm_sframes_t)xfer : err;
-+				goto error;
- 			if (frames > cont)
- 				frames = cont;
- 			frames = (plugin->read)(pcm, areas, hw_offset, frames,
-@@ -508,14 +526,14 @@ static snd_pcm_sframes_t snd_pcm_plugin_avail_update(snd_pcm_t *pcm)
- 				
- 				res = plugin->undo_read(slave, areas, hw_offset, frames, slave_frames - result);
- 				if (res < 0) {
--					snd_atomic_write_end(&plugin->watom);
--					return xfer > 0 ? (snd_pcm_sframes_t)xfer : res;
-+					err = res;
-+					goto error_atomic;
- 				}
- 				frames -= res;
- 			}
- 			if (result <= 0) {
--				snd_atomic_write_end(&plugin->watom);
--				return xfer > 0 ? (snd_pcm_sframes_t)xfer : result;
-+				err = result;
-+				goto error_atomic;
- 			}
- 			snd_pcm_mmap_hw_forward(pcm, frames);
- 			snd_atomic_write_end(&plugin->watom);
-@@ -528,6 +546,11 @@ static snd_pcm_sframes_t snd_pcm_plugin_avail_update(snd_pcm_t *pcm)
- 			xfer += frames;
- 		}
- 		return (snd_pcm_sframes_t)xfer;
-+
-+	error_atomic:
-+		snd_atomic_write_end(&plugin->watom);
-+	error:
-+		return xfer > 0 ? (snd_pcm_sframes_t)xfer : err;
- 	}
- }
- 
--- 
-2.5.5
-
-From 374c5fa9c5cb80efa41ef8a3afd215aa48b48436 Mon Sep 17 00:00:00 2001
-From: Mengdong Lin <mengdong.lin@linux.intel.com>
-Date: Thu, 7 Apr 2016 15:28:42 +0800
-Subject: [PATCH 03/34] topology: Use the generic pointer to free an element's
- object
-
-The element is a wrapper for different types of objects.So use the
-generic pointer 'obj' instead of the type-specific pointer to free
-the object.
-
-Signed-off-by: Mengdong Lin <mengdong.lin@linux.intel.com>
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
----
- src/topology/elem.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/src/topology/elem.c b/src/topology/elem.c
-index 12d6a72..00f9eea 100644
---- a/src/topology/elem.c
-+++ b/src/topology/elem.c
-@@ -83,8 +83,8 @@ void tplg_elem_free(struct tplg_elem *elem)
- 	/* free struct snd_tplg_ object,
- 	 * the union pointers share the same address
- 	 */
--	if (elem->mixer_ctrl)
--		free(elem->mixer_ctrl);
-+	if (elem->obj)
-+		free(elem->obj);
- 
- 	free(elem);
- }
--- 
-2.5.5
-
-From 6b31bf8edb407f4c184576909f40c41bdc8439e4 Mon Sep 17 00:00:00 2001
-From: Mengdong Lin <mengdong.lin@linux.intel.com>
-Date: Thu, 7 Apr 2016 15:29:01 +0800
-Subject: [PATCH 04/34] topology: Define a free handler for the element
-
-This handler is defined for type-specific destruction of an element.
-
-Signed-off-by: Mengdong Lin <mengdong.lin@linux.intel.com>
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
----
- src/topology/elem.c       | 6 +++++-
- src/topology/tplg_local.h | 2 ++
- 2 files changed, 7 insertions(+), 1 deletion(-)
-
-diff --git a/src/topology/elem.c b/src/topology/elem.c
-index 00f9eea..f2afaaf 100644
---- a/src/topology/elem.c
-+++ b/src/topology/elem.c
-@@ -83,8 +83,12 @@ void tplg_elem_free(struct tplg_elem *elem)
- 	/* free struct snd_tplg_ object,
- 	 * the union pointers share the same address
- 	 */
--	if (elem->obj)
-+	if (elem->obj) {
-+		if (elem->free)
-+			elem->free(elem->obj);
-+
- 		free(elem->obj);
-+	}
- 
- 	free(elem);
- }
-diff --git a/src/topology/tplg_local.h b/src/topology/tplg_local.h
-index 4915b1a..7368a86 100644
---- a/src/topology/tplg_local.h
-+++ b/src/topology/tplg_local.h
-@@ -127,6 +127,8 @@ struct tplg_elem {
- 	 */
- 	struct list_head ref_list;
- 	struct list_head list; /* list of all elements with same type */
-+
-+	void (*free)(void *obj);
- };
- 
- struct map_elem {
--- 
-2.5.5
-
-From 2fd8d388f530b03872d8afb51b0f98c6474646c7 Mon Sep 17 00:00:00 2001
-From: Mengdong Lin <mengdong.lin@linux.intel.com>
-Date: Thu, 7 Apr 2016 15:29:15 +0800
-Subject: [PATCH 05/34] topology: Add doc for vendor tuples
-
-Describe how to define vendor tokens and tuples in the text conf file.
-
-Signed-off-by: Mengdong Lin <mengdong.lin@linux.intel.com>
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
----
- include/topology.h | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++---
- 1 file changed, 73 insertions(+), 4 deletions(-)
-
-diff --git a/include/topology.h b/include/topology.h
-index 011f6ae..51d282f 100644
---- a/include/topology.h
-+++ b/include/topology.h
-@@ -203,12 +203,77 @@ extern "C" {
-  *	bytes "0x12,0x34,0x56,0x78"
-  *	shorts "0x1122,0x3344,0x5566,0x7788"
-  *	words "0xaabbccdd,0x11223344,0x66aa77bb,0xefef1234"
-+ *	tuples "section id of the vendor tuples"
-  * };
-  * </pre>
-- * The file, bytes, shorts and words keywords are all mutually exclusive as
-- * the private data should only be taken from one source.  The private data can
-- * either be read from a separate file or defined in the topology file using
-- * the bytes, shorts or words keywords.
-+ * The file, bytes, shorts, words and tuples keywords are all mutually
-+ * exclusive as the private data should only be taken from one source.
-+ * The private data can either be read from a separate file or defined in
-+ * the topology file using the bytes, shorts, words or tuples keywords.
-+ * The keyword tuples is to define vendor specific tuples. Please refer to
-+ * section Vendor Tokens and Vendor tuples.
-+ *
-+ *  <h6>Vendor Tokens</h6>
-+ * A vendor token list is defined as a new section. Each token element is
-+ * a pair of string ID and integer value. And both the ID and value are
-+ * vendor-specific.
-+ *
-+ * <pre>
-+ * SectionVendorTokens."id of the vendor tokens" {
-+ *	comment "optional comments"
-+ *	VENDOR_TOKEN_ID1 "1"
-+ *	VENDOR_TOKEN_ID2 "2"
-+ *	VENDOR_TOKEN_ID3 "3"
-+ *	...
-+ * }
-+ * </pre>
-+ *
-+ *  <h6>Vendor Tuples</h6>
-+ * Vendor tuples are defined as a new section. It contains a reference to
-+ * a vendor token list and several tuple arrays.
-+ * All arrays share a vendor token list, defined by the tokens keyword.
-+ * Each tuple array is for a specific type, defined by the string following
-+ * the tuples keyword. Supported types are: string, uuid, bool, byte,
-+ * short and word.
-+ *
-+ * <pre>
-+ * SectionVendorTuples."id of the vendor tuples" {
-+ *	tokens "id of the vendor tokens"
-+ *
-+ *	tuples."string" {
-+ *		VENDOR_TOKEN_ID1 "character string"
-+ *		...
-+ *	}
-+ *
-+ *	tuples."uuid" {
-+ *		VENDOR_TOKEN_ID2 "16 character uuid"
-+ *		...
-+ *	}
-+ *
-+ *	tuples."bool" {
-+ *		VENDOR_TOKEN_ID3 "true/false"
-+ *		...
-+ *	}
-+ *
-+ *	tuples."byte" {
-+ *		VENDOR_TOKEN_ID4 "0x11"
-+ *		VENDOR_TOKEN_ID5 "0x22"
-+ *		...
-+ *	}
-+ *
-+ *	tuples."short" {
-+ *		VENDOR_TOKEN_ID6 "0x1122"
-+ *		VENDOR_TOKEN_ID7 "0x3344"
-+ *		...
-+ *	}
-+ *
-+ *	tuples."word" {
-+ *		VENDOR_TOKEN_ID8 "0x11223344"
-+ *		VENDOR_TOKEN_ID9 "0x55667788"
-+ *		...
-+ *	}
-+ * }
-+ * </pre>
-  *
-  * <h5>Mixer Controls</h5>
-  * A mixer control is defined as a new section that can include channel mapping,
-@@ -389,6 +454,10 @@ extern "C" {
-  * fields are the same for widgets as they are for controls whilst the other
-  * fields map on very closely to the driver widget fields.
-  *
-+ * <h5>Widget Private Data</h5>
-+ * Widget can have private data. For the format of the private data, please
-+ * refer to section Control Private Data.
-+ *
-  * <h4>PCM Capabilities</h4>
-  * Topology can also define the capabilities of FE and BE PCMs. Capabilities
-  * can be defined with the following section :-
--- 
-2.5.5
-
-From 768a006089fab94d5aeffd9115da3fbe951a94f8 Mon Sep 17 00:00:00 2001
-From: Mengdong Lin <mengdong.lin@linux.intel.com>
-Date: Thu, 7 Apr 2016 15:29:27 +0800
-Subject: [PATCH 06/34] topology: ABI - Define types for vendor tuples
-
-Tuples, a pair of token and value, can be used to define vendor specific
-data, for controls and widgets. This can avoid importing binary data blob
-from other files.
-
-Vendor specific tuple arrays will be embeded in the private data buffer
-of a control or widget object. To be backward compatible, union is used
-to define the tuple arrays in the existing private data ABI object
-'struct snd_soc_tplg_private'.
-
-Vendors need to make sure the token values defined by the topology conf
-file match those defined by their driver.
-
-Now supported tuple types are uuid, string, bool, byte, short and word.
-
-Signed-off-by: Mengdong Lin <mengdong.lin@linux.intel.com>
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
----
- include/sound/asoc.h | 42 +++++++++++++++++++++++++++++++++++++++++-
- 1 file changed, 41 insertions(+), 1 deletion(-)
-
-diff --git a/include/sound/asoc.h b/include/sound/asoc.h
-index a29c05c..920c9e0 100644
---- a/include/sound/asoc.h
-+++ b/include/sound/asoc.h
-@@ -107,6 +107,14 @@
- #define SND_SOC_TPLG_STREAM_PLAYBACK	0
- #define SND_SOC_TPLG_STREAM_CAPTURE	1
- 
-+/* vendor tuple types */
-+#define SND_SOC_TPLG_TUPLE_TYPE_UUID	0
-+#define SND_SOC_TPLG_TUPLE_TYPE_STRING	1
-+#define SND_SOC_TPLG_TUPLE_TYPE_BOOL	2
-+#define SND_SOC_TPLG_TUPLE_TYPE_BYTE	3
-+#define SND_SOC_TPLG_TUPLE_TYPE_WORD	4
-+#define SND_SOC_TPLG_TUPLE_TYPE_SHORT	5
-+
- /*
-  * Block Header.
-  * This header precedes all object and object arrays below.
-@@ -123,6 +131,35 @@ struct snd_soc_tplg_hdr {
- 	__le32 count;		/* number of elements in block */
- } __attribute__((packed));
- 
-+/* vendor tuple for uuid */
-+struct snd_soc_tplg_vendor_uuid_elem {
-+	__le32 token;
-+	char uuid[16];
-+} __attribute__((packed));
-+
-+/* vendor tuple for a bool/byte/short/word value */
-+struct snd_soc_tplg_vendor_value_elem {
-+	__le32 token;
-+	__le32 value;
-+} __attribute__((packed));
-+
-+/* vendor tuple for string */
-+struct snd_soc_tplg_vendor_string_elem {
-+	__le32 token;
-+	char string[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
-+} __attribute__((packed));
-+
-+struct snd_soc_tplg_vendor_array {
-+	__le32 size;	/* size in bytes of the array, including all elements */
-+	__le32 type;	/* SND_SOC_TPLG_TUPLE_TYPE_ */
-+	__le32 num_elems;	/* number of elements in array */
-+	union {
-+		struct snd_soc_tplg_vendor_uuid_elem uuid[0];
-+		struct snd_soc_tplg_vendor_value_elem value[0];
-+		struct snd_soc_tplg_vendor_string_elem string[0];
-+	};
-+} __attribute__((packed));
-+
- /*
-  * Private data.
-  * All topology objects may have private data that can be used by the driver or
-@@ -130,7 +167,10 @@ struct snd_soc_tplg_hdr {
-  */
- struct snd_soc_tplg_private {
- 	__le32 size;	/* in bytes of private data */
--	char data[0];
-+	union {
-+		char data[0];
-+		struct snd_soc_tplg_vendor_array array[0];
-+	};
- } __attribute__((packed));
- 
- /*
--- 
-2.5.5
-
-From 9b751b38cbb60bfb08ee796a59d72f40e3cd196d Mon Sep 17 00:00:00 2001
-From: Mengdong Lin <mengdong.lin@linux.intel.com>
-Date: Thu, 7 Apr 2016 15:29:36 +0800
-Subject: [PATCH 07/34] topology: Add support for vendor tokens
-
-Vendor can define a token list in SectionVendorTokens. Each token element
-is a pair of string ID and integer value. And both the ID and value are
-vendor-specific.
-
-Signed-off-by: Mengdong Lin <mengdong.lin@linux.intel.com>
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
----
- include/topology.h        |  1 +
- src/topology/data.c       | 50 +++++++++++++++++++++++++++++++++++++++++++++++
- src/topology/elem.c       |  3 +++
- src/topology/parser.c     | 10 ++++++++++
- src/topology/tplg_local.h | 15 ++++++++++++++
- 5 files changed, 79 insertions(+)
-
-diff --git a/include/topology.h b/include/topology.h
-index 51d282f..0df112c 100644
---- a/include/topology.h
-+++ b/include/topology.h
-@@ -578,6 +578,7 @@ enum snd_tplg_type {
- 	SND_TPLG_TYPE_BE,		/*!< BE DAI link */
- 	SND_TPLG_TYPE_CC,		/*!< Hostless codec <-> codec link */
- 	SND_TPLG_TYPE_MANIFEST,		/*!< Topology manifest */
-+	SND_TPLG_TYPE_TOKEN,		/*!< Vendor tokens */
- };
- 
- /**
-diff --git a/src/topology/data.c b/src/topology/data.c
-index 370c0fa..8455c15 100644
---- a/src/topology/data.c
-+++ b/src/topology/data.c
-@@ -253,6 +253,56 @@ static int tplg_parse_data_hex(snd_config_t *cfg, struct tplg_elem *elem,
- 	return ret;
- }
- 
-+/* Parse vendor tokens
-+ */
-+int tplg_parse_tokens(snd_tplg_t *tplg, snd_config_t *cfg,
-+	void *private ATTRIBUTE_UNUSED)
-+{
-+	snd_config_iterator_t i, next;
-+	snd_config_t *n;
-+	const char *id, *value;
-+	struct tplg_elem *elem;
-+	struct tplg_vendor_tokens *tokens;
-+	int num_tokens = 0;
-+
-+	elem = tplg_elem_new_common(tplg, cfg, NULL, SND_TPLG_TYPE_TOKEN);
-+	if (!elem)
-+		return -ENOMEM;
-+
-+	snd_config_for_each(i, next, cfg) {
-+		num_tokens++;
-+	}
-+
-+	if (!num_tokens)
-+		return 0;
-+
-+	tplg_dbg(" Vendor tokens: %s, %d tokens\n", elem->id, num_tokens);
-+
-+	tokens = calloc(1, sizeof(*tokens)
-+			+ num_tokens * sizeof(struct tplg_token));
-+	if (!tokens)
-+		return -ENOMEM;
-+	elem->tokens = tokens;
-+
-+	snd_config_for_each(i, next, cfg) {
-+
-+		n = snd_config_iterator_entry(i);
-+		if (snd_config_get_id(n, &id) < 0)
-+			continue;
-+
-+		if (snd_config_get_string(n, &value) < 0)
-+			continue;
-+
-+		elem_copy_text(tokens->token[tokens->num_tokens].id, id,
-+				SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
-+		tokens->token[tokens->num_tokens].value = atoi(value);
-+		tplg_dbg("\t\t %s : %d\n", tokens->token[tokens->num_tokens].id,
-+			tokens->token[tokens->num_tokens].value);
-+		tokens->num_tokens++;
-+	}
-+
-+	return 0;
-+}
- 
- /* Parse Private data.
-  *
-diff --git a/src/topology/elem.c b/src/topology/elem.c
-index f2afaaf..95e3fd4 100644
---- a/src/topology/elem.c
-+++ b/src/topology/elem.c
-@@ -193,6 +193,9 @@ struct tplg_elem* tplg_elem_new_common(snd_tplg_t *tplg,
- 		list_add_tail(&elem->list, &tplg->cc_list);
- 		obj_size = sizeof(struct snd_soc_tplg_link_config);
- 		break;
-+	case SND_TPLG_TYPE_TOKEN:
-+		list_add_tail(&elem->list, &tplg->token_list);
-+		break;
- 	default:
- 		free(elem);
- 		return NULL;
-diff --git a/src/topology/parser.c b/src/topology/parser.c
-index 4546257..264abc8 100644
---- a/src/topology/parser.c
-+++ b/src/topology/parser.c
-@@ -173,6 +173,14 @@ static int tplg_parse_config(snd_tplg_t *tplg, snd_config_t *cfg)
- 			continue;
- 		}
- 
-+		if (strcmp(id, "SectionVendorTokens") == 0) {
-+			err = tplg_parse_compound(tplg, n, tplg_parse_tokens,
-+				NULL);
-+			if (err < 0)
-+				return err;
-+			continue;
-+		}
-+
- 		SNDERR("error: unknown section %s\n", id);
- 	}
- 	return 0;
-@@ -407,6 +415,7 @@ snd_tplg_t *snd_tplg_new(void)
- 	INIT_LIST_HEAD(&tplg->mixer_list);
- 	INIT_LIST_HEAD(&tplg->enum_list);
- 	INIT_LIST_HEAD(&tplg->bytes_ext_list);
-+	INIT_LIST_HEAD(&tplg->token_list);
- 
- 	return tplg;
- }
-@@ -426,6 +435,7 @@ void snd_tplg_free(snd_tplg_t *tplg)
- 	tplg_elem_free_list(&tplg->mixer_list);
- 	tplg_elem_free_list(&tplg->enum_list);
- 	tplg_elem_free_list(&tplg->bytes_ext_list);
-+	tplg_elem_free_list(&tplg->token_list);
- 
- 	free(tplg);
- }
-diff --git a/src/topology/tplg_local.h b/src/topology/tplg_local.h
-index 7368a86..679bfff 100644
---- a/src/topology/tplg_local.h
-+++ b/src/topology/tplg_local.h
-@@ -69,6 +69,7 @@ struct snd_tplg {
- 	struct list_head route_list;
- 	struct list_head text_list;
- 	struct list_head pdata_list;
-+	struct list_head token_list;
- 	struct list_head pcm_config_list;
- 	struct list_head pcm_caps_list;
- 
-@@ -86,6 +87,16 @@ struct tplg_ref {
- 	struct list_head list;
- };
- 
-+/* element for vendor tokens */
-+struct tplg_token {
-+	char id[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
-+	unsigned int value;
-+};
-+
-+struct tplg_vendor_tokens {
-+	unsigned int num_tokens;
-+	struct tplg_token token[0];
-+};
- /* topology element */
- struct tplg_elem {
- 
-@@ -118,6 +129,7 @@ struct tplg_elem {
- 		/* these do not map to UAPI structs but are internal only */
- 		struct snd_soc_tplg_ctl_tlv *tlv;
- 		struct snd_soc_tplg_private *data;
-+		struct tplg_vendor_tokens *tokens;
- 	};
- 
- 	/* an element may refer to other elements:
-@@ -151,6 +163,9 @@ int tplg_parse_text(snd_tplg_t *tplg, snd_config_t *cfg,
- int tplg_parse_data(snd_tplg_t *tplg, snd_config_t *cfg,
- 	void *private ATTRIBUTE_UNUSED);
- 
-+int tplg_parse_tokens(snd_tplg_t *tplg, snd_config_t *cfg,
-+	void *private ATTRIBUTE_UNUSED);
-+
- int tplg_parse_control_bytes(snd_tplg_t *tplg,
- 	snd_config_t *cfg, void *private ATTRIBUTE_UNUSED);
- 
--- 
-2.5.5
-
-From fdb9a6d19f8b7cc8252d27e83907d8d1c5e4b53d Mon Sep 17 00:00:00 2001
-From: Mengdong Lin <mengdong.lin@linux.intel.com>
-Date: Thu, 7 Apr 2016 15:29:43 +0800
-Subject: [PATCH 08/34] topology: Add support for parsing vendor tuples
-
-Vendor can define several tuple arrays in 'SectionVendorTuples', as
-well as the reference to a vendor token list object.
-
-A later patche will copy vendor tuples in ABI format to the private
-buffer of its parent data object in the building phase.
-
-Signed-off-by: Mengdong Lin <mengdong.lin@linux.intel.com>
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
----
- include/topology.h        |   1 +
- src/topology/data.c       | 240 +++++++++++++++++++++++++++++++++++++++++++++-
- src/topology/elem.c       |   4 +
- src/topology/parser.c     |  10 ++
- src/topology/tplg_local.h |  29 ++++++
- 5 files changed, 283 insertions(+), 1 deletion(-)
-
-diff --git a/include/topology.h b/include/topology.h
-index 0df112c..b47f422 100644
---- a/include/topology.h
-+++ b/include/topology.h
-@@ -579,6 +579,7 @@ enum snd_tplg_type {
- 	SND_TPLG_TYPE_CC,		/*!< Hostless codec <-> codec link */
- 	SND_TPLG_TYPE_MANIFEST,		/*!< Topology manifest */
- 	SND_TPLG_TYPE_TOKEN,		/*!< Vendor tokens */
-+	SND_TPLG_TYPE_TUPLE,		/*!< Vendor tuples */
- };
- 
- /**
-diff --git a/src/topology/data.c b/src/topology/data.c
-index 8455c15..606fcd3 100644
---- a/src/topology/data.c
-+++ b/src/topology/data.c
-@@ -253,6 +253,175 @@ static int tplg_parse_data_hex(snd_config_t *cfg, struct tplg_elem *elem,
- 	return ret;
- }
- 
-+static int parse_tuple_set(snd_tplg_t *tplg, snd_config_t *cfg,
-+	struct tplg_tuple_set **s)
-+{
-+	snd_config_iterator_t i, next;
-+	snd_config_t *n;
-+	const char *id, *value;
-+	struct tplg_tuple_set *set;
-+	unsigned int type, num_tuples = 0;
-+	struct tplg_tuple *tuple;
-+	unsigned long int tuple_val;
-+	int len;
-+
-+	snd_config_get_id(cfg, &id);
-+
-+	if (strcmp(id, "uuid") == 0)
-+		type = SND_SOC_TPLG_TUPLE_TYPE_UUID;
-+	else if (strcmp(id, "string") == 0)
-+		type = SND_SOC_TPLG_TUPLE_TYPE_STRING;
-+	else if (strcmp(id, "bool") == 0)
-+		type = SND_SOC_TPLG_TUPLE_TYPE_BOOL;
-+	else if (strcmp(id, "byte") == 0)
-+		type = SND_SOC_TPLG_TUPLE_TYPE_BYTE;
-+	else if (strcmp(id, "short") == 0)
-+		type = SND_SOC_TPLG_TUPLE_TYPE_SHORT;
-+	else if (strcmp(id, "word") == 0)
-+		type = SND_SOC_TPLG_TUPLE_TYPE_WORD;
-+	else {
-+		SNDERR("error: invalid tuple type '%s'\n", id);
-+		return -EINVAL;
-+	}
-+
-+	snd_config_for_each(i, next, cfg)
-+		num_tuples++;
-+	if (!num_tuples)
-+		return 0;
-+
-+	tplg_dbg("\t %d %s tuples:\n", num_tuples, id);
-+	set = calloc(1, sizeof(*set) + num_tuples * sizeof(struct tplg_tuple));
-+	if (!set)
-+		return -ENOMEM;
-+
-+	set->type = type;
-+
-+	snd_config_for_each(i, next, cfg) {
-+
-+		n = snd_config_iterator_entry(i);
-+
-+		/* get id */
-+		if (snd_config_get_id(n, &id) < 0)
-+			continue;
-+
-+		/* get value */
-+		if (snd_config_get_string(n, &value) < 0)
-+			continue;
-+
-+		tuple = &set->tuple[set->num_tuples];
-+		elem_copy_text(tuple->token, id,
-+				SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
-+
-+		switch (type) {
-+		case SND_SOC_TPLG_TUPLE_TYPE_UUID:
-+			len = strlen(value);
-+			if (len > 16 || len == 0) {
-+				SNDERR("error: tuple %s: invalid uuid\n", id);
-+				goto err;
-+			}
-+
-+			memcpy(tuple->uuid, value, len);
-+			tplg_dbg("\t\t%s = %s\n", tuple->token, tuple->uuid);
-+			break;
-+
-+		case SND_SOC_TPLG_TUPLE_TYPE_STRING:
-+			elem_copy_text(tuple->string, value,
-+				SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
-+			tplg_dbg("\t\t%s = %s\n", tuple->token, tuple->string);
-+			break;
-+
-+		case SND_SOC_TPLG_TUPLE_TYPE_BOOL:
-+			if (strcmp(value, "true") == 0)
-+				tuple->value = 1;
-+			tplg_dbg("\t\t%s = %d\n", tuple->token, tuple->value);
-+			break;
-+
-+		case SND_SOC_TPLG_TUPLE_TYPE_BYTE:
-+		case SND_SOC_TPLG_TUPLE_TYPE_SHORT:
-+		case SND_SOC_TPLG_TUPLE_TYPE_WORD:
-+			errno = 0;
-+			/* no support for negative value */
-+			tuple_val = strtoul(value, NULL, 0);
-+			if ((errno == ERANGE && tuple_val == ULONG_MAX)
-+				|| (errno != 0 && tuple_val == 0)) {
-+				SNDERR("error: tuple %s:strtoul fail\n", id);
-+				goto err;
-+			}
-+
-+			if ((type == SND_SOC_TPLG_TUPLE_TYPE_WORD
-+					&& tuple_val > UINT_MAX)
-+				|| (type == SND_SOC_TPLG_TUPLE_TYPE_SHORT
-+					&& tuple_val > USHRT_MAX)
-+				|| (type == SND_SOC_TPLG_TUPLE_TYPE_BYTE
-+					&& tuple_val > UCHAR_MAX)) {
-+				SNDERR("error: tuple %s: invalid value\n", id);
-+				goto err;
-+			}
-+
-+			tuple->value = (unsigned int) tuple_val;
-+			tplg_dbg("\t\t%s = 0x%x\n", tuple->token, tuple->value);
-+			break;
-+
-+		default:
-+			break;
-+		}
-+
-+		set->num_tuples++;
-+	}
-+
-+	*s = set;
-+	return 0;
-+
-+err:
-+	free(set);
-+	return -EINVAL;
-+}
-+
-+static int parse_tuple_sets(snd_tplg_t *tplg, snd_config_t *cfg,
-+	struct tplg_vendor_tuples *tuples)
-+{
-+	snd_config_iterator_t i, next;
-+	snd_config_t *n;
-+	const char *id;
-+	unsigned int num_tuple_sets = 0;
-+	int err;
-+
-+	if (snd_config_get_type(cfg) != SND_CONFIG_TYPE_COMPOUND) {
-+		SNDERR("error: compound type expected for %s", id);
-+		return -EINVAL;
-+	}
-+
-+	snd_config_for_each(i, next, cfg) {
-+		num_tuple_sets++;
-+	}
-+
-+	if (!num_tuple_sets)
-+		return 0;
-+
-+	tuples->set = calloc(1, num_tuple_sets * sizeof(void *));
-+	if (!tuples->set)
-+		return -ENOMEM;
-+
-+	snd_config_for_each(i, next, cfg) {
-+		n = snd_config_iterator_entry(i);
-+		if (snd_config_get_type(n) != SND_CONFIG_TYPE_COMPOUND) {
-+			SNDERR("error: compound type expected for %s, is %d",
-+			id, snd_config_get_type(n));
-+			return -EINVAL;
-+		}
-+
-+		err = parse_tuple_set(tplg, n, &tuples->set[tuples->num_sets]);
-+		if (err < 0)
-+			return err;
-+
-+		/* overlook empty tuple sets */
-+		if (tuples->set[tuples->num_sets])
-+			tuples->num_sets++;
-+	}
-+
-+	return 0;
-+}
-+
- /* Parse vendor tokens
-  */
- int tplg_parse_tokens(snd_tplg_t *tplg, snd_config_t *cfg,
-@@ -304,10 +473,71 @@ int tplg_parse_tokens(snd_tplg_t *tplg, snd_config_t *cfg,
- 	return 0;
- }
- 
-+/* Parse vendor tuples.
-+ */
-+int tplg_parse_tuples(snd_tplg_t *tplg, snd_config_t *cfg,
-+	void *private ATTRIBUTE_UNUSED)
-+{
-+	snd_config_iterator_t i, next;
-+	snd_config_t *n;
-+	const char *id, *value;
-+	struct tplg_elem *elem;
-+	struct tplg_vendor_tuples *tuples;
-+	int err;
-+
-+	elem = tplg_elem_new_common(tplg, cfg, NULL, SND_TPLG_TYPE_TUPLE);
-+	if (!elem)
-+		return -ENOMEM;
-+
-+	tplg_dbg(" Vendor Tuples: %s\n", elem->id);
-+
-+	tuples = calloc(1, sizeof(*tuples));
-+	if (!tuples)
-+		return -ENOMEM;
-+	elem->tuples = tuples;
-+
-+	snd_config_for_each(i, next, cfg) {
-+
-+		n = snd_config_iterator_entry(i);
-+		if (snd_config_get_id(n, &id) < 0)
-+			continue;
-+
-+		if (strcmp(id, "tokens") == 0) {
-+			if (snd_config_get_string(n, &value) < 0)
-+				return -EINVAL;
-+			tplg_ref_add(elem, SND_TPLG_TYPE_TOKEN, value);
-+			tplg_dbg("\t refer to vendor tokens: %s\n", value);
-+		}
-+
-+		if (strcmp(id, "tuples") == 0) {
-+			err = parse_tuple_sets(tplg, n, tuples);
-+			if (err < 0)
-+				return err;
-+		}
-+	}
-+
-+	return 0;
-+}
-+
-+/* Free handler of tuples */
-+void tplg_free_tuples(void *obj)
-+{
-+	struct tplg_vendor_tuples *tuples = (struct tplg_vendor_tuples *)obj;
-+	int i;
-+
-+	if (!tuples || !tuples->set)
-+		return;
-+
-+	for (i = 0; i < tuples->num_sets; i++)
-+		free(tuples->set[i]);
-+
-+	free(tuples->set);
-+}
-+
- /* Parse Private data.
-  *
-  * Object private data can either be from file or defined as bytes, shorts,
-- * words.
-+ * words, tuples.
-  */
- int tplg_parse_data(snd_tplg_t *tplg, snd_config_t *cfg,
- 	void *private ATTRIBUTE_UNUSED)
-@@ -365,6 +595,14 @@ int tplg_parse_data(snd_tplg_t *tplg, snd_config_t *cfg,
- 			continue;
- 		}
- 
-+		if (strcmp(id, "tuples") == 0) {
-+			if (snd_config_get_string(n, &val) < 0)
-+				return -EINVAL;
-+			tplg_dbg(" Data: %s\n", val);
-+			tplg_ref_add(elem, SND_TPLG_TYPE_TUPLE, val);
-+			continue;
-+		}
-+
- 		if (strcmp(id, "index") == 0) {
- 			if (snd_config_get_string(n, &val) < 0)
- 				return -EINVAL;
-diff --git a/src/topology/elem.c b/src/topology/elem.c
-index 95e3fd4..50414f0 100644
---- a/src/topology/elem.c
-+++ b/src/topology/elem.c
-@@ -196,6 +196,10 @@ struct tplg_elem* tplg_elem_new_common(snd_tplg_t *tplg,
- 	case SND_TPLG_TYPE_TOKEN:
- 		list_add_tail(&elem->list, &tplg->token_list);
- 		break;
-+	case SND_TPLG_TYPE_TUPLE:
-+		list_add_tail(&elem->list, &tplg->tuple_list);
-+		elem->free = tplg_free_tuples;
-+		break;
- 	default:
- 		free(elem);
- 		return NULL;
-diff --git a/src/topology/parser.c b/src/topology/parser.c
-index 264abc8..0d967b4 100644
---- a/src/topology/parser.c
-+++ b/src/topology/parser.c
-@@ -181,6 +181,14 @@ static int tplg_parse_config(snd_tplg_t *tplg, snd_config_t *cfg)
- 			continue;
- 		}
- 
-+		if (strcmp(id, "SectionVendorTuples") == 0) {
-+			err = tplg_parse_compound(tplg, n, tplg_parse_tuples,
-+				NULL);
-+			if (err < 0)
-+				return err;
-+			continue;
-+		}
-+
- 		SNDERR("error: unknown section %s\n", id);
- 	}
- 	return 0;
-@@ -416,6 +424,7 @@ snd_tplg_t *snd_tplg_new(void)
- 	INIT_LIST_HEAD(&tplg->enum_list);
- 	INIT_LIST_HEAD(&tplg->bytes_ext_list);
- 	INIT_LIST_HEAD(&tplg->token_list);
-+	INIT_LIST_HEAD(&tplg->tuple_list);
- 
- 	return tplg;
- }
-@@ -436,6 +445,7 @@ void snd_tplg_free(snd_tplg_t *tplg)
- 	tplg_elem_free_list(&tplg->enum_list);
- 	tplg_elem_free_list(&tplg->bytes_ext_list);
- 	tplg_elem_free_list(&tplg->token_list);
-+	tplg_elem_free_list(&tplg->tuple_list);
- 
- 	free(tplg);
- }
-diff --git a/src/topology/tplg_local.h b/src/topology/tplg_local.h
-index 679bfff..4d59a1f 100644
---- a/src/topology/tplg_local.h
-+++ b/src/topology/tplg_local.h
-@@ -70,6 +70,7 @@ struct snd_tplg {
- 	struct list_head text_list;
- 	struct list_head pdata_list;
- 	struct list_head token_list;
-+	struct list_head tuple_list;
- 	struct list_head pcm_config_list;
- 	struct list_head pcm_caps_list;
- 
-@@ -97,6 +98,28 @@ struct tplg_vendor_tokens {
- 	unsigned int num_tokens;
- 	struct tplg_token token[0];
- };
-+
-+/* element for vendor tuples */
-+struct tplg_tuple {
-+	char token[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
-+	union {
-+		char string[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
-+		char uuid[16];
-+		unsigned int value;
-+	};
-+};
-+
-+struct tplg_tuple_set {
-+	unsigned int  type; /* uuid, bool, byte, short, word, string*/
-+	unsigned int  num_tuples;
-+	struct tplg_tuple tuple[0];
-+};
-+
-+struct tplg_vendor_tuples {
-+	unsigned int  num_sets;
-+	struct tplg_tuple_set **set;
-+};
-+
- /* topology element */
- struct tplg_elem {
- 
-@@ -130,6 +153,7 @@ struct tplg_elem {
- 		struct snd_soc_tplg_ctl_tlv *tlv;
- 		struct snd_soc_tplg_private *data;
- 		struct tplg_vendor_tokens *tokens;
-+		struct tplg_vendor_tuples *tuples;
- 	};
- 
- 	/* an element may refer to other elements:
-@@ -166,6 +190,11 @@ int tplg_parse_data(snd_tplg_t *tplg, snd_config_t *cfg,
- int tplg_parse_tokens(snd_tplg_t *tplg, snd_config_t *cfg,
- 	void *private ATTRIBUTE_UNUSED);
- 
-+int tplg_parse_tuples(snd_tplg_t *tplg, snd_config_t *cfg,
-+	void *private ATTRIBUTE_UNUSED);
-+
-+void tplg_free_tuples(void *obj);
-+
- int tplg_parse_control_bytes(snd_tplg_t *tplg,
- 	snd_config_t *cfg, void *private ATTRIBUTE_UNUSED);
- 
--- 
-2.5.5
-
-From 0c5e5c1801e5b1b55e46144ee29ca7a71f2812b0 Mon Sep 17 00:00:00 2001
-From: Mengdong Lin <mengdong.lin@linux.intel.com>
-Date: Thu, 7 Apr 2016 15:29:49 +0800
-Subject: [PATCH 09/34] topology: Build data objects with tuples
-
-For data objects with tuples, the parser will bind the vendor tuples
-and tokens, copy the tuples to the private buffer of its parent data
-object. Then later the builder will export the vendor tuples as private
-binary data for the control or widgets objects.
-
-Signed-off-by: Mengdong Lin <mengdong.lin@linux.intel.com>
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
----
- src/topology/data.c       | 213 ++++++++++++++++++++++++++++++++++++++++++++++
- src/topology/parser.c     |   4 +
- src/topology/tplg_local.h |   1 +
- 3 files changed, 218 insertions(+)
-
-diff --git a/src/topology/data.c b/src/topology/data.c
-index 606fcd3..19c31bf 100644
---- a/src/topology/data.c
-+++ b/src/topology/data.c
-@@ -253,6 +253,198 @@ static int tplg_parse_data_hex(snd_config_t *cfg, struct tplg_elem *elem,
- 	return ret;
- }
- 
-+/* get the token integer value from its id */
-+static int get_token_value(const char *token_id,
-+	struct tplg_vendor_tokens *tokens)
-+{
-+	int i;
-+
-+	for (i = 0; i < tokens->num_tokens; i++) {
-+		if (strcmp(token_id, tokens->token[i].id) == 0)
-+			return tokens->token[i].value;
-+	}
-+
-+	SNDERR("error: cannot find token id '%s'\n", token_id);
-+	return -1;
-+}
-+
-+/* get the vendor tokens referred by the vendor tuples */
-+static struct tplg_elem *get_tokens(snd_tplg_t *tplg, struct tplg_elem *elem)
-+{
-+	struct tplg_ref *ref;
-+	struct list_head *base, *pos;
-+	int err = 0;
-+
-+	base = &elem->ref_list;
-+	list_for_each(pos, base) {
-+
-+		ref = list_entry(pos, struct tplg_ref, list);
-+
-+		if (!ref->id || ref->type != SND_TPLG_TYPE_TOKEN)
-+			continue;
-+
-+		if (!ref->elem) {
-+			ref->elem = tplg_elem_lookup(&tplg->token_list,
-+						ref->id, SND_TPLG_TYPE_TOKEN);
-+		}
-+
-+		return ref->elem;
-+	}
-+
-+	return NULL;
-+}
-+
-+/* check if a data element has tuples */
-+static bool has_tuples(struct tplg_elem *elem)
-+{
-+	struct tplg_ref *ref;
-+	struct list_head *base, *pos;
-+	int err = 0;
-+
-+	base = &elem->ref_list;
-+	list_for_each(pos, base) {
-+
-+		ref = list_entry(pos, struct tplg_ref, list);
-+		if (ref->id && ref->type == SND_TPLG_TYPE_TUPLE)
-+			return true;
-+	}
-+
-+	return false;
-+}
-+
-+/* get size of a tuple element from its type */
-+static unsigned int get_tuple_size(int type)
-+{
-+	switch (type) {
-+
-+	case SND_SOC_TPLG_TUPLE_TYPE_UUID:
-+		return sizeof(struct snd_soc_tplg_vendor_uuid_elem);
-+
-+	case SND_SOC_TPLG_TUPLE_TYPE_STRING:
-+		return sizeof(struct snd_soc_tplg_vendor_string_elem);
-+
-+	default:
-+		return sizeof(struct snd_soc_tplg_vendor_value_elem);
-+	}
-+}
-+
-+/* fill a data element's private buffer with its tuples */
-+static int copy_tuples(struct tplg_elem *elem,
-+	struct tplg_vendor_tuples *tuples, struct tplg_vendor_tokens *tokens)
-+{
-+	struct snd_soc_tplg_private *priv = elem->data;
-+	struct tplg_tuple_set *tuple_set;
-+	struct tplg_tuple *tuple;
-+	struct snd_soc_tplg_vendor_array *array;
-+	struct snd_soc_tplg_vendor_uuid_elem *uuid;
-+	struct snd_soc_tplg_vendor_string_elem *string;
-+	struct snd_soc_tplg_vendor_value_elem *value;
-+	int set_size, size, off;
-+	int i, j, token_val;
-+
-+	if (priv) {
-+		SNDERR("error: %s has more data than tuples\n", elem->id);
-+		return -EINVAL;
-+	}
-+
-+	size = 0;
-+	for (i = 0; i < tuples->num_sets ; i++) {
-+		tuple_set = tuples->set[i];
-+		set_size = sizeof(struct snd_soc_tplg_vendor_array)
-+			+ get_tuple_size(tuple_set->type)
-+			* tuple_set->num_tuples;
-+		size += set_size;
-+		if (size > TPLG_MAX_PRIV_SIZE) {
-+			SNDERR("error: data too big %d\n", size);
-+			return -EINVAL;
-+		}
-+
-+		if (priv != NULL)
-+			priv = realloc(priv, sizeof(*priv) + size);
-+		else
-+			priv = calloc(1, sizeof(*priv) + size);
-+		if (!priv)
-+			return -ENOMEM;
-+
-+		off = priv->size;
-+		priv->size = size;
-+
-+		array = (struct snd_soc_tplg_vendor_array *)(priv->data + off);
-+		array->size = set_size;
-+		array->type = tuple_set->type;
-+		array->num_elems = tuple_set->num_tuples;
-+
-+		/* fill the private data buffer */
-+		for (j = 0; j < tuple_set->num_tuples; j++) {
-+			tuple = &tuple_set->tuple[j];
-+			token_val = get_token_value(tuple->token, tokens);
-+			if (token_val  < 0)
-+				return -EINVAL;
-+
-+			switch (tuple_set->type) {
-+			case SND_SOC_TPLG_TUPLE_TYPE_UUID:
-+				uuid = &array->uuid[j];
-+				uuid->token = token_val;
-+				memcpy(uuid->uuid, tuple->uuid, 16);
-+				break;
-+
-+			case SND_SOC_TPLG_TUPLE_TYPE_STRING:
-+				string = &array->string[j];
-+				string->token = token_val;
-+				elem_copy_text(string->string, tuple->string,
-+					SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
-+				break;
-+
-+			default:
-+				value = &array->value[j];
-+				value->token = token_val;
-+				value->value = tuple->value;
-+				break;
-+			}
-+		}
-+	}
-+
-+	elem->data = priv;
-+	return 0;
-+}
-+
-+/* build a data element from its tuples */
-+static int build_tuples(snd_tplg_t *tplg, struct tplg_elem *elem)
-+{
-+	struct tplg_ref *ref;
-+	struct list_head *base, *pos;
-+	struct tplg_elem *tuples, *tokens;
-+
-+	base = &elem->ref_list;
-+	list_for_each(pos, base) {
-+
-+		ref = list_entry(pos, struct tplg_ref, list);
-+
-+		if (!ref->id || ref->type != SND_TPLG_TYPE_TUPLE)
-+			continue;
-+
-+		tplg_dbg("look up tuples %s\n", ref->id);
-+
-+		if (!ref->elem)
-+			ref->elem = tplg_elem_lookup(&tplg->tuple_list,
-+						ref->id, SND_TPLG_TYPE_TUPLE);
-+		tuples = ref->elem;
-+		if (!tuples)
-+			return -EINVAL;
-+
-+		tplg_dbg("found tuples %s\n", tuples->id);
-+		tokens = get_tokens(tplg, tuples);
-+		if (!tokens)
-+			return -EINVAL;
-+
-+		tplg_dbg("found tokens %s\n", tokens->id);
-+		/* a data object can only have one tuples object */
-+		return copy_tuples(elem, tuples->tuples, tokens->tokens);
-+	}
-+
-+	return 0;
-+}
-+
- static int parse_tuple_set(snd_tplg_t *tplg, snd_config_t *cfg,
- 	struct tplg_tuple_set **s)
- {
-@@ -683,3 +875,24 @@ int tplg_copy_data(struct tplg_elem *elem, struct tplg_elem *ref)
- 	memcpy(priv->data, ref->data->data, priv_data_size);
- 	return 0;
- }
-+
-+/* check data objects and build those with tuples */
-+int tplg_build_data(snd_tplg_t *tplg)
-+{
-+	struct list_head *base, *pos;
-+	struct tplg_elem *elem;
-+	int err = 0;
-+
-+	base = &tplg->pdata_list;
-+	list_for_each(pos, base) {
-+
-+		elem = list_entry(pos, struct tplg_elem, list);
-+		if (has_tuples(elem)) {
-+			err = build_tuples(tplg, elem);
-+			if (err < 0)
-+				return err;
-+		}
-+	}
-+
-+	return 0;
-+}
-diff --git a/src/topology/parser.c b/src/topology/parser.c
-index 0d967b4..30d91f9 100644
---- a/src/topology/parser.c
-+++ b/src/topology/parser.c
-@@ -242,6 +242,10 @@ static int tplg_build_integ(snd_tplg_t *tplg)
- {
- 	int err;
- 
-+	err = tplg_build_data(tplg);
-+	if (err <  0)
-+		return err;
-+
- 	err = tplg_build_controls(tplg);
- 	if (err <  0)
- 		return err;
-diff --git a/src/topology/tplg_local.h b/src/topology/tplg_local.h
-index 4d59a1f..4c601d4 100644
---- a/src/topology/tplg_local.h
-+++ b/src/topology/tplg_local.h
-@@ -222,6 +222,7 @@ int tplg_parse_be(snd_tplg_t *tplg,
- int tplg_parse_cc(snd_tplg_t *tplg,
- 	snd_config_t *cfg, void *private ATTRIBUTE_UNUSED);
- 
-+int tplg_build_data(snd_tplg_t *tplg);
- int tplg_build_controls(snd_tplg_t *tplg);
- int tplg_build_widgets(snd_tplg_t *tplg);
- int tplg_build_routes(snd_tplg_t *tplg);
--- 
-2.5.5
-
-From e57b521c61f0df14b660ce6ba8c5009a63f5b115 Mon Sep 17 00:00:00 2001
-From: Hsin-Yu Chao <hychao@chromium.org>
-Date: Wed, 13 Apr 2016 18:53:09 +0800
-Subject: [PATCH 10/34] ucm: add cset-tlv
-
-This patch enables UCM to set a file in TLV format to kcontrol by:
-cset-tlv "name='<kcontrol-name>' <path-to-file>"
-This new 'cset-tlv' command will be used to write audio DSP to
-specific alsa control, where the driver expectes a file in TLV
-format.
-The TLV file to set to kcontrol will be checked first by file size
-not larger than 16 MB, and then examine if the length field reports
-correct number of bytes in the TLV file.
-
-Signed-off-by: Hsin-Yu Chao <hychao@chromium.org>
-Reviewed-by: Vinod Koul <vinod.koul@intel.com>
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
----
- src/ucm/main.c      | 94 +++++++++++++++++++++++++++++++++++++++++++++--------
- src/ucm/parser.c    | 10 ++++++
- src/ucm/ucm_local.h |  1 +
- 3 files changed, 92 insertions(+), 13 deletions(-)
-
-diff --git a/src/ucm/main.c b/src/ucm/main.c
-index 7e44603..24d9510 100644
---- a/src/ucm/main.c
-+++ b/src/ucm/main.c
-@@ -161,6 +161,57 @@ static int open_ctl(snd_use_case_mgr_t *uc_mgr,
- 	return 0;
- }
- 
-+static int read_tlv_file(unsigned int **res,
-+			 const char *filepath)
-+{
-+	int err = 0;
-+	int fd;
-+	struct stat st;
-+	size_t sz;
-+	ssize_t sz_read;
-+	struct snd_ctl_tlv *tlv;
-+
-+	fd = open(filepath, O_RDONLY);
-+	if (fd < 0) {
-+		err = -errno;
-+		return err;
-+	}
-+	if (fstat(fd, &st) == -1) {
-+		err = -errno;
-+		goto __fail;
-+	}
-+	sz = st.st_size;
-+	if (sz > 16 * 1024 * 1024 || sz < 8 || sz % 4) {
-+		uc_error("File size should be less than 16 MB "
-+			 "and multiple of 4");
-+		err = -EINVAL;
-+		goto __fail;
-+	}
-+	*res = malloc(sz);
-+	if (res == NULL) {
-+		err = -ENOMEM;
-+		goto __fail;
-+	}
-+	sz_read = read(fd, *res, sz);
-+	if (sz_read < 0 || (size_t)sz_read != sz) {
-+		err = -EIO;
-+		free(*res);
-+		*res = NULL;
-+	}
-+	/* Check if the tlv file specifies valid size. */
-+	tlv = (struct snd_ctl_tlv *)(*res);
-+	if (tlv->length + 2 * sizeof(unsigned int) != sz) {
-+		uc_error("Invalid tlv size: %d", tlv->length);
-+		err = -EINVAL;
-+		free(*res);
-+		*res = NULL;
-+	}
-+
-+__fail:
-+	close(fd);
-+	return err;
-+}
-+
- static int binary_file_parse(snd_ctl_elem_value_t *dst,
- 			      snd_ctl_elem_info_t *info,
- 			      const char *filepath)
-@@ -226,6 +277,7 @@ static int execute_cset(snd_ctl_t *ctl, const char *cset, unsigned int type)
- 	snd_ctl_elem_id_t *id;
- 	snd_ctl_elem_value_t *value;
- 	snd_ctl_elem_info_t *info;
-+	unsigned int *res = NULL;
- 
- 	snd_ctl_elem_id_malloc(&id);
- 	snd_ctl_elem_value_malloc(&value);
-@@ -241,23 +293,36 @@ static int execute_cset(snd_ctl_t *ctl, const char *cset, unsigned int type)
- 		err = -EINVAL;
- 		goto __fail;
- 	}
--	snd_ctl_elem_value_set_id(value, id);
- 	snd_ctl_elem_info_set_id(info, id);
--	err = snd_ctl_elem_read(ctl, value);
--	if (err < 0)
--		goto __fail;
- 	err = snd_ctl_elem_info(ctl, info);
- 	if (err < 0)
- 		goto __fail;
--	if (type == SEQUENCE_ELEMENT_TYPE_CSET_BIN_FILE)
--		err = binary_file_parse(value, info, pos);
--	else
--		err = snd_ctl_ascii_value_parse(ctl, value, info, pos);
--	if (err < 0)
--		goto __fail;
--	err = snd_ctl_elem_write(ctl, value);
--	if (err < 0)
--		goto __fail;
-+	if (type == SEQUENCE_ELEMENT_TYPE_CSET_TLV) {
-+		if (!snd_ctl_elem_info_is_tlv_writable(info)) {
-+			err = -EINVAL;
-+			goto __fail;
-+		}
-+		err = read_tlv_file(&res, pos);
-+		if (err < 0)
-+			goto __fail;
-+		err = snd_ctl_elem_tlv_write(ctl, id, res);
-+		if (err < 0)
-+			goto __fail;
-+	} else {
-+		snd_ctl_elem_value_set_id(value, id);
-+		err = snd_ctl_elem_read(ctl, value);
-+		if (err < 0)
-+			goto __fail;
-+		if (type == SEQUENCE_ELEMENT_TYPE_CSET_BIN_FILE)
-+			err = binary_file_parse(value, info, pos);
-+		else
-+			err = snd_ctl_ascii_value_parse(ctl, value, info, pos);
-+		if (err < 0)
-+			goto __fail;
-+		err = snd_ctl_elem_write(ctl, value);
-+		if (err < 0)
-+			goto __fail;
-+	}
- 	err = 0;
-       __fail:
- 	if (id != NULL)
-@@ -266,6 +331,8 @@ static int execute_cset(snd_ctl_t *ctl, const char *cset, unsigned int type)
- 		free(value);
- 	if (info != NULL)
- 		free(info);
-+	if (res != NULL)
-+		free(res);
- 
- 	return err;
- }
-@@ -298,6 +365,7 @@ static int execute_sequence(snd_use_case_mgr_t *uc_mgr,
- 			break;
- 		case SEQUENCE_ELEMENT_TYPE_CSET:
- 		case SEQUENCE_ELEMENT_TYPE_CSET_BIN_FILE:
-+		case SEQUENCE_ELEMENT_TYPE_CSET_TLV:
- 			if (cdev == NULL) {
- 				char *playback_ctl = NULL;
- 				char *capture_ctl = NULL;
-diff --git a/src/ucm/parser.c b/src/ucm/parser.c
-index 8405bd2..13f62d7 100644
---- a/src/ucm/parser.c
-+++ b/src/ucm/parser.c
-@@ -316,6 +316,16 @@ static int parse_sequence(snd_use_case_mgr_t *uc_mgr ATTRIBUTE_UNUSED,
- 			continue;
- 		}
- 
-+		if (strcmp(cmd, "cset-tlv") == 0) {
-+			curr->type = SEQUENCE_ELEMENT_TYPE_CSET_TLV;
-+			err = parse_string(n, &curr->data.cset);
-+			if (err < 0) {
-+				uc_error("error: cset-tlv requires a string!");
-+				return err;
-+			}
-+			continue;
-+		}
-+
- 		if (strcmp(cmd, "usleep") == 0) {
- 			curr->type = SEQUENCE_ELEMENT_TYPE_SLEEP;
- 			err = snd_config_get_integer(n, &curr->data.sleep);
-diff --git a/src/ucm/ucm_local.h b/src/ucm/ucm_local.h
-index 3a5d2c2..b89de2a 100644
---- a/src/ucm/ucm_local.h
-+++ b/src/ucm/ucm_local.h
-@@ -48,6 +48,7 @@
- #define SEQUENCE_ELEMENT_TYPE_SLEEP	3
- #define SEQUENCE_ELEMENT_TYPE_EXEC	4
- #define SEQUENCE_ELEMENT_TYPE_CSET_BIN_FILE	5
-+#define SEQUENCE_ELEMENT_TYPE_CSET_TLV	6
- 
- struct ucm_value {
-         struct list_head list;
--- 
-2.5.5
-
-From fdba9e1bad8f769a6137e565471f0227f23a3132 Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Thu, 14 Apr 2016 17:33:03 +0200
-Subject: [PATCH 11/34] pcm: Fallback open as the first instance for dmix & co
-
-dmix and other PCM plugins tries to open a secondary stream with
-O_APPEND flag when the shmem was already attached by another.
-However, when another streams have been already closed after the
-shmem check, this open may return the error EBADFD, since the kernel
-accepts O_APPEND only for the secondary streams.
-
-This patch adds a workaround for such a case.  It just retries opening
-the stream as the first instance (i.e. without O_APPEND flag).
-This is basically safe behavior (the kernel takes care of races), even
-we may do this even unconditionally.  But it's bad from the
-performance POV, so we do it only when really needed.
-
-Reported-by: Lars Lindqvist <lars.lindqvist@yandex.ru>
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
----
- src/pcm/pcm_dmix.c   | 8 ++++++++
- src/pcm/pcm_dshare.c | 8 ++++++++
- src/pcm/pcm_dsnoop.c | 8 ++++++++
- 3 files changed, 24 insertions(+)
-
-diff --git a/src/pcm/pcm_dmix.c b/src/pcm/pcm_dmix.c
-index b26a5c7..007d356 100644
---- a/src/pcm/pcm_dmix.c
-+++ b/src/pcm/pcm_dmix.c
-@@ -1020,6 +1020,7 @@ int snd_pcm_dmix_open(snd_pcm_t **pcmp, const char *name,
- 	dmix->max_periods = opts->max_periods;
- 	dmix->sync_ptr = snd_pcm_dmix_sync_ptr;
- 
-+ retry:
- 	if (first_instance) {
- 		/* recursion is already checked in
- 		   snd_pcm_direct_get_slave_ipc_offset() */
-@@ -1076,6 +1077,13 @@ int snd_pcm_dmix_open(snd_pcm_t **pcmp, const char *name,
- 						 SND_PCM_APPEND,
- 						 NULL);
- 			if (ret < 0) {
-+				/* all other streams have been closed;
-+				 * retry as the first instance
-+				 */
-+				if (ret == -EBADFD) {
-+					first_instance = 1;
-+					goto retry;
-+				}
- 				SNDERR("unable to open slave");
- 				goto _err;
- 			}
-diff --git a/src/pcm/pcm_dshare.c b/src/pcm/pcm_dshare.c
-index 58e47bb..adb3587 100644
---- a/src/pcm/pcm_dshare.c
-+++ b/src/pcm/pcm_dshare.c
-@@ -690,6 +690,7 @@ int snd_pcm_dshare_open(snd_pcm_t **pcmp, const char *name,
- 		break;
- 	}
- 
-+ retry:
- 	first_instance = ret = snd_pcm_direct_shm_create_or_connect(dshare);
- 	if (ret < 0) {
- 		SNDERR("unable to create IPC shm instance");
-@@ -758,6 +759,13 @@ int snd_pcm_dshare_open(snd_pcm_t **pcmp, const char *name,
- 						 SND_PCM_APPEND,
- 						 NULL);
- 			if (ret < 0) {
-+				/* all other streams have been closed;
-+				 * retry as the first instance
-+				 */
-+				if (ret == -EBADFD) {
-+					first_instance = 1;
-+					goto retry;
-+				}
- 				SNDERR("unable to open slave");
- 				goto _err;
- 			}
-diff --git a/src/pcm/pcm_dsnoop.c b/src/pcm/pcm_dsnoop.c
-index 576c35b..8ff0ba5 100644
---- a/src/pcm/pcm_dsnoop.c
-+++ b/src/pcm/pcm_dsnoop.c
-@@ -583,6 +583,7 @@ int snd_pcm_dsnoop_open(snd_pcm_t **pcmp, const char *name,
- 		break;
- 	}
- 		
-+ retry:
- 	first_instance = ret = snd_pcm_direct_shm_create_or_connect(dsnoop);
- 	if (ret < 0) {
- 		SNDERR("unable to create IPC shm instance");
-@@ -651,6 +652,13 @@ int snd_pcm_dsnoop_open(snd_pcm_t **pcmp, const char *name,
- 						 SND_PCM_APPEND,
- 						 NULL);
- 			if (ret < 0) {
-+				/* all other streams have been closed;
-+				 * retry as the first instance
-+				 */
-+				if (ret == -EBADFD) {
-+					first_instance = 1;
-+					goto retry;
-+				}
- 				SNDERR("unable to open slave");
- 				goto _err;
- 			}
--- 
-2.5.5
-
-From f5c313eae5c26d6843a4f860743151f53b2f4041 Mon Sep 17 00:00:00 2001
-From: Shreyas NC <shreyas.nc@intel.com>
-Date: Thu, 28 Apr 2016 11:07:56 +0530
-Subject: [PATCH 12/34] conf: topology: Add Skylake i2s conf
-
-The Skylake topology configuration for simple topology graph is
-provided. This exposes the PCM capabilities of the DSP.
-
-Signed-off-by: Shreyas NC <shreyas.nc@intel.com>
-Signed-off-by: Subhransu S. Prusty <subhransu.s.prusty@intel.com>
-Signed-off-by: Vinod Koul <vinod.koul@intel.com>
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
----
- configure.ac                                       |   1 +
- src/conf/topology/Makefile.am                      |   2 +-
- src/conf/topology/sklrt286/Makefile.am             |   4 +
- src/conf/topology/sklrt286/codec0_in-cpr-1.bin     | Bin 0 -> 4244 bytes
- src/conf/topology/sklrt286/codec0_in-mi.bin        | Bin 0 -> 4244 bytes
- src/conf/topology/sklrt286/codec0_out-cpr-4.bin    | Bin 0 -> 4244 bytes
- src/conf/topology/sklrt286/codec0_out-mo.bin       | Bin 0 -> 4244 bytes
- src/conf/topology/sklrt286/codec1_out-cpr-5.bin    | Bin 0 -> 4244 bytes
- src/conf/topology/sklrt286/codec1_out-mo.bin       | Bin 0 -> 4244 bytes
- .../topology/sklrt286/dmic01_hifi_in-cpr-3.bin     | Bin 0 -> 4244 bytes
- src/conf/topology/sklrt286/dmic01_hifi_in-mi.bin   | Bin 0 -> 4244 bytes
- src/conf/topology/sklrt286/hdmi1_pt_out-cpr-7.bin  | Bin 0 -> 4244 bytes
- src/conf/topology/sklrt286/hdmi1_pt_out-cpr-8.bin  | Bin 0 -> 4244 bytes
- src/conf/topology/sklrt286/hdmi2_pt_out-cpr-10.bin | Bin 0 -> 4244 bytes
- src/conf/topology/sklrt286/hdmi2_pt_out-cpr-9.bin  | Bin 0 -> 4244 bytes
- src/conf/topology/sklrt286/hdmi3_pt_out-cpr-11.bin | Bin 0 -> 4244 bytes
- src/conf/topology/sklrt286/hdmi3_pt_out-cpr-12.bin | Bin 0 -> 4244 bytes
- src/conf/topology/sklrt286/media0_in-cpr-0.bin     | Bin 0 -> 4244 bytes
- src/conf/topology/sklrt286/media0_in-mi.bin        | Bin 0 -> 4244 bytes
- src/conf/topology/sklrt286/media0_out-cpr-6.bin    | Bin 0 -> 4244 bytes
- src/conf/topology/sklrt286/media0_out-mo.bin       | Bin 0 -> 4244 bytes
- src/conf/topology/sklrt286/skl_i2s.conf            | 342 +++++++++++++++++++++
- 22 files changed, 348 insertions(+), 1 deletion(-)
- create mode 100644 src/conf/topology/sklrt286/Makefile.am
- create mode 100644 src/conf/topology/sklrt286/codec0_in-cpr-1.bin
- create mode 100644 src/conf/topology/sklrt286/codec0_in-mi.bin
- create mode 100644 src/conf/topology/sklrt286/codec0_out-cpr-4.bin
- create mode 100644 src/conf/topology/sklrt286/codec0_out-mo.bin
- create mode 100644 src/conf/topology/sklrt286/codec1_out-cpr-5.bin
- create mode 100644 src/conf/topology/sklrt286/codec1_out-mo.bin
- create mode 100644 src/conf/topology/sklrt286/dmic01_hifi_in-cpr-3.bin
- create mode 100644 src/conf/topology/sklrt286/dmic01_hifi_in-mi.bin
- create mode 100644 src/conf/topology/sklrt286/hdmi1_pt_out-cpr-7.bin
- create mode 100644 src/conf/topology/sklrt286/hdmi1_pt_out-cpr-8.bin
- create mode 100644 src/conf/topology/sklrt286/hdmi2_pt_out-cpr-10.bin
- create mode 100644 src/conf/topology/sklrt286/hdmi2_pt_out-cpr-9.bin
- create mode 100644 src/conf/topology/sklrt286/hdmi3_pt_out-cpr-11.bin
- create mode 100644 src/conf/topology/sklrt286/hdmi3_pt_out-cpr-12.bin
- create mode 100644 src/conf/topology/sklrt286/media0_in-cpr-0.bin
- create mode 100644 src/conf/topology/sklrt286/media0_in-mi.bin
- create mode 100644 src/conf/topology/sklrt286/media0_out-cpr-6.bin
- create mode 100644 src/conf/topology/sklrt286/media0_out-mo.bin
- create mode 100644 src/conf/topology/sklrt286/skl_i2s.conf
-
-diff --git a/configure.ac b/configure.ac
-index c265ec9..1bf75e6 100644
---- a/configure.ac
-+++ b/configure.ac
-@@ -661,6 +661,7 @@ AC_OUTPUT(Makefile doc/Makefile doc/pictures/Makefile doc/doxygen.cfg \
- 	  src/conf/topology/Makefile \
- 	  src/conf/topology/broadwell/Makefile \
- 	  modules/Makefile modules/mixer/Makefile modules/mixer/simple/Makefile \
-+	  src/conf/topology/sklrt286/Makefile \
- 	  alsalisp/Makefile aserver/Makefile \
- 	  test/Makefile test/lsb/Makefile \
- 	  utils/Makefile utils/alsa-lib.spec utils/alsa.pc)
-diff --git a/src/conf/topology/Makefile.am b/src/conf/topology/Makefile.am
-index f56a96c..cbdb7cf 100644
---- a/src/conf/topology/Makefile.am
-+++ b/src/conf/topology/Makefile.am
-@@ -1 +1 @@
--SUBDIRS=broadwell
-+SUBDIRS=broadwell sklrt286
-diff --git a/src/conf/topology/sklrt286/Makefile.am b/src/conf/topology/sklrt286/Makefile.am
-new file mode 100644
-index 0000000..facc508
---- /dev/null
-+++ b/src/conf/topology/sklrt286/Makefile.am
-@@ -0,0 +1,4 @@
-+alsaconfigdir = @ALSA_CONFIG_DIR@
-+sklrt286dir = $(alsaconfigdir)/topology/sklrt286
-+sklrt286_DATA = skl_i2s.conf media0_in-cpr-0.bin media0_in-mi.bin media0_out-mo.bin media0_out-cpr-6.bin codec0_out-mo.bin codec0_out-cpr-4.bin codec1_out-mo.bin codec1_out-cpr-5.bin codec0_in-cpr-1.bin codec0_in-mi.bin dmic01_hifi_in-cpr-3.bin dmic01_hifi_in-mi.bin hdmi1_pt_out-cpr-7.bin hdmi1_pt_out-cpr-8.bin hdmi2_pt_out-cpr-9.bin hdmi2_pt_out-cpr-10.bin hdmi3_pt_out-cpr-11.bin hdmi3_pt_out-cpr-12.bin 
-+EXTRA_DIST = $(sklrt286_DATA)
-diff --git a/src/conf/topology/sklrt286/skl_i2s.conf b/src/conf/topology/sklrt286/skl_i2s.conf
-new file mode 100644
-index 0000000..6da224f
---- /dev/null
-+++ b/src/conf/topology/sklrt286/skl_i2s.conf
-@@ -0,0 +1,342 @@
-+SectionData."media0_in cpr 0" {
-+	file "sklrt286/media0_in-cpr-0.bin"
-+}
-+SectionData."media0_in mi" {
-+	file "sklrt286/media0_in-mi.bin"
-+}
-+SectionData."media0_out mo" {
-+	file "sklrt286/media0_out-mo.bin"
-+}
-+SectionData."media0_out cpr 6" {
-+	file "sklrt286/media0_out-cpr-6.bin"
-+}
-+SectionData."codec0_out mo" {
-+	file "sklrt286/codec0_out-mo.bin"
-+}
-+SectionData."codec0_out cpr 4" {
-+	file "sklrt286/codec0_out-cpr-4.bin"
-+}
-+SectionData."codec1_out mo" {
-+	file "sklrt286/codec1_out-mo.bin"
-+}
-+SectionData."codec1_out cpr 5" {
-+	file "sklrt286/codec1_out-cpr-5.bin"
-+}
-+SectionData."codec0_in cpr 1" {
-+	file "sklrt286/codec0_in-cpr-1.bin"
-+}
-+SectionData."codec0_in mi" {
-+	file "sklrt286/codec0_in-mi.bin"
-+}
-+SectionData."dmic01_hifi_in cpr 3" {
-+	file "sklrt286/dmic01_hifi_in-cpr-3.bin"
-+}
-+SectionData."dmic01_hifi_in mi" {
-+	file "sklrt286/dmic01_hifi_in-mi.bin"
-+}
-+SectionData."hdmi1_pt_out cpr 7" {
-+	file "sklrt286/hdmi1_pt_out-cpr-7.bin"
-+}
-+SectionData."hdmi1_pt_out cpr 8" {
-+	file "sklrt286/hdmi1_pt_out-cpr-8.bin"
-+}
-+SectionData."hdmi2_pt_out cpr 9" {
-+	file "sklrt286/hdmi2_pt_out-cpr-9.bin"
-+}
-+SectionData."hdmi2_pt_out cpr 10" {
-+	file "sklrt286/hdmi2_pt_out-cpr-10.bin"
-+}
-+SectionData."hdmi3_pt_out cpr 11" {
-+	file "sklrt286/hdmi3_pt_out-cpr-11.bin"
-+}
-+SectionData."hdmi3_pt_out cpr 12" {
-+	file "sklrt286/hdmi3_pt_out-cpr-12.bin"
-+}
-+
-+SectionControlMixer."media0_in mi Switch" {
-+	index"1"
-+	invert "false"
-+	max "1"
-+	min"0"
-+	no_pm "true"
-+	channel."fl" {
-+		reg "-1"
-+		shift "0"
-+	}
-+	channel."fr" {
-+		reg "-1"
-+		shift "0"
-+	}
-+	ops."ctl" {
-+		get "64"
-+		put "64"
-+		info "64"
-+	}
-+}
-+SectionControlMixer."codec0_in mi Switch" {
-+	index"1"
-+	invert "false"
-+	max "1"
-+	min"0"
-+	no_pm "true"
-+	channel."fl" {
-+		reg "-1"
-+		shift "0"
-+	}
-+	channel."fr" {
-+		reg "-1"
-+		shift "0"
-+	}
-+	ops."ctl" {
-+		get "64"
-+		put "64"
-+		info "64"
-+	}
-+}
-+SectionControlMixer."dmic01_hifi_in mi Switch" {
-+	index"1"
-+	invert "false"
-+	max "1"
-+	min"0"
-+	no_pm "true"
-+	channel."fl" {
-+		reg "-1"
-+		shift "0"
-+	}
-+	channel."fr" {
-+		reg "-1"
-+		shift "0"
-+	}
-+	ops."ctl" {
-+		get "64"
-+		put "64"
-+		info "64"
-+	}
-+}
-+
-+
-+SectionWidget."media0_in cpr 0" {
-+	index"1"
-+	type"mixer"
-+	no_pm "true"
-+	event_type "3"
-+	event_flags "9"
-+	data "media0_in cpr 0"
-+}
-+SectionWidget."media0_in mi" {
-+	index"1"
-+	type"pga"
-+	no_pm "true"
-+	event_type "4"
-+	event_flags "9"
-+	subseq "10"
-+	data "media0_in mi"
-+}
-+SectionWidget."media0_out mo" {
-+	index"1"
-+	type"mixer"
-+	no_pm "true"
-+	event_type "1"
-+	event_flags "15"
-+	subseq "10"
-+	data "media0_out mo"
-+	mixer [
-+		"media0_in mi Switch"
-+		"codec0_in mi Switch"
-+		"dmic01_hifi_in mi Switch"
-+	]
-+}
-+SectionWidget."media0_out cpr 6" {
-+	index"1"
-+	type"pga"
-+	no_pm "true"
-+	event_type "4"
-+	data "media0_out cpr 6"
-+}
-+SectionWidget."codec0_out mo" {
-+	index"1"
-+	type"mixer"
-+	no_pm "true"
-+	event_type "1"
-+	event_flags "15"
-+	subseq "10"
-+	data "codec0_out mo"
-+	mixer [
-+		"media0_in mi Switch"
-+		"codec0_in mi Switch"
-+		"dmic01_hifi_in mi Switch"
-+	]
-+}
-+SectionWidget."codec0_out cpr 4" {
-+	index"1"
-+	type"pga"
-+	no_pm "true"
-+	event_type "4"
-+	data "codec0_out cpr 4"
-+}
-+SectionWidget."codec0_out" {
-+	index"1"
-+	type"aif_out"
-+	no_pm "true"
-+}
-+SectionWidget."codec1_out mo" {
-+	index"1"
-+	type"mixer"
-+	no_pm "true"
-+	event_type "1"
-+	event_flags "15"
-+	subseq "10"
-+	data "codec1_out mo"
-+	mixer [
-+		"media0_in mi Switch"
-+		"codec0_in mi Switch"
-+		"dmic01_hifi_in mi Switch"
-+	]
-+}
-+SectionWidget."codec1_out cpr 5" {
-+	index"1"
-+	type"pga"
-+	no_pm "true"
-+	event_type "4"
-+	data "codec1_out cpr 5"
-+}
-+SectionWidget."codec1_out" {
-+	index"1"
-+	type"aif_out"
-+	no_pm "true"
-+}
-+SectionWidget."codec0_in cpr 1" {
-+	index"1"
-+	type"mixer"
-+	no_pm "true"
-+	event_type "3"
-+	event_flags "9"
-+	data "codec0_in cpr 1"
-+}
-+SectionWidget."codec0_in mi" {
-+	index"1"
-+	type"pga"
-+	no_pm "true"
-+	event_type "4"
-+	event_flags "9"
-+	subseq "10"
-+	data "codec0_in mi"
-+}
-+SectionWidget."codec0_in" {
-+	index"1"
-+	type"aif_in"
-+	no_pm "true"
-+}
-+SectionWidget."dmic01_hifi_in cpr 3" {
-+	index"1"
-+	type"mixer"
-+	no_pm "true"
-+	event_type "3"
-+	event_flags "9"
-+	data "dmic01_hifi_in cpr 3"
-+}
-+SectionWidget."dmic01_hifi_in mi" {
-+	index"1"
-+	type"pga"
-+	no_pm "true"
-+	event_type "4"
-+	event_flags "9"
-+	subseq "10"
-+	data "dmic01_hifi_in mi"
-+}
-+SectionWidget."dmic01_hifi" {
-+	index"1"
-+	type"aif_in"
-+	no_pm "true"
-+}
-+SectionWidget."hdmi1_pt_out cpr 7" {
-+	index"1"
-+	type"mixer"
-+	no_pm "true"
-+	event_type "3"
-+	event_flags "9"
-+	data "hdmi1_pt_out cpr 7"
-+}
-+SectionWidget."hdmi1_pt_out cpr 8" {
-+	index"1"
-+	type"pga"
-+	no_pm "true"
-+	event_type "4"
-+	data "hdmi1_pt_out cpr 8"
-+}
-+SectionWidget."iDisp1_out" {
-+	index"1"
-+	type"aif_out"
-+	no_pm "true"
-+}
-+SectionWidget."hdmi2_pt_out cpr 9" {
-+	index"1"
-+	type"mixer"
-+	no_pm "true"
-+	event_type "3"
-+	event_flags "9"
-+	data "hdmi2_pt_out cpr 9"
-+}
-+SectionWidget."hdmi2_pt_out cpr 10" {
-+	index"1"
-+	type"pga"
-+	no_pm "true"
-+	event_type "4"
-+	data "hdmi2_pt_out cpr 10"
-+}
-+SectionWidget."iDisp2_out" {
-+	index"1"
-+	type"aif_out"
-+	no_pm "true"
-+}
-+SectionWidget."hdmi3_pt_out cpr 11" {
-+	index"1"
-+	type"mixer"
-+	no_pm "true"
-+	event_type "3"
-+	event_flags "9"
-+	data "hdmi3_pt_out cpr 11"
-+}
-+SectionWidget."hdmi3_pt_out cpr 12" {
-+	index"1"
-+	type"pga"
-+	no_pm "true"
-+	event_type "4"
-+	data "hdmi3_pt_out cpr 12"
-+}
-+SectionGraph."Pipeline 1 Graph" {
-+	index"1"
-+	lines [
-+		"media0_in mi, , media0_in cpr 0"
-+		"media0_in cpr 0, , System Playback"
-+		"media0_out mo, media0_in mi Switch, media0_in mi"
-+		"media0_out mo, codec0_in mi Switch, codec0_in mi"
-+		"media0_out mo, dmic01_hifi_in mi Switch, dmic01_hifi_in mi"
-+		"media0_out cpr 6, , media0_out mo"
-+		"System Capture, , media0_out cpr 6"
-+		"codec0_out mo, media0_in mi Switch, media0_in mi"
-+		"codec0_out mo, codec0_in mi Switch, codec0_in mi"
-+		"codec0_out mo, dmic01_hifi_in mi Switch, dmic01_hifi_in mi"
-+		"codec0_out cpr 4, , codec0_out mo"
-+		"codec0_out, , codec0_out cpr 4"
-+		"codec1_out mo, media0_in mi Switch, media0_in mi"
-+		"codec1_out mo, codec0_in mi Switch, codec0_in mi"
-+		"codec1_out mo, dmic01_hifi_in mi Switch, dmic01_hifi_in mi"
-+		"codec1_out cpr 5, , codec1_out mo"
-+		"codec1_out, , codec1_out cpr 5"
-+		"codec0_in mi, , codec0_in cpr 1"
-+		"codec0_in cpr 1, , codec0_in"
-+		"dmic01_hifi_in mi, , dmic01_hifi_in cpr 3"
-+		"dmic01_hifi_in cpr 3, , dmic01_hifi"
-+		"hdmi1_pt_out cpr 8, , hdmi1_pt_out cpr 7"
-+		"hdmi1_pt_out cpr 7, , HDMI1 Playback"
-+		"iDisp1_out, , hdmi1_pt_out cpr 8"
-+		"hdmi2_pt_out cpr 10, , hdmi2_pt_out cpr 9"
-+		"hdmi2_pt_out cpr 9, , HDMI2 Playback"
-+		"iDisp2_out, , hdmi2_pt_out cpr 10"
-+		"hdmi3_pt_out cpr 12, , hdmi3_pt_out cpr 11"
-+		"hdmi3_pt_out cpr 11, , HDMI3 Playback"
-+		"iDisp1_out, , hdmi3_pt_out cpr 12"
-+	]
-+}
-+
--- 
-2.5.5
-
-From a8ca6d1c4b942616dad43d51d954c31894e3c608 Mon Sep 17 00:00:00 2001
-From: Shreyas NC <shreyas.nc@intel.com>
-Date: Thu, 28 Apr 2016 11:07:57 +0530
-Subject: [PATCH 13/34] Add u8 in type_compat.h
-
-Skylake headers use u8 data types which were not present in
-type_compat so add them.
-
-Signed-off-by: Shreyas NC <shreyas.nc@intel.com>
-Signed-off-by: Vinod Koul <vinod.koul@intel.com>
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
----
- include/sound/type_compat.h | 2 ++
- 1 file changed, 2 insertions(+)
-
-diff --git a/include/sound/type_compat.h b/include/sound/type_compat.h
-index eec86e4..e973ff3 100644
---- a/include/sound/type_compat.h
-+++ b/include/sound/type_compat.h
-@@ -32,9 +32,11 @@ typedef int32_t __s32;
- #define __le64 __u64
- #define __le32 __u32
- #define __le16 __u16
-+#define __le8  __u8
- #define __be64 __u64
- #define __be32 __u32
- #define __be16 __u16
-+#define __be8  __u8
- #endif /* DOC_HIDDEN */
- 
- #endif /* __TYPE_COMPAT_H */
--- 
-2.5.5
-
-From 65b271034a36580badc980b3ff0bd77e7b9837ce Mon Sep 17 00:00:00 2001
-From: Shreyas NC <shreyas.nc@intel.com>
-Date: Thu, 28 Apr 2016 11:07:58 +0530
-Subject: [PATCH 14/34] conf: topology: Generate Private data binary blobs
-
-The DSP modules need private data and that is provided as binary
-blob. These blobs are compiled from C structures which specify module
-configuration.
-
-Signed-off-by: Shreyas NC <shreyas.nc@intel.com>
-Signed-off-by: Vinod Koul <vinod.koul@intel.com>
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
----
- configure.ac                                       |    1 +
- src/conf/topology/sklrt286/Makefile.am             |    1 +
- src/conf/topology/sklrt286/data/Makefile.am        |    4 +
- src/conf/topology/sklrt286/data/pvt.c              | 1815 ++++++++++++++++++++
- src/conf/topology/sklrt286/data/pvt_data.c         |   90 +
- src/conf/topology/sklrt286/data/pvt_local.h        |    9 +
- .../topology/sklrt286/data/skl-tplg-interface.h    |  232 +++
- 7 files changed, 2152 insertions(+)
- create mode 100644 src/conf/topology/sklrt286/data/Makefile.am
- create mode 100644 src/conf/topology/sklrt286/data/pvt.c
- create mode 100644 src/conf/topology/sklrt286/data/pvt_data.c
- create mode 100644 src/conf/topology/sklrt286/data/pvt_local.h
- create mode 100644 src/conf/topology/sklrt286/data/skl-tplg-interface.h
-
-diff --git a/configure.ac b/configure.ac
-index 1bf75e6..28fcd24 100644
---- a/configure.ac
-+++ b/configure.ac
-@@ -661,6 +661,7 @@ AC_OUTPUT(Makefile doc/Makefile doc/pictures/Makefile doc/doxygen.cfg \
- 	  src/conf/topology/Makefile \
- 	  src/conf/topology/broadwell/Makefile \
- 	  modules/Makefile modules/mixer/Makefile modules/mixer/simple/Makefile \
-+	  src/conf/topology/sklrt286/data/Makefile \
- 	  src/conf/topology/sklrt286/Makefile \
- 	  alsalisp/Makefile aserver/Makefile \
- 	  test/Makefile test/lsb/Makefile \
-diff --git a/src/conf/topology/sklrt286/Makefile.am b/src/conf/topology/sklrt286/Makefile.am
-index facc508..ed58b77 100644
---- a/src/conf/topology/sklrt286/Makefile.am
-+++ b/src/conf/topology/sklrt286/Makefile.am
-@@ -1,4 +1,5 @@
- alsaconfigdir = @ALSA_CONFIG_DIR@
-+SUBDIRS = data
- sklrt286dir = $(alsaconfigdir)/topology/sklrt286
- sklrt286_DATA = skl_i2s.conf media0_in-cpr-0.bin media0_in-mi.bin media0_out-mo.bin media0_out-cpr-6.bin codec0_out-mo.bin codec0_out-cpr-4.bin codec1_out-mo.bin codec1_out-cpr-5.bin codec0_in-cpr-1.bin codec0_in-mi.bin dmic01_hifi_in-cpr-3.bin dmic01_hifi_in-mi.bin hdmi1_pt_out-cpr-7.bin hdmi1_pt_out-cpr-8.bin hdmi2_pt_out-cpr-9.bin hdmi2_pt_out-cpr-10.bin hdmi3_pt_out-cpr-11.bin hdmi3_pt_out-cpr-12.bin 
- EXTRA_DIST = $(sklrt286_DATA)
-diff --git a/src/conf/topology/sklrt286/data/Makefile.am b/src/conf/topology/sklrt286/data/Makefile.am
-new file mode 100644
-index 0000000..888ce16
---- /dev/null
-+++ b/src/conf/topology/sklrt286/data/Makefile.am
-@@ -0,0 +1,4 @@
-+noinst_PROGRAMS = pvt_data
-+pvt_data_SOURCES = pvt_data.c
-+AM_CPPFLAGS = \
-+         -Wall -I$(top_srcdir)/include
-diff --git a/src/conf/topology/sklrt286/data/pvt.c b/src/conf/topology/sklrt286/data/pvt.c
-new file mode 100644
-index 0000000..3447e3e
---- /dev/null
-+++ b/src/conf/topology/sklrt286/data/pvt.c
-@@ -0,0 +1,1815 @@
-+/*
-+* Copyright(c) 2014-2016 Intel Corporation
-+* All rights reserved.
-+*
-+* This library is free software; you can redistribute it and/or
-+* modify it under the terms of the GNU Lesser General Public
-+* License as published by the Free Software Foundation; either
-+* version 2 of the License, or (at your option) any later version.
-+
-+* This library is distributed in the hope that it will be useful,
-+* but WITHOUT ANY WARRANTY; without even the implied warranty of
-+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+* General Public License for more details.
-+*
-+* Authors: Shreyas Nc <shreyas.nc@intel.com>
-+*
-+*/
-+#include "pvt_local.h"
-+
-+struct skl_dfw_module_mod dfw_wrap[] = {
-+{
-+.name = "media0_in cpr 0",
-+.skl_dfw_mod = {
-+	.uuid = {131, 12, 160, 155, 18, 202, 131, 74, 148, 60, 31, 162, 232, 47, 157, 218},
-+	.module_id = 3,
-+	.instance_id = 0,
-+	.max_mcps = 0x186a0,
-+	.mem_pages = 0x1,
-+	.obs = 384,
-+	.ibs = 384,
-+	.vbus_id = -1,
-+	.max_in_queue = 1,
-+	.max_out_queue = 2,
-+	.time_slot = 0,
-+	.core_id = 0,
-+	.rsvd1 = 0,
-+	.module_type = 1,
-+	.conn_type = 1,
-+	.dev_type = 5,
-+	.hw_conn_type = 1,
-+	.rsvd2 = 0,
-+	.params_fixup = 0,
-+	.converter = 0,
-+	.input_pin_type = 0,
-+	.output_pin_type = 0,
-+	.is_dynamic_in_pin = 1,
-+	.is_dynamic_out_pin = 1,
-+	.is_loadable = 0,
-+	.rsvd3 = 0,
-+	.pipe = {
-+		.pipe_id = 1,
-+		.pipe_priority = 0,
-+		.conn_type = 1,
-+		.rsvd = 0,
-+		.memory_pages = 0x2,
-+	},
-+	.in_fmt = {
-+		{
-+			.channels = 2,
-+			.freq = 48000,
-+			.bit_depth = 32,
-+			.valid_bit_depth = 32,
-+			.ch_cfg = 1,
-+			.interleaving_style = 0,
-+			.sample_type = 0,
-+			.ch_map = 0xffffff10,
-+		},
-+	},
-+	.out_fmt = {
-+		{
-+			.channels = 2,
-+			.freq = 48000,
-+			.bit_depth = 32,
-+			.valid_bit_depth = 32,
-+			.ch_cfg = 1,
-+			.interleaving_style = 0,
-+			.sample_type = 0,
-+			.ch_map = 0xffffff10,
-+		},
-+		{
-+			.channels = 2,
-+			.freq = 48000,
-+			.bit_depth = 32,
-+			.valid_bit_depth = 32,
-+			.ch_cfg = 1,
-+			.interleaving_style = 0,
-+			.sample_type = 0,
-+			.ch_map = 0xffffff10,
-+		},
-+	},
-+	.in_pin = {
-+		{
-+			.module_id = 0,
-+			.instance_id = 0,
-+		},
-+	},
-+	.out_pin = {
-+		{
-+			.module_id = 0,
-+			.instance_id = 0,
-+		},
-+		{
-+			.module_id = 0,
-+			.instance_id = 0,
-+		},
-+	},
-+	},
-+},
-+{
-+.name = "media0_in mi",
-+.skl_dfw_mod = {
-+	.uuid = {178, 110, 101, 57, 113, 59, 73, 64, 141, 63, 249, 44, 213, 196, 60, 9},
-+	.module_id = 1,
-+	.instance_id = 0,
-+	.max_mcps = 0x186a0,
-+	.mem_pages = 0x1,
-+	.obs = 384,
-+	.ibs = 384,
-+	.vbus_id = -1,
-+	.max_in_queue = 1,
-+	.max_out_queue = 1,
-+	.time_slot = 0,
-+	.core_id = 0,
-+	.rsvd1 = 0,
-+	.module_type = 0,
-+	.conn_type = 0,
-+	.dev_type = 6,
-+	.hw_conn_type = 1,
-+	.rsvd2 = 0,
-+	.params_fixup = 0,
-+	.converter = 0,
-+	.input_pin_type = 0,
-+	.output_pin_type = 0,
-+	.is_dynamic_in_pin = 1,
-+	.is_dynamic_out_pin = 1,
-+	.is_loadable = 0,
-+	.rsvd3 = 0,
-+	.pipe = {
-+		.pipe_id = 1,
-+		.pipe_priority = 0,
-+		.conn_type = 1,
-+		.rsvd = 0,
-+		.memory_pages = 0x2,
-+	},
-+	.in_fmt = {
-+		{
-+			.channels = 2,
-+			.freq = 48000,
-+			.bit_depth = 32,
-+			.valid_bit_depth = 32,
-+			.ch_cfg = 1,
-+			.interleaving_style = 0,
-+			.sample_type = 0,
-+			.ch_map = 0xffffff10,
-+		},
-+	},
-+	.out_fmt = {
-+		{
-+			.channels = 2,
-+			.freq = 48000,
-+			.bit_depth = 32,
-+			.valid_bit_depth = 32,
-+			.ch_cfg = 1,
-+			.interleaving_style = 0,
-+			.sample_type = 0,
-+			.ch_map = 0xffffff10,
-+		},
-+	},
-+	.in_pin = {
-+		{
-+			.module_id = 0,
-+			.instance_id = 0,
-+		},
-+	},
-+	.out_pin = {
-+		{
-+			.module_id = 0,
-+			.instance_id = 0,
-+		},
-+	},
-+	},
-+},
-+{
-+.name = "media0_out mo",
-+.skl_dfw_mod = {
-+	.uuid = {90, 80, 86, 60, 215, 36, 143, 65, 189, 220, 193, 245, 163, 172, 42, 224},
-+	.module_id = 2,
-+	.instance_id = 2,
-+	.max_mcps = 0x186a0,
-+	.mem_pages = 0x1,
-+	.obs = 384,
-+	.ibs = 384,
-+	.vbus_id = -1,
-+	.max_in_queue = 8,
-+	.max_out_queue = 1,
-+	.time_slot = 0,
-+	.core_id = 0,
-+	.rsvd1 = 0,
-+	.module_type = 0,
-+	.conn_type = 0,
-+	.dev_type = 6,
-+	.hw_conn_type = 2,
-+	.rsvd2 = 0,
-+	.params_fixup = 0,
-+	.converter = 0,
-+	.input_pin_type = 0,
-+	.output_pin_type = 0,
-+	.is_dynamic_in_pin = 1,
-+	.is_dynamic_out_pin = 1,
-+	.is_loadable = 0,
-+	.rsvd3 = 0,
-+	.pipe = {
-+		.pipe_id = 2,
-+		.pipe_priority = 0,
-+		.conn_type = 1,
-+		.rsvd = 0,
-+		.memory_pages = 0x2,
-+	},
-+	.in_fmt = {
-+		{
-+			.channels = 2,
-+			.freq = 48000,
-+			.bit_depth = 32,
-+			.valid_bit_depth = 32,
-+			.ch_cfg = 1,
-+			.interleaving_style = 0,
-+			.sample_type = 0,
-+			.ch_map = 0xffffff10,
-+		},
-+		{
-+			.channels = 2,
-+			.freq = 48000,
-+			.bit_depth = 32,
-+			.valid_bit_depth = 32,
-+			.ch_cfg = 1,
-+			.interleaving_style = 0,
-+			.sample_type = 0,
-+			.ch_map = 0xffffff10,
-+		},
-+		{
-+			.channels = 2,
-+			.freq = 48000,
-+			.bit_depth = 32,
-+			.valid_bit_depth = 32,
-+			.ch_cfg = 1,
-+			.interleaving_style = 0,
-+			.sample_type = 0,
-+			.ch_map = 0xffffff10,
-+		},
-+		{
-+			.channels = 2,
-+			.freq = 48000,
-+			.bit_depth = 32,
-+			.valid_bit_depth = 32,
-+			.ch_cfg = 1,
-+			.interleaving_style = 0,
-+			.sample_type = 0,
-+			.ch_map = 0xffffff10,
-+		},
-+		{
-+			.channels = 2,
-+			.freq = 48000,
-+			.bit_depth = 32,
-+			.valid_bit_depth = 32,
-+			.ch_cfg = 1,
-+			.interleaving_style = 0,
-+			.sample_type = 0,
-+			.ch_map = 0xffffff10,
-+		},
-+		{
-+			.channels = 2,
-+			.freq = 48000,
-+			.bit_depth = 32,
-+			.valid_bit_depth = 32,
-+			.ch_cfg = 1,
-+			.interleaving_style = 0,
-+			.sample_type = 0,
-+			.ch_map = 0xffffff10,
-+		},
-+		{
-+			.channels = 2,
-+			.freq = 48000,
-+			.bit_depth = 32,
-+			.valid_bit_depth = 32,
-+			.ch_cfg = 1,
-+			.interleaving_style = 0,
-+			.sample_type = 0,
-+			.ch_map = 0xffffff10,
-+		},
-+		{
-+			.channels = 2,
-+			.freq = 48000,
-+			.bit_depth = 32,
-+			.valid_bit_depth = 32,
-+			.ch_cfg = 1,
-+			.interleaving_style = 0,
-+			.sample_type = 0,
-+			.ch_map = 0xffffff10,
-+		},
-+	},
-+	.out_fmt = {
-+		{
-+			.channels = 2,
-+			.freq = 48000,
-+			.bit_depth = 32,
-+			.valid_bit_depth = 32,
-+			.ch_cfg = 1,
-+			.interleaving_style = 0,
-+			.sample_type = 0,
-+			.ch_map = 0xffffff10,
-+		},
-+	},
-+	.in_pin = {
-+		{
-+			.module_id = 0,
-+			.instance_id = 0,
-+		},
-+		{
-+			.module_id = 0,
-+			.instance_id = 0,
-+		},
-+		{
-+			.module_id = 0,
-+			.instance_id = 0,
-+		},
-+		{
-+			.module_id = 0,
-+			.instance_id = 0,
-+		},
-+		{
-+			.module_id = 0,
-+			.instance_id = 0,
-+		},
-+		{
-+			.module_id = 0,
-+			.instance_id = 0,
-+		},
-+		{
-+			.module_id = 0,
-+			.instance_id = 0,
-+		},
-+		{
-+			.module_id = 0,
-+			.instance_id = 0,
-+		},
-+	},
-+	.out_pin = {
-+		{
-+			.module_id = 0,
-+			.instance_id = 0,
-+		},
-+	},
-+	},
-+},
-+{
-+.name = "media0_out cpr 6",
-+.skl_dfw_mod = {
-+	.uuid = {131, 12, 160, 155, 18, 202, 131, 74, 148, 60, 31, 162, 232, 47, 157, 218},
-+	.module_id = 3,
-+	.instance_id = 6,
-+	.max_mcps = 0x186a0,
-+	.mem_pages = 0x1,
-+	.obs = 384,
-+	.ibs = 384,
-+	.vbus_id = -1,
-+	.max_in_queue = 1,
-+	.max_out_queue = 2,
-+	.time_slot = 0,
-+	.core_id = 0,
-+	.rsvd1 = 0,
-+	.module_type = 1,
-+	.conn_type = 0,
-+	.dev_type = 5,
-+	.hw_conn_type = 2,
-+	.rsvd2 = 0,
-+	.params_fixup = 0,
-+	.converter = 0,
-+	.input_pin_type = 0,
-+	.output_pin_type = 0,
-+	.is_dynamic_in_pin = 1,
-+	.is_dynamic_out_pin = 1,
-+	.is_loadable = 0,
-+	.rsvd3 = 0,
-+	.pipe = {
-+		.pipe_id = 2,
-+		.pipe_priority = 0,
-+		.conn_type = 1,
-+		.rsvd = 0,
-+		.memory_pages = 0x2,
-+	},
-+	.in_fmt = {
-+		{
-+			.channels = 2,
-+			.freq = 48000,
-+			.bit_depth = 32,
-+			.valid_bit_depth = 32,
-+			.ch_cfg = 1,
-+			.interleaving_style = 0,
-+			.sample_type = 0,
-+			.ch_map = 0xffffff10,
-+		},
-+	},
-+	.out_fmt = {
-+		{
-+			.channels = 2,
-+			.freq = 48000,
-+			.bit_depth = 32,
-+			.valid_bit_depth = 32,
-+			.ch_cfg = 1,
-+			.interleaving_style = 0,
-+			.sample_type = 0,
-+			.ch_map = 0xffffff10,
-+		},
-+		{
-+			.channels = 2,
-+			.freq = 48000,
-+			.bit_depth = 32,
-+			.valid_bit_depth = 32,
-+			.ch_cfg = 1,
-+			.interleaving_style = 0,
-+			.sample_type = 0,
-+			.ch_map = 0xffffff10,
-+		},
-+	},
-+	.in_pin = {
-+		{
-+			.module_id = 0,
-+			.instance_id = 0,
-+		},
-+	},
-+	.out_pin = {
-+		{
-+			.module_id = 0,
-+			.instance_id = 0,
-+		},
-+		{
-+			.module_id = 0,
-+			.instance_id = 0,
-+		},
-+	},
-+	},
-+},
-+{
-+.name = "codec0_out mo",
-+.skl_dfw_mod = {
-+	.uuid = {90, 80, 86, 60, 215, 36, 143, 65, 189, 220, 193, 245, 163, 172, 42, 224},
-+	.module_id = 2,
-+	.instance_id = 0,
-+	.max_mcps = 0x186a0,
-+	.mem_pages = 0x1,
-+	.obs = 384,
-+	.ibs = 384,
-+	.vbus_id = -1,
-+	.max_in_queue = 8,
-+	.max_out_queue = 1,
-+	.time_slot = 0,
-+	.core_id = 0,
-+	.rsvd1 = 0,
-+	.module_type = 0,
-+	.conn_type = 0,
-+	.dev_type = 6,
-+	.hw_conn_type = 1,
-+	.rsvd2 = 0,
-+	.params_fixup = 0,
-+	.converter = 0,
-+	.input_pin_type = 0,
-+	.output_pin_type = 0,
-+	.is_dynamic_in_pin = 1,
-+	.is_dynamic_out_pin = 1,
-+	.is_loadable = 0,
-+	.rsvd3 = 0,
-+	.pipe = {
-+		.pipe_id = 3,
-+		.pipe_priority = 0,
-+		.conn_type = 2,
-+		.rsvd = 0,
-+		.memory_pages = 0x4,
-+	},
-+	.in_fmt = {
-+		{
-+			.channels = 2,
-+			.freq = 48000,
-+			.bit_depth = 32,
-+			.valid_bit_depth = 32,
-+			.ch_cfg = 1,
-+			.interleaving_style = 0,
-+			.sample_type = 0,
-+			.ch_map = 0xffffff10,
-+		},
-+		{
-+			.channels = 2,
-+			.freq = 48000,
-+			.bit_depth = 32,
-+			.valid_bit_depth = 32,
-+			.ch_cfg = 1,
-+			.interleaving_style = 0,
-+			.sample_type = 0,
-+			.ch_map = 0xffffff10,
-+		},
-+		{
-+			.channels = 2,
-+			.freq = 48000,
-+			.bit_depth = 32,
-+			.valid_bit_depth = 32,
-+			.ch_cfg = 1,
-+			.interleaving_style = 0,
-+			.sample_type = 0,
-+			.ch_map = 0xffffff10,
-+		},
-+		{
-+			.channels = 2,
-+			.freq = 48000,
-+			.bit_depth = 32,
-+			.valid_bit_depth = 32,
-+			.ch_cfg = 1,
-+			.interleaving_style = 0,
-+			.sample_type = 0,
-+			.ch_map = 0xffffff10,
-+		},
-+		{
-+			.channels = 2,
-+			.freq = 48000,
-+			.bit_depth = 32,
-+			.valid_bit_depth = 32,
-+			.ch_cfg = 1,
-+			.interleaving_style = 0,
-+			.sample_type = 0,
-+			.ch_map = 0xffffff10,
-+		},
-+		{
-+			.channels = 2,
-+			.freq = 48000,
-+			.bit_depth = 32,
-+			.valid_bit_depth = 32,
-+			.ch_cfg = 1,
-+			.interleaving_style = 0,
-+			.sample_type = 0,
-+			.ch_map = 0xffffff10,
-+		},
-+		{
-+			.channels = 2,
-+			.freq = 48000,
-+			.bit_depth = 32,
-+			.valid_bit_depth = 32,
-+			.ch_cfg = 1,
-+			.interleaving_style = 0,
-+			.sample_type = 0,
-+			.ch_map = 0xffffff10,
-+		},
-+		{
-+			.channels = 2,
-+			.freq = 48000,
-+			.bit_depth = 32,
-+			.valid_bit_depth = 32,
-+			.ch_cfg = 1,
-+			.interleaving_style = 0,
-+			.sample_type = 0,
-+			.ch_map = 0xffffff10,
-+		},
-+	},
-+	.out_fmt = {
-+		{
-+			.channels = 2,
-+			.freq = 48000,
-+			.bit_depth = 32,
-+			.valid_bit_depth = 32,
-+			.ch_cfg = 1,
-+			.interleaving_style = 0,
-+			.sample_type = 0,
-+			.ch_map = 0xffffff10,
-+		},
-+	},
-+	.in_pin = {
-+		{
-+			.module_id = 0,
-+			.instance_id = 0,
-+		},
-+		{
-+			.module_id = 0,
-+			.instance_id = 0,
-+		},
-+		{
-+			.module_id = 0,
-+			.instance_id = 0,
-+		},
-+		{
-+			.module_id = 0,
-+			.instance_id = 0,
-+		},
-+		{
-+			.module_id = 0,
-+			.instance_id = 0,
-+		},
-+		{
-+			.module_id = 0,
-+			.instance_id = 0,
-+		},
-+		{
-+			.module_id = 0,
-+			.instance_id = 0,
-+		},
-+		{
-+			.module_id = 0,
-+			.instance_id = 0,
-+		},
-+	},
-+	.out_pin = {
-+		{
-+			.module_id = 0,
-+			.instance_id = 0,
-+		},
-+	},
-+	},
-+},
-+{
-+.name = "codec0_out cpr 4",
-+.skl_dfw_mod = {
-+	.uuid = {131, 12, 160, 155, 18, 202, 131, 74, 148, 60, 31, 162, 232, 47, 157, 218},
-+	.module_id = 3,
-+	.instance_id = 4,
-+	.max_mcps = 0x186a0,
-+	.mem_pages = 0x1,
-+	.obs = 384,
-+	.ibs = 384,
-+	.vbus_id = 0,
-+	.max_in_queue = 1,
-+	.max_out_queue = 2,
-+	.time_slot = 0,
-+	.core_id = 0,
-+	.rsvd1 = 0,
-+	.module_type = 1,
-+	.conn_type = 2,
-+	.dev_type = 2,
-+	.hw_conn_type = 1,
-+	.rsvd2 = 0,
-+	.params_fixup = 0,
-+	.converter = 0,
-+	.input_pin_type = 0,
-+	.output_pin_type = 0,
-+	.is_dynamic_in_pin = 1,
-+	.is_dynamic_out_pin = 1,
-+	.is_loadable = 0,
-+	.rsvd3 = 0,
-+	.pipe = {
-+		.pipe_id = 3,
-+		.pipe_priority = 0,
-+		.conn_type = 2,
-+		.rsvd = 0,
-+		.memory_pages = 0x4,
-+	},
-+	.in_fmt = {
-+		{
-+			.channels = 2,
-+			.freq = 48000,
-+			.bit_depth = 32,
-+			.valid_bit_depth = 24,
-+			.ch_cfg = 1,
-+			.interleaving_style = 0,
-+			.sample_type = 0,
-+			.ch_map = 0xffffff10,
-+		},
-+	},
-+	.out_fmt = {
-+		{
-+			.channels = 2,
-+			.freq = 48000,
-+			.bit_depth = 32,
-+			.valid_bit_depth = 24,
-+			.ch_cfg = 1,
-+			.interleaving_style = 0,
-+			.sample_type = 0,
-+			.ch_map = 0xffffff10,
-+		},
-+		{
-+			.channels = 2,
-+			.freq = 48000,
-+			.bit_depth = 32,
-+			.valid_bit_depth = 24,
-+			.ch_cfg = 1,
-+			.interleaving_style = 0,
-+			.sample_type = 0,
-+			.ch_map = 0xffffff10,
-+		},
-+	},
-+	.in_pin = {
-+		{
-+			.module_id = 0,
-+			.instance_id = 0,
-+		},
-+	},
-+	.out_pin = {
-+		{
-+			.module_id = 0,
-+			.instance_id = 0,
-+		},
-+		{
-+			.module_id = 0,
-+			.instance_id = 0,
-+		},
-+	},
-+	},
-+},
-+{
-+.name = "codec1_out mo",
-+.skl_dfw_mod = {
-+	.uuid = {90, 80, 86, 60, 215, 36, 143, 65, 189, 220, 193, 245, 163, 172, 42, 224},
-+	.module_id = 2,
-+	.instance_id = 1,
-+	.max_mcps = 0x186a0,
-+	.mem_pages = 0x1,
-+	.obs = 384,
-+	.ibs = 384,
-+	.vbus_id = -1,
-+	.max_in_queue = 8,
-+	.max_out_queue = 1,
-+	.time_slot = 0,
-+	.core_id = 0,
-+	.rsvd1 = 0,
-+	.module_type = 0,
-+	.conn_type = 0,
-+	.dev_type = 6,
-+	.hw_conn_type = 1,
-+	.rsvd2 = 0,
-+	.params_fixup = 0,
-+	.converter = 0,
-+	.input_pin_type = 0,
-+	.output_pin_type = 0,
-+	.is_dynamic_in_pin = 1,
-+	.is_dynamic_out_pin = 1,
-+	.is_loadable = 0,
-+	.rsvd3 = 0,
-+	.pipe = {
-+		.pipe_id = 4,
-+		.pipe_priority = 0,
-+		.conn_type = 2,
-+		.rsvd = 0,
-+		.memory_pages = 0x2,
-+	},
-+	.in_fmt = {
-+		{
-+			.channels = 2,
-+			.freq = 48000,
-+			.bit_depth = 32,
-+			.valid_bit_depth = 32,
-+			.ch_cfg = 1,
-+			.interleaving_style = 0,
-+			.sample_type = 0,
-+			.ch_map = 0xffffff10,
-+		},
-+		{
-+			.channels = 2,
-+			.freq = 48000,
-+			.bit_depth = 32,
-+			.valid_bit_depth = 32,
-+			.ch_cfg = 1,
-+			.interleaving_style = 0,
-+			.sample_type = 0,
-+			.ch_map = 0xffffff10,
-+		},
-+		{
-+			.channels = 2,
-+			.freq = 48000,
-+			.bit_depth = 32,
-+			.valid_bit_depth = 32,
-+			.ch_cfg = 1,
-+			.interleaving_style = 0,
-+			.sample_type = 0,
-+			.ch_map = 0xffffff10,
-+		},
-+		{
-+			.channels = 2,
-+			.freq = 48000,
-+			.bit_depth = 32,
-+			.valid_bit_depth = 32,
-+			.ch_cfg = 1,
-+			.interleaving_style = 0,
-+			.sample_type = 0,
-+			.ch_map = 0xffffff10,
-+		},
-+		{
-+			.channels = 2,
-+			.freq = 48000,
-+			.bit_depth = 32,
-+			.valid_bit_depth = 32,
-+			.ch_cfg = 1,
-+			.interleaving_style = 0,
-+			.sample_type = 0,
-+			.ch_map = 0xffffff10,
-+		},
-+		{
-+			.channels = 2,
-+			.freq = 48000,
-+			.bit_depth = 32,
-+			.valid_bit_depth = 32,
-+			.ch_cfg = 1,
-+			.interleaving_style = 0,
-+			.sample_type = 0,
-+			.ch_map = 0xffffff10,
-+		},
-+		{
-+			.channels = 2,
-+			.freq = 48000,
-+			.bit_depth = 32,
-+			.valid_bit_depth = 32,
-+			.ch_cfg = 1,
-+			.interleaving_style = 0,
-+			.sample_type = 0,
-+			.ch_map = 0xffffff10,
-+		},
-+		{
-+			.channels = 2,
-+			.freq = 48000,
-+			.bit_depth = 32,
-+			.valid_bit_depth = 32,
-+			.ch_cfg = 1,
-+			.interleaving_style = 0,
-+			.sample_type = 0,
-+			.ch_map = 0xffffff10,
-+		},
-+	},
-+	.out_fmt = {
-+		{
-+			.channels = 2,
-+			.freq = 48000,
-+			.bit_depth = 32,
-+			.valid_bit_depth = 32,
-+			.ch_cfg = 1,
-+			.interleaving_style = 0,
-+			.sample_type = 0,
-+			.ch_map = 0xffffff10,
-+		},
-+	},
-+	.in_pin = {
-+		{
-+			.module_id = 0,
-+			.instance_id = 0,
-+		},
-+		{
-+			.module_id = 0,
-+			.instance_id = 0,
-+		},
-+		{
-+			.module_id = 0,
-+			.instance_id = 0,
-+		},
-+		{
-+			.module_id = 0,
-+			.instance_id = 0,
-+		},
-+		{
-+			.module_id = 0,
-+			.instance_id = 0,
-+		},
-+		{
-+			.module_id = 0,
-+			.instance_id = 0,
-+		},
-+		{
-+			.module_id = 0,
-+			.instance_id = 0,
-+		},
-+		{
-+			.module_id = 0,
-+			.instance_id = 0,
-+		},
-+	},
-+	.out_pin = {
-+		{
-+			.module_id = 0,
-+			.instance_id = 0,
-+		},
-+	},
-+	},
-+},
-+{
-+.name = "codec1_out cpr 5",
-+.skl_dfw_mod = {
-+	.uuid = {131, 12, 160, 155, 18, 202, 131, 74, 148, 60, 31, 162, 232, 47, 157, 218},
-+	.module_id = 3,
-+	.instance_id = 5,
-+	.max_mcps = 0x186a0,
-+	.mem_pages = 0x1,
-+	.obs = 384,
-+	.ibs = 384,
-+	.vbus_id = 0,
-+	.max_in_queue = 1,
-+	.max_out_queue = 2,
-+	.time_slot = 2,
-+	.core_id = 0,
-+	.rsvd1 = 0,
-+	.module_type = 1,
-+	.conn_type = 2,
-+	.dev_type = 2,
-+	.hw_conn_type = 1,
-+	.rsvd2 = 0,
-+	.params_fixup = 0,
-+	.converter = 0,
-+	.input_pin_type = 0,
-+	.output_pin_type = 0,
-+	.is_dynamic_in_pin = 1,
-+	.is_dynamic_out_pin = 1,
-+	.is_loadable = 0,
-+	.rsvd3 = 0,
-+	.pipe = {
-+		.pipe_id = 4,
-+		.pipe_priority = 0,
-+		.conn_type = 2,
-+		.rsvd = 0,
-+		.memory_pages = 0x2,
-+	},
-+	.in_fmt = {
-+		{
-+			.channels = 2,
-+			.freq = 48000,
-+			.bit_depth = 32,
-+			.valid_bit_depth = 24,
-+			.ch_cfg = 1,
-+			.interleaving_style = 0,
-+			.sample_type = 0,
-+			.ch_map = 0xffffff10,
-+		},
-+	},
-+	.out_fmt = {
-+		{
-+			.channels = 2,
-+			.freq = 48000,
-+			.bit_depth = 32,
-+			.valid_bit_depth = 24,
-+			.ch_cfg = 1,
-+			.interleaving_style = 0,
-+			.sample_type = 0,
-+			.ch_map = 0xffffff10,
-+		},
-+		{
-+			.channels = 2,
-+			.freq = 48000,
-+			.bit_depth = 32,
-+			.valid_bit_depth = 24,
-+			.ch_cfg = 1,
-+			.interleaving_style = 0,
-+			.sample_type = 0,
-+			.ch_map = 0xffffff10,
-+		},
-+	},
-+	.in_pin = {
-+		{
-+			.module_id = 0,
-+			.instance_id = 0,
-+		},
-+	},
-+	.out_pin = {
-+		{
-+			.module_id = 0,
-+			.instance_id = 0,
-+		},
-+		{
-+			.module_id = 0,
-+			.instance_id = 0,
-+		},
-+	},
-+	},
-+},
-+{
-+.name = "codec0_in cpr 1",
-+.skl_dfw_mod = {
-+	.uuid = {131, 12, 160, 155, 18, 202, 131, 74, 148, 60, 31, 162, 232, 47, 157, 218},
-+	.module_id = 3,
-+	.instance_id = 1,
-+	.max_mcps = 0x186a0,
-+	.mem_pages = 0x1,
-+	.obs = 384,
-+	.ibs = 384,
-+	.vbus_id = 0,
-+	.max_in_queue = 1,
-+	.max_out_queue = 2,
-+	.time_slot = 0,
-+	.core_id = 0,
-+	.rsvd1 = 0,
-+	.module_type = 1,
-+	.conn_type = 2,
-+	.dev_type = 2,
-+	.hw_conn_type = 2,
-+	.rsvd2 = 0,
-+	.params_fixup = 0,
-+	.converter = 0,
-+	.input_pin_type = 0,
-+	.output_pin_type = 0,
-+	.is_dynamic_in_pin = 1,
-+	.is_dynamic_out_pin = 1,
-+	.is_loadable = 0,
-+	.rsvd3 = 0,
-+	.pipe = {
-+		.pipe_id = 5,
-+		.pipe_priority = 0,
-+		.conn_type = 2,
-+		.rsvd = 0,
-+		.memory_pages = 0x2,
-+	},
-+	.in_fmt = {
-+		{
-+			.channels = 2,
-+			.freq = 48000,
-+			.bit_depth = 32,
-+			.valid_bit_depth = 24,
-+			.ch_cfg = 1,
-+			.interleaving_style = 0,
-+			.sample_type = 0,
-+			.ch_map = 0xffffff10,
-+		},
-+	},
-+	.out_fmt = {
-+		{
-+			.channels = 2,
-+			.freq = 48000,
-+			.bit_depth = 32,
-+			.valid_bit_depth = 24,
-+			.ch_cfg = 1,
-+			.interleaving_style = 0,
-+			.sample_type = 0,
-+			.ch_map = 0xffffff10,
-+		},
-+		{
-+			.channels = 2,
-+			.freq = 48000,
-+			.bit_depth = 32,
-+			.valid_bit_depth = 24,
-+			.ch_cfg = 1,
-+			.interleaving_style = 0,
-+			.sample_type = 0,
-+			.ch_map = 0xffffff10,
-+		},
-+	},
-+	.in_pin = {
-+		{
-+			.module_id = 0,
-+			.instance_id = 0,
-+		},
-+	},
-+	.out_pin = {
-+		{
-+			.module_id = 0,
-+			.instance_id = 0,
-+		},
-+		{
-+			.module_id = 0,
-+			.instance_id = 0,
-+		},
-+	},
-+	},
-+},
-+{
-+.name = "codec0_in mi",
-+.skl_dfw_mod = {
-+	.uuid = {178, 110, 101, 57, 113, 59, 73, 64, 141, 63, 249, 44, 213, 196, 60, 9},
-+	.module_id = 1,
-+	.instance_id = 1,
-+	.max_mcps = 0x186a0,
-+	.mem_pages = 0x1,
-+	.obs = 384,
-+	.ibs = 384,
-+	.vbus_id = -1,
-+	.max_in_queue = 1,
-+	.max_out_queue = 1,
-+	.time_slot = 0,
-+	.core_id = 0,
-+	.rsvd1 = 0,
-+	.module_type = 0,
-+	.conn_type = 0,
-+	.dev_type = 6,
-+	.hw_conn_type = 2,
-+	.rsvd2 = 0,
-+	.params_fixup = 0,
-+	.converter = 0,
-+	.input_pin_type = 0,
-+	.output_pin_type = 0,
-+	.is_dynamic_in_pin = 1,
-+	.is_dynamic_out_pin = 1,
-+	.is_loadable = 0,
-+	.rsvd3 = 0,
-+	.pipe = {
-+		.pipe_id = 5,
-+		.pipe_priority = 0,
-+		.conn_type = 2,
-+		.rsvd = 0,
-+		.memory_pages = 0x2,
-+	},
-+	.in_fmt = {
-+		{
-+			.channels = 2,
-+			.freq = 48000,
-+			.bit_depth = 32,
-+			.valid_bit_depth = 32,
-+			.ch_cfg = 1,
-+			.interleaving_style = 0,
-+			.sample_type = 0,
-+			.ch_map = 0xffffff10,
-+		},
-+	},
-+	.out_fmt = {
-+		{
-+			.channels = 2,
-+			.freq = 48000,
-+			.bit_depth = 32,
-+			.valid_bit_depth = 32,
-+			.ch_cfg = 1,
-+			.interleaving_style = 0,
-+			.sample_type = 0,
-+			.ch_map = 0xffffff10,
-+		},
-+	},
-+	.in_pin = {
-+		{
-+			.module_id = 0,
-+			.instance_id = 0,
-+		},
-+	},
-+	.out_pin = {
-+		{
-+			.module_id = 0,
-+			.instance_id = 0,
-+		},
-+	},
-+	},
-+},
-+{
-+.name = "dmic01_hifi_in cpr 3",
-+.skl_dfw_mod = {
-+	.uuid = {131, 12, 160, 155, 18, 202, 131, 74, 148, 60, 31, 162, 232, 47, 157, 218},
-+	.module_id = 3,
-+	.instance_id = 3,
-+	.max_mcps = 0x186a0,
-+	.mem_pages = 0x1,
-+	.obs = 384,
-+	.ibs = 384,
-+	.vbus_id = 0,
-+	.max_in_queue = 1,
-+	.max_out_queue = 2,
-+	.time_slot = 0,
-+	.core_id = 0,
-+	.rsvd1 = 0,
-+	.module_type = 1,
-+	.conn_type = 2,
-+	.dev_type = 1,
-+	.hw_conn_type = 2,
-+	.rsvd2 = 0,
-+	.params_fixup = 4,
-+	.converter = 4,
-+	.input_pin_type = 0,
-+	.output_pin_type = 0,
-+	.is_dynamic_in_pin = 1,
-+	.is_dynamic_out_pin = 1,
-+	.is_loadable = 0,
-+	.rsvd3 = 0,
-+	.pipe = {
-+		.pipe_id = 6,
-+		.pipe_priority = 0,
-+		.conn_type = 2,
-+		.rsvd = 0,
-+		.memory_pages = 0x2,
-+	},
-+	.in_fmt = {
-+		{
-+			.channels = 2,
-+			.freq = 48000,
-+			.bit_depth = 32,
-+			.valid_bit_depth = 32,
-+			.ch_cfg = 1,
-+			.interleaving_style = 0,
-+			.sample_type = 0,
-+			.ch_map = 0xffffff10,
-+		},
-+	},
-+	.out_fmt = {
-+		{
-+			.channels = 2,
-+			.freq = 48000,
-+			.bit_depth = 32,
-+			.valid_bit_depth = 32,
-+			.ch_cfg = 1,
-+			.interleaving_style = 0,
-+			.sample_type = 0,
-+			.ch_map = 0xffffff10,
-+		},
-+		{
-+			.channels = 2,
-+			.freq = 48000,
-+			.bit_depth = 32,
-+			.valid_bit_depth = 32,
-+			.ch_cfg = 1,
-+			.interleaving_style = 0,
-+			.sample_type = 0,
-+			.ch_map = 0xffffff10,
-+		},
-+	},
-+	.in_pin = {
-+		{
-+			.module_id = 0,
-+			.instance_id = 0,
-+		},
-+	},
-+	.out_pin = {
-+		{
-+			.module_id = 0,
-+			.instance_id = 0,
-+		},
-+		{
-+			.module_id = 0,
-+			.instance_id = 0,
-+		},
-+	},
-+	},
-+},
-+{
-+.name = "dmic01_hifi_in mi",
-+.skl_dfw_mod = {
-+	.uuid = {178, 110, 101, 57, 113, 59, 73, 64, 141, 63, 249, 44, 213, 196, 60, 9},
-+	.module_id = 1,
-+	.instance_id = 3,
-+	.max_mcps = 0x186a0,
-+	.mem_pages = 0x1,
-+	.obs = 384,
-+	.ibs = 384,
-+	.vbus_id = -1,
-+	.max_in_queue = 1,
-+	.max_out_queue = 1,
-+	.time_slot = 0,
-+	.core_id = 0,
-+	.rsvd1 = 0,
-+	.module_type = 0,
-+	.conn_type = 0,
-+	.dev_type = 6,
-+	.hw_conn_type = 2,
-+	.rsvd2 = 0,
-+	.params_fixup = 0,
-+	.converter = 0,
-+	.input_pin_type = 0,
-+	.output_pin_type = 0,
-+	.is_dynamic_in_pin = 1,
-+	.is_dynamic_out_pin = 1,
-+	.is_loadable = 0,
-+	.rsvd3 = 0,
-+	.pipe = {
-+		.pipe_id = 6,
-+		.pipe_priority = 0,
-+		.conn_type = 2,
-+		.rsvd = 0,
-+		.memory_pages = 0x2,
-+	},
-+	.in_fmt = {
-+		{
-+			.channels = 2,
-+			.freq = 48000,
-+			.bit_depth = 32,
-+			.valid_bit_depth = 32,
-+			.ch_cfg = 1,
-+			.interleaving_style = 0,
-+			.sample_type = 0,
-+			.ch_map = 0xffffff10,
-+		},
-+	},
-+	.out_fmt = {
-+		{
-+			.channels = 2,
-+			.freq = 48000,
-+			.bit_depth = 32,
-+			.valid_bit_depth = 32,
-+			.ch_cfg = 1,
-+			.interleaving_style = 0,
-+			.sample_type = 0,
-+			.ch_map = 0xffffff10,
-+		},
-+	},
-+	.in_pin = {
-+		{
-+			.module_id = 0,
-+			.instance_id = 0,
-+		},
-+	},
-+	.out_pin = {
-+		{
-+			.module_id = 0,
-+			.instance_id = 0,
-+		},
-+	},
-+	},
-+},
-+{
-+.name = "hdmi1_pt_out cpr 7",
-+.skl_dfw_mod = {
-+	.uuid = {131, 12, 160, 155, 18, 202, 131, 74, 148, 60, 31, 162, 232, 47, 157, 218},
-+	.module_id = 3,
-+	.instance_id = 7,
-+	.max_mcps = 0x186a0,
-+	.mem_pages = 0x1,
-+	.obs = 384,
-+	.ibs = 384,
-+	.vbus_id = -1,
-+	.max_in_queue = 1,
-+	.max_out_queue = 2,
-+	.time_slot = 0,
-+	.core_id = 0,
-+	.rsvd1 = 0,
-+	.module_type = 1,
-+	.conn_type = 1,
-+	.dev_type = 5,
-+	.hw_conn_type = 1,
-+	.rsvd2 = 0,
-+	.params_fixup = 7,
-+	.converter = 0,
-+	.input_pin_type = 0,
-+	.output_pin_type = 0,
-+	.is_dynamic_in_pin = 1,
-+	.is_dynamic_out_pin = 1,
-+	.is_loadable = 0,
-+	.rsvd3 = 0,
-+	.pipe = {
-+		.pipe_id = 7,
-+		.pipe_priority = 0,
-+		.conn_type = 1,
-+		.rsvd = 0,
-+		.memory_pages = 0x2,
-+	},
-+	.in_fmt = {
-+		{
-+			.channels = 2,
-+			.freq = 48000,
-+			.bit_depth = 32,
-+			.valid_bit_depth = 32,
-+			.ch_cfg = 1,
-+			.interleaving_style = 0,
-+			.sample_type = 0,
-+			.ch_map = 0xffffff10,
-+		},
-+	},
-+	.out_fmt = {
-+		{
-+			.channels = 2,
-+			.freq = 48000,
-+			.bit_depth = 32,
-+			.valid_bit_depth = 32,
-+			.ch_cfg = 1,
-+			.interleaving_style = 0,
-+			.sample_type = 0,
-+			.ch_map = 0xffffff10,
-+		},
-+		{
-+			.channels = 2,
-+			.freq = 48000,
-+			.bit_depth = 32,
-+			.valid_bit_depth = 32,
-+			.ch_cfg = 1,
-+			.interleaving_style = 0,
-+			.sample_type = 0,
-+			.ch_map = 0xffffff10,
-+		},
-+	},
-+	.in_pin = {
-+		{
-+			.module_id = 0,
-+			.instance_id = 0,
-+		},
-+	},
-+	.out_pin = {
-+		{
-+			.module_id = 0,
-+			.instance_id = 0,
-+		},
-+		{
-+			.module_id = 0,
-+			.instance_id = 0,
-+		},
-+	},
-+	},
-+},
-+{
-+.name = "hdmi1_pt_out cpr 8",
-+.skl_dfw_mod = {
-+	.uuid = {131, 12, 160, 155, 18, 202, 131, 74, 148, 60, 31, 162, 232, 47, 157, 218},
-+	.module_id = 3,
-+	.instance_id = 8,
-+	.max_mcps = 0x186a0,
-+	.mem_pages = 0x1,
-+	.obs = 384,
-+	.ibs = 384,
-+	.vbus_id = -1,
-+	.max_in_queue = 1,
-+	.max_out_queue = 2,
-+	.time_slot = 0,
-+	.core_id = 0,
-+	.rsvd1 = 0,
-+	.module_type = 1,
-+	.conn_type = 1,
-+	.dev_type = 4,
-+	.hw_conn_type = 1,
-+	.rsvd2 = 0,
-+	.params_fixup = 7,
-+	.converter = 0,
-+	.input_pin_type = 0,
-+	.output_pin_type = 0,
-+	.is_dynamic_in_pin = 1,
-+	.is_dynamic_out_pin = 1,
-+	.is_loadable = 0,
-+	.rsvd3 = 0,
-+	.pipe = {
-+		.pipe_id = 7,
-+		.pipe_priority = 0,
-+		.conn_type = 1,
-+		.rsvd = 0,
-+		.memory_pages = 0x2,
-+	},
-+	.in_fmt = {
-+		{
-+			.channels = 2,
-+			.freq = 48000,
-+			.bit_depth = 32,
-+			.valid_bit_depth = 24,
-+			.ch_cfg = 1,
-+			.interleaving_style = 0,
-+			.sample_type = 0,
-+			.ch_map = 0xffffff10,
-+		},
-+	},
-+	.out_fmt = {
-+		{
-+			.channels = 2,
-+			.freq = 48000,
-+			.bit_depth = 32,
-+			.valid_bit_depth = 24,
-+			.ch_cfg = 1,
-+			.interleaving_style = 0,
-+			.sample_type = 0,
-+			.ch_map = 0xffffff10,
-+		},
-+		{
-+			.channels = 2,
-+			.freq = 48000,
-+			.bit_depth = 32,
-+			.valid_bit_depth = 24,
-+			.ch_cfg = 1,
-+			.interleaving_style = 0,
-+			.sample_type = 0,
-+			.ch_map = 0xffffff10,
-+		},
-+	},
-+	.in_pin = {
-+		{
-+			.module_id = 0,
-+			.instance_id = 0,
-+		},
-+	},
-+	.out_pin = {
-+		{
-+			.module_id = 0,
-+			.instance_id = 0,
-+		},
-+		{
-+			.module_id = 0,
-+			.instance_id = 0,
-+		},
-+	},
-+	},
-+},
-+{
-+.name = "hdmi2_pt_out cpr 9",
-+.skl_dfw_mod = {
-+	.uuid = {131, 12, 160, 155, 18, 202, 131, 74, 148, 60, 31, 162, 232, 47, 157, 218},
-+	.module_id = 3,
-+	.instance_id = 9,
-+	.max_mcps = 0x186a0,
-+	.mem_pages = 0x1,
-+	.obs = 384,
-+	.ibs = 384,
-+	.vbus_id = -1,
-+	.max_in_queue = 1,
-+	.max_out_queue = 2,
-+	.time_slot = 0,
-+	.core_id = 0,
-+	.rsvd1 = 0,
-+	.module_type = 1,
-+	.conn_type = 1,
-+	.dev_type = 5,
-+	.hw_conn_type = 1,
-+	.rsvd2 = 0,
-+	.params_fixup = 7,
-+	.converter = 0,
-+	.input_pin_type = 0,
-+	.output_pin_type = 0,
-+	.is_dynamic_in_pin = 1,
-+	.is_dynamic_out_pin = 1,
-+	.is_loadable = 0,
-+	.rsvd3 = 0,
-+	.pipe = {
-+		.pipe_id = 8,
-+		.pipe_priority = 0,
-+		.conn_type = 1,
-+		.rsvd = 0,
-+		.memory_pages = 0x2,
-+	},
-+	.in_fmt = {
-+		{
-+			.channels = 2,
-+			.freq = 48000,
-+			.bit_depth = 32,
-+			.valid_bit_depth = 32,
-+			.ch_cfg = 1,
-+			.interleaving_style = 0,
-+			.sample_type = 0,
-+			.ch_map = 0xffffff10,
-+		},
-+	},
-+	.out_fmt = {
-+		{
-+			.channels = 2,
-+			.freq = 48000,
-+			.bit_depth = 32,
-+			.valid_bit_depth = 32,
-+			.ch_cfg = 1,
-+			.interleaving_style = 0,
-+			.sample_type = 0,
-+			.ch_map = 0xffffff10,
-+		},
-+		{
-+			.channels = 2,
-+			.freq = 48000,
-+			.bit_depth = 32,
-+			.valid_bit_depth = 32,
-+			.ch_cfg = 1,
-+			.interleaving_style = 0,
-+			.sample_type = 0,
-+			.ch_map = 0xffffff10,
-+		},
-+	},
-+	.in_pin = {
-+		{
-+			.module_id = 0,
-+			.instance_id = 0,
-+		},
-+	},
-+	.out_pin = {
-+		{
-+			.module_id = 0,
-+			.instance_id = 0,
-+		},
-+		{
-+			.module_id = 0,
-+			.instance_id = 0,
-+		},
-+	},
-+	},
-+},
-+{
-+.name = "hdmi2_pt_out cpr 10",
-+.skl_dfw_mod = {
-+	.uuid = {131, 12, 160, 155, 18, 202, 131, 74, 148, 60, 31, 162, 232, 47, 157, 218},
-+	.module_id = 3,
-+	.instance_id = 10,
-+	.max_mcps = 0x186a0,
-+	.mem_pages = 0x1,
-+	.obs = 384,
-+	.ibs = 384,
-+	.vbus_id = -1,
-+	.max_in_queue = 1,
-+	.max_out_queue = 2,
-+	.time_slot = 0,
-+	.core_id = 0,
-+	.rsvd1 = 0,
-+	.module_type = 1,
-+	.conn_type = 1,
-+	.dev_type = 4,
-+	.hw_conn_type = 1,
-+	.rsvd2 = 0,
-+	.params_fixup = 7,
-+	.converter = 0,
-+	.input_pin_type = 0,
-+	.output_pin_type = 0,
-+	.is_dynamic_in_pin = 1,
-+	.is_dynamic_out_pin = 1,
-+	.is_loadable = 0,
-+	.rsvd3 = 0,
-+	.pipe = {
-+		.pipe_id = 8,
-+		.pipe_priority = 0,
-+		.conn_type = 1,
-+		.rsvd = 0,
-+		.memory_pages = 0x2,
-+	},
-+	.in_fmt = {
-+		{
-+			.channels = 2,
-+			.freq = 48000,
-+			.bit_depth = 32,
-+			.valid_bit_depth = 24,
-+			.ch_cfg = 1,
-+			.interleaving_style = 0,
-+			.sample_type = 0,
-+			.ch_map = 0xffffff10,
-+		},
-+	},
-+	.out_fmt = {
-+		{
-+			.channels = 2,
-+			.freq = 48000,
-+			.bit_depth = 32,
-+			.valid_bit_depth = 24,
-+			.ch_cfg = 1,
-+			.interleaving_style = 0,
-+			.sample_type = 0,
-+			.ch_map = 0xffffff10,
-+		},
-+		{
-+			.channels = 2,
-+			.freq = 48000,
-+			.bit_depth = 32,
-+			.valid_bit_depth = 24,
-+			.ch_cfg = 1,
-+			.interleaving_style = 0,
-+			.sample_type = 0,
-+			.ch_map = 0xffffff10,
-+		},
-+	},
-+	.in_pin = {
-+		{
-+			.module_id = 0,
-+			.instance_id = 0,
-+		},
-+	},
-+	.out_pin = {
-+		{
-+			.module_id = 0,
-+			.instance_id = 0,
-+		},
-+		{
-+			.module_id = 0,
-+			.instance_id = 0,
-+		},
-+	},
-+	},
-+},
-+{
-+.name = "hdmi3_pt_out cpr 11",
-+.skl_dfw_mod = {
-+	.uuid = {131, 12, 160, 155, 18, 202, 131, 74, 148, 60, 31, 162, 232, 47, 157, 218},
-+	.module_id = 3,
-+	.instance_id = 11,
-+	.max_mcps = 0x186a0,
-+	.mem_pages = 0x1,
-+	.obs = 384,
-+	.ibs = 384,
-+	.vbus_id = -1,
-+	.max_in_queue = 1,
-+	.max_out_queue = 2,
-+	.time_slot = 0,
-+	.core_id = 0,
-+	.rsvd1 = 0,
-+	.module_type = 1,
-+	.conn_type = 1,
-+	.dev_type = 5,
-+	.hw_conn_type = 1,
-+	.rsvd2 = 0,
-+	.params_fixup = 7,
-+	.converter = 0,
-+	.input_pin_type = 0,
-+	.output_pin_type = 0,
-+	.is_dynamic_in_pin = 1,
-+	.is_dynamic_out_pin = 1,
-+	.is_loadable = 0,
-+	.rsvd3 = 0,
-+	.pipe = {
-+		.pipe_id = 9,
-+		.pipe_priority = 0,
-+		.conn_type = 1,
-+		.rsvd = 0,
-+		.memory_pages = 0x2,
-+	},
-+	.in_fmt = {
-+		{
-+			.channels = 2,
-+			.freq = 48000,
-+			.bit_depth = 32,
-+			.valid_bit_depth = 32,
-+			.ch_cfg = 1,
-+			.interleaving_style = 0,
-+			.sample_type = 0,
-+			.ch_map = 0xffffff10,
-+		},
-+	},
-+	.out_fmt = {
-+		{
-+			.channels = 2,
-+			.freq = 48000,
-+			.bit_depth = 32,
-+			.valid_bit_depth = 32,
-+			.ch_cfg = 1,
-+			.interleaving_style = 0,
-+			.sample_type = 0,
-+			.ch_map = 0xffffff10,
-+		},
-+		{
-+			.channels = 2,
-+			.freq = 48000,
-+			.bit_depth = 32,
-+			.valid_bit_depth = 32,
-+			.ch_cfg = 1,
-+			.interleaving_style = 0,
-+			.sample_type = 0,
-+			.ch_map = 0xffffff10,
-+		},
-+	},
-+	.in_pin = {
-+		{
-+			.module_id = 0,
-+			.instance_id = 0,
-+		},
-+	},
-+	.out_pin = {
-+		{
-+			.module_id = 0,
-+			.instance_id = 0,
-+		},
-+		{
-+			.module_id = 0,
-+			.instance_id = 0,
-+		},
-+	},
-+	},
-+},
-+{
-+.name = "hdmi3_pt_out cpr 12",
-+.skl_dfw_mod = {
-+	.uuid = {131, 12, 160, 155, 18, 202, 131, 74, 148, 60, 31, 162, 232, 47, 157, 218},
-+	.module_id = 3,
-+	.instance_id = 12,
-+	.max_mcps = 0x186a0,
-+	.mem_pages = 0x1,
-+	.obs = 384,
-+	.ibs = 384,
-+	.vbus_id = -1,
-+	.max_in_queue = 1,
-+	.max_out_queue = 2,
-+	.time_slot = 0,
-+	.core_id = 0,
-+	.rsvd1 = 0,
-+	.module_type = 1,
-+	.conn_type = 1,
-+	.dev_type = 4,
-+	.hw_conn_type = 1,
-+	.rsvd2 = 0,
-+	.params_fixup = 7,
-+	.converter = 0,
-+	.input_pin_type = 0,
-+	.output_pin_type = 0,
-+	.is_dynamic_in_pin = 1,
-+	.is_dynamic_out_pin = 1,
-+	.is_loadable = 0,
-+	.rsvd3 = 0,
-+	.pipe = {
-+		.pipe_id = 9,
-+		.pipe_priority = 0,
-+		.conn_type = 1,
-+		.rsvd = 0,
-+		.memory_pages = 0x2,
-+	},
-+	.in_fmt = {
-+		{
-+			.channels = 2,
-+			.freq = 48000,
-+			.bit_depth = 32,
-+			.valid_bit_depth = 24,
-+			.ch_cfg = 1,
-+			.interleaving_style = 0,
-+			.sample_type = 0,
-+			.ch_map = 0xffffff10,
-+		},
-+	},
-+	.out_fmt = {
-+		{
-+			.channels = 2,
-+			.freq = 48000,
-+			.bit_depth = 32,
-+			.valid_bit_depth = 24,
-+			.ch_cfg = 1,
-+			.interleaving_style = 0,
-+			.sample_type = 0,
-+			.ch_map = 0xffffff10,
-+		},
-+		{
-+			.channels = 2,
-+			.freq = 48000,
-+			.bit_depth = 32,
-+			.valid_bit_depth = 24,
-+			.ch_cfg = 1,
-+			.interleaving_style = 0,
-+			.sample_type = 0,
-+			.ch_map = 0xffffff10,
-+		},
-+	},
-+	.in_pin = {
-+		{
-+			.module_id = 0,
-+			.instance_id = 0,
-+		},
-+	},
-+	.out_pin = {
-+		{
-+			.module_id = 0,
-+			.instance_id = 0,
-+		},
-+		{
-+			.module_id = 0,
-+			.instance_id = 0,
-+		},
-+	},
-+	},
-+},
-+	};
-diff --git a/src/conf/topology/sklrt286/data/pvt_data.c b/src/conf/topology/sklrt286/data/pvt_data.c
-new file mode 100644
-index 0000000..dd55c3a
---- /dev/null
-+++ b/src/conf/topology/sklrt286/data/pvt_data.c
-@@ -0,0 +1,90 @@
-+/*
-+ * Copyright(c) 2014-2016 Intel Corporation
-+ * All rights reserved.
-+ *
-+ *  This library is free software; you can redistribute it and/or
-+ *  modify it under the terms of the GNU Lesser General Public
-+ *  License as published by the Free Software Foundation; either
-+ *  version 2 of the License, or (at your option) any later version.
-+ *
-+ *  This library is distributed in the hope that it will be useful,
-+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+ *  Lesser General Public License for more details.
-+ *
-+ * Authors: Shreyas Nc <shreyas.nc@intel.com>
-+ *
-+ */
-+#include "pvt.c"
-+#include "stdio.h"
-+#include "fcntl.h"
-+#include <local.h>
-+#include <limits.h>
-+#include <stdint.h>
-+#include <linux/types.h>
-+#include "global.h"
-+#include "list.h"
-+
-+#include <sound/asound.h>
-+#include <sound/asoc.h>
-+
-+int replace_space(char *path, char *newpath)
-+{
-+	char buffer[52];
-+	char *p;
-+
-+	strcpy(buffer, path);
-+
-+	while ((p = strchr(buffer, ' ')))
-+		p[0] = '-';
-+
-+	strcpy(newpath, buffer);
-+	return 0;
-+}
-+
-+/*
-+ * The private data structures are written into a
-+ * binary blob. These contain module private data
-+ * information
-+ */
-+int main(void)
-+{
-+	unsigned int i;
-+	FILE  *fd;
-+	char path[128];
-+	char new_path[128];
-+	struct snd_soc_tplg_private *priv = NULL;
-+
-+	memset(path, 0, sizeof(path));
-+	memset(new_path, 0, sizeof(new_path));
-+
-+	priv = calloc(1, sizeof(dfw_wrap) + sizeof(uint32_t));
-+
-+	for (i = 0; i < ARRAY_SIZE(dfw_wrap); i++) {
-+		strcat(path, "../");
-+		strcat(path, dfw_wrap[i].name);
-+		strcat(path, ".bin");
-+
-+		replace_space(path, new_path);
-+
-+		priv->size = (uint32_t)sizeof(dfw_wrap[i].skl_dfw_mod);
-+
-+		memcpy(priv->data, &dfw_wrap[i].skl_dfw_mod,
-+				priv->size);
-+
-+		fd = fopen(new_path, "wb");
-+
-+		if (fd == NULL)
-+			return -ENOENT;
-+
-+		if (fwrite(priv->data, priv->size, 1, fd) != 1) {
-+			fclose(fd);
-+			return -1;
-+		}
-+
-+		memset(path, 0, sizeof(path));
-+	}
-+
-+	free(priv);
-+	return 0;
-+}
-diff --git a/src/conf/topology/sklrt286/data/pvt_local.h b/src/conf/topology/sklrt286/data/pvt_local.h
-new file mode 100644
-index 0000000..5edf7bd
---- /dev/null
-+++ b/src/conf/topology/sklrt286/data/pvt_local.h
-@@ -0,0 +1,9 @@
-+#include <stdio.h>
-+#include "skl-tplg-interface.h"
-+
-+struct skl_dfw_module_mod {
-+	char name[100];
-+	struct skl_dfw_module skl_dfw_mod;
-+};
-+
-+
-diff --git a/src/conf/topology/sklrt286/data/skl-tplg-interface.h b/src/conf/topology/sklrt286/data/skl-tplg-interface.h
-new file mode 100644
-index 0000000..e7389bc
---- /dev/null
-+++ b/src/conf/topology/sklrt286/data/skl-tplg-interface.h
-@@ -0,0 +1,232 @@
-+/*
-+ * skl-tplg-interface.h - Intel DSP FW private data interface
-+ *
-+ * Copyright (C) 2015 Intel Corp
-+ * Author: Jeeja KP <jeeja.kp@intel.com>
-+ *	    Nilofer, Samreen <samreen.nilofer@intel.com>
-+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as version 2, as
-+ * published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope that it will be useful, but
-+ * WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+ * General Public License for more details.
-+ */
-+
-+#ifndef __HDA_TPLG_INTERFACE_H__
-+#define __HDA_TPLG_INTERFACE_H__
-+
-+#include <sound/type_compat.h>
-+/*
-+ * Default types range from 0~12. type can range from 0 to 0xff
-+ * SST types start at higher to avoid any overlapping in future
-+ */
-+#define SKL_CONTROL_TYPE_BYTE_TLV	0x100
-+
-+#define HDA_SST_CFG_MAX	900 /* size of copier cfg*/
-+#define MAX_IN_QUEUE 8
-+#define MAX_OUT_QUEUE 8
-+
-+#define SKL_UUID_STR_SZ 40
-+/* Event types goes here */
-+/* Reserve event type 0 for no event handlers */
-+enum skl_event_types {
-+	SKL_EVENT_NONE = 0,
-+	SKL_MIXER_EVENT,
-+	SKL_MUX_EVENT,
-+	SKL_VMIXER_EVENT,
-+	SKL_PGA_EVENT
-+};
-+
-+/**
-+ * enum skl_ch_cfg - channel configuration
-+ *
-+ * @SKL_CH_CFG_MONO:	One channel only
-+ * @SKL_CH_CFG_STEREO:	L & R
-+ * @SKL_CH_CFG_2_1:	L, R & LFE
-+ * @SKL_CH_CFG_3_0:	L, C & R
-+ * @SKL_CH_CFG_3_1:	L, C, R & LFE
-+ * @SKL_CH_CFG_QUATRO:	L, R, Ls & Rs
-+ * @SKL_CH_CFG_4_0:	L, C, R & Cs
-+ * @SKL_CH_CFG_5_0:	L, C, R, Ls & Rs
-+ * @SKL_CH_CFG_5_1:	L, C, R, Ls, Rs & LFE
-+ * @SKL_CH_CFG_DUAL_MONO: One channel replicated in two
-+ * @SKL_CH_CFG_I2S_DUAL_STEREO_0: Stereo(L,R) in 4 slots, 1st stream:[ L, R, -, - ]
-+ * @SKL_CH_CFG_I2S_DUAL_STEREO_1: Stereo(L,R) in 4 slots, 2nd stream:[ -, -, L, R ]
-+ * @SKL_CH_CFG_INVALID:	Invalid
-+ */
-+enum skl_ch_cfg {
-+	SKL_CH_CFG_MONO = 0,
-+	SKL_CH_CFG_STEREO = 1,
-+	SKL_CH_CFG_2_1 = 2,
-+	SKL_CH_CFG_3_0 = 3,
-+	SKL_CH_CFG_3_1 = 4,
-+	SKL_CH_CFG_QUATRO = 5,
-+	SKL_CH_CFG_4_0 = 6,
-+	SKL_CH_CFG_5_0 = 7,
-+	SKL_CH_CFG_5_1 = 8,
-+	SKL_CH_CFG_DUAL_MONO = 9,
-+	SKL_CH_CFG_I2S_DUAL_STEREO_0 = 10,
-+	SKL_CH_CFG_I2S_DUAL_STEREO_1 = 11,
-+	SKL_CH_CFG_4_CHANNEL = 12,
-+	SKL_CH_CFG_INVALID
-+};
-+
-+enum skl_module_type {
-+	SKL_MODULE_TYPE_MIXER = 0,
-+	SKL_MODULE_TYPE_COPIER,
-+	SKL_MODULE_TYPE_UPDWMIX,
-+	SKL_MODULE_TYPE_SRCINT,
-+	SKL_MODULE_TYPE_ALGO,
-+	SKL_MODULE_TYPE_BASE_OUTFMT
-+};
-+
-+enum skl_core_affinity {
-+	SKL_AFFINITY_CORE_0 = 0,
-+	SKL_AFFINITY_CORE_1,
-+	SKL_AFFINITY_CORE_MAX
-+};
-+
-+enum skl_pipe_conn_type {
-+	SKL_PIPE_CONN_TYPE_NONE = 0,
-+	SKL_PIPE_CONN_TYPE_FE,
-+	SKL_PIPE_CONN_TYPE_BE
-+};
-+
-+enum skl_hw_conn_type {
-+	SKL_CONN_NONE = 0,
-+	SKL_CONN_SOURCE = 1,
-+	SKL_CONN_SINK = 2
-+};
-+
-+enum skl_dev_type {
-+	SKL_DEVICE_BT = 0x0,
-+	SKL_DEVICE_DMIC = 0x1,
-+	SKL_DEVICE_I2S = 0x2,
-+	SKL_DEVICE_SLIMBUS = 0x3,
-+	SKL_DEVICE_HDALINK = 0x4,
-+	SKL_DEVICE_HDAHOST = 0x5,
-+	SKL_DEVICE_NONE
-+};
-+
-+/**
-+ * enum skl_interleaving - interleaving style
-+ *
-+ * @SKL_INTERLEAVING_PER_CHANNEL: [s1_ch1...s1_chN,...,sM_ch1...sM_chN]
-+ * @SKL_INTERLEAVING_PER_SAMPLE: [s1_ch1...sM_ch1,...,s1_chN...sM_chN]
-+ */
-+enum skl_interleaving {
-+	SKL_INTERLEAVING_PER_CHANNEL = 0,
-+	SKL_INTERLEAVING_PER_SAMPLE = 1,
-+};
-+
-+enum skl_sample_type {
-+	SKL_SAMPLE_TYPE_INT_MSB = 0,
-+	SKL_SAMPLE_TYPE_INT_LSB = 1,
-+	SKL_SAMPLE_TYPE_INT_SIGNED = 2,
-+	SKL_SAMPLE_TYPE_INT_UNSIGNED = 3,
-+	SKL_SAMPLE_TYPE_FLOAT = 4
-+};
-+
-+enum module_pin_type {
-+	/* All pins of the module takes same PCM inputs or outputs
-+	* e.g. mixout
-+	*/
-+	SKL_PIN_TYPE_HOMOGENEOUS,
-+	/* All pins of the module takes different PCM inputs or outputs
-+	* e.g mux
-+	*/
-+	SKL_PIN_TYPE_HETEROGENEOUS,
-+};
-+
-+enum skl_module_param_type {
-+	SKL_PARAM_DEFAULT = 0,
-+	SKL_PARAM_INIT,
-+	SKL_PARAM_SET,
-+	SKL_PARAM_BIND
-+};
-+
-+struct skl_dfw_module_pin {
-+	__le16 module_id;
-+	__le16 instance_id;
-+} __attribute__((packed));
-+
-+struct skl_dfw_module_fmt {
-+	__le32 channels;
-+	__le32 freq;
-+	__le32 bit_depth;
-+	__le32 valid_bit_depth;
-+	__le32 ch_cfg;
-+	__le32 interleaving_style;
-+	__le32 sample_type;
-+	__le32 ch_map;
-+} __attribute__((packed));
-+
-+struct skl_dfw_module_caps {
-+	__le32 set_params:2;
-+	__le32 rsvd:30;
-+	__le32 param_id;
-+	__le32 caps_size;
-+	__le32 caps[HDA_SST_CFG_MAX];
-+};
-+
-+struct skl_dfw_pipe {
-+	__le8 pipe_id;
-+	__le8 pipe_priority;
-+	__le16 conn_type:4;
-+	__le16 rsvd:4;
-+	__le16 memory_pages:8;
-+} __attribute__((packed));
-+
-+struct skl_dfw_module {
-+	__le8 uuid[16];
-+
-+	__le16 module_id;
-+	__le16 instance_id;
-+	__le32 max_mcps;
-+	__le32 mem_pages;
-+	__le32 obs;
-+	__le32 ibs;
-+	__le32 vbus_id;
-+
-+	__le32 max_in_queue:8;
-+	__le32 max_out_queue:8;
-+	__le32 time_slot:8;
-+	__le32 core_id:4;
-+	__le32 rsvd1:4;
-+
-+	__le32 module_type:8;
-+	__le32 conn_type:4;
-+	__le32 dev_type:4;
-+	__le32 hw_conn_type:4;
-+	__le32 rsvd2:12;
-+
-+	__le32 params_fixup:8;
-+	__le32 converter:8;
-+	__le32 input_pin_type:1;
-+	__le32 output_pin_type:1;
-+	__le32 is_dynamic_in_pin:1;
-+	__le32 is_dynamic_out_pin:1;
-+	__le32 is_loadable:1;
-+	__le32 rsvd3:11;
-+
-+	struct skl_dfw_pipe pipe;
-+	struct skl_dfw_module_fmt in_fmt[MAX_IN_QUEUE];
-+	struct skl_dfw_module_fmt out_fmt[MAX_OUT_QUEUE];
-+	struct skl_dfw_module_pin in_pin[MAX_IN_QUEUE];
-+	struct skl_dfw_module_pin out_pin[MAX_OUT_QUEUE];
-+	struct skl_dfw_module_caps caps;
-+} __attribute__((packed));
-+
-+struct skl_dfw_algo_data {
-+	__le32 set_params:2;
-+	__le32 rsvd:30;
-+	__le32 param_id;
-+	__le32 max;
-+	char params[0];
-+} __attribute__((packed));
-+
-+#endif
--- 
-2.5.5
-
-From e64334df2b2fe6756539178d89133a0b56e83c9d Mon Sep 17 00:00:00 2001
-From: Mengdong Lin <mengdong.lin@linux.intel.com>
-Date: Fri, 29 Apr 2016 11:02:57 +0800
-Subject: [PATCH 16/34] topology: Set manifest size for ABI
-
-The topology kernel driver will check the size of manifest struct, and
-will stop loading topology info if size mismatch is detected.
-
-Signed-off-by: Mengdong Lin <mengdong.lin@linux.intel.com>
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
----
- src/topology/parser.c | 2 ++
- 1 file changed, 2 insertions(+)
-
-diff --git a/src/topology/parser.c b/src/topology/parser.c
-index 30d91f9..84117c3 100644
---- a/src/topology/parser.c
-+++ b/src/topology/parser.c
-@@ -414,6 +414,8 @@ snd_tplg_t *snd_tplg_new(void)
- 	if (!tplg)
- 		return NULL;
- 
-+	tplg->manifest.size = sizeof(struct snd_soc_tplg_manifest);
-+
- 	INIT_LIST_HEAD(&tplg->tlv_list);
- 	INIT_LIST_HEAD(&tplg->widget_list);
- 	INIT_LIST_HEAD(&tplg->pcm_list);
--- 
-2.5.5
-
-From 86ec8b49008fbcfa45756f7ab1803392c3bb464e Mon Sep 17 00:00:00 2001
-From: Mengdong Lin <mengdong.lin@linux.intel.com>
-Date: Fri, 29 Apr 2016 11:03:04 +0800
-Subject: [PATCH 17/34] topology: Refactor functions to parse and build streams
-
-Previously these functions are only used by pcm elements (front-end DAI
-& DAI link) to parse stream capablities. Now refactor them to be reused
-by back-end DAI elements later.
-
-Signed-off-by: Mengdong Lin <mengdong.lin@linux.intel.com>
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
----
- src/topology/parser.c     |  2 +-
- src/topology/pcm.c        | 60 +++++++++++++++++++++++++++--------------------
- src/topology/tplg_local.h |  2 +-
- 3 files changed, 36 insertions(+), 28 deletions(-)
-
-diff --git a/src/topology/parser.c b/src/topology/parser.c
-index 84117c3..f6fc944 100644
---- a/src/topology/parser.c
-+++ b/src/topology/parser.c
-@@ -119,7 +119,7 @@ static int tplg_parse_config(snd_tplg_t *tplg, snd_config_t *cfg)
- 
- 		if (strcmp(id, "SectionPCMCapabilities") == 0) {
- 			err = tplg_parse_compound(tplg, n,
--				tplg_parse_pcm_caps, NULL);
-+				tplg_parse_stream_caps, NULL);
- 			if (err < 0)
- 				return err;
- 			continue;
-diff --git a/src/topology/pcm.c b/src/topology/pcm.c
-index d75aad8..1df4f54 100644
---- a/src/topology/pcm.c
-+++ b/src/topology/pcm.c
-@@ -40,9 +40,9 @@ struct tplg_elem *lookup_pcm_dai_stream(struct list_head *base, const char* id)
- 	return NULL;
- }
- 
--/* copy referenced caps to the pcm */
--static void copy_pcm_caps(const char *id, struct snd_soc_tplg_stream_caps *caps,
--	struct tplg_elem *ref_elem)
-+/* copy referenced caps to the parent (pcm or be dai) */
-+static void copy_stream_caps(const char *id,
-+	struct snd_soc_tplg_stream_caps *caps, struct tplg_elem *ref_elem)
- {
- 	struct snd_soc_tplg_stream_caps *ref_caps = ref_elem->stream_caps;
- 
-@@ -52,24 +52,19 @@ static void copy_pcm_caps(const char *id, struct snd_soc_tplg_stream_caps *caps,
- 	*caps =  *ref_caps;
- }
- 
--/* check referenced config and caps for a pcm */
--static int tplg_build_pcm_caps(snd_tplg_t *tplg, struct tplg_elem *elem)
-+/* find and copy the referenced stream caps */
-+static int tplg_build_stream_caps(snd_tplg_t *tplg,
-+	const char *id, struct snd_soc_tplg_stream_caps *caps)
- {
- 	struct tplg_elem *ref_elem = NULL;
--	struct snd_soc_tplg_pcm *pcm;
--	struct snd_soc_tplg_stream_caps *caps;
- 	unsigned int i;
- 
--	pcm = elem->pcm;
--
- 	for (i = 0; i < 2; i++) {
--		caps = &pcm->caps[i];
--
- 		ref_elem = tplg_elem_lookup(&tplg->pcm_caps_list,
--			caps->name, SND_TPLG_TYPE_STREAM_CAPS);
-+			caps[i].name, SND_TPLG_TYPE_STREAM_CAPS);
- 
- 		if (ref_elem != NULL)
--			copy_pcm_caps(elem->id, caps, ref_elem);
-+			copy_stream_caps(id, &caps[i], ref_elem);
- 	}
- 
- 	return 0;
-@@ -91,7 +86,7 @@ int tplg_build_pcm(snd_tplg_t *tplg, unsigned int type)
- 			return -EINVAL;
- 		}
- 
--		err = tplg_build_pcm_caps(tplg, elem);
-+		err = tplg_build_stream_caps(tplg, elem->id, elem->pcm->caps);
- 		if (err < 0)
- 			return err;
- 
-@@ -184,8 +179,8 @@ static int split_format(struct snd_soc_tplg_stream_caps *caps, char *str)
- 	return 0;
- }
- 
--/* Parse pcm Capabilities */
--int tplg_parse_pcm_caps(snd_tplg_t *tplg,
-+/* Parse pcm stream capabilities */
-+int tplg_parse_stream_caps(snd_tplg_t *tplg,
- 	snd_config_t *cfg, void *private ATTRIBUTE_UNUSED)
- {
- 	struct snd_soc_tplg_stream_caps *sc;
-@@ -263,29 +258,40 @@ int tplg_parse_pcm_caps(snd_tplg_t *tplg,
- 	return 0;
- }
- 
--/* Parse the caps of a pcm stream */
--int tplg_parse_stream_caps(snd_tplg_t *tplg, snd_config_t *cfg,
-+/* Parse the caps and config of a pcm stream */
-+static int tplg_parse_streams(snd_tplg_t *tplg, snd_config_t *cfg,
- 	void *private)
- {
- 	snd_config_iterator_t i, next;
- 	snd_config_t *n;
- 	struct tplg_elem *elem = private;
- 	struct snd_soc_tplg_pcm *pcm;
-+	unsigned int *playback, *capture;
-+	struct snd_soc_tplg_stream_caps *caps;
- 	const char *id, *value;
- 	int stream;
- 
--	pcm = elem->pcm;
--
- 	snd_config_get_id(cfg, &id);
- 
- 	tplg_dbg("\t%s:\n", id);
- 
-+	switch (elem->type) {
-+	case SND_TPLG_TYPE_PCM:
-+		pcm = elem->pcm;
-+		playback = &pcm->playback;
-+		capture = &pcm->capture;
-+		caps = pcm->caps;
-+		break;
-+	default:
-+		return -EINVAL;
-+	}
-+
- 	if (strcmp(id, "playback") == 0) {
- 		stream = SND_SOC_TPLG_STREAM_PLAYBACK;
--		pcm->playback = 1;
-+		*playback = 1;
- 	} else if (strcmp(id, "capture") == 0) {
- 		stream = SND_SOC_TPLG_STREAM_CAPTURE;
--		pcm->capture = 1;
-+		*capture = 1;
- 	} else
- 		return -EINVAL;
- 
-@@ -300,8 +306,10 @@ int tplg_parse_stream_caps(snd_tplg_t *tplg, snd_config_t *cfg,
- 		if (strcmp(id, "capabilities") == 0) {
- 			if (snd_config_get_string(n, &value) < 0)
- 				continue;
--
--			elem_copy_text(pcm->caps[stream].name, value,
-+			/* store stream caps name, to find and merge
-+			 * the caps in building phase.
-+			 */
-+			elem_copy_text(caps[stream].name, value,
- 				SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
- 
- 			tplg_dbg("\t\t%s\n\t\t\t%s\n", id, value);
-@@ -312,7 +320,7 @@ int tplg_parse_stream_caps(snd_tplg_t *tplg, snd_config_t *cfg,
- 	return 0;
- }
- 
--/* Parse pcm */
-+/* Parse pcm (for front end DAI & DAI link) */
- int tplg_parse_pcm(snd_tplg_t *tplg,
- 	snd_config_t *cfg, void *private ATTRIBUTE_UNUSED)
- {
-@@ -365,7 +373,7 @@ int tplg_parse_pcm(snd_tplg_t *tplg,
- 
- 		if (strcmp(id, "pcm") == 0) {
- 			err = tplg_parse_compound(tplg, n,
--				tplg_parse_stream_caps, elem);
-+				tplg_parse_streams, elem);
- 			if (err < 0)
- 				return err;
- 			continue;
-diff --git a/src/topology/tplg_local.h b/src/topology/tplg_local.h
-index 4c601d4..9239aef 100644
---- a/src/topology/tplg_local.h
-+++ b/src/topology/tplg_local.h
-@@ -210,7 +210,7 @@ int tplg_parse_dapm_graph(snd_tplg_t *tplg, snd_config_t *cfg,
- int tplg_parse_dapm_widget(snd_tplg_t *tplg,
- 	snd_config_t *cfg, void *private ATTRIBUTE_UNUSED);
- 
--int tplg_parse_pcm_caps(snd_tplg_t *tplg,
-+int tplg_parse_stream_caps(snd_tplg_t *tplg,
- 	snd_config_t *cfg, void *private ATTRIBUTE_UNUSED);
- 
- int tplg_parse_pcm(snd_tplg_t *tplg,
--- 
-2.5.5
-
-From 0935e32d40e065e61255550ac4c5b7c6710dd028 Mon Sep 17 00:00:00 2001
-From: Mengdong Lin <mengdong.lin@linux.intel.com>
-Date: Fri, 29 Apr 2016 11:03:22 +0800
-Subject: [PATCH 18/34] topology: Use generic pointer to realloc buffer for
- private data
-
-Many element types have private data. So use the generic obj pointer
-instead of the type-specific pointer when reallocating the object to
-accommodate the private data.
-
-Empty private data will be overlooked.
-
-Signed-off-by: Mengdong Lin <mengdong.lin@linux.intel.com>
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
----
- src/topology/data.c | 26 +++++++++-----------------
- 1 file changed, 9 insertions(+), 17 deletions(-)
-
-diff --git a/src/topology/data.c b/src/topology/data.c
-index 19c31bf..9f8d5d0 100644
---- a/src/topology/data.c
-+++ b/src/topology/data.c
-@@ -822,44 +822,36 @@ int tplg_copy_data(struct tplg_elem *elem, struct tplg_elem *ref)
- {
- 	struct snd_soc_tplg_private *priv;
- 	int priv_data_size;
-+	void *obj;
- 
- 	if (!ref)
- 		return -EINVAL;
- 
- 	tplg_dbg("Data '%s' used by '%s'\n", ref->id, elem->id);
-+	if (!ref->data || !ref->data->size) /* overlook empty private data */
-+		return 0;
-+
- 	priv_data_size = ref->data->size;
-+	obj = realloc(elem->obj,
-+			elem->size + priv_data_size);
-+	if (!obj)
-+		return -ENOMEM;
-+	elem->obj = obj;
- 
- 	switch (elem->type) {
- 	case SND_TPLG_TYPE_MIXER:
--		elem->mixer_ctrl = realloc(elem->mixer_ctrl,
--			elem->size + priv_data_size);
--		if (!elem->mixer_ctrl)
--			return -ENOMEM;
- 		priv = &elem->mixer_ctrl->priv;
- 		break;
- 
- 	case SND_TPLG_TYPE_ENUM:
--		elem->enum_ctrl = realloc(elem->enum_ctrl,
--			elem->size + priv_data_size);
--		if (!elem->enum_ctrl)
--			return -ENOMEM;
- 		priv = &elem->enum_ctrl->priv;
- 		break;
- 
- 	case SND_TPLG_TYPE_BYTES:
--		elem->bytes_ext = realloc(elem->bytes_ext,
--			elem->size + priv_data_size);
--		if (!elem->bytes_ext)
--			return -ENOMEM;
- 		priv = &elem->bytes_ext->priv;
- 		break;
- 
--
- 	case SND_TPLG_TYPE_DAPM_WIDGET:
--		elem->widget = realloc(elem->widget,
--			elem->size + priv_data_size);
--		if (!elem->widget)
--			return -ENOMEM;
- 		priv = &elem->widget->priv;
- 		break;
- 
--- 
-2.5.5
-
-From 5d23c406d1757d1b65e1d17a71c69620d9af71d7 Mon Sep 17 00:00:00 2001
-From: Mengdong Lin <mengdong.lin@linux.intel.com>
-Date: Fri, 29 Apr 2016 11:03:30 +0800
-Subject: [PATCH 19/34] topology: Fix pcm ID & name parsing
-
-The name and ID of SectionPCM should be set to pcm_name and pcm_id,
-for a front-end DAI link in the kernel, not for the front-end DAI
-of the link.
-
-Signed-off-by: Mengdong Lin <mengdong.lin@linux.intel.com>
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
----
- include/sound/asoc.h | 2 +-
- src/topology/pcm.c   | 6 +++---
- 2 files changed, 4 insertions(+), 4 deletions(-)
-
-diff --git a/include/sound/asoc.h b/include/sound/asoc.h
-index 920c9e0..abe49c5 100644
---- a/include/sound/asoc.h
-+++ b/include/sound/asoc.h
-@@ -414,7 +414,7 @@ struct snd_soc_tplg_pcm {
- 	__le32 size;		/* in bytes of this structure */
- 	char pcm_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
- 	char dai_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
--	__le32 pcm_id;		/* unique ID - used to match */
-+	__le32 pcm_id;		/* unique ID - used to match with DAI link */
- 	__le32 dai_id;		/* unique ID - used to match */
- 	__le32 playback;	/* supports playback mode */
- 	__le32 capture;		/* supports capture mode */
-diff --git a/src/topology/pcm.c b/src/topology/pcm.c
-index 1df4f54..1661821 100644
---- a/src/topology/pcm.c
-+++ b/src/topology/pcm.c
-@@ -337,7 +337,7 @@ int tplg_parse_pcm(snd_tplg_t *tplg,
- 
- 	pcm = elem->pcm;
- 	pcm->size = elem->size;
--	elem_copy_text(pcm->dai_name, elem->id, SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
-+	elem_copy_text(pcm->pcm_name, elem->id, SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
- 
- 	tplg_dbg(" PCM: %s\n", elem->id);
- 
-@@ -366,8 +366,8 @@ int tplg_parse_pcm(snd_tplg_t *tplg,
- 			if (snd_config_get_string(n, &val) < 0)
- 				return -EINVAL;
- 
--			pcm->dai_id = atoi(val);
--			tplg_dbg("\t%s: %d\n", id, pcm->dai_id);
-+			pcm->pcm_id = atoi(val);
-+			tplg_dbg("\t%s: %d\n", id, pcm->pcm_id);
- 			continue;
- 		}
- 
--- 
-2.5.5
-
-From 25d6f8e6a8e162259dcf84600496dc8ebd8196e7 Mon Sep 17 00:00:00 2001
-From: Mengdong Lin <mengdong.lin@linux.intel.com>
-Date: Fri, 29 Apr 2016 11:03:37 +0800
-Subject: [PATCH 20/34] topology: Parse front-end DAI name and ID for the PCM
-
-These two fields are necessary to create the front-end DAIs
-in kernel but the support is missing in text conf previously.
-
-Signed-off-by: Mengdong Lin <mengdong.lin@linux.intel.com>
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
----
- include/topology.h |  4 ++++
- src/topology/pcm.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++
- 2 files changed, 57 insertions(+)
-
-diff --git a/include/topology.h b/include/topology.h
-index b47f422..9d57ce3 100644
---- a/include/topology.h
-+++ b/include/topology.h
-@@ -533,6 +533,10 @@ extern "C" {
-  *
-  *	id "0"				# used for binding to the PCM
-  *
-+ *	dai."name of front-end DAI" {
-+ *		id "0"		# used for binding to the front-end DAI
-+ *	}
-+ *
-  *	pcm."playback" {
-  *		capabilities "capabilities1"	# capabilities for playback
-  *
-diff --git a/src/topology/pcm.c b/src/topology/pcm.c
-index 1661821..efee58b 100644
---- a/src/topology/pcm.c
-+++ b/src/topology/pcm.c
-@@ -320,6 +320,51 @@ static int tplg_parse_streams(snd_tplg_t *tplg, snd_config_t *cfg,
- 	return 0;
- }
- 
-+/* Parse name and id of a front-end DAI (ie. cpu dai of a FE DAI link) */
-+static int tplg_parse_fe_dai(snd_tplg_t *tplg, snd_config_t *cfg,
-+	void *private)
-+{
-+	struct tplg_elem *elem = private;
-+	struct snd_soc_tplg_pcm *pcm = elem->pcm;
-+	snd_config_iterator_t i, next;
-+	snd_config_t *n;
-+	const char *id, *value = NULL;
-+	unsigned long int id_val;
-+	int err;
-+
-+	snd_config_get_id(cfg, &id);
-+	tplg_dbg("\t\tFE DAI %s:\n", id);
-+	elem_copy_text(pcm->dai_name, id, SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
-+
-+	snd_config_for_each(i, next, cfg) {
-+
-+		n = snd_config_iterator_entry(i);
-+
-+		/* get id */
-+		if (snd_config_get_id(n, &id) < 0)
-+			continue;
-+
-+		if (strcmp(id, "id") == 0) {
-+			if (snd_config_get_string(n, &value) < 0)
-+				continue;
-+			errno = 0;
-+			/* no support for negative value */
-+			id_val = strtoul(value, NULL, 0);
-+			if ((errno == ERANGE && id_val == ULONG_MAX)
-+				|| (errno != 0 && id_val == 0)
-+				|| id_val > UINT_MAX) {
-+				SNDERR("error: invalid fe dai ID\n");
-+				return -EINVAL;
-+			}
-+
-+			pcm->dai_id = (int) id_val;
-+			tplg_dbg("\t\t\tindex: %d\n", pcm->dai_id);
-+		}
-+	}
-+
-+	return 0;
-+}
-+
- /* Parse pcm (for front end DAI & DAI link) */
- int tplg_parse_pcm(snd_tplg_t *tplg,
- 	snd_config_t *cfg, void *private ATTRIBUTE_UNUSED)
-@@ -378,6 +423,14 @@ int tplg_parse_pcm(snd_tplg_t *tplg,
- 				return err;
- 			continue;
- 		}
-+
-+		if (strcmp(id, "dai") == 0) {
-+			err = tplg_parse_compound(tplg, n,
-+				tplg_parse_fe_dai, elem);
-+			if (err < 0)
-+				return err;
-+			continue;
-+		}
- 	}
- 
- 	return 0;
--- 
-2.5.5
-
-From 76af5bf833323d8ae1caa23d592a959e74990932 Mon Sep 17 00:00:00 2001
-From: Mengdong Lin <mengdong.lin@linux.intel.com>
-Date: Fri, 29 Apr 2016 11:03:45 +0800
-Subject: [PATCH 21/34] topology: Update PCM configurations in Broadwell text
- conf file
-
-To make this conf file a better example, update the name & ID of PCMs
-(front-end DAI link) and their cpu DAI (front-end DAI), same as those
-defined by Broadwell upstream driver.
-
-Signed-off-by: Mengdong Lin <mengdong.lin@linux.intel.com>
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
----
- src/conf/topology/broadwell/broadwell.conf | 34 ++++++++++++++++++++++--------
- 1 file changed, 25 insertions(+), 9 deletions(-)
-
-diff --git a/src/conf/topology/broadwell/broadwell.conf b/src/conf/topology/broadwell/broadwell.conf
-index 05b3889..eb89377 100644
---- a/src/conf/topology/broadwell/broadwell.conf
-+++ b/src/conf/topology/broadwell/broadwell.conf
-@@ -272,18 +272,22 @@ SectionPCMCapabilities."Offload0 Playback" {
- SectionPCMCapabilities."Offload1 Playback" {
- 	formats "S24_LE,S16_LE"
- 	rate_min "8000"
--	rate_max "48000"
-+	rate_max "192000"
- 	channels_min "2"
- 	channels_max "2"
- }
- 
- # PCM devices exported by Firmware
--SectionPCM."System Pin" {
-+SectionPCM."System Playback/Capture" {
- 
- 	index "1"
- 
- 	# used for binding to the PCM
--	ID "0"
-+	id "0"
-+
-+	dai."System Pin" {
-+		id "0"
-+	}
- 
- 	pcm."playback" {
- 
-@@ -307,12 +311,16 @@ SectionPCM."System Pin" {
- 	}
- }
- 
--SectionPCM."Offload0 Pin" {
-+SectionPCM."Offload0 Playback" {
- 
- 	index "1"
- 
- 	# used for binding to the PCM
--	ID "1"
-+	id "1"
-+
-+	dai."Offload0 Pin" {
-+		id "1"
-+	}
- 
- 	pcm."playback" {
- 
-@@ -325,12 +333,16 @@ SectionPCM."Offload0 Pin" {
- 	}
- }
- 
--SectionPCM."Offload1 Pin" {
-+SectionPCM."Offload1 Playback" {
- 
- 	index "1"
- 
- 	# used for binding to the PCM
--	ID "2"
-+	id "2"
-+
-+	dai."Offload1 Pin" {
-+		id "2"
-+	}
- 
- 	pcm."playback" {
- 
-@@ -343,12 +355,16 @@ SectionPCM."Offload1 Pin" {
- 	}
- }
- 
--SectionPCM."Loopback Pin" {
-+SectionPCM."Loopback PCM" {
- 
- 	index "1"
- 
- 	# used for binding to the PCM
--	ID "3"
-+	id "3"
-+
-+	dai."Loopback Pin" {
-+		id "3"
-+	}
- 
- 	pcm."capture" {
- 
--- 
-2.5.5
-
-From 85bf9915989e0a338632739684c75192c1753239 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?J=C3=B6rg=20Krause?= <joerg.krause@embedded.rocks>
-Date: Sun, 8 May 2016 20:48:42 +0200
-Subject: [PATCH 22/34] pcm: softvol: fix conversion of TLVs min_db and max_dB
- value
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Both, min_dB and max_dB, are floating type whereas the TLV is (always)
-unsigned.
-
-The problem with the conversion of a negative floating-point number into an
-unsigned integer is, that the behavior is undefined. This may, depending on
-the platform, result in a wrong TLV, i.e. for the default values of min_dB
-(-51dB) and max_dB (0dB), alsactl generates the following state on an ARM
-cpu build with GCC:
-
-	control.1 {
-                iface MIXER
-                name Master
-                value.0 255
-                value.1 255
-                comment {
-                        access 'read write user'
-                        type INTEGER
-                        count 2
-                        range '0 - 255'
-                        tlv '00000001000000080000000000000014'
-                        dbmin 0
-                        dbmax 5100
-                        dbvalue.0 5100
-                        dbvalue.1 5100
-                }
-        }
-
-With the fix applied, alsactl stores the correct TLV:
-
-	control.1 {
-                iface MIXER
-                name Master
-                value.0 255
-                value.1 255
-                comment {
-                        access 'read write user'
-                        type INTEGER
-                        count 2
-                        range '0 - 255'
-                        tlv '0000000100000008ffffec1400000014'
-                        dbmin -5100
-                        dbmax 0
-                        dbvalue.0 0
-                        dbvalue.1 0
-                }
-        }
-
-Also tested for different combinations of min_dB and max_dB other than the
-default values.
-
-Replaces:
-http://mailman.alsa-project.org/pipermail/alsa-devel/2016-May/107733.html
-
-Fixes:
-http://mailman.alsa-project.org/pipermail/alsa-devel/2016-May/107628.html
-
-Cc: Clemens Ladisch <clemens@ladisch.de>
-Signed-off-by: Jörg Krause <joerg.krause@embedded.rocks>
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
----
- src/pcm/pcm_softvol.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/src/pcm/pcm_softvol.c b/src/pcm/pcm_softvol.c
-index 802aa4b..5492db8 100644
---- a/src/pcm/pcm_softvol.c
-+++ b/src/pcm/pcm_softvol.c
-@@ -658,8 +658,8 @@ static int add_tlv_info(snd_pcm_softvol_t *svol, snd_ctl_elem_info_t *cinfo)
- 	unsigned int tlv[4];
- 	tlv[0] = SND_CTL_TLVT_DB_SCALE;
- 	tlv[1] = 2 * sizeof(int);
--	tlv[2] = svol->min_dB * 100;
--	tlv[3] = (svol->max_dB - svol->min_dB) * 100 / svol->max_val;
-+	tlv[2] = (int)(svol->min_dB * 100);
-+	tlv[3] = (int)((svol->max_dB - svol->min_dB) * 100 / svol->max_val);
- 	return snd_ctl_elem_tlv_write(svol->ctl, &cinfo->id, tlv);
- }
- 
--- 
-2.5.5
-
-From a192f52fc63a86e1fbb9a09adb0bc2a6bbc8dab1 Mon Sep 17 00:00:00 2001
-From: Enric Balletbo i Serra <enric.balletbo@collabora.com>
-Date: Thu, 5 May 2016 08:32:06 +0200
-Subject: [PATCH 23/34] conf/ucm: ROCKCHIP-I2S: add Rockchip I2S UCM config.
-
-Taken from the ChromeOS sources, this configuration was tested on Veyron
-Jerry based Chromebook from Google.
-
-[Added missing Makefile changes by tiwai]
-
-Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
----
- configure.ac                                |  1 +
- src/conf/ucm/Makefile.am                    |  2 +-
- src/conf/ucm/ROCKCHIP-I2S/HiFi.conf         | 94 +++++++++++++++++++++++++++++
- src/conf/ucm/ROCKCHIP-I2S/Makefile.am       |  4 ++
- src/conf/ucm/ROCKCHIP-I2S/ROCKCHIP-I2S.conf |  6 ++
- 5 files changed, 106 insertions(+), 1 deletion(-)
- create mode 100644 src/conf/ucm/ROCKCHIP-I2S/HiFi.conf
- create mode 100644 src/conf/ucm/ROCKCHIP-I2S/Makefile.am
- create mode 100644 src/conf/ucm/ROCKCHIP-I2S/ROCKCHIP-I2S.conf
-
-diff --git a/configure.ac b/configure.ac
-index 28fcd24..ff340a8 100644
---- a/configure.ac
-+++ b/configure.ac
-@@ -658,6 +658,7 @@ AC_OUTPUT(Makefile doc/Makefile doc/pictures/Makefile doc/doxygen.cfg \
- 	  src/conf/ucm/PAZ00/Makefile \
- 	  src/conf/ucm/GoogleNyan/Makefile \
- 	  src/conf/ucm/broadwell-rt286/Makefile \
-+	  src/conf/ucm/ROCKCHIP-I2S/Makefile \
- 	  src/conf/topology/Makefile \
- 	  src/conf/topology/broadwell/Makefile \
- 	  modules/Makefile modules/mixer/Makefile modules/mixer/simple/Makefile \
-diff --git a/src/conf/ucm/Makefile.am b/src/conf/ucm/Makefile.am
-index e6a6325..d1d51e5 100644
---- a/src/conf/ucm/Makefile.am
-+++ b/src/conf/ucm/Makefile.am
-@@ -1 +1 @@
--SUBDIRS=DAISY-I2S PandaBoard PandaBoardES SDP4430 tegraalc5632 PAZ00 GoogleNyan broadwell-rt286
-+SUBDIRS=DAISY-I2S PandaBoard PandaBoardES SDP4430 tegraalc5632 PAZ00 GoogleNyan broadwell-rt286 ROCKCHIP-I2S
-diff --git a/src/conf/ucm/ROCKCHIP-I2S/HiFi.conf b/src/conf/ucm/ROCKCHIP-I2S/HiFi.conf
-new file mode 100644
-index 0000000..7bfe995
---- /dev/null
-+++ b/src/conf/ucm/ROCKCHIP-I2S/HiFi.conf
-@@ -0,0 +1,94 @@
-+SectionVerb {
-+	Value {
-+		OutputDspName "speaker_eq"
-+		MinBufferLevel "512"
-+	}
-+
-+	EnableSequence [
-+		cdev "hw:ROCKCHIPI2S"
-+
-+		cset "name='Left Speaker Mixer Left DAC Switch' on"
-+		cset "name='Right Speaker Mixer Right DAC Switch' on"
-+		cset "name='Headphone Left Switch' off"
-+		cset "name='Headphone Right Switch' off"
-+		cset "name='Digital EQ 3 Band Switch' off"
-+		cset "name='Digital EQ 5 Band Switch' off"
-+		cset "name='Digital EQ 7 Band Switch' off"
-+		cset "name='Biquad Switch' off"
-+		cset "name='Filter Mode' Music"
-+		cset "name='ADC Oversampling Rate' 0"
-+
-+		cset "name='DMIC Mux' DMIC"
-+		cset "name='MIC2 Mux' IN34"
-+		cset "name='Right ADC Mixer MIC2 Switch' on"
-+		cset "name='Left ADC Mixer MIC2 Switch' on"
-+		cset "name='MIC2 Volume' 20"
-+		cset "name='Headset Mic Switch' off"
-+		cset "name='Int Mic Switch' on"
-+
-+		cset "name='ADCR Boost Volume' 4"
-+		cset "name='ADCL Boost Volume' 4"
-+		cset "name='ADCR Volume' 11"
-+		cset "name='ADCL Volume' 11"
-+
-+		cset "name='Left Speaker Mixer Left DAC Switch' on"
-+		cset "name='Right Speaker Mixer Right DAC Switch' on"
-+		cset "name='Speaker Left Mixer Volume' 2"
-+		cset "name='Speaker Right Mixer Volume' 2"
-+		cset "name='Record Path DC Blocking' on"
-+		cset "name='Playback Path DC Blocking' on"
-+
-+		cset "name='Speaker Left Switch' on"
-+		cset "name='Speaker Right Switch' on"
-+		cset "name='Speaker Switch' on"
-+	]
-+
-+	DisableSequence [
-+	]
-+}
-+
-+SectionDevice."Headphone".0 {
-+	Value {
-+		JackName "ROCKCHIP-I2S Headset Jack"
-+		OutputDspName ""
-+	}
-+
-+	EnableSequence [
-+		cdev "hw:ROCKCHIPI2S"
-+
-+		cset "name='Speaker Switch' off"
-+		cset "name='Headphone Left Switch' on"
-+		cset "name='Headphone Right Switch' on"
-+	]
-+	DisableSequence [
-+		cdev "hw:ROCKCHIPI2S"
-+
-+		cset "name='Headphone Left Switch' off"
-+		cset "name='Headphone Right Switch' off"
-+		cset "name='Speaker Switch' on"
-+	]
-+}
-+
-+SectionDevice."Mic".0 {
-+	Value {
-+		JackName "ROCKCHIP-I2S Headset Jack"
-+	}
-+
-+	EnableSequence [
-+		cdev "hw:ROCKCHIPI2S"
-+
-+		cset "name='Int Mic Switch' off"
-+		cset "name='DMIC Mux' ADC"
-+		cset "name='Headset Mic Switch' on"
-+		cset "name='Record Path DC Blocking' on"
-+	]
-+
-+	DisableSequence [
-+		cdev "hw:ROCKCHIPI2S"
-+
-+		cset "name='Headset Mic Switch' off"
-+		cset "name='DMIC Mux' DMIC"
-+		cset "name='Int Mic Switch' on"
-+		cset "name='Record Path DC Blocking' off"
-+	]
-+}
-diff --git a/src/conf/ucm/ROCKCHIP-I2S/Makefile.am b/src/conf/ucm/ROCKCHIP-I2S/Makefile.am
-new file mode 100644
-index 0000000..485a740
---- /dev/null
-+++ b/src/conf/ucm/ROCKCHIP-I2S/Makefile.am
-@@ -0,0 +1,4 @@
-+alsaconfigdir = @ALSA_CONFIG_DIR@
-+ucmdir = $(alsaconfigdir)/ucm/ROCKCHIP-I2S
-+ucm_DATA = ROCKCHIP-I2S.conf HiFi.conf
-+EXTRA_DIST = $(ucm_DATA)
-diff --git a/src/conf/ucm/ROCKCHIP-I2S/ROCKCHIP-I2S.conf b/src/conf/ucm/ROCKCHIP-I2S/ROCKCHIP-I2S.conf
-new file mode 100644
-index 0000000..0c399b0
---- /dev/null
-+++ b/src/conf/ucm/ROCKCHIP-I2S/ROCKCHIP-I2S.conf
-@@ -0,0 +1,6 @@
-+Comment "Rockchip card"
-+
-+SectionUseCase."HiFi" {
-+	File "HiFi.conf"
-+	Comment "Default"
-+}
--- 
-2.5.5
-
-From c14b0a08f0bf58e4f62307c68f8ff0137b4dec19 Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Wed, 11 May 2016 09:06:47 +0200
-Subject: [PATCH 24/34] pcm: Fix suspend/resume regression with dmix & co
-
-The recent fix commit [8985742d91db: pcm: dmix: Handle slave PCM xrun
-and unexpected states properly] caused a regression in dmix and other
-plugins regarding suspend/resume.  For example, aplay endlessly prints
-"Suspended. Trying resume. Done." message if suspend and resume are
-performed in the middle of playback.
-
-The reason is that the commit above changed the shadow PCM state
-(dmix->state) to SUSPENDED when the slave PCM is in suspend, while it
-doesn't restore the shadow state upon resume.  Thus it appears as if
-it's always suspended even after the resume is invoked.
-
-The fix is just to add the proper update of the shadow state in
-snd_pcm_direct_resume().
-
-Reported-by: Shengjiu Wang <shengjiu.wang@freescale.com>
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
----
- src/pcm/pcm_direct.c | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/src/pcm/pcm_direct.c b/src/pcm/pcm_direct.c
-index 14de734..e28738b 100644
---- a/src/pcm/pcm_direct.c
-+++ b/src/pcm/pcm_direct.c
-@@ -848,6 +848,7 @@ int snd_pcm_direct_resume(snd_pcm_t *pcm)
- 		snd_pcm_start(dmix->spcm);
- 		err = 0;
- 	}
-+	dmix->state = snd_pcm_state(dmix->spcm);
- 	snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT);
- 	return err;
- }
--- 
-2.5.5
-
-From 5610b356b5f110f7f8e586f56e5b74e0f0c2db38 Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Wed, 11 May 2016 13:06:25 +0200
-Subject: [PATCH 25/34] pcm: dmix: Fix doubly resume of slave PCM
-
-The dmix plugin and co may trigger the resume for each instance in
-snd_pcm_direct_resume().  It means that the slave PCM gets resumed or
-re-prepared/started by each opened dmix stream, and this may end up
-with the doubly triggers even though the slave PCM has been already
-resumed by another dmix stream.
-
-For avoiding this conflicts, check the slave PCM state and resume only
-when it's still in the suspended state.  Meanwhile we keep the shadow
-state updated no matter whether the slave was triggered or not.
-
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
----
- src/pcm/pcm_direct.c | 7 +++++++
- 1 file changed, 7 insertions(+)
-
-diff --git a/src/pcm/pcm_direct.c b/src/pcm/pcm_direct.c
-index e28738b..ac082f1 100644
---- a/src/pcm/pcm_direct.c
-+++ b/src/pcm/pcm_direct.c
-@@ -841,6 +841,12 @@ int snd_pcm_direct_resume(snd_pcm_t *pcm)
- 	int err;
- 	
- 	snd_pcm_direct_semaphore_down(dmix, DIRECT_IPC_SEM_CLIENT);
-+	/* resume only when the slave PCM is still in suspended state */
-+	if (snd_pcm_state(dmix->spcm) != SND_PCM_STATE_SUSPENDED) {
-+		err = 0;
-+		goto out;
-+	}
-+
- 	err = snd_pcm_resume(dmix->spcm);
- 	if (err == -ENOSYS) {
- 		/* FIXME: error handling? */
-@@ -848,6 +854,7 @@ int snd_pcm_direct_resume(snd_pcm_t *pcm)
- 		snd_pcm_start(dmix->spcm);
- 		err = 0;
- 	}
-+ out:
- 	dmix->state = snd_pcm_state(dmix->spcm);
- 	snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT);
- 	return err;
--- 
-2.5.5
-
-From 8cdbdae73109c901aec4984f6ba65e5b25722f13 Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Thu, 12 May 2016 16:30:44 +0200
-Subject: [PATCH 26/34] namehint: Don't enumerate as duplex if only a single
- direction is defined
-
-When a hint description has only either device_input or device_output,
-we shouldn't handle it as a full duplex but rather a single
-direction.  In that way, we can avoid to list up a playback stream
-like dmix or surround51 as a capture stream in the namehint.
-
-Reported-by: Trent Reed <treed0803@gmail.com>
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
----
- src/control/namehint.c | 10 ++++++++--
- 1 file changed, 8 insertions(+), 2 deletions(-)
-
-diff --git a/src/control/namehint.c b/src/control/namehint.c
-index 856957c..ad8dda3 100644
---- a/src/control/namehint.c
-+++ b/src/control/namehint.c
-@@ -28,6 +28,7 @@
- #include "local.h"
- 
- #ifndef DOC_HIDDEN
-+#define DEV_SKIP	9999 /* some non-existing device number */
- struct hint_list {
- 	char **list;
- 	unsigned int count;
-@@ -90,7 +91,7 @@ static int get_dev_name1(struct hint_list *list, char **res, int device,
- 			 int stream)
- {
- 	*res = NULL;
--	if (device < 0)
-+	if (device < 0 || device == DEV_SKIP)
- 		return 0;
- 	switch (list->iface) {
- #ifdef BUILD_HWDEP
-@@ -317,7 +318,9 @@ static int try_config(snd_config_t *config,
- 				err = -EINVAL;
- 				goto __cleanup;
- 			}
--			list->device_output = -1;
-+			/* skip the counterpart if only a single direction is defined */
-+			if (list->device_output < 0)
-+				list->device_output = DEV_SKIP;
- 		}
- 		if (snd_config_search(cfg, "device_output", &n) >= 0) {
- 			if (snd_config_get_integer(n, &list->device_output) < 0) {
-@@ -325,6 +328,9 @@ static int try_config(snd_config_t *config,
- 				err = -EINVAL;
- 				goto __cleanup;
- 			}
-+			/* skip the counterpart if only a single direction is defined */
-+			if (list->device_input < 0)
-+				list->device_input = DEV_SKIP;
- 		}
- 	} else if (level == 1 && !list->show_all)
- 		goto __skip_add;
--- 
-2.5.5
-
-From 5fb3fe17249c3fffb8b8e15108ff72f27ba5e81c Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Thu, 12 May 2016 16:33:19 +0200
-Subject: [PATCH 27/34] pcm: Define namehint for single directional PCM types
-
-The PCM namehint for some PCM types like dmix, dsnoop and surround51
-should be defined as single directional.
-
-Reported-by: Trent Reed <treed0803@gmail.com>
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
----
- src/conf/pcm/dmix.conf       | 2 +-
- src/conf/pcm/dsnoop.conf     | 2 +-
- src/conf/pcm/surround21.conf | 2 +-
- src/conf/pcm/surround40.conf | 2 +-
- src/conf/pcm/surround41.conf | 2 +-
- src/conf/pcm/surround50.conf | 2 +-
- src/conf/pcm/surround51.conf | 2 +-
- src/conf/pcm/surround71.conf | 2 +-
- 8 files changed, 8 insertions(+), 8 deletions(-)
-
-diff --git a/src/conf/pcm/dmix.conf b/src/conf/pcm/dmix.conf
-index e62cb29..7d0aa01 100644
---- a/src/conf/pcm/dmix.conf
-+++ b/src/conf/pcm/dmix.conf
-@@ -110,6 +110,6 @@ pcm.!dmix {
- 			name defaults.namehint.extended
- 		}
- 		description "Direct sample mixing device"
--		device $DEV
-+		device_output $DEV
- 	}
- }
-diff --git a/src/conf/pcm/dsnoop.conf b/src/conf/pcm/dsnoop.conf
-index 49cfca9..abbd44f 100644
---- a/src/conf/pcm/dsnoop.conf
-+++ b/src/conf/pcm/dsnoop.conf
-@@ -110,6 +110,6 @@ pcm.!dsnoop {
- 			name defaults.namehint.extended
- 		}
- 		description "Direct sample snooping device"
--		device $DEV
-+		device_input $DEV
- 	}
- }
-diff --git a/src/conf/pcm/surround21.conf b/src/conf/pcm/surround21.conf
-index 7f4676b..1cf1b7a 100644
---- a/src/conf/pcm/surround21.conf
-+++ b/src/conf/pcm/surround21.conf
-@@ -56,6 +56,6 @@ pcm.!surround21 {
- 	ttable.2.LFE 1
- 	hint {
- 		description "2.1 Surround output to Front and Subwoofer speakers"
--		device $DEV
-+		device_output $DEV
- 	}
- }
-diff --git a/src/conf/pcm/surround40.conf b/src/conf/pcm/surround40.conf
-index 361ccaa..9788ad4 100644
---- a/src/conf/pcm/surround40.conf
-+++ b/src/conf/pcm/surround40.conf
-@@ -54,6 +54,6 @@ pcm.!surround40 {
- 	}
- 	hint {
- 		description "4.0 Surround output to Front and Rear speakers"
--		device $DEV
-+		device_output $DEV
- 	}
- }
-diff --git a/src/conf/pcm/surround41.conf b/src/conf/pcm/surround41.conf
-index 2f82381..7b4ef3b 100644
---- a/src/conf/pcm/surround41.conf
-+++ b/src/conf/pcm/surround41.conf
-@@ -60,6 +60,6 @@ pcm.!surround41 {
- 	ttable.4.LFE 1
- 	hint {
- 		description "4.1 Surround output to Front, Rear and Subwoofer speakers"
--		device $DEV
-+		device_output $DEV
- 	}
- }
-diff --git a/src/conf/pcm/surround50.conf b/src/conf/pcm/surround50.conf
-index dc95c17..7d9a9e7 100644
---- a/src/conf/pcm/surround50.conf
-+++ b/src/conf/pcm/surround50.conf
-@@ -60,6 +60,6 @@ pcm.!surround50 {
- 	ttable.4.FC 1
- 	hint {
- 		description "5.0 Surround output to Front, Center and Rear speakers"
--		device $DEV
-+		device_output $DEV
- 	}
- }
-diff --git a/src/conf/pcm/surround51.conf b/src/conf/pcm/surround51.conf
-index 3a7543f..e67f007 100644
---- a/src/conf/pcm/surround51.conf
-+++ b/src/conf/pcm/surround51.conf
-@@ -56,6 +56,6 @@ pcm.!surround51 {
- 	}
- 	hint {
- 		description "5.1 Surround output to Front, Center, Rear and Subwoofer speakers"
--		device $DEV
-+		device_output $DEV
- 	}
- }
-diff --git a/src/conf/pcm/surround71.conf b/src/conf/pcm/surround71.conf
-index 076a97d..a26c3f3 100644
---- a/src/conf/pcm/surround71.conf
-+++ b/src/conf/pcm/surround71.conf
-@@ -58,6 +58,6 @@ pcm.!surround71 {
- 	}
- 	hint {
- 		description "7.1 Surround output to Front, Center, Side, Rear and Woofer speakers"
--		device $DEV
-+		device_output $DEV
- 	}
- }
--- 
-2.5.5
-
-From c9a0d7d601e8ab069f8745968c03c8470b24d20d Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Tue, 17 May 2016 15:39:07 +0200
-Subject: [PATCH 28/34] conf: Add thread-safe global tree reference
-
-Most of open functions in alsa-lib have the call pattern:
-  snd_config_update();
-  return snd_xxx_open(x, snd_config, ...);
-
-This means that the toplevel config gets updated, and passed to a
-local open function.  Although snd_config_update() itself has a
-pthread mutex to be thread safe, the whole procedure above isn't
-thread safe.  Namely, the global snd_config tree may be deleted and
-recreated at any time while the open function is being processed.
-This may lead to a data corruption and crash of the program.
-
-For avoiding the corruption, this patch introduces a refcount to
-config tree object.  A few new helper functions are introduced as
-well:
-- snd_config_update_ref() does update and take the refcount of the
-  toplevel tree.   The obtained config tree has to be freed via
-  snd_config_unref() below.
-- snd_config_ref() and snd_config_unref() manage the refcount of the
-  config object.  The latter eventually deletes the object when all
-  references are gone.
-
-Along with these additions, the caller of snd_config_update() and
-snd_config global tree in alsa-lib are replaced with the new helpers.
-
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
----
- include/conf.h          |  4 +++
- src/conf.c              | 79 +++++++++++++++++++++++++++++++++++++++++++++++++
- src/control/control.c   |  8 +++--
- src/hwdep/hwdep.c       |  8 +++--
- src/pcm/pcm.c           |  8 +++--
- src/rawmidi/rawmidi.c   |  8 +++--
- src/seq/seq.c           |  8 +++--
- src/timer/timer.c       |  8 +++--
- src/timer/timer_query.c |  8 +++--
- 9 files changed, 125 insertions(+), 14 deletions(-)
-
-diff --git a/include/conf.h b/include/conf.h
-index 087c05d..5d293d5 100644
---- a/include/conf.h
-+++ b/include/conf.h
-@@ -94,6 +94,10 @@ int snd_config_update_r(snd_config_t **top, snd_config_update_t **update, const
- int snd_config_update_free(snd_config_update_t *update);
- int snd_config_update_free_global(void);
- 
-+int snd_config_update_ref(snd_config_t **top);
-+void snd_config_ref(snd_config_t *top);
-+void snd_config_unref(snd_config_t *top);
-+
- int snd_config_search(snd_config_t *config, const char *key,
- 		      snd_config_t **result);
- int snd_config_searchv(snd_config_t *config, 
-diff --git a/src/conf.c b/src/conf.c
-index f8b7a66..a516611 100644
---- a/src/conf.c
-+++ b/src/conf.c
-@@ -434,6 +434,7 @@ static pthread_once_t snd_config_update_mutex_once = PTHREAD_ONCE_INIT;
- struct _snd_config {
- 	char *id;
- 	snd_config_type_t type;
-+	int refcount; /* default = 0 */
- 	union {
- 		long integer;
- 		long long integer64;
-@@ -1825,6 +1826,10 @@ int snd_config_remove(snd_config_t *config)
-  * If the node is a compound node, its descendants (the whole subtree)
-  * are deleted recursively.
-  *
-+ * The function is supposed to be called only for locally copied config
-+ * trees.  For the global tree, take the reference via #snd_config_update_ref
-+ * and free it via #snd_config_unref.
-+ *
-  * \par Conforming to:
-  * LSB 3.2
-  *
-@@ -1833,6 +1838,10 @@ int snd_config_remove(snd_config_t *config)
- int snd_config_delete(snd_config_t *config)
- {
- 	assert(config);
-+	if (config->refcount > 0) {
-+		config->refcount--;
-+		return 0;
-+	}
- 	switch (config->type) {
- 	case SND_CONFIG_TYPE_COMPOUND:
- 	{
-@@ -3833,6 +3842,8 @@ int snd_config_update_r(snd_config_t **_top, snd_config_update_t **_update, cons
-  * \warning Whenever #snd_config is updated, all string pointers and
-  * configuration node handles previously obtained from it may become
-  * invalid.
-+ * For safer operations, use #snd_config_update_ref and release the config
-+ * via #snd_config_unref.
-  *
-  * \par Errors:
-  * Any errors encountered when parsing the input or returned by hooks or
-@@ -3851,6 +3862,74 @@ int snd_config_update(void)
- 	return err;
- }
- 
-+/**
-+ * \brief Updates #snd_config and takes its reference.
-+ * \return 0 if #snd_config was up to date, 1 if #snd_config was
-+ *         updated, otherwise a negative error code.
-+ *
-+ * Unlike #snd_config_update, this function increases a reference counter
-+ * so that the obtained tree won't be deleted until unreferenced by
-+ * #snd_config_unref.
-+ *
-+ * This function is supposed to be thread-safe.
-+ */
-+int snd_config_update_ref(snd_config_t **top)
-+{
-+	int err;
-+
-+	if (top)
-+		*top = NULL;
-+	snd_config_lock();
-+	err = snd_config_update_r(&snd_config, &snd_config_global_update, NULL);
-+	if (err >= 0) {
-+		if (snd_config) {
-+			if (top) {
-+				snd_config->refcount++;
-+				*top = snd_config;
-+			}
-+		} else {
-+			err = -ENODEV;
-+		}
-+	}
-+	snd_config_unlock();
-+	return err;
-+}
-+
-+/**
-+ * \brief Take the reference of the config tree.
-+ *
-+ * Increases a reference counter of the given config tree.
-+ *
-+ * This function is supposed to be thread-safe.
-+ */
-+void snd_config_ref(snd_config_t *cfg)
-+{
-+	snd_config_lock();
-+	if (cfg)
-+		cfg->refcount++;
-+	snd_config_unlock();
-+}
-+
-+/**
-+ * \brief Unreference the config tree.
-+ *
-+ * Decreases a reference counter of the given config tree, and eventually
-+ * deletes the tree if all references are gone.  This is the counterpart of
-+ * #snd_config_unref.
-+ *
-+ * Also, the config taken via #snd_config_update_ref must be unreferenced
-+ * by this function, too.
-+ *
-+ * This function is supposed to be thread-safe.
-+ */
-+void snd_config_unref(snd_config_t *cfg)
-+{
-+	snd_config_lock();
-+	if (cfg)
-+		snd_config_delete(cfg);
-+	snd_config_unlock();
-+}
-+
- /** 
-  * \brief Frees a private update structure.
-  * \param[in] update The private update structure to free.
-diff --git a/src/control/control.c b/src/control/control.c
-index 8a5d530..ae78843 100644
---- a/src/control/control.c
-+++ b/src/control/control.c
-@@ -968,12 +968,16 @@ static int snd_ctl_open_noupdate(snd_ctl_t **ctlp, snd_config_t *root, const cha
-  */
- int snd_ctl_open(snd_ctl_t **ctlp, const char *name, int mode)
- {
-+	snd_config_t *top;
- 	int err;
-+
- 	assert(ctlp && name);
--	err = snd_config_update();
-+	err = snd_config_update_ref(&top);
- 	if (err < 0)
- 		return err;
--	return snd_ctl_open_noupdate(ctlp, snd_config, name, mode);
-+	err = snd_ctl_open_noupdate(ctlp, top, name, mode);
-+	snd_config_unref(top);
-+	return err;
- }
- 
- /**
-diff --git a/src/hwdep/hwdep.c b/src/hwdep/hwdep.c
-index 5dc791c..bac634b 100644
---- a/src/hwdep/hwdep.c
-+++ b/src/hwdep/hwdep.c
-@@ -168,12 +168,16 @@ static int snd_hwdep_open_noupdate(snd_hwdep_t **hwdep, snd_config_t *root, cons
-  */
- int snd_hwdep_open(snd_hwdep_t **hwdep, const char *name, int mode)
- {
-+	snd_config_t *top;
- 	int err;
-+
- 	assert(hwdep && name);
--	err = snd_config_update();
-+	err = snd_config_update_ref(&top);
- 	if (err < 0)
- 		return err;
--	return snd_hwdep_open_noupdate(hwdep, snd_config, name, mode);
-+	err = snd_hwdep_open_noupdate(hwdep, top, name, mode);
-+	snd_config_unref(top);
-+	return err;
- }
- 
- /**
-diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c
-index 203e7a5..0d0d093 100644
---- a/src/pcm/pcm.c
-+++ b/src/pcm/pcm.c
-@@ -2288,12 +2288,16 @@ static int snd_pcm_open_noupdate(snd_pcm_t **pcmp, snd_config_t *root,
- int snd_pcm_open(snd_pcm_t **pcmp, const char *name, 
- 		 snd_pcm_stream_t stream, int mode)
- {
-+	snd_config_t *top;
- 	int err;
-+
- 	assert(pcmp && name);
--	err = snd_config_update();
-+	err = snd_config_update_ref(&top);
- 	if (err < 0)
- 		return err;
--	return snd_pcm_open_noupdate(pcmp, snd_config, name, stream, mode, 0);
-+	err = snd_pcm_open_noupdate(pcmp, top, name, stream, mode, 0);
-+	snd_config_unref(top);
-+	return err;
- }
- 
- /**
-diff --git a/src/rawmidi/rawmidi.c b/src/rawmidi/rawmidi.c
-index 0c89b8b..4701b43 100644
---- a/src/rawmidi/rawmidi.c
-+++ b/src/rawmidi/rawmidi.c
-@@ -305,12 +305,16 @@ static int snd_rawmidi_open_noupdate(snd_rawmidi_t **inputp, snd_rawmidi_t **out
- int snd_rawmidi_open(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp,
- 		     const char *name, int mode)
- {
-+	snd_config_t *top;
- 	int err;
-+
- 	assert((inputp || outputp) && name);
--	err = snd_config_update();
-+	err = snd_config_update_ref(&top);
- 	if (err < 0)
- 		return err;
--	return snd_rawmidi_open_noupdate(inputp, outputp, snd_config, name, mode);
-+	err = snd_rawmidi_open_noupdate(inputp, outputp, top, name, mode);
-+	snd_config_unref(top);
-+	return err;
- }
- 
- /**
-diff --git a/src/seq/seq.c b/src/seq/seq.c
-index 4405e68..9279830 100644
---- a/src/seq/seq.c
-+++ b/src/seq/seq.c
-@@ -974,12 +974,16 @@ static int snd_seq_open_noupdate(snd_seq_t **seqp, snd_config_t *root,
- int snd_seq_open(snd_seq_t **seqp, const char *name, 
- 		 int streams, int mode)
- {
-+	snd_config_t *top;
- 	int err;
-+
- 	assert(seqp && name);
--	err = snd_config_update();
-+	err = snd_config_update_ref(&top);
- 	if (err < 0)
- 		return err;
--	return snd_seq_open_noupdate(seqp, snd_config, name, streams, mode, 0);
-+	err = snd_seq_open_noupdate(seqp, top, name, streams, mode, 0);
-+	snd_config_unref(top);
-+	return err;
- }
- 
- /**
-diff --git a/src/timer/timer.c b/src/timer/timer.c
-index a25e4f7..b253471 100644
---- a/src/timer/timer.c
-+++ b/src/timer/timer.c
-@@ -201,12 +201,16 @@ static int snd_timer_open_noupdate(snd_timer_t **timer, snd_config_t *root, cons
-  */
- int snd_timer_open(snd_timer_t **timer, const char *name, int mode)
- {
-+	snd_config_t *top;
- 	int err;
-+
- 	assert(timer && name);
--	err = snd_config_update();
-+	err = snd_config_update_ref(&top);
- 	if (err < 0)
- 		return err;
--	return snd_timer_open_noupdate(timer, snd_config, name, mode);
-+	err = snd_timer_open_noupdate(timer, top, name, mode);
-+	snd_config_unref(top);
-+	return err;
- }
- 
- /**
-diff --git a/src/timer/timer_query.c b/src/timer/timer_query.c
-index 93d2455..2072cea 100644
---- a/src/timer/timer_query.c
-+++ b/src/timer/timer_query.c
-@@ -159,12 +159,16 @@ static int snd_timer_query_open_noupdate(snd_timer_query_t **timer, snd_config_t
-  */
- int snd_timer_query_open(snd_timer_query_t **timer, const char *name, int mode)
- {
-+	snd_config_t *top;
- 	int err;
-+
- 	assert(timer && name);
--	err = snd_config_update();
-+	err = snd_config_update_ref(&top);
- 	if (err < 0)
- 		return err;
--	return snd_timer_query_open_noupdate(timer, snd_config, name, mode);
-+	err = snd_timer_query_open_noupdate(timer, top, name, mode);
-+	snd_config_unref(top);
-+	return err;
- }
- 
- /**
--- 
-2.5.5
-
-From d942498bfbd315c4c4559ccd573685e09aa03383 Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Wed, 18 May 2016 10:38:27 +0200
-Subject: [PATCH 29/34] pcm: Remove resume support from dmix & co
-
-PCM dmix and other plugins inherit the resume behavior from the slave
-PCM.  However, the resume on dmix can't work reliably even if the
-slave PCM may do resume.  The running state of each dmix stream is
-individual and may be PREPARED or RUN_PENDING while the slave PCM is
-already in RUNNING.  And, when the slave PCM is resumed, the whole
-samples that have been already mapped are also played back, even if
-the corresponding dmix stream is still in SUSPENDED.  Such
-inconsistencies can't be avoided as long as we manage each stream
-individually.
-
-That said, dmix & co can't provide the proper resume support "by
-design".  For aligning with it, we should drop the whole resume code
-and clear the PCM SND_PCM_INFO_RESUME flag.
-
-Reported-by: Shengjiu Wang <shengjiu.wang@nxp.com>
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
----
- src/pcm/pcm_direct.c | 24 ++----------------------
- 1 file changed, 2 insertions(+), 22 deletions(-)
-
-diff --git a/src/pcm/pcm_direct.c b/src/pcm/pcm_direct.c
-index ac082f1..53c4992 100644
---- a/src/pcm/pcm_direct.c
-+++ b/src/pcm/pcm_direct.c
-@@ -837,27 +837,7 @@ int snd_pcm_direct_prepare(snd_pcm_t *pcm)
- 
- int snd_pcm_direct_resume(snd_pcm_t *pcm)
- {
--	snd_pcm_direct_t *dmix = pcm->private_data;
--	int err;
--	
--	snd_pcm_direct_semaphore_down(dmix, DIRECT_IPC_SEM_CLIENT);
--	/* resume only when the slave PCM is still in suspended state */
--	if (snd_pcm_state(dmix->spcm) != SND_PCM_STATE_SUSPENDED) {
--		err = 0;
--		goto out;
--	}
--
--	err = snd_pcm_resume(dmix->spcm);
--	if (err == -ENOSYS) {
--		/* FIXME: error handling? */
--		snd_pcm_prepare(dmix->spcm);
--		snd_pcm_start(dmix->spcm);
--		err = 0;
--	}
-- out:
--	dmix->state = snd_pcm_state(dmix->spcm);
--	snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT);
--	return err;
-+	return -ENOSYS;
- }
- 
- #define COPY_SLAVE(field) (dmix->shmptr->s.field = spcm->field)
-@@ -865,7 +845,7 @@ int snd_pcm_direct_resume(snd_pcm_t *pcm)
- /* copy the slave setting */
- static void save_slave_setting(snd_pcm_direct_t *dmix, snd_pcm_t *spcm)
- {
--	spcm->info &= ~SND_PCM_INFO_PAUSE;
-+	spcm->info &= ~(SND_PCM_INFO_PAUSE | SND_PCM_INFO_RESUME);
- 
- 	COPY_SLAVE(access);
- 	COPY_SLAVE(format);
--- 
-2.5.5
-
-From 2fa36eb03c000560128f7abce701536546b4a618 Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Sat, 28 May 2016 10:37:26 +0200
-Subject: [PATCH 30/34] pcm: Fix secondary retry in dsnoop and dshare
-
-The commit [fdba9e1bad8f: pcm: Fallback open as the first instance for
-dmix & co] introduced a mechanism to retry the open of slave PCM for
-the secondary streams, but this also introduced a regression in dsnoop
-and dshare plugins: since the retry goto-tag was placed at a wrong
-position, it retries to re-fetch the shm unnecessarily and eventually
-leads to the fatal error.
-
-The bug can be easily reproduced by starting arecord and killing it
-via SIGKILL, then starting arecord again.  The second arecord fails.
-
-The fix is obviously to move the wrong retry goto-tags to the right
-positions.
-
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
----
- src/pcm/pcm_dshare.c | 2 +-
- src/pcm/pcm_dsnoop.c | 2 +-
- 2 files changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/src/pcm/pcm_dshare.c b/src/pcm/pcm_dshare.c
-index adb3587..05854de 100644
---- a/src/pcm/pcm_dshare.c
-+++ b/src/pcm/pcm_dshare.c
-@@ -690,7 +690,6 @@ int snd_pcm_dshare_open(snd_pcm_t **pcmp, const char *name,
- 		break;
- 	}
- 
-- retry:
- 	first_instance = ret = snd_pcm_direct_shm_create_or_connect(dshare);
- 	if (ret < 0) {
- 		SNDERR("unable to create IPC shm instance");
-@@ -705,6 +704,7 @@ int snd_pcm_dshare_open(snd_pcm_t **pcmp, const char *name,
- 	dshare->max_periods = opts->max_periods;
- 	dshare->sync_ptr = snd_pcm_dshare_sync_ptr;
- 
-+ retry:
- 	if (first_instance) {
- 		/* recursion is already checked in
- 		   snd_pcm_direct_get_slave_ipc_offset() */
-diff --git a/src/pcm/pcm_dsnoop.c b/src/pcm/pcm_dsnoop.c
-index 8ff0ba5..2d45171 100644
---- a/src/pcm/pcm_dsnoop.c
-+++ b/src/pcm/pcm_dsnoop.c
-@@ -583,7 +583,6 @@ int snd_pcm_dsnoop_open(snd_pcm_t **pcmp, const char *name,
- 		break;
- 	}
- 		
-- retry:
- 	first_instance = ret = snd_pcm_direct_shm_create_or_connect(dsnoop);
- 	if (ret < 0) {
- 		SNDERR("unable to create IPC shm instance");
-@@ -598,6 +597,7 @@ int snd_pcm_dsnoop_open(snd_pcm_t **pcmp, const char *name,
- 	dsnoop->max_periods = opts->max_periods;
- 	dsnoop->sync_ptr = snd_pcm_dsnoop_sync_ptr;
- 
-+ retry:
- 	if (first_instance) {
- 		/* recursion is already checked in
- 		   snd_pcm_direct_get_slave_ipc_offset() */
--- 
-2.5.5
-
-From 6d1d620eadf32c6d963468ce56ff52cc3a2f32e2 Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Wed, 25 May 2016 15:03:51 +0200
-Subject: [PATCH 31/34] pcm: dmix: resume workaround for buggy driver
-
-The previous commit removed the whole handling of resume in dmix, but
-this seems causing another regression; some buggy drivers assume that
-the device-resume needs to be triggered before transitioning to
-PREPARED state.  As an ugly workaround, in this patch, when the slave
-PCM supports resume, snd_pcm_direct_resume() does resume of the slave
-PCM but immediately drop the stream after that.  In that way, the
-device is brought to the sane active state, then the apps can prepare
-and restart the stream properly.
-
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
----
- src/pcm/pcm_direct.c | 25 ++++++++++++++++++++++++-
- 1 file changed, 24 insertions(+), 1 deletion(-)
-
-diff --git a/src/pcm/pcm_direct.c b/src/pcm/pcm_direct.c
-index 53c4992..343fd3c 100644
---- a/src/pcm/pcm_direct.c
-+++ b/src/pcm/pcm_direct.c
-@@ -837,6 +837,27 @@ int snd_pcm_direct_prepare(snd_pcm_t *pcm)
- 
- int snd_pcm_direct_resume(snd_pcm_t *pcm)
- {
-+	snd_pcm_direct_t *dmix = pcm->private_data;
-+	snd_pcm_t *spcm = dmix->spcm;
-+
-+	snd_pcm_direct_semaphore_down(dmix, DIRECT_IPC_SEM_CLIENT);
-+	/* some buggy drivers require the device resumed before prepared;
-+	 * when a device has RESUME flag and is in SUSPENDED state, resume
-+	 * here but immediately drop to bring it to a sane active state.
-+	 */
-+	if ((spcm->info & SND_PCM_INFO_RESUME) &&
-+	    snd_pcm_state(spcm) == SND_PCM_STATE_SUSPENDED) {
-+		snd_pcm_resume(spcm);
-+		snd_pcm_drop(spcm);
-+		snd_pcm_direct_timer_stop(dmix);
-+		snd_pcm_direct_clear_timer_queue(dmix);
-+		snd_pcm_areas_silence(snd_pcm_mmap_areas(spcm), 0,
-+				      spcm->channels, spcm->buffer_size,
-+				      spcm->format);
-+		snd_pcm_prepare(spcm);
-+		snd_pcm_start(spcm);
-+	}
-+	snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT);
- 	return -ENOSYS;
- }
- 
-@@ -845,7 +866,7 @@ int snd_pcm_direct_resume(snd_pcm_t *pcm)
- /* copy the slave setting */
- static void save_slave_setting(snd_pcm_direct_t *dmix, snd_pcm_t *spcm)
- {
--	spcm->info &= ~(SND_PCM_INFO_PAUSE | SND_PCM_INFO_RESUME);
-+	spcm->info &= ~SND_PCM_INFO_PAUSE;
- 
- 	COPY_SLAVE(access);
- 	COPY_SLAVE(format);
-@@ -874,6 +895,8 @@ static void save_slave_setting(snd_pcm_direct_t *dmix, snd_pcm_t *spcm)
- 	COPY_SLAVE(buffer_time);
- 	COPY_SLAVE(sample_bits);
- 	COPY_SLAVE(frame_bits);
-+
-+	dmix->shmptr->s.info &= ~SND_PCM_INFO_RESUME;
- }
- 
- #undef COPY_SLAVE
--- 
-2.5.5
-
-From 8feb96ed9b457c2aa62ddea2c48651475b7c3411 Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Tue, 31 May 2016 12:46:03 +0200
-Subject: [PATCH 32/34] pcm: dmix: Prepare slave when it's in SETUP, too
-
-SETUP is an unusual state, but it's still possible.
-
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
----
- src/pcm/pcm_direct.c | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/src/pcm/pcm_direct.c b/src/pcm/pcm_direct.c
-index 343fd3c..fbf9a59 100644
---- a/src/pcm/pcm_direct.c
-+++ b/src/pcm/pcm_direct.c
-@@ -819,6 +819,7 @@ int snd_pcm_direct_prepare(snd_pcm_t *pcm)
- 	int err;
- 
- 	switch (snd_pcm_state(dmix->spcm)) {
-+	case SND_PCM_STATE_SETUP:
- 	case SND_PCM_STATE_XRUN:
- 	case SND_PCM_STATE_SUSPENDED:
- 	case SND_PCM_STATE_DISCONNECTED:
--- 
-2.5.5
-
-From 614ce73d3d6eba13946f863bec24981d355902e1 Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Tue, 31 May 2016 12:48:40 +0200
-Subject: [PATCH 33/34] pcm: dmix: Return error when slave is in OPEN or
- DISCONNECTED
-
-A slave PCM in OPEN or DISCONNECTED state can't be used properly at
-all, so the best option is to return -EBADFD error.
-
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
----
- src/pcm/pcm_direct.c | 4 +++-
- 1 file changed, 3 insertions(+), 1 deletion(-)
-
-diff --git a/src/pcm/pcm_direct.c b/src/pcm/pcm_direct.c
-index fbf9a59..21f98e7 100644
---- a/src/pcm/pcm_direct.c
-+++ b/src/pcm/pcm_direct.c
-@@ -822,12 +822,14 @@ int snd_pcm_direct_prepare(snd_pcm_t *pcm)
- 	case SND_PCM_STATE_SETUP:
- 	case SND_PCM_STATE_XRUN:
- 	case SND_PCM_STATE_SUSPENDED:
--	case SND_PCM_STATE_DISCONNECTED:
- 		err = snd_pcm_prepare(dmix->spcm);
- 		if (err < 0)
- 			return err;
- 		snd_pcm_start(dmix->spcm);
- 		break;
-+	case SND_PCM_STATE_OPEN:
-+	case SND_PCM_STATE_DISCONNECTED:
-+		return -EBADFD;
- 	}
- 	snd_pcm_direct_check_interleave(dmix, pcm);
- 	dmix->state = SND_PCM_STATE_PREPARED;
--- 
-2.5.5
-
-From d39e1879b9c72d51fe1ca4aeb5ba742e97b2175a Mon Sep 17 00:00:00 2001
-From: Eliot Miranda <eliot.miranda@gmail.com>
-Date: Wed, 1 Jun 2016 08:16:31 +0200
-Subject: [PATCH 34/34] async: Handle previously installed signal handler
-
-The issue is with the signal handler installed and deinstalled in
-alsa-lib async handler.  This code makes no attempt to remember any
-previously installed signal handlers for SIGIO, if SIGIO is used.
-Consequently it does not call any previous handlers from its own
-handler once installed, and does not reinstall any previous handler
-when deinstalling its handler.  Consequently, use of also-lib within
-applications that depend on SIGIO will break those applications,
-rendering them inoperative once alsa-lib is running because their
-signal handlers are no longer called.
-
-This patch does remember and restore any previous handler, and chains
-calls to the handler if it exists.
-
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
----
- src/async.c | 20 +++++++++++++-------
- 1 file changed, 13 insertions(+), 7 deletions(-)
-
-diff --git a/src/async.c b/src/async.c
-index 98aec78..0e133c3 100644
---- a/src/async.c
-+++ b/src/async.c
-@@ -28,6 +28,9 @@
- #include "control/control_local.h"
- #include <signal.h>
- 
-+static struct sigaction previous_action;
-+#define MAX_SIG_FUNCTION_CODE 10 /* i.e. SIG_DFL SIG_IGN SIG_HOLD et al */
-+
- #ifdef SND_ASYNC_RT_SIGNAL
- /** async signal number */
- static int snd_async_signo;
-@@ -54,6 +57,9 @@ static void snd_async_handler(int signo ATTRIBUTE_UNUSED, siginfo_t *siginfo, vo
- 	int fd;
- 	struct list_head *i;
- 	//assert(siginfo->si_code == SI_SIGIO);
-+	if (signo == SIGIO
-+	 && (unsigned long)(previous_action.sa_sigaction) > MAX_SIG_FUNCTION_CODE)
-+		previous_action.sa_sigaction(signo, siginfo, context);
- 	fd = siginfo->si_fd;
- 	list_for_each(i, &snd_async_handlers) {
- 		snd_async_handler_t *h = list_entry(i, snd_async_handler_t, glist);
-@@ -114,7 +120,8 @@ int snd_async_add_handler(snd_async_handler_t **handler, int fd,
- 		act.sa_flags = SA_RESTART | SA_SIGINFO;
- 		act.sa_sigaction = snd_async_handler;
- 		sigemptyset(&act.sa_mask);
--		err = sigaction(snd_async_signo, &act, NULL);
-+		assert(!previous_action.sa_sigaction);
-+		err = sigaction(snd_async_signo, &act, &previous_action);
- 		if (err < 0) {
- 			SYSERR("sigaction");
- 			return -errno;
-@@ -131,18 +138,17 @@ int snd_async_add_handler(snd_async_handler_t **handler, int fd,
- int snd_async_del_handler(snd_async_handler_t *handler)
- {
- 	int err = 0;
-+	int was_empty = list_empty(&snd_async_handlers);
- 	assert(handler);
- 	list_del(&handler->glist);
--	if (list_empty(&snd_async_handlers)) {
--		struct sigaction act;
--		memset(&act, 0, sizeof(act));
--		act.sa_flags = 0;
--		act.sa_handler = SIG_DFL;
--		err = sigaction(snd_async_signo, &act, NULL);
-+	if (!was_empty
-+	 && list_empty(&snd_async_handlers)) {
-+		err = sigaction(snd_async_signo, &previous_action, NULL);
- 		if (err < 0) {
- 			SYSERR("sigaction");
- 			return -errno;
- 		}
-+		memset(&previous_action, 0, sizeof(previous_action));
- 	}
- 	if (handler->type == SND_ASYNC_HANDLER_GENERIC)
- 		goto _end;
--- 
-2.5.5
-
diff --git a/SOURCES/alsa-lib-1.1.3-post.patch b/SOURCES/alsa-lib-1.1.3-post.patch
new file mode 100644
index 0000000..d0f5fc8
--- /dev/null
+++ b/SOURCES/alsa-lib-1.1.3-post.patch
@@ -0,0 +1,3874 @@
+From 6ad2a9763d9aaab30c0470d039877b1bb61dda3b Mon Sep 17 00:00:00 2001
+From: Mengdong Lin <mengdong.lin@linux.intel.com>
+Date: Tue, 27 Dec 2016 18:08:58 +0800
+Subject: [PATCH 01/37] ucm: Add ATTRIBUTE_UNUSED for unused parameters of
+ execute_component_seq()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+To fix the following warnings:
+
+main.c: In function ‘execute_component_seq’:
+main.c:489:24: warning: unused parameter ‘value_list1’ [-Wunused-parameter]
+      struct list_head *value_list1,
+                        ^
+main.c:490:24: warning: unused parameter ‘value_list2’ [-Wunused-parameter]
+      struct list_head *value_list2,
+                        ^
+main.c:491:24: warning: unused parameter ‘value_list3’ [-Wunused-parameter]
+      struct list_head *value_list3,
+                        ^
+
+Signed-off-by: Mengdong Lin <mengdong.lin@linux.intel.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+---
+ src/ucm/main.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/src/ucm/main.c b/src/ucm/main.c
+index 750e65d..38a5e81 100644
+--- a/src/ucm/main.c
++++ b/src/ucm/main.c
+@@ -486,9 +486,9 @@ static int execute_sequence(snd_use_case_mgr_t *uc_mgr,
+  */
+ static int execute_component_seq(snd_use_case_mgr_t *uc_mgr,
+ 				 struct component_sequence *cmpt_seq,
+-				 struct list_head *value_list1,
+-				 struct list_head *value_list2,
+-				 struct list_head *value_list3,
++				 struct list_head *value_list1 ATTRIBUTE_UNUSED,
++				 struct list_head *value_list2 ATTRIBUTE_UNUSED,
++				 struct list_head *value_list3 ATTRIBUTE_UNUSED,
+ 				 char *cdev)
+ {
+ 	struct use_case_device *device = cmpt_seq->device;
+-- 
+2.9.3
+
+
+From 9ed4075f05a4242f32331f7f2c365767970f5003 Mon Sep 17 00:00:00 2001
+From: Gustavo Zacarias <gustavo@zacarias.com.ar>
+Date: Wed, 21 Dec 2016 19:46:34 -0300
+Subject: [PATCH 02/37] ucm: parser needs limits.h
+
+It's using PATH_MAX which is defined there, otherwise the build fails on
+musl libc.
+
+Signed-off-by: Gustavo Zacarias <gustavo@zacarias.com.ar>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+---
+ src/ucm/parser.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/src/ucm/parser.c b/src/ucm/parser.c
+index c98373a..f520abc 100644
+--- a/src/ucm/parser.c
++++ b/src/ucm/parser.c
+@@ -32,6 +32,7 @@
+ 
+ #include "ucm_local.h"
+ #include <dirent.h>
++#include <limits.h>
+ 
+ /** The name of the environment variable containing the UCM directory */
+ #define ALSA_CONFIG_UCM_VAR "ALSA_CONFIG_UCM"
+-- 
+2.9.3
+
+
+From 0a61c796810fcec8b386e5311e871b1744b45a67 Mon Sep 17 00:00:00 2001
+From: Joshua Frkuska <joshua_frkuska@mentor.com>
+Date: Fri, 30 Dec 2016 11:56:15 +0530
+Subject: [PATCH 03/37] pcm: direct: allow users to configure different period
+ sizes
+
+This patch allows the effective period size to be a multiple of the
+slave-pcm period size.
+Allowing only exact multiple of original period size is achieved by
+borrowing code from the kernel hwrules implementation.
+
+This patch is intended to save cpu workload when for example, the
+slave operates with very small periods but a user does not need that
+small periods.
+
+This feature is enabled by default and can be disabled by adding
+config option 'var_periodsize 0'.
+
+Signed-off-by: Alexander Jahn <ajahn@de.adit-jv.com>
+Signed-off-by: Andreas Pape <apape@de.adit-jv.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+---
+ src/pcm/pcm_direct.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++------
+ src/pcm/pcm_direct.h |  3 ++
+ src/pcm/pcm_dmix.c   |  1 +
+ src/pcm/pcm_dshare.c |  1 +
+ src/pcm/pcm_dsnoop.c |  1 +
+ 5 files changed, 84 insertions(+), 10 deletions(-)
+
+diff --git a/src/pcm/pcm_direct.c b/src/pcm/pcm_direct.c
+index 6434983..f5d922f 100644
+--- a/src/pcm/pcm_direct.c
++++ b/src/pcm/pcm_direct.c
+@@ -660,6 +660,29 @@ static int hw_param_interval_refine_minmax(snd_pcm_hw_params_t *params,
+ 	return hw_param_interval_refine_one(params, var, &t);
+ }
+ 
++/* this code is used 'as-is' from the alsa kernel code */
++static int snd_interval_step(struct snd_interval *i, unsigned int min,
++			     unsigned int step)
++{
++	unsigned int n;
++	int changed = 0;
++	n = (i->min - min) % step;
++	if (n != 0 || i->openmin) {
++		i->min += step - n;
++		changed = 1;
++	}
++	n = (i->max - min) % step;
++	if (n != 0 || i->openmax) {
++		i->max -= n;
++		changed = 1;
++	}
++	if (snd_interval_checkempty(i)) {
++		i->empty = 1;
++		return -EINVAL;
++	}
++	return changed;
++}
++
+ #undef REFINE_DEBUG
+ 
+ int snd_pcm_direct_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
+@@ -710,15 +733,16 @@ int snd_pcm_direct_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
+ 					   &dshare->shmptr->hw.rate);
+ 	if (err < 0)
+ 		return err;
+-	err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_PERIOD_SIZE,
+-					   &dshare->shmptr->hw.period_size);
+-	if (err < 0)
+-		return err;
+-	err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_PERIOD_TIME,
+-					   &dshare->shmptr->hw.period_time);
+-	if (err < 0)
+-		return err;
++
+ 	if (dshare->max_periods < 0) {
++		err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_PERIOD_SIZE,
++						   &dshare->shmptr->hw.period_size);
++		if (err < 0)
++			return err;
++		err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_PERIOD_TIME,
++						   &dshare->shmptr->hw.period_time);
++		if (err < 0)
++			return err;
+ 		err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_BUFFER_SIZE,
+ 						   &dshare->shmptr->hw.buffer_size);
+ 		if (err < 0)
+@@ -730,11 +754,38 @@ int snd_pcm_direct_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
+ 	} else if (params->rmask & ((1<<SND_PCM_HW_PARAM_PERIODS)|
+ 				    (1<<SND_PCM_HW_PARAM_BUFFER_BYTES)|
+ 				    (1<<SND_PCM_HW_PARAM_BUFFER_SIZE)|
+-				    (1<<SND_PCM_HW_PARAM_BUFFER_TIME))) {
++				    (1<<SND_PCM_HW_PARAM_BUFFER_TIME)|
++				    (1<<SND_PCM_HW_PARAM_PERIOD_TIME)|
++				    (1<<SND_PCM_HW_PARAM_PERIOD_SIZE)|
++				    (1<<SND_PCM_HW_PARAM_PERIOD_BYTES))) {
++		snd_interval_t period_size = dshare->shmptr->hw.period_size;
++		snd_interval_t period_time = dshare->shmptr->hw.period_time;
+ 		int changed;
+ 		unsigned int max_periods = dshare->max_periods;
+ 		if (max_periods < 2)
+ 			max_periods = dshare->slave_buffer_size / dshare->slave_period_size;
++
++		/* make sure buffer size does not exceed slave buffer size */
++		err = hw_param_interval_refine_minmax(params, SND_PCM_HW_PARAM_BUFFER_SIZE,
++					2 * dshare->slave_period_size, dshare->slave_buffer_size);
++		if (err < 0)
++			return err;
++		if (dshare->var_periodsize) {
++			/* more tolerant settings... */
++			if (dshare->shmptr->hw.buffer_size.max / 2 > period_size.max)
++				period_size.max = dshare->shmptr->hw.buffer_size.max / 2;
++			if (dshare->shmptr->hw.buffer_time.max / 2 > period_time.max)
++				period_time.max = dshare->shmptr->hw.buffer_time.max / 2;
++		}
++
++		err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_PERIOD_SIZE,
++						   &period_size);
++		if (err < 0)
++			return err;
++		err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_PERIOD_TIME,
++						   &period_time);
++		if (err < 0)
++			return err;
+ 		do {
+ 			changed = 0;
+ 			err = hw_param_interval_refine_minmax(params, SND_PCM_HW_PARAM_PERIODS,
+@@ -746,8 +797,16 @@ int snd_pcm_direct_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
+ 			if (err < 0)
+ 				return err;
+ 			changed |= err;
++			err = snd_interval_step(hw_param_interval(params, SND_PCM_HW_PARAM_PERIOD_SIZE),
++								0, dshare->slave_period_size);
++			if (err < 0)
++				return err;
++			changed |= err;
++			if (err)
++				params->rmask |= (1 << SND_PCM_HW_PARAM_PERIOD_SIZE);
+ 		} while (changed);
+ 	}
++	dshare->timer_ticks = hw_param_interval(params, SND_PCM_HW_PARAM_PERIOD_SIZE)->max / dshare->slave_period_size;
+ 	params->info = dshare->shmptr->s.info;
+ #ifdef REFINE_DEBUG
+ 	snd_output_puts(log, "DMIX REFINE (end):\n");
+@@ -1183,6 +1242,7 @@ int snd_pcm_direct_initialize_poll_fd(snd_pcm_direct_t *dmix)
+ 
+ 	dmix->tread = 1;
+ 	dmix->timer_need_poll = 0;
++	dmix->timer_ticks = 1;
+ 	ret = snd_pcm_info(dmix->spcm, &info);
+ 	if (ret < 0) {
+ 		SNDERR("unable to info for slave pcm");
+@@ -1366,7 +1426,7 @@ int snd_pcm_direct_set_timer_params(snd_pcm_direct_t *dmix)
+ 	snd_timer_params_set_auto_start(&params, 1);
+ 	if (dmix->type != SND_PCM_TYPE_DSNOOP)
+ 		snd_timer_params_set_early_event(&params, 1);
+-	snd_timer_params_set_ticks(&params, 1);
++	snd_timer_params_set_ticks(&params, dmix->timer_ticks);
+ 	if (dmix->tread) {
+ 		filter = (1<<SND_TIMER_EVENT_TICK) |
+ 			 dmix->timer_events;
+@@ -1656,6 +1716,7 @@ int snd_pcm_direct_parse_open_conf(snd_config_t *root, snd_config_t *conf,
+ 	rec->ipc_gid = -1;
+ 	rec->slowptr = 1;
+ 	rec->max_periods = 0;
++	rec->var_periodsize = 1;
+ 
+ 	/* read defaults */
+ 	if (snd_config_search(root, "defaults.pcm.dmix_max_periods", &n) >= 0) {
+@@ -1762,6 +1823,13 @@ int snd_pcm_direct_parse_open_conf(snd_config_t *root, snd_config_t *conf,
+ 			rec->max_periods = val;
+ 			continue;
+ 		}
++		if (strcmp(id, "var_periodsize") == 0) {
++			err = snd_config_get_bool(n);
++			if (err < 0)
++				return err;
++			rec->var_periodsize = err;
++			continue;
++		}
+ 		SNDERR("Unknown field %s", id);
+ 		return -EINVAL;
+ 	}
+diff --git a/src/pcm/pcm_direct.h b/src/pcm/pcm_direct.h
+index 611ad29..91e816c 100644
+--- a/src/pcm/pcm_direct.h
++++ b/src/pcm/pcm_direct.h
+@@ -147,12 +147,14 @@ struct snd_pcm_direct {
+ 	int tread: 1;
+ 	int timer_need_poll: 1;
+ 	unsigned int timer_events;
++	unsigned int timer_ticks;
+ 	int server_fd;
+ 	pid_t server_pid;
+ 	snd_timer_t *timer; 		/* timer used as poll_fd */
+ 	int interleaved;	 	/* we have interleaved buffer */
+ 	int slowptr;			/* use slow but more precise ptr updates */
+ 	int max_periods;		/* max periods (-1 = fixed periods, 0 = max buffer size) */
++	int var_periodsize;		/* allow variable period size if max_periods is != -1*/
+ 	unsigned int channels;		/* client's channels */
+ 	unsigned int *bindings;
+ 	union {
+@@ -326,6 +328,7 @@ struct snd_pcm_direct_open_conf {
+ 	int ipc_gid;
+ 	int slowptr;
+ 	int max_periods;
++	int var_periodsize;
+ 	snd_config_t *slave;
+ 	snd_config_t *bindings;
+ };
+diff --git a/src/pcm/pcm_dmix.c b/src/pcm/pcm_dmix.c
+index 825677f..0ab7323 100644
+--- a/src/pcm/pcm_dmix.c
++++ b/src/pcm/pcm_dmix.c
+@@ -1040,6 +1040,7 @@ int snd_pcm_dmix_open(snd_pcm_t **pcmp, const char *name,
+ 	dmix->state = SND_PCM_STATE_OPEN;
+ 	dmix->slowptr = opts->slowptr;
+ 	dmix->max_periods = opts->max_periods;
++	dmix->var_periodsize = opts->var_periodsize;
+ 	dmix->sync_ptr = snd_pcm_dmix_sync_ptr;
+ 
+  retry:
+diff --git a/src/pcm/pcm_dshare.c b/src/pcm/pcm_dshare.c
+index 29cd6c6..a1fed5d 100644
+--- a/src/pcm/pcm_dshare.c
++++ b/src/pcm/pcm_dshare.c
+@@ -725,6 +725,7 @@ int snd_pcm_dshare_open(snd_pcm_t **pcmp, const char *name,
+ 	dshare->state = SND_PCM_STATE_OPEN;
+ 	dshare->slowptr = opts->slowptr;
+ 	dshare->max_periods = opts->max_periods;
++	dshare->var_periodsize = opts->var_periodsize;
+ 	dshare->sync_ptr = snd_pcm_dshare_sync_ptr;
+ 
+  retry:
+diff --git a/src/pcm/pcm_dsnoop.c b/src/pcm/pcm_dsnoop.c
+index 1aedf3c..85f0ff4 100644
+--- a/src/pcm/pcm_dsnoop.c
++++ b/src/pcm/pcm_dsnoop.c
+@@ -606,6 +606,7 @@ int snd_pcm_dsnoop_open(snd_pcm_t **pcmp, const char *name,
+ 	dsnoop->state = SND_PCM_STATE_OPEN;
+ 	dsnoop->slowptr = opts->slowptr;
+ 	dsnoop->max_periods = opts->max_periods;
++	dsnoop->var_periodsize = opts->var_periodsize;
+ 	dsnoop->sync_ptr = snd_pcm_dsnoop_sync_ptr;
+ 
+  retry:
+-- 
+2.9.3
+
+
+From 8eeee1ab7d7db3110b7b3bb31cfb989304dced94 Mon Sep 17 00:00:00 2001
+From: Alexander Jahn <ajahn@de.adit-jv.com>
+Date: Fri, 30 Dec 2016 11:59:11 +0530
+Subject: [PATCH 04/37] pcm: dshare: enable silence
+
+This issue depends on system load - if the process using dshare is
+scheduled fast enough, then there is no noise. A delay of e.g >~2ms
+produces hearable noise.
+
+Reproduction with instrumented aplay(sleep every 100th period for a
+given time):
+During the sleep time of 2000000us (2s) the hardware plays old samples
+in a loop before xrun is detected and recovered after the sleep.
+This is resolved by placing it in silence, in case of dshare plugin.
+
+Signed-off-by: Alexander Jahn <ajahn@de.adit-jv.com>
+Signed-off-by: Andreas Pape <apape@de.adit-jv.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+---
+ src/pcm/pcm_direct.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/src/pcm/pcm_direct.c b/src/pcm/pcm_direct.c
+index f5d922f..0770abc 100644
+--- a/src/pcm/pcm_direct.c
++++ b/src/pcm/pcm_direct.c
+@@ -1161,7 +1161,8 @@ int snd_pcm_direct_initialize_slave(snd_pcm_direct_t *dmix, snd_pcm_t *spcm, str
+ 		return ret;
+ 	}
+ 
+-	if (dmix->type != SND_PCM_TYPE_DMIX)
++	if (dmix->type != SND_PCM_TYPE_DMIX &&
++	    dmix->type != SND_PCM_TYPE_DSHARE)
+ 		goto __skip_silencing;
+ 
+ 	ret = snd_pcm_sw_params_set_silence_threshold(spcm, &sw_params, 0);
+-- 
+2.9.3
+
+
+From 7570e5d77514d8d8af387da04a010fa2ccaf543c Mon Sep 17 00:00:00 2001
+From: "mahendran.k" <mahendran.kuppusamy@in.bosch.com>
+Date: Fri, 30 Dec 2016 11:59:27 +0530
+Subject: [PATCH 05/37] pcm: rate: fix the hw_ptr update until the boundary
+ available
+
+For long time test case, the slave_hw_ptr will exceed the boundary
+and wraparound the slave_hw_ptr. This slave boundary wraparound will
+cause the rate->hw_ptr to wraparound irrespective of the
+rate->boundary availability and due to that the available size goes
+wrong.
+
+Hence, to get the correct available size,
+- Its necessary to increment the rate->hw_ptr upto the rate->boundary
+and then wraparound the rate->hw_ptr.
+- While handling fraction part of slave period, rounded value will be
+introduced by input_frames(). To eliminate rounding issue on
+rate->hw_ptr, subtract last rounded value from rate->hw_ptr and add
+new rounded value of present slave_hw_ptr fraction part to
+rate->hw_ptr.
+
+Signed-off-by: mahendran.k <mahendran.kuppusamy@in.bosch.com>
+Signed-off-by: Mounesh Sutar <mounesh_sutar@mentor.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+---
+ src/pcm/pcm_rate.c | 31 +++++++++++++++++++++++++------
+ 1 file changed, 25 insertions(+), 6 deletions(-)
+
+diff --git a/src/pcm/pcm_rate.c b/src/pcm/pcm_rate.c
+index 1f830dd..61cf979 100644
+--- a/src/pcm/pcm_rate.c
++++ b/src/pcm/pcm_rate.c
+@@ -50,7 +50,7 @@ typedef struct _snd_pcm_rate snd_pcm_rate_t;
+ 
+ struct _snd_pcm_rate {
+ 	snd_pcm_generic_t gen;
+-	snd_pcm_uframes_t appl_ptr, hw_ptr;
++	snd_pcm_uframes_t appl_ptr, hw_ptr, last_slave_hw_ptr;
+ 	snd_pcm_uframes_t last_commit_ptr;
+ 	snd_pcm_uframes_t orig_avail_min;
+ 	snd_pcm_sw_params_t sw_params;
+@@ -563,14 +563,31 @@ static inline void snd_pcm_rate_sync_hwptr0(snd_pcm_t *pcm, snd_pcm_uframes_t sl
+ {
+ 	snd_pcm_rate_t *rate = pcm->private_data;
+ 
++	snd_pcm_sframes_t slave_hw_ptr_diff = slave_hw_ptr - rate->last_slave_hw_ptr;
++	snd_pcm_sframes_t last_slave_hw_ptr_frac;
++
+ 	if (pcm->stream != SND_PCM_STREAM_PLAYBACK)
+ 		return;
+-	/* FIXME: boundary overlap of slave hw_ptr isn't evaluated here!
+-	 *        e.g. if slave rate is small... 
++
++	if (slave_hw_ptr_diff < 0)
++		slave_hw_ptr_diff += rate->gen.slave->boundary; /* slave boundary wraparound */
++	else if (slave_hw_ptr_diff == 0)
++		return;
++	last_slave_hw_ptr_frac = rate->last_slave_hw_ptr % rate->gen.slave->period_size;
++	/* While handling fraction part fo slave period, rounded value will be
++	 * introduced by input_frames().
++	 * To eliminate rounding issue on rate->hw_ptr, subtract last rounded
++	 * value from rate->hw_ptr and add new rounded value of present
++	 * slave_hw_ptr fraction part to rate->hw_ptr. Hence,
++	 * rate->hw_ptr += [ (no. of updated slave periods * pcm rate period size) -
++	 * 	fractional part of last_slave_hw_ptr rounded value +
++	 * 	fractional part of updated slave hw ptr's rounded value ]
+ 	 */
+-	rate->hw_ptr =
+-		(slave_hw_ptr / rate->gen.slave->period_size) * pcm->period_size +
+-		rate->ops.input_frames(rate->obj, slave_hw_ptr % rate->gen.slave->period_size);
++	rate->hw_ptr += (
++			(((last_slave_hw_ptr_frac + slave_hw_ptr_diff) / rate->gen.slave->period_size) * pcm->period_size) -
++			rate->ops.input_frames(rate->obj, last_slave_hw_ptr_frac) +
++			rate->ops.input_frames(rate->obj, (last_slave_hw_ptr_frac + slave_hw_ptr_diff) % rate->gen.slave->period_size));
++	rate->last_slave_hw_ptr = slave_hw_ptr;
+ 
+ 	rate->hw_ptr %= pcm->boundary;
+ }
+@@ -635,6 +652,7 @@ static int snd_pcm_rate_prepare(snd_pcm_t *pcm)
+ 		return err;
+ 	*pcm->hw.ptr = 0;
+ 	*pcm->appl.ptr = 0;
++	rate->last_slave_hw_ptr = 0;
+ 	err = snd_pcm_rate_init(pcm);
+ 	if (err < 0)
+ 		return err;
+@@ -650,6 +668,7 @@ static int snd_pcm_rate_reset(snd_pcm_t *pcm)
+ 		return err;
+ 	*pcm->hw.ptr = 0;
+ 	*pcm->appl.ptr = 0;
++	rate->last_slave_hw_ptr = 0;
+ 	err = snd_pcm_rate_init(pcm);
+ 	if (err < 0)
+ 		return err;
+-- 
+2.9.3
+
+
+From 88e4ae27bb4e47029ed57cc8e02fb1ddf2157fd9 Mon Sep 17 00:00:00 2001
+From: Andreas Pape <apape@de.adit-jv.com>
+Date: Mon, 19 Dec 2016 12:37:50 +0900
+Subject: [PATCH 06/37] plugin: dynamically update avail_min on slave
+
+mmapped capture access on some plugins can fetch data from
+slave in the 'background'. A subsequent snd_pcm_wait waits
+for too long time to reach avail_min threshold again.
+Waiting too long leads to xruns on other devices waiting for
+the capture data.
+As a fix the avail_min on slave is recalculated dynamically.
+
+V2: updated patch to fix within 80 characters per line
+
+Signed-off-by: Andreas Pape <apape@de.adit-jv.com>
+Signed-off-by: Jiada Wang <jiada_wang@mentor.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+---
+ src/pcm/pcm_plugin.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++-
+ 1 file changed, 63 insertions(+), 1 deletion(-)
+
+diff --git a/src/pcm/pcm_plugin.c b/src/pcm/pcm_plugin.c
+index e53c5bb..5b65ac3 100644
+--- a/src/pcm/pcm_plugin.c
++++ b/src/pcm/pcm_plugin.c
+@@ -535,6 +535,68 @@ static int snd_pcm_plugin_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
+ 	return 0;
+ }
+ 
++static int snd_pcm_plugin_may_wait_for_avail_min(snd_pcm_t *pcm,
++						 snd_pcm_uframes_t avail)
++{
++	if (pcm->stream == SND_PCM_STREAM_CAPTURE &&
++	    pcm->access != SND_PCM_ACCESS_RW_INTERLEAVED &&
++	    pcm->access != SND_PCM_ACCESS_RW_NONINTERLEAVED) {
++		/* mmap access on capture device already consumes data from
++		 * slave in avail_update operation. Entering snd_pcm_wait after
++		 * having already consumed some fragments leads to waiting for
++		 * too long time, as slave will unnecessarily wait for avail_min
++		 * condition reached again. To avoid unnecessary wait times we
++		 * adapt the avail_min threshold on slave dynamically. Just
++		 * modifying slave->avail_min as a shortcut and lightweight
++		 * solution does not work for all slave plugin types and in
++		 * addition it will not propagate the change through all
++		 * downstream plugins, so we have to use the sw_params API.
++		 * note: reading fragmental parts from slave will only happen
++		 * in case
++		 * a) the slave can provide contineous hw_ptr between periods
++		 * b) avail_min does not match one slave_period
++		 */
++		snd_pcm_plugin_t *plugin = pcm->private_data;
++		snd_pcm_t *slave = plugin->gen.slave;
++		snd_pcm_uframes_t needed_slave_avail_min;
++		snd_pcm_sframes_t available;
++
++		/* update, as it might have changed. This will also call
++		 * avail_update on slave and also can return error
++		 */
++		available = snd_pcm_avail_update(pcm);
++		if (available < 0)
++			return 0;
++
++		if (available >= pcm->avail_min)
++			/* don't wait at all. As we can't configure avail_min
++			 * of slave to 0 return here
++			 */
++			return 0;
++
++		needed_slave_avail_min = pcm->avail_min - available;
++		if (slave->avail_min != needed_slave_avail_min) {
++			snd_pcm_sw_params_t *swparams;
++			snd_pcm_sw_params_alloca(&swparams);
++			/* pray that changing sw_params while running is
++			 * properly implemented in all downstream plugins...
++			 * it's legal but not commonly used.
++			 */
++			snd_pcm_sw_params_current(slave, swparams);
++			/* snd_pcm_sw_params_set_avail_min() restricts setting
++			 * to >= period size. This conflicts at least with our
++			 * dshare patch which allows combining multiple periods
++			 * or with slaves which return hw postions between
++			 * periods -> set directly in sw_param structure
++			 */
++			swparams->avail_min = needed_slave_avail_min;
++			snd_pcm_sw_params(slave, swparams);
++		}
++		avail = available;
++	}
++	return snd_pcm_generic_may_wait_for_avail_min(pcm, avail);
++}
++
+ const snd_pcm_fast_ops_t snd_pcm_plugin_fast_ops = {
+ 	.status = snd_pcm_plugin_status,
+ 	.state = snd_pcm_generic_state,
+@@ -564,7 +626,7 @@ const snd_pcm_fast_ops_t snd_pcm_plugin_fast_ops = {
+ 	.poll_descriptors_count = snd_pcm_generic_poll_descriptors_count,
+ 	.poll_descriptors = snd_pcm_generic_poll_descriptors,
+ 	.poll_revents = snd_pcm_generic_poll_revents,
+-	.may_wait_for_avail_min = snd_pcm_generic_may_wait_for_avail_min,
++	.may_wait_for_avail_min = snd_pcm_plugin_may_wait_for_avail_min,
+ };
+ 
+ #endif
+-- 
+2.9.3
+
+
+From ff1f669df4b05da3c44dc4a79ce00233fe9de9b7 Mon Sep 17 00:00:00 2001
+From: Andreas Pape <apape@de.adit-jv.com>
+Date: Mon, 19 Dec 2016 12:37:51 +0900
+Subject: [PATCH 07/37] rate: dynamic update avail_min on slave
+
+Signed-off-by: Andreas Pape <apape@de.adit-jv.com>
+Signed-off-by: Jiada Wang <jiada_wang@mentor.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+---
+ src/pcm/pcm_plugin.c | 4 ++--
+ src/pcm/pcm_plugin.h | 3 +++
+ src/pcm/pcm_rate.c   | 2 +-
+ 3 files changed, 6 insertions(+), 3 deletions(-)
+
+diff --git a/src/pcm/pcm_plugin.c b/src/pcm/pcm_plugin.c
+index 5b65ac3..ad4a102 100644
+--- a/src/pcm/pcm_plugin.c
++++ b/src/pcm/pcm_plugin.c
+@@ -535,8 +535,8 @@ static int snd_pcm_plugin_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
+ 	return 0;
+ }
+ 
+-static int snd_pcm_plugin_may_wait_for_avail_min(snd_pcm_t *pcm,
+-						 snd_pcm_uframes_t avail)
++int snd_pcm_plugin_may_wait_for_avail_min(snd_pcm_t *pcm,
++					  snd_pcm_uframes_t avail)
+ {
+ 	if (pcm->stream == SND_PCM_STREAM_CAPTURE &&
+ 	    pcm->access != SND_PCM_ACCESS_RW_INTERLEAVED &&
+diff --git a/src/pcm/pcm_plugin.h b/src/pcm/pcm_plugin.h
+index 217f075..95aacb3 100644
+--- a/src/pcm/pcm_plugin.h
++++ b/src/pcm/pcm_plugin.h
+@@ -50,6 +50,8 @@ typedef struct {
+ /* make local functions really local */
+ #define snd_pcm_plugin_init \
+ 	snd1_pcm_plugin_init
++#define snd_pcm_plugin_may_wait_for_avail_min \
++	snd1_pcm_plugin_may_wait_for_avail_min
+ #define snd_pcm_plugin_fast_ops \
+ 	snd1_pcm_plugin_fast_ops
+ #define snd_pcm_plugin_undo_read_generic \
+@@ -64,6 +66,7 @@ typedef struct {
+ void snd_pcm_plugin_init(snd_pcm_plugin_t *plugin);
+ snd_pcm_sframes_t snd_pcm_plugin_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames);
+ snd_pcm_sframes_t snd_pcm_plugin_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames);
++int snd_pcm_plugin_may_wait_for_avail_min(snd_pcm_t *pcm, snd_pcm_uframes_t avail);
+ 
+ extern const snd_pcm_fast_ops_t snd_pcm_plugin_fast_ops;
+ 
+diff --git a/src/pcm/pcm_rate.c b/src/pcm/pcm_rate.c
+index 61cf979..cbb7618 100644
+--- a/src/pcm/pcm_rate.c
++++ b/src/pcm/pcm_rate.c
+@@ -1213,7 +1213,7 @@ static const snd_pcm_fast_ops_t snd_pcm_rate_fast_ops = {
+ 	.poll_descriptors_count = snd_pcm_generic_poll_descriptors_count,
+ 	.poll_descriptors = snd_pcm_generic_poll_descriptors,
+ 	.poll_revents = snd_pcm_rate_poll_revents,
+-	.may_wait_for_avail_min = snd_pcm_generic_may_wait_for_avail_min,
++	.may_wait_for_avail_min = snd_pcm_plugin_may_wait_for_avail_min,
+ };
+ 
+ static const snd_pcm_ops_t snd_pcm_rate_ops = {
+-- 
+2.9.3
+
+
+From 6f7eaf92e7de73eb32bd97bad83a14fcb0f408f7 Mon Sep 17 00:00:00 2001
+From: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Date: Wed, 30 Nov 2016 00:44:32 +0900
+Subject: [PATCH 08/37] topology: fix unused-const-variable warning
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Last year, unused static const variable was added, then compiler generates
+a below warning.
+
+dapm.c:43:30: warning: ‘widget_control_map’ defined but not used [-Wunused-const-variable=]
+ static const struct map_elem widget_control_map[] = {
+                              ^~~~~~~~~~~~~~~~~~
+
+This commit removes it.
+
+Fixes: 01a0e1a1c219 ("topology: Add DAPM object parser")
+Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Acked-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+---
+ src/topology/dapm.c | 8 --------
+ 1 file changed, 8 deletions(-)
+
+diff --git a/src/topology/dapm.c b/src/topology/dapm.c
+index e830751..8c585a7 100644
+--- a/src/topology/dapm.c
++++ b/src/topology/dapm.c
+@@ -39,14 +39,6 @@ static const struct map_elem widget_map[] = {
+ 	{"dai_link", SND_SOC_TPLG_DAPM_DAI_LINK},
+ };
+ 
+-/* mapping of widget kcontrol text names to types */
+-static const struct map_elem widget_control_map[] = {
+-	{"volsw", SND_SOC_TPLG_DAPM_CTL_VOLSW},
+-	{"enum_double", SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE},
+-	{"enum_virt", SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT},
+-	{"enum_value", SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE},
+-};
+-
+ static int lookup_widget(const char *w)
+ {
+ 	unsigned int i;
+-- 
+2.9.3
+
+
+From 1eddf1f918845d1e6cbcac5516319b20cad80f2f Mon Sep 17 00:00:00 2001
+From: Adam Goode <agoode@google.com>
+Date: Tue, 3 Jan 2017 08:33:42 -0500
+Subject: [PATCH 09/37] seq: improve documentation about new get pid/card
+ functions
+
+Document the technique for determining if the running kernel supports
+the new snd_seq_client_info_get_pid and snd_seq_client_info_get_card
+functions. Also add a little information about how to use these
+functions and add some cross references.
+
+Signed-off-by: Adam Goode <agoode@google.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+---
+ src/seq/seq.c | 44 ++++++++++++++++++++++++++++++++++++++++++--
+ 1 file changed, 42 insertions(+), 2 deletions(-)
+
+diff --git a/src/seq/seq.c b/src/seq/seq.c
+index 9279830..b206e2f 100644
+--- a/src/seq/seq.c
++++ b/src/seq/seq.c
+@@ -1530,7 +1530,25 @@ int snd_seq_client_info_get_error_bounce(const snd_seq_client_info_t *info)
+  * \param info client_info container
+  * \return card number or -1 if value is not available.
+  *
+- * Only available for SND_SEQ_KERNEL_CLIENT clients.
++ * Only available for #SND_SEQ_KERNEL_CLIENT clients.
++ *
++ * The card number can be used to query state about the hardware
++ * device providing this client, by concatenating <code>"hw:CARD="</code>
++ * with the card number and using it as the <code>name</code> parameter
++ * to #snd_ctl_open().
++ *
++ * \note
++ * The return value of -1 is returned for two different conditions: when the
++ * running kernel does not support this operation, and when the client
++ * does not have a hardware card attached. See
++ * #snd_seq_client_info_get_pid() for a way to determine if the
++ * currently running kernel has support for this operation.
++ *
++ * \sa snd_seq_client_info_get_pid(),
++ *     snd_card_get_name(),
++ *     snd_card_get_longname(),
++ *     snd_ctl_open(),
++ *     snd_ctl_card_info()
+  */
+ int snd_seq_client_info_get_card(const snd_seq_client_info_t *info)
+ {
+@@ -1543,7 +1561,29 @@ int snd_seq_client_info_get_card(const snd_seq_client_info_t *info)
+  * \param info client_info container
+  * \return pid or -1 if value is not available.
+  *
+- * Only available for SND_SEQ_USER_CLIENT clients.
++ * Only available for #SND_SEQ_USER_CLIENT clients.
++ *
++ * \note
++ * The functionality for getting a client's PID and getting a
++ * client's card was added to the kernel at the same time, so you can
++ * use this function to determine if the running kernel
++ * supports reporting these values. If your own client has a valid
++ * PID as reported by this function, then the running kernel supports
++ * both #snd_seq_client_info_get_card() and #snd_seq_client_info_get_pid().
++ *
++ * \note
++ * Example code for determining kernel support:
++ * \code
++ *   int is_get_card_or_pid_supported(snd_seq_t *seq)
++ *   {
++ *   	snd_seq_client_info_t *my_client_info;
++ *   	snd_seq_client_info_alloca(&my_client_info);
++ *   	snd_seq_get_client_info(seq, my_client_info);
++ *   	return snd_seq_client_info_get_pid(my_client_info) != -1;
++ *   }
++ * \endcode
++ *
++ * \sa snd_seq_client_info_get_card()
+  */
+ int snd_seq_client_info_get_pid(const snd_seq_client_info_t *info)
+ {
+-- 
+2.9.3
+
+
+From 3f0dc404f16af58d20b4489b0daafcf87555dfb7 Mon Sep 17 00:00:00 2001
+From: Mounesh Sutar <sutar.mounesh@gmail.com>
+Date: Tue, 10 Jan 2017 12:03:17 +0530
+Subject: [PATCH 10/37] pcm: direct: returning semop error code for semaphore
+ up/down failures
+
+Signed-off-by: Mounesh Sutar <sutar.mounesh@gmail.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+---
+ src/pcm/pcm_direct.h | 10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+diff --git a/src/pcm/pcm_direct.h b/src/pcm/pcm_direct.h
+index 91e816c..aee38c5 100644
+--- a/src/pcm/pcm_direct.h
++++ b/src/pcm/pcm_direct.h
+@@ -263,7 +263,10 @@ static inline int snd_pcm_direct_semaphore_down(snd_pcm_direct_t *dmix, int sem_
+ {
+ 	struct sembuf op[2] = { { sem_num, 0, 0 }, { sem_num, 1, SEM_UNDO } };
+ 	int err = semop(dmix->semid, op, 2);
+-	if (err == 0) dmix->locked[sem_num]++;
++	if (err == 0)
++		dmix->locked[sem_num]++;
++	else if (err == -1)
++		err = -errno;
+ 	return err;
+ }
+ 
+@@ -271,7 +274,10 @@ static inline int snd_pcm_direct_semaphore_up(snd_pcm_direct_t *dmix, int sem_nu
+ {
+ 	struct sembuf op = { sem_num, -1, SEM_UNDO | IPC_NOWAIT };
+ 	int err = semop(dmix->semid, &op, 1);
+-	if (err == 0) dmix->locked[sem_num]--;
++	if (err == 0)
++		dmix->locked[sem_num]--;
++	else if (err == -1)
++		err = -errno;
+ 	return err;
+ }
+ 
+-- 
+2.9.3
+
+
+From 1a9bd0f0448106b917ae7f7bedccfcbf6ce84802 Mon Sep 17 00:00:00 2001
+From: Andreas Pape <apape@de.adit-jv.com>
+Date: Tue, 10 Jan 2017 12:03:36 +0530
+Subject: [PATCH 11/37] pcm: direct: Fix for sync issue on xrun recover
+
+If using very short periods, DSHARE/DSNOOP/DMIX may report underruns while in
+status 'prepared'. This prohibits correct recovery. Now slave xrun conditions
+for DSHARE/DSNOOP/DMIX are being handled properly.
+
+Signed-off-by: Andreas Pape <apape@de.adit-jv.com>
+Signed-off-by: Joshua Frkuska <joshua_frkuska@mentor.com>
+Signed-off-by: Mounesh Sutar <mounesh_sutar@mentor.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+---
+ src/pcm/pcm_direct.c | 102 +++++++++++++++++++++++++++++++++++++++++++++++++++
+ src/pcm/pcm_direct.h |   5 ++-
+ src/pcm/pcm_dmix.c   |  27 +++++++++++---
+ src/pcm/pcm_dshare.c |  29 +++++++++++----
+ src/pcm/pcm_dsnoop.c |  15 +++++++-
+ 5 files changed, 162 insertions(+), 16 deletions(-)
+
+diff --git a/src/pcm/pcm_direct.c b/src/pcm/pcm_direct.c
+index 0770abc..a512dd2 100644
+--- a/src/pcm/pcm_direct.c
++++ b/src/pcm/pcm_direct.c
+@@ -550,6 +550,101 @@ int snd_pcm_direct_timer_stop(snd_pcm_direct_t *dmix)
+ 	return 0;
+ }
+ 
++/*
++ * Recover slave on XRUN.
++ * Even if direct plugins disable xrun detection, there might be an xrun
++ * raised directly by some drivers.
++ * The first client recovers slave pcm.
++ * Each client needs to execute sw xrun handling afterwards
++ */
++int snd_pcm_direct_slave_recover(snd_pcm_direct_t *direct)
++{
++	int ret;
++	int semerr;
++
++	semerr = snd_pcm_direct_semaphore_down(direct,
++						   DIRECT_IPC_SEM_CLIENT);
++	if (semerr < 0) {
++		SNDERR("SEMDOWN FAILED with err %d", semerr);
++		return semerr;
++	}
++
++	if (snd_pcm_state(direct->spcm) != SND_PCM_STATE_XRUN) {
++		/* ignore... someone else already did recovery */
++		semerr = snd_pcm_direct_semaphore_up(direct,
++						     DIRECT_IPC_SEM_CLIENT);
++		if (semerr < 0) {
++			SNDERR("SEMUP FAILED with err %d", semerr);
++			return semerr;
++		}
++		return 0;
++	}
++
++	ret = snd_pcm_prepare(direct->spcm);
++	if (ret < 0) {
++		SNDERR("recover: unable to prepare slave");
++		semerr = snd_pcm_direct_semaphore_up(direct,
++						     DIRECT_IPC_SEM_CLIENT);
++		if (semerr < 0) {
++			SNDERR("SEMUP FAILED with err %d", semerr);
++			return semerr;
++		}
++		return ret;
++	}
++
++	if (direct->type == SND_PCM_TYPE_DSHARE) {
++		const snd_pcm_channel_area_t *dst_areas;
++		dst_areas = snd_pcm_mmap_areas(direct->spcm);
++		snd_pcm_areas_silence(dst_areas, 0, direct->spcm->channels,
++				      direct->spcm->buffer_size,
++				      direct->spcm->format);
++	}
++
++	ret = snd_pcm_start(direct->spcm);
++	if (ret < 0) {
++		SNDERR("recover: unable to start slave");
++		semerr = snd_pcm_direct_semaphore_up(direct,
++						     DIRECT_IPC_SEM_CLIENT);
++		if (semerr < 0) {
++			SNDERR("SEMUP FAILED with err %d", semerr);
++			return semerr;
++		}
++		return ret;
++	}
++	direct->shmptr->recoveries++;
++	semerr = snd_pcm_direct_semaphore_up(direct,
++						 DIRECT_IPC_SEM_CLIENT);
++	if (semerr < 0) {
++		SNDERR("SEMUP FAILED with err %d", semerr);
++		return semerr;
++	}
++	return 0;
++}
++
++/*
++ * enter xrun state, if slave xrun occurred
++ * @return: 0 - no xrun >0: xrun happened
++ */
++int snd_pcm_direct_client_chk_xrun(snd_pcm_direct_t *direct, snd_pcm_t *pcm)
++{
++	if (direct->shmptr->recoveries != direct->recoveries) {
++		/* no matter how many xruns we missed -
++		 * so don't increment but just update to actual counter
++		 */
++		direct->recoveries = direct->shmptr->recoveries;
++		pcm->fast_ops->drop(pcm);
++		/* trigger_tstamp update is missing in drop callbacks */
++		gettimestamp(&direct->trigger_tstamp, pcm->tstamp_type);
++		/* no timer clear:
++		 * if slave already entered xrun again the event is lost.
++		 * snd_pcm_direct_clear_timer_queue(direct);
++		 */
++		direct->state = SND_PCM_STATE_XRUN;
++		return 1;
++	}
++	return 0;
++}
++
+ int snd_pcm_direct_poll_revents(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int nfds, unsigned short *revents)
+ {
+ 	snd_pcm_direct_t *dmix = pcm->private_data;
+@@ -572,6 +667,12 @@ int snd_pcm_direct_poll_revents(snd_pcm_t *pcm, struct pollfd *pfds, unsigned in
+ 	}
+ 	switch (snd_pcm_state(dmix->spcm)) {
+ 	case SND_PCM_STATE_XRUN:
++		/* recover slave and update client state to xrun
++		 * before returning POLLERR
++		 */
++		snd_pcm_direct_slave_recover(dmix);
++		snd_pcm_direct_client_chk_xrun(dmix, pcm);
++		/* fallthrough */
+ 	case SND_PCM_STATE_SUSPENDED:
+ 	case SND_PCM_STATE_SETUP:
+ 		events |= POLLERR;
+@@ -1382,6 +1483,7 @@ int snd_pcm_direct_open_secondary_client(snd_pcm_t **spcmp, snd_pcm_direct_t *dm
+ 	dmix->slave_buffer_size = spcm->buffer_size;
+ 	dmix->slave_period_size = dmix->shmptr->s.period_size;
+ 	dmix->slave_boundary = spcm->boundary;
++	dmix->recoveries = dmix->shmptr->recoveries;
+ 
+ 	ret = snd_pcm_mmap(spcm);
+ 	if (ret < 0) {
+diff --git a/src/pcm/pcm_direct.h b/src/pcm/pcm_direct.h
+index aee38c5..d48f6b4 100644
+--- a/src/pcm/pcm_direct.h
++++ b/src/pcm/pcm_direct.h
+@@ -66,6 +66,7 @@ typedef struct {
+ 	char socket_name[256];			/* name of communication socket */
+ 	snd_pcm_type_t type;			/* PCM type (currently only hw) */
+ 	int use_server;
++	unsigned int recoveries;		/* no of executed recoveries on slave*/
+ 	struct {
+ 		unsigned int format;
+ 		snd_interval_t rate;
+@@ -157,6 +158,7 @@ struct snd_pcm_direct {
+ 	int var_periodsize;		/* allow variable period size if max_periods is != -1*/
+ 	unsigned int channels;		/* client's channels */
+ 	unsigned int *bindings;
++	unsigned int recoveries;	/* mirror of executed recoveries on slave */
+ 	union {
+ 		struct {
+ 			int shmid_sum;			/* IPC global sum ring buffer memory identification */
+@@ -324,7 +326,8 @@ int snd_pcm_direct_open_secondary_client(snd_pcm_t **spcmp, snd_pcm_direct_t *dm
+ snd_pcm_chmap_query_t **snd_pcm_direct_query_chmaps(snd_pcm_t *pcm);
+ snd_pcm_chmap_t *snd_pcm_direct_get_chmap(snd_pcm_t *pcm);
+ int snd_pcm_direct_set_chmap(snd_pcm_t *pcm, const snd_pcm_chmap_t *map);
+-
++int snd_pcm_direct_slave_recover(snd_pcm_direct_t *direct);
++int snd_pcm_direct_client_chk_xrun(snd_pcm_direct_t *direct, snd_pcm_t *pcm);
+ int snd_timer_async(snd_timer_t *timer, int sig, pid_t pid);
+ struct timespec snd_pcm_hw_fast_tstamp(snd_pcm_t *pcm);
+ 
+diff --git a/src/pcm/pcm_dmix.c b/src/pcm/pcm_dmix.c
+index 0ab7323..f72ee67 100644
+--- a/src/pcm/pcm_dmix.c
++++ b/src/pcm/pcm_dmix.c
+@@ -434,15 +434,21 @@ static int snd_pcm_dmix_sync_ptr0(snd_pcm_t *pcm, snd_pcm_uframes_t slave_hw_ptr
+ static int snd_pcm_dmix_sync_ptr(snd_pcm_t *pcm)
+ {
+ 	snd_pcm_direct_t *dmix = pcm->private_data;
++	int err;
+ 
+ 	switch (snd_pcm_state(dmix->spcm)) {
+ 	case SND_PCM_STATE_DISCONNECTED:
+ 		dmix->state = SND_PCM_STATE_DISCONNECTED;
+ 		return -ENODEV;
++	case SND_PCM_STATE_XRUN:
++		if ((err = snd_pcm_direct_slave_recover(dmix)) < 0)
++			return err;
++		break;
+ 	default:
+ 		break;
+ 	}
+-
++	if (snd_pcm_direct_client_chk_xrun(dmix, pcm))
++		return -EPIPE;
+ 	if (dmix->slowptr)
+ 		snd_pcm_hwsync(dmix->spcm);
+ 
+@@ -828,12 +834,16 @@ static snd_pcm_sframes_t snd_pcm_dmix_mmap_commit(snd_pcm_t *pcm,
+ 
+ 	switch (snd_pcm_state(dmix->spcm)) {
+ 	case SND_PCM_STATE_XRUN:
+-		return -EPIPE;
++		if ((err = snd_pcm_direct_slave_recover(dmix)) < 0)
++			return err;
++		break;
+ 	case SND_PCM_STATE_SUSPENDED:
+ 		return -ESTRPIPE;
+ 	default:
+ 		break;
+ 	}
++	if (snd_pcm_direct_client_chk_xrun(dmix, pcm))
++		return -EPIPE;
+ 	if (! size)
+ 		return 0;
+ 	snd_pcm_mmap_appl_forward(pcm, size);
+@@ -841,8 +851,10 @@ static snd_pcm_sframes_t snd_pcm_dmix_mmap_commit(snd_pcm_t *pcm,
+ 		if ((err = snd_pcm_dmix_start_timer(pcm, dmix)) < 0)
+ 			return err;
+ 	} else if (dmix->state == SND_PCM_STATE_RUNNING ||
+-		   dmix->state == SND_PCM_STATE_DRAINING)
+-		snd_pcm_dmix_sync_ptr(pcm);
++		   dmix->state == SND_PCM_STATE_DRAINING) {
++		if ((err = snd_pcm_dmix_sync_ptr(pcm)) < 0)
++			return err;
++	}
+ 	if (dmix->state == SND_PCM_STATE_RUNNING ||
+ 	    dmix->state == SND_PCM_STATE_DRAINING) {
+ 		/* ok, we commit the changes after the validation of area */
+@@ -858,10 +870,13 @@ static snd_pcm_sframes_t snd_pcm_dmix_mmap_commit(snd_pcm_t *pcm,
+ static snd_pcm_sframes_t snd_pcm_dmix_avail_update(snd_pcm_t *pcm)
+ {
+ 	snd_pcm_direct_t *dmix = pcm->private_data;
++	int err;
+ 	
+ 	if (dmix->state == SND_PCM_STATE_RUNNING ||
+-	    dmix->state == SND_PCM_STATE_DRAINING)
+-		snd_pcm_dmix_sync_ptr(pcm);
++	    dmix->state == SND_PCM_STATE_DRAINING) {
++		if ((err = snd_pcm_dmix_sync_ptr(pcm)) < 0)
++			return err;
++	}
+ 	return snd_pcm_mmap_playback_avail(pcm);
+ }
+ 
+diff --git a/src/pcm/pcm_dshare.c b/src/pcm/pcm_dshare.c
+index a1fed5d..0d80037 100644
+--- a/src/pcm/pcm_dshare.c
++++ b/src/pcm/pcm_dshare.c
+@@ -162,7 +162,7 @@ static int snd_pcm_dshare_sync_ptr0(snd_pcm_t *pcm, snd_pcm_uframes_t slave_hw_p
+ 	snd_pcm_direct_t *dshare = pcm->private_data;
+ 	snd_pcm_uframes_t old_slave_hw_ptr, avail;
+ 	snd_pcm_sframes_t diff;
+-	
++
+ 	old_slave_hw_ptr = dshare->slave_hw_ptr;
+ 	dshare->slave_hw_ptr = slave_hw_ptr;
+ 	diff = slave_hw_ptr - old_slave_hw_ptr;
+@@ -202,15 +202,21 @@ static int snd_pcm_dshare_sync_ptr0(snd_pcm_t *pcm, snd_pcm_uframes_t slave_hw_p
+ static int snd_pcm_dshare_sync_ptr(snd_pcm_t *pcm)
+ {
+ 	snd_pcm_direct_t *dshare = pcm->private_data;
++	int err;
+ 
+ 	switch (snd_pcm_state(dshare->spcm)) {
+ 	case SND_PCM_STATE_DISCONNECTED:
+ 		dshare->state = SNDRV_PCM_STATE_DISCONNECTED;
+ 		return -ENODEV;
++	case SND_PCM_STATE_XRUN:
++		if ((err = snd_pcm_direct_slave_recover(dshare)) < 0)
++			return err;
++		break;
+ 	default:
+ 		break;
+ 	}
+-
++	if (snd_pcm_direct_client_chk_xrun(dshare, pcm))
++		return -EPIPE;
+ 	if (dshare->slowptr)
+ 		snd_pcm_hwsync(dshare->spcm);
+ 
+@@ -516,12 +522,16 @@ static snd_pcm_sframes_t snd_pcm_dshare_mmap_commit(snd_pcm_t *pcm,
+ 
+ 	switch (snd_pcm_state(dshare->spcm)) {
+ 	case SND_PCM_STATE_XRUN:
+-		return -EPIPE;
++		if ((err = snd_pcm_direct_slave_recover(dshare)) < 0)
++			return err;
++		break;
+ 	case SND_PCM_STATE_SUSPENDED:
+ 		return -ESTRPIPE;
+ 	default:
+ 		break;
+ 	}
++	if (snd_pcm_direct_client_chk_xrun(dshare, pcm))
++		return -EPIPE;
+ 	if (! size)
+ 		return 0;
+ 	snd_pcm_mmap_appl_forward(pcm, size);
+@@ -529,8 +539,10 @@ static snd_pcm_sframes_t snd_pcm_dshare_mmap_commit(snd_pcm_t *pcm,
+ 		if ((err = snd_pcm_dshare_start_timer(dshare)) < 0)
+ 			return err;
+ 	} else if (dshare->state == SND_PCM_STATE_RUNNING ||
+-		   dshare->state == SND_PCM_STATE_DRAINING)
+-		snd_pcm_dshare_sync_ptr(pcm);
++		   dshare->state == SND_PCM_STATE_DRAINING) {
++		if ((err = snd_pcm_dshare_sync_ptr(pcm)) < 0)
++			return err;
++	}
+ 	if (dshare->state == SND_PCM_STATE_RUNNING ||
+ 	    dshare->state == SND_PCM_STATE_DRAINING) {
+ 		/* ok, we commit the changes after the validation of area */
+@@ -546,10 +558,13 @@ static snd_pcm_sframes_t snd_pcm_dshare_mmap_commit(snd_pcm_t *pcm,
+ static snd_pcm_sframes_t snd_pcm_dshare_avail_update(snd_pcm_t *pcm)
+ {
+ 	snd_pcm_direct_t *dshare = pcm->private_data;
++	int err;
+ 	
+ 	if (dshare->state == SND_PCM_STATE_RUNNING ||
+-	    dshare->state == SND_PCM_STATE_DRAINING)
+-		snd_pcm_dshare_sync_ptr(pcm);
++	    dshare->state == SND_PCM_STATE_DRAINING) {
++		if ((err = snd_pcm_dshare_sync_ptr(pcm)) < 0)
++			return err;
++	}
+ 	return snd_pcm_mmap_playback_avail(pcm);
+ }
+ 
+diff --git a/src/pcm/pcm_dsnoop.c b/src/pcm/pcm_dsnoop.c
+index 85f0ff4..618d469 100644
+--- a/src/pcm/pcm_dsnoop.c
++++ b/src/pcm/pcm_dsnoop.c
+@@ -132,14 +132,21 @@ static int snd_pcm_dsnoop_sync_ptr(snd_pcm_t *pcm)
+ 	snd_pcm_direct_t *dsnoop = pcm->private_data;
+ 	snd_pcm_uframes_t slave_hw_ptr, old_slave_hw_ptr, avail;
+ 	snd_pcm_sframes_t diff;
+-	
++	int err;
++
+ 	switch (snd_pcm_state(dsnoop->spcm)) {
+ 	case SND_PCM_STATE_DISCONNECTED:
+ 		dsnoop->state = SNDRV_PCM_STATE_DISCONNECTED;
+ 		return -ENODEV;
++	case SND_PCM_STATE_XRUN:
++		if ((err = snd_pcm_direct_slave_recover(dsnoop)) < 0)
++			return err;
++		break;
+ 	default:
+ 		break;
+ 	}
++	if (snd_pcm_direct_client_chk_xrun(dsnoop, pcm))
++		return -EPIPE;
+ 	if (dsnoop->slowptr)
+ 		snd_pcm_hwsync(dsnoop->spcm);
+ 	old_slave_hw_ptr = dsnoop->slave_hw_ptr;
+@@ -410,12 +417,16 @@ static snd_pcm_sframes_t snd_pcm_dsnoop_mmap_commit(snd_pcm_t *pcm,
+ 
+ 	switch (snd_pcm_state(dsnoop->spcm)) {
+ 	case SND_PCM_STATE_XRUN:
+-		return -EPIPE;
++		if ((err = snd_pcm_direct_slave_recover(dsnoop)) < 0)
++			return err;
++		break;
+ 	case SND_PCM_STATE_SUSPENDED:
+ 		return -ESTRPIPE;
+ 	default:
+ 		break;
+ 	}
++	if (snd_pcm_direct_client_chk_xrun(dsnoop, pcm))
++		return -EPIPE;
+ 	if (dsnoop->state == SND_PCM_STATE_RUNNING) {
+ 		err = snd_pcm_dsnoop_sync_ptr(pcm);
+ 		if (err < 0)
+-- 
+2.9.3
+
+
+From 789ee39727a12d6573b4d79e9cd7a375e6b8b005 Mon Sep 17 00:00:00 2001
+From: Andreas Pape <apape@de.adit-jv.com>
+Date: Tue, 10 Jan 2017 12:03:54 +0530
+Subject: [PATCH 12/37] pcm: direct: check state before enter poll on timer
+
+To avoid the chances of timeout, we need to check the enter poll
+in state xrun.
+
+Signed-off-by: Andreas Pape <apape@de.adit-jv.com>
+Signed-off-by: Mounesh Sutar <mounesh_sutar@mentor.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+---
+ src/pcm/pcm_direct.c | 40 ++++++++++++++++++++++++++++++++++++++++
+ src/pcm/pcm_direct.h |  2 ++
+ src/pcm/pcm_dmix.c   |  9 +++++++--
+ src/pcm/pcm_dshare.c |  9 +++++++--
+ src/pcm/pcm_dsnoop.c |  9 +++++++--
+ 5 files changed, 63 insertions(+), 6 deletions(-)
+
+diff --git a/src/pcm/pcm_direct.c b/src/pcm/pcm_direct.c
+index a512dd2..f4d7c3f 100644
+--- a/src/pcm/pcm_direct.c
++++ b/src/pcm/pcm_direct.c
+@@ -645,6 +645,46 @@ int snd_pcm_direct_client_chk_xrun(snd_pcm_direct_t *direct, snd_pcm_t *pcm)
+ 	return 0;
+ }
+ 
++/*
++ * This is the only operation guaranteed to be called before entering poll().
++ * Direct plugins use fd of snd_timer to poll on, these timers do NOT check
++ * state of substream in kernel by intention.
++ * Only the enter to xrun might be notified once (SND_TIMER_EVENT_MSTOP).
++ * If xrun event was not correctly handled or was ignored it will never be
++ * evaluated again afterwards.
++ * This will result in snd_pcm_wait() always returning timeout.
++ * In contrast poll() on pcm hardware checks ALSA state and will immediately
++ * return POLLERR on XRUN.
++ *
++ * To prevent timeout and applications endlessly spinning without xrun
++ * detected we add a state check here which may trigger the xrun sequence.
++ *
++ * return count of filled descriptors or negative error code
++ */
++int snd_pcm_direct_poll_descriptors(snd_pcm_t *pcm, struct pollfd *pfds,
++				    unsigned int space)
++{
++	if (pcm->poll_fd < 0) {
++		SNDMSG("poll_fd < 0");
++		return -EIO;
++	}
++	if (space >= 1 && pfds) {
++		pfds->fd = pcm->poll_fd;
++		pfds->events = pcm->poll_events | POLLERR | POLLNVAL;
++	} else {
++		return 0;
++	}
++
++	/* this will also evaluate slave state and enter xrun if necessary */
++	switch (snd_pcm_state(pcm)) {
++	case SND_PCM_STATE_XRUN:
++		return -EPIPE;
++	default:
++		break;
++	}
++	return 1;
++}
++
+ int snd_pcm_direct_poll_revents(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int nfds, unsigned short *revents)
+ {
+ 	snd_pcm_direct_t *dmix = pcm->private_data;
+diff --git a/src/pcm/pcm_direct.h b/src/pcm/pcm_direct.h
+index d48f6b4..66107ec 100644
+--- a/src/pcm/pcm_direct.h
++++ b/src/pcm/pcm_direct.h
+@@ -307,6 +307,8 @@ int snd_pcm_direct_parse_bindings(snd_pcm_direct_t *dmix,
+ 				  snd_config_t *cfg);
+ int snd_pcm_direct_nonblock(snd_pcm_t *pcm, int nonblock);
+ int snd_pcm_direct_async(snd_pcm_t *pcm, int sig, pid_t pid);
++int snd_pcm_direct_poll_descriptors(snd_pcm_t *pcm, struct pollfd *pfds,
++				    unsigned int space);
+ int snd_pcm_direct_poll_revents(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int nfds, unsigned short *revents);
+ int snd_pcm_direct_info(snd_pcm_t *pcm, snd_pcm_info_t * info);
+ int snd_pcm_direct_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params);
+diff --git a/src/pcm/pcm_dmix.c b/src/pcm/pcm_dmix.c
+index f72ee67..6664210 100644
+--- a/src/pcm/pcm_dmix.c
++++ b/src/pcm/pcm_dmix.c
+@@ -462,17 +462,22 @@ static int snd_pcm_dmix_sync_ptr(snd_pcm_t *pcm)
+ static snd_pcm_state_t snd_pcm_dmix_state(snd_pcm_t *pcm)
+ {
+ 	snd_pcm_direct_t *dmix = pcm->private_data;
++	int err;
+ 	snd_pcm_state_t state;
+ 	state = snd_pcm_state(dmix->spcm);
+ 	switch (state) {
+-	case SND_PCM_STATE_XRUN:
+ 	case SND_PCM_STATE_SUSPENDED:
+ 	case SND_PCM_STATE_DISCONNECTED:
+ 		dmix->state = state;
+ 		return state;
++	case SND_PCM_STATE_XRUN:
++		if ((err = snd_pcm_direct_slave_recover(dmix)) < 0)
++			return err;
++		break;
+ 	default:
+ 		break;
+ 	}
++	snd_pcm_direct_client_chk_xrun(dmix, pcm);
+ 	if (dmix->state == STATE_RUN_PENDING)
+ 		return SNDRV_PCM_STATE_RUNNING;
+ 	return dmix->state;
+@@ -968,7 +973,7 @@ static const snd_pcm_fast_ops_t snd_pcm_dmix_fast_ops = {
+ 	.avail_update = snd_pcm_dmix_avail_update,
+ 	.mmap_commit = snd_pcm_dmix_mmap_commit,
+ 	.htimestamp = snd_pcm_dmix_htimestamp,
+-	.poll_descriptors = NULL,
++	.poll_descriptors = snd_pcm_direct_poll_descriptors,
+ 	.poll_descriptors_count = NULL,
+ 	.poll_revents = snd_pcm_dmix_poll_revents,
+ };
+diff --git a/src/pcm/pcm_dshare.c b/src/pcm/pcm_dshare.c
+index 0d80037..fdc95e3 100644
+--- a/src/pcm/pcm_dshare.c
++++ b/src/pcm/pcm_dshare.c
+@@ -255,17 +255,22 @@ static int snd_pcm_dshare_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
+ static snd_pcm_state_t snd_pcm_dshare_state(snd_pcm_t *pcm)
+ {
+ 	snd_pcm_direct_t *dshare = pcm->private_data;
++	int err;
+ 	snd_pcm_state_t state;
+ 	state = snd_pcm_state(dshare->spcm);
+ 	switch (state) {
+-	case SND_PCM_STATE_XRUN:
+ 	case SND_PCM_STATE_SUSPENDED:
+ 	case SND_PCM_STATE_DISCONNECTED:
+ 		dshare->state = state;
+ 		return state;
++	case SND_PCM_STATE_XRUN:
++		if ((err = snd_pcm_direct_slave_recover(dshare)) < 0)
++			return err;
++		break;
+ 	default:
+ 		break;
+ 	}
++	snd_pcm_direct_client_chk_xrun(dshare, pcm);
+ 	if (dshare->state == STATE_RUN_PENDING)
+ 		return SNDRV_PCM_STATE_RUNNING;
+ 	return dshare->state;
+@@ -646,7 +651,7 @@ static const snd_pcm_fast_ops_t snd_pcm_dshare_fast_ops = {
+ 	.avail_update = snd_pcm_dshare_avail_update,
+ 	.mmap_commit = snd_pcm_dshare_mmap_commit,
+ 	.htimestamp = snd_pcm_dshare_htimestamp,
+-	.poll_descriptors = NULL,
++	.poll_descriptors = snd_pcm_direct_poll_descriptors,
+ 	.poll_descriptors_count = NULL,
+ 	.poll_revents = snd_pcm_direct_poll_revents,
+ };
+diff --git a/src/pcm/pcm_dsnoop.c b/src/pcm/pcm_dsnoop.c
+index 618d469..a148771 100644
+--- a/src/pcm/pcm_dsnoop.c
++++ b/src/pcm/pcm_dsnoop.c
+@@ -208,17 +208,22 @@ static int snd_pcm_dsnoop_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
+ static snd_pcm_state_t snd_pcm_dsnoop_state(snd_pcm_t *pcm)
+ {
+ 	snd_pcm_direct_t *dsnoop = pcm->private_data;
++	int err;
+ 	snd_pcm_state_t state;
+ 	state = snd_pcm_state(dsnoop->spcm);
+ 	switch (state) {
+-	case SND_PCM_STATE_XRUN:
+ 	case SND_PCM_STATE_SUSPENDED:
+ 	case SND_PCM_STATE_DISCONNECTED:
+ 		dsnoop->state = state;
+ 		return state;
++	case SND_PCM_STATE_XRUN:
++		if ((err = snd_pcm_direct_slave_recover(dsnoop)) < 0)
++			return err;
++		break;
+ 	default:
+ 		break;
+ 	}
++	snd_pcm_direct_client_chk_xrun(dsnoop, pcm);
+ 	return dsnoop->state;
+ }
+ 
+@@ -531,7 +536,7 @@ static const snd_pcm_fast_ops_t snd_pcm_dsnoop_fast_ops = {
+ 	.avail_update = snd_pcm_dsnoop_avail_update,
+ 	.mmap_commit = snd_pcm_dsnoop_mmap_commit,
+ 	.htimestamp = snd_pcm_dsnoop_htimestamp,
+-	.poll_descriptors = NULL,
++	.poll_descriptors = snd_pcm_direct_poll_descriptors,
+ 	.poll_descriptors_count = NULL,
+ 	.poll_revents = snd_pcm_direct_poll_revents,
+ };
+-- 
+2.9.3
+
+
+From 79a358ae26f74ed9b92b2190d4725325edf0c787 Mon Sep 17 00:00:00 2001
+From: Andreas Pape <apape@de.adit-jv.com>
+Date: Tue, 10 Jan 2017 12:04:09 +0530
+Subject: [PATCH 13/37] pcm: direct: don't return bogus buffer levels in xrun
+ state
+
+Signed-off-by: Andreas Pape <apape@de.adit-jv.com>
+Signed-off-by: Mounesh Sutar <mounesh_sutar@mentor.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+---
+ src/pcm/pcm_dmix.c   | 3 +++
+ src/pcm/pcm_dshare.c | 3 +++
+ src/pcm/pcm_dsnoop.c | 3 +++
+ 3 files changed, 9 insertions(+)
+
+diff --git a/src/pcm/pcm_dmix.c b/src/pcm/pcm_dmix.c
+index 6664210..2ef6159 100644
+--- a/src/pcm/pcm_dmix.c
++++ b/src/pcm/pcm_dmix.c
+@@ -882,6 +882,9 @@ static snd_pcm_sframes_t snd_pcm_dmix_avail_update(snd_pcm_t *pcm)
+ 		if ((err = snd_pcm_dmix_sync_ptr(pcm)) < 0)
+ 			return err;
+ 	}
++	if (dmix->state == SND_PCM_STATE_XRUN)
++		return -EPIPE;
++
+ 	return snd_pcm_mmap_playback_avail(pcm);
+ }
+ 
+diff --git a/src/pcm/pcm_dshare.c b/src/pcm/pcm_dshare.c
+index fdc95e3..331f799 100644
+--- a/src/pcm/pcm_dshare.c
++++ b/src/pcm/pcm_dshare.c
+@@ -570,6 +570,9 @@ static snd_pcm_sframes_t snd_pcm_dshare_avail_update(snd_pcm_t *pcm)
+ 		if ((err = snd_pcm_dshare_sync_ptr(pcm)) < 0)
+ 			return err;
+ 	}
++	if (dshare->state == SND_PCM_STATE_XRUN)
++		return -EPIPE;
++
+ 	return snd_pcm_mmap_playback_avail(pcm);
+ }
+ 
+diff --git a/src/pcm/pcm_dsnoop.c b/src/pcm/pcm_dsnoop.c
+index a148771..539b671 100644
+--- a/src/pcm/pcm_dsnoop.c
++++ b/src/pcm/pcm_dsnoop.c
+@@ -454,6 +454,9 @@ static snd_pcm_sframes_t snd_pcm_dsnoop_avail_update(snd_pcm_t *pcm)
+ 		if (err < 0)
+ 			return err;
+ 	}
++	if (dsnoop->state == SND_PCM_STATE_XRUN)
++		return -EPIPE;
++
+ 	return snd_pcm_mmap_capture_avail(pcm);
+ }
+ 
+-- 
+2.9.3
+
+
+From 360c976aaa051809c34cb412ffa52380baeaabee Mon Sep 17 00:00:00 2001
+From: Vinod Koul <vinod.koul@intel.com>
+Date: Thu, 12 Jan 2017 14:50:28 +0530
+Subject: [PATCH 14/37] conf/ucm: broxton: add broxton-rt298 conf files
+
+This adds the UCM conf files for broxton enabling with rt298 codec on
+I2S audio, HDMI and DMIC ports.
+
+Signed-off-by: Nishit Sharma <nishitx.sharma@intel.com>
+Signed-off-by: G Kranthi <gudishax.kranthikumar@intel.com>
+Signed-off-by: Vinod Koul <vinod.koul@intel.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+---
+ configure.ac                                  |   1 +
+ src/conf/ucm/Makefile.am                      |   2 +-
+ src/conf/ucm/broxton-rt298/Hdmi1              |  22 +++++
+ src/conf/ucm/broxton-rt298/Hdmi2              |  14 +++
+ src/conf/ucm/broxton-rt298/HiFi               | 129 ++++++++++++++++++++++++++
+ src/conf/ucm/broxton-rt298/Makefile.am        |   4 +
+ src/conf/ucm/broxton-rt298/broxton-rt298.conf |  58 ++++++++++++
+ 7 files changed, 229 insertions(+), 1 deletion(-)
+ create mode 100644 src/conf/ucm/broxton-rt298/Hdmi1
+ create mode 100644 src/conf/ucm/broxton-rt298/Hdmi2
+ create mode 100644 src/conf/ucm/broxton-rt298/HiFi
+ create mode 100644 src/conf/ucm/broxton-rt298/Makefile.am
+ create mode 100644 src/conf/ucm/broxton-rt298/broxton-rt298.conf
+
+diff --git a/configure.ac b/configure.ac
+index 71bd852..d645ab6 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -684,6 +684,7 @@ AC_OUTPUT(Makefile doc/Makefile doc/pictures/Makefile doc/doxygen.cfg \
+ 	  src/conf/topology/bxtrt298/Makefile \
+ 	  alsalisp/Makefile aserver/Makefile \
+ 	  test/Makefile test/lsb/Makefile \
++	  src/conf/ucm/broxton-rt298/Makefile \
+ 	  utils/Makefile utils/alsa-lib.spec utils/alsa.pc)
+ 
+ dnl Create asoundlib.h dynamically according to configure options
+diff --git a/src/conf/ucm/Makefile.am b/src/conf/ucm/Makefile.am
+index a11d324..ea9b385 100644
+--- a/src/conf/ucm/Makefile.am
++++ b/src/conf/ucm/Makefile.am
+@@ -1 +1 @@
+-SUBDIRS=DAISY-I2S PandaBoard PandaBoardES SDP4430 tegraalc5632 PAZ00 GoogleNyan broadwell-rt286 skylake-rt286 VEYRON-I2S chtrt5645 DB410c
++SUBDIRS=DAISY-I2S PandaBoard PandaBoardES SDP4430 tegraalc5632 PAZ00 GoogleNyan broadwell-rt286 skylake-rt286 VEYRON-I2S chtrt5645 DB410c broxton-rt298
+diff --git a/src/conf/ucm/broxton-rt298/Hdmi1 b/src/conf/ucm/broxton-rt298/Hdmi1
+new file mode 100644
+index 0000000..48514f4
+--- /dev/null
++++ b/src/conf/ucm/broxton-rt298/Hdmi1
+@@ -0,0 +1,22 @@
++# Usecase for device HDMI1/Display Port stereo playback on Intel SKYLAKE/KABYLAKE platforms
++# For Audio in I2S mode
++
++SectionDevice."Hdmi1" {
++        Comment "HDMI/Display Port 1 Stereo"
++
++        EnableSequence [
++                exec "echo Hdmi1 EnableSequnece"
++        ]
++
++        DisableSequence [
++                exec "echo Hdmi1 DisableSequnece"
++        ]
++
++        Value {
++                PlaybackPCM "hw:broxtonrt298,4"
++                PlaybackChannels "2"
++                PlaybackPriority "3"
++                JackControl "HDMI/DP, pcm=4 Jack"
++        }
++}
++
+diff --git a/src/conf/ucm/broxton-rt298/Hdmi2 b/src/conf/ucm/broxton-rt298/Hdmi2
+new file mode 100644
+index 0000000..764f8b9
+--- /dev/null
++++ b/src/conf/ucm/broxton-rt298/Hdmi2
+@@ -0,0 +1,14 @@
++# Usecase for device HDMI2/Display Port stereo playback on Intel Broxton platforms
++# For Audio in I2S mode
++
++SectionDevice."Hdmi2" {
++        Comment "HDMI/Display Port 2 Stereo"
++
++        Value {
++                PlaybackPCM "hw:broxtonrt298,5"
++                PlaybackChannels "2"
++                PlaybackPriority "4"
++                JackControl "HDMI/DP, pcm=5 Jack"
++        }
++}
++
+diff --git a/src/conf/ucm/broxton-rt298/HiFi b/src/conf/ucm/broxton-rt298/HiFi
+new file mode 100644
+index 0000000..2e2d6fe
+--- /dev/null
++++ b/src/conf/ucm/broxton-rt298/HiFi
+@@ -0,0 +1,129 @@
++# Usecase for stereo playback Speaker and Headset, Recording on DMIC and Headset MIC.
++# For Audio in I2S mode on Intel Broxton platforms
++
++SectionVerb {
++
++	EnableSequence [
++		cdev "hw:broxtonrt298"
++		cset "name='media0_out mo dmic01_hifi_in mi Switch' 1"
++	]
++
++	DisableSequence [
++		cdev "hw:broxtonrt298"
++	]
++
++	Value {
++		TQ "HiFi"
++		CapturePCM "hw:broxtonrt298,1"
++		PlaybackPCM "hw:broxtonrt298,0"
++	}
++}
++
++SectionDevice."dmiccap" {
++	Comment "DMIC Stereo"
++
++	ConflictingDevice [
++		"Headset"
++	]
++
++	EnableSequence [
++
++		cdev "hw:broxtonrt298"
++		exec "echo broxtonrt298 dmiccap called"
++		cset "name='media0_out mo dmic01_hifi_in mi Switch' 1"
++		cset "name='media0_out mo codec0_in mi Switch' 0"
++		cset "name='Mic Jack Switch' 0"
++
++	]
++
++	DisableSequence [
++		cdev "hw:broxtonrt298"
++		cset "name='media0_out mo codec0_in mi Switch' 1"
++		cset "name='media0_out mo dmic01_hifi_in mi Switch' 0"
++		cset "name='Mic Jack Switch' 1"
++		cset "name='ADC 0 Mux' 0"
++	]
++	Value {
++		CaptureChannels "2"
++		CapturePriority "2"
++	}
++}
++
++SectionDevice."Headphones" {
++	Comment "Headphones"
++
++	ConflictingDevice [
++		"Speaker"
++	]
++	EnableSequence [
++		cdev "hw:broxtonrt298"
++		exec "echo broxtonrt298 Headphone called"
++		cset "name='HPO L Switch' 1"
++		cset "name='HPO R Switch' 1"
++		cset "name='Headphone Jack Switch' 1"
++		cset "name='Speaker Playback Switch' 0,0"
++	]
++
++	DisableSequence [
++		cdev "hw:broxtonrt298"
++	]
++	Value {
++		PlaybackChannels "2"
++		PlaybackPriority "1"
++		JackControl "Headphone Jack"
++		JackHWMute "Speaker"
++	}
++}
++
++SectionDevice."Speaker" {
++	Comment "Speaker"
++
++	ConflictingDevice [
++		"Headphones"
++	]
++	EnableSequence [
++		cdev "hw:broxtonrt298"
++		exec "echo broxtonrt298 speaker called"
++		cset "name='SPO Switch' 1"
++		cset "name='Speaker Playback Switch' 1,1"
++		cset "name='Speaker Switch' 1"
++		cset "name='HPO L Switch' 0"
++		cset "name='HPO R Switch' 0"
++	]
++
++	DisableSequence [
++	]
++	Value {
++		PlaybackChannels "2"
++		PlaybackPriority "1"
++		JackHWMute "Headphones"
++	}
++}
++
++SectionDevice."Headset" {
++	Comment "Headset Mic"
++
++	ConflictingDevice [
++		"dmiccap"
++	]
++	EnableSequence [
++		cdev "hw:broxtonrt298"
++		exec "echo broxtonrt298 Headset called"
++		cset "name='media0_out mo codec0_in mi Switch' 1"
++		cset "name='ADC0 Capture Volume' 105,105"
++		cset "name='ADC 0 Mux' 0"
++		cset "name='Mic Jack Switch' 1"
++		cset "name='media0_out mo dmic01_hifi_in mi Switch' 0"
++	]
++
++	DisableSequence [
++		cdev "hw:broxtonrt298"
++		cset "name='media0_out mo dmic01_hifi_in mi Switch' 1"
++		cset "name='media0_out mo codec0_in mi Switch' 0"
++	]
++	Value {
++		CaptureChannels "2"
++		CapturePriority "2"
++		JackControl "Mic Jack"
++	}
++}
+diff --git a/src/conf/ucm/broxton-rt298/Makefile.am b/src/conf/ucm/broxton-rt298/Makefile.am
+new file mode 100644
+index 0000000..80f480e
+--- /dev/null
++++ b/src/conf/ucm/broxton-rt298/Makefile.am
+@@ -0,0 +1,4 @@
++alsaconfigdir = @ALSA_CONFIG_DIR@
++ucmdir = $(alsaconfigdir)/ucm/broxton-rt298
++ucm_DATA = broxton-rt298.conf HiFi Hdmi1 Hdmi2
++EXTRA_DIST = $(ucm_DATA)
+diff --git a/src/conf/ucm/broxton-rt298/broxton-rt298.conf b/src/conf/ucm/broxton-rt298/broxton-rt298.conf
+new file mode 100644
+index 0000000..3f3d0be
+--- /dev/null
++++ b/src/conf/ucm/broxton-rt298/broxton-rt298.conf
+@@ -0,0 +1,58 @@
++# UCM for Intel Broxton platforms
++# For Audio in I2S mode
++
++SectionUseCase."HiFi" {
++	File "HiFi"
++	Comment "Play and record HiFi quality Music"
++}
++
++SectionUseCase."Hdmi1" {
++        File "Hdmi1"
++        Comment "Play on Hdmi/DP 1"
++}
++
++SectionUseCase."Hdmi2" {
++        File "Hdmi2"
++        Comment "Play on Hdmi/DP 2"
++}
++
++ValueDefaults {
++	PlaybackCTL "hw:broxtonrt298"
++	CaptureCTL "hw:broxtonrt298"
++	CaptureChannels "2"
++	CapturePriority "2"
++}
++
++SectionDefaults [
++	cdev "hw:broxtonrt298"
++	exec "echo broxtonrt298 CONF Defaults"
++	cset "name='Headphone Jack Switch' 1"
++	cset "name='Speaker Switch' 1"
++	cset "name='Speaker Playback Switch' 0,0"
++	cset "name='Front DAC Switch' 1"
++	cset "name='Front RECMIX Switch' 0"
++	cset "name='Mic Jack Switch' 1"
++	cset "name='ADC 0 Mux' 2"
++	cset "name='ADC 1 Mux' 0"
++	cset "name='DAC0 Playback Volume' 100,100"
++	cset "name='HPO L Switch' 0"
++	cset "name='HPO Mux' 0"
++	cset "name='HPO R Switch' 0"
++	cset "name='Pin 5 Mux' 1"
++	cset "name='Pin 6 Mux' 2"
++	cset "name='Pin 7 Mux' 3"
++	cset "name='RECMIX Beep Switch' 0"
++	cset "name='RECMIX Line1 Switch' 0"
++	cset "name='RECMIX Mic1 Switch' 0"
++	cset "name='SPK Mux' 0"
++	cset "name='SPO Switch' 1"
++	cset "name='codec0_out mo codec0_in mi Switch' 0"
++	cset "name='codec0_out mo dmic01_hifi_in mi Switch' 0"
++	cset "name='codec0_out mo media0_in mi Switch' 1"
++	cset "name='codec1_out mo codec0_in mi Switch' 0"
++	cset "name='codec1_out mo dmic01_hifi_in mi Switch' 0"
++	cset "name='codec1_out mo media0_in mi Switch' 0"
++	cset "name='media0_out mo codec0_in mi Switch' 1"
++	cset "name='media0_out mo dmic01_hifi_in mi Switch' 1"
++	cset "name='media0_out mo media0_in mi Switch' 0"
++]
+-- 
+2.9.3
+
+
+From 24e63b75275e9c923c336b8dba3919b980e8f234 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Mon, 16 Jan 2017 16:21:52 +0100
+Subject: [PATCH 15/37] pcm: direct: Fix deadlock in poll_descriptors
+
+The recent change in PCM direct plugins to check XRUN in
+poll_descriptors callback caused a regression; as consequence, the
+whole playback hangs up.
+
+The culprit is a mutex dead lock by the call in snd_pcm_state() inside
+the new snd_pcm_direct_poll_descriptors().  The poll_descriptors code
+path is protected with pcm mutex, thus an unlocked version
+(__snd_pcm_state()) has to be used inside the callback instead.
+
+Fixes: 789ee39727a1 ("pcm: direct: check state before enter poll on timer")
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+---
+ src/pcm/pcm_direct.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/src/pcm/pcm_direct.c b/src/pcm/pcm_direct.c
+index f4d7c3f..e4bef78 100644
+--- a/src/pcm/pcm_direct.c
++++ b/src/pcm/pcm_direct.c
+@@ -676,7 +676,8 @@ int snd_pcm_direct_poll_descriptors(snd_pcm_t *pcm, struct pollfd *pfds,
+ 	}
+ 
+ 	/* this will also evaluate slave state and enter xrun if necessary */
+-	switch (snd_pcm_state(pcm)) {
++	/* using __snd_pcm_state() since this function is called inside lock */
++	switch (__snd_pcm_state(pcm)) {
+ 	case SND_PCM_STATE_XRUN:
+ 		return -EPIPE;
+ 	default:
+-- 
+2.9.3
+
+
+From 2b9b3f013467765219c8ab8a50943d3c7db68f75 Mon Sep 17 00:00:00 2001
+From: Mengdong Lin <mengdong.lin@linux.intel.com>
+Date: Wed, 18 Jan 2017 11:52:35 +0800
+Subject: [PATCH 16/37] ucm: Assure the user input card name not to exceed max
+ size of card long name
+
+Users can load a card's UCM configuration file by giving the card short
+name or long name, which should not exceed the maximum card long name
+defined by the kernel. The kernel uses an 80-character buffer to store
+the card long name.
+
+Signed-off-by: Mengdong Lin <mengdong.lin@linux.intel.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+---
+ src/ucm/parser.c    | 6 ++++++
+ src/ucm/ucm_local.h | 1 +
+ 2 files changed, 7 insertions(+)
+
+diff --git a/src/ucm/parser.c b/src/ucm/parser.c
+index f520abc..f61201a 100644
+--- a/src/ucm/parser.c
++++ b/src/ucm/parser.c
+@@ -1335,6 +1335,12 @@ static int load_master_config(const char *card_name, snd_config_t **cfg)
+ 	char *env = getenv(ALSA_CONFIG_UCM_VAR);
+ 	int err;
+ 
++	if (strnlen(card_name, MAX_CARD_LONG_NAME) == MAX_CARD_LONG_NAME) {
++		uc_error("error: invalid card name %s (at most %d chars)\n",
++			 card_name, MAX_CARD_LONG_NAME - 1);
++		return -EINVAL;
++	}
++
+ 	snprintf(filename, sizeof(filename)-1,
+ 		"%s/%s/%s.conf", env ? env : ALSA_USE_CASE_DIR,
+ 		card_name, card_name);
+diff --git a/src/ucm/ucm_local.h b/src/ucm/ucm_local.h
+index 6d3302f..e41aafa 100644
+--- a/src/ucm/ucm_local.h
++++ b/src/ucm/ucm_local.h
+@@ -41,6 +41,7 @@
+ #include "use-case.h"
+ 
+ #define MAX_FILE		256
++#define MAX_CARD_LONG_NAME	80
+ #define ALSA_USE_CASE_DIR	ALSA_CONFIG_DIR "/ucm"
+ 
+ #define SEQUENCE_ELEMENT_TYPE_CDEV	1
+-- 
+2.9.3
+
+
+From 4b9297e65f541f1a6c1b4a036f66936b9cafe030 Mon Sep 17 00:00:00 2001
+From: Mengdong Lin <mengdong.lin@linux.intel.com>
+Date: Wed, 18 Jan 2017 11:53:35 +0800
+Subject: [PATCH 17/37] ucm: Load device-specific configuration file based on
+ the card long name
+
+Intel DSP platform drivers are used by many different devices. For user
+space to differentiate them, ASoC machine drivers may use the DMI info
+(vendor-product-version-board) as card long name. Possible card long names
+are:
+DellInc.-XPS139343-01-0310JH
+ASUSTeKCOMPUTERINC.-T100TA-1.0-T100TA
+Circuitco-MinnowboardMaxD0PLATFORM-D0-MinnowBoardMAX
+...
+
+If we want to define a device-specific UCM config file for a card, we
+need to use the card long name as the name of both the directory that
+contains the UCM config file and the UCM config file itself, like
+longname/longname.conf
+
+When being asked to load configuration file of a card, UCM will try to
+find the card in the local machine and get its long name. If the card
+long name is available, try to load the file longname/longname.conf to
+get the best device-specific configuration; if this file is not available,
+fall back to load the default configuration file shortname/shortname.conf
+as before.
+
+This update is backward compatible, because if ASoC machine drivers don't
+explicity use DMI or other means to set the card long name, ASoC core
+will use the card short name as the long name. And so UCM will load the
+config file that matches both the card short name and the long name.
+
+Signed-off-by: Mengdong Lin <mengdong.lin@linux.intel.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+---
+ src/ucm/parser.c    | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++---
+ src/ucm/ucm_local.h |  2 ++
+ 2 files changed, 97 insertions(+), 4 deletions(-)
+
+diff --git a/src/ucm/parser.c b/src/ucm/parser.c
+index f61201a..798bf48 100644
+--- a/src/ucm/parser.c
++++ b/src/ucm/parser.c
+@@ -56,6 +56,9 @@ static const char * const component_dir[] = {
+ 	NULL,		/* terminator */
+ };
+ 
++static int filename_filter(const struct dirent *dirent);
++static int is_component_directory(const char *dir);
++
+ static int parse_sequence(snd_use_case_mgr_t *uc_mgr,
+ 			  struct list_head *base,
+ 			  snd_config_t *cfg);
+@@ -1329,6 +1332,66 @@ static int parse_master_file(snd_use_case_mgr_t *uc_mgr, snd_config_t *cfg)
+ 	return 0;
+ }
+ 
++/* find the card in the local machine and store the card long name */
++static int get_card_long_name(snd_use_case_mgr_t *mgr)
++{
++	const char *card_name = mgr->card_name;
++	snd_ctl_t *handle;
++	int card, err;
++	snd_ctl_card_info_t *info;
++	const char *_name, *_long_name;
++
++	snd_ctl_card_info_alloca(&info);
++
++	card = -1;
++	if (snd_card_next(&card) < 0 || card < 0) {
++		uc_error("no soundcards found...");
++		return -1;
++	}
++
++	while (card >= 0) {
++		char name[32];
++
++		sprintf(name, "hw:%d", card);
++		err = snd_ctl_open(&handle, name, 0);
++		if (err < 0) {
++			uc_error("control open (%i): %s", card,
++				 snd_strerror(err));
++			goto next_card;
++		}
++
++		err = snd_ctl_card_info(handle, info);
++		if (err < 0) {
++			uc_error("control hardware info (%i): %s", card,
++				 snd_strerror(err));
++			snd_ctl_close(handle);
++			goto next_card;
++		}
++
++		/* Find the local card by comparing the given name with the
++		 * card short name and long name. The given card name may be
++		 * either a short name or long name, because users may open
++		 * the card by either of the two names.
++		 */
++		_name = snd_ctl_card_info_get_name(info);
++		_long_name = snd_ctl_card_info_get_longname(info);
++		if (!strcmp(card_name, _name)
++		    || !strcmp(card_name, _long_name)) {
++			strcpy(mgr->card_long_name, _long_name);
++			snd_ctl_close(handle);
++			return 0;
++		}
++
++		snd_ctl_close(handle);
++next_card:
++		if (snd_card_next(&card) < 0) {
++			uc_error("snd_card_next");
++			break;
++		}
++	}
++
++	return -1;
++}
+ static int load_master_config(const char *card_name, snd_config_t **cfg)
+ {
+ 	char filename[MAX_FILE];
+@@ -1356,15 +1419,43 @@ static int load_master_config(const char *card_name, snd_config_t **cfg)
+ 	return 0;
+ }
+ 
+-/* load master use case file for sound card */
++/* load master use case file for sound card
++ *
++ * The same ASoC machine driver can be shared by many different devices.
++ * For user space to differentiate them and get the best device-specific
++ * configuration, ASoC machine drivers may use the DMI info
++ * (vendor-product-version-board) as the card long name. And user space can
++ * define configuration files like longnamei/longname.conf for a specific device.
++ *
++ * This function will try to find the card in the local machine and get its
++ * long name, then load the file longname/longname.conf to get the best
++ * device-specific configuration. If the card is not found in the local
++ * machine or the device-specific file is not available, fall back to load
++ * the default configuration file name/name.conf.
++ */
+ int uc_mgr_import_master_config(snd_use_case_mgr_t *uc_mgr)
+ {
+ 	snd_config_t *cfg;
+ 	int err;
+ 
+-	err = load_master_config(uc_mgr->card_name, &cfg);
+-	if (err < 0)
+-		return err;
++	err = get_card_long_name(uc_mgr);
++	if (err == 0)	/* load file that maches the card long name */
++		err = load_master_config(uc_mgr->card_long_name, &cfg);
++
++	if (err == 0) {
++		/* got device-specific file that matches the card long name */
++		strcpy(uc_mgr->conf_file_name, uc_mgr->card_long_name);
++	} else {
++		/* Fall back to the file that maches the given card name,
++		 * either short name or long name (users may open a card by
++		 * its name or long name).
++		 */
++		err = load_master_config(uc_mgr->card_name, &cfg);
++		if (err < 0)
++			return err;
++		strcpy(uc_mgr->conf_file_name, uc_mgr->card_name);
++	}
++
+ 	err = parse_master_file(uc_mgr, cfg);
+ 	snd_config_delete(cfg);
+ 	if (err < 0)
+diff --git a/src/ucm/ucm_local.h b/src/ucm/ucm_local.h
+index e41aafa..299a5b9 100644
+--- a/src/ucm/ucm_local.h
++++ b/src/ucm/ucm_local.h
+@@ -191,6 +191,8 @@ struct use_case_verb {
+  */
+ struct snd_use_case_mgr {
+ 	char *card_name;
++	char card_long_name[MAX_CARD_LONG_NAME];
++	char conf_file_name[MAX_CARD_LONG_NAME];
+ 	char *comment;
+ 
+ 	/* use case verb, devices and modifier configs parsed from files */
+-- 
+2.9.3
+
+
+From e93d93a8cd37f94f119aba72ca05d7f92b648bcc Mon Sep 17 00:00:00 2001
+From: Mengdong Lin <mengdong.lin@linux.intel.com>
+Date: Wed, 18 Jan 2017 11:53:42 +0800
+Subject: [PATCH 18/37] ucm: Add command 'get _file' to get the config file
+ name of the opened card
+
+After opening a card, this command can show the name of the actually
+loaded configuration file, either matches the card name or card long name.
+So developers can check if there is a device-sepcific configuration file
+available for a given card.
+
+Signed-off-by: Mengdong Lin <mengdong.lin@linux.intel.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+---
+ include/use-case.h |  1 +
+ src/ucm/main.c     | 14 ++++++++++++++
+ 2 files changed, 15 insertions(+)
+
+diff --git a/include/use-case.h b/include/use-case.h
+index 8911645..ae22bde 100644
+--- a/include/use-case.h
++++ b/include/use-case.h
+@@ -230,6 +230,7 @@ int snd_use_case_get_list(snd_use_case_mgr_t *uc_mgr,
+  * Known identifiers:
+  *   - NULL 		- return current card
+  *   - _verb		- return current verb
++ *   - _file		- return configuration file loaded for current card
+  *
+  *   - [=]{NAME}[/[{modifier}|{/device}][/{verb}]]
+  *                      - value identifier {NAME}
+diff --git a/src/ucm/main.c b/src/ucm/main.c
+index 38a5e81..2d33886 100644
+--- a/src/ucm/main.c
++++ b/src/ucm/main.c
+@@ -1528,6 +1528,20 @@ int snd_use_case_get(snd_use_case_mgr_t *uc_mgr,
+                         goto __end;
+                 }
+ 	        err = 0;
++	} else if (strcmp(identifier, "_file") == 0) {
++		/* get the conf file name of the opened card */
++		if ((uc_mgr->card_name == NULL)
++		    || (uc_mgr->conf_file_name[0] == '\0')) {
++			err = -ENOENT;
++			goto __end;
++		}
++		*value = strndup(uc_mgr->conf_file_name, MAX_FILE);
++		if (*value == NULL) {
++			err = -ENOMEM;
++			goto __end;
++		}
++		err = 0;
++
+ 	} else if (identifier[0] == '_') {
+ 		err = -ENOENT;
+ 		goto __end;
+-- 
+2.9.3
+
+
+From ec40aafa4374f2388876702513c4b3eee2e2235f Mon Sep 17 00:00:00 2001
+From: Liam Girdwood <liam.r.girdwood@linux.intel.com>
+Date: Tue, 24 Jan 2017 14:59:08 +0000
+Subject: [PATCH 19/37] topology: Fix incorrect license in source comments.
+
+The topology source files had the wrong licence specified in the
+comments when initially upstreamed. The topology source files are all
+licensed under the LGPL-2.1 and not the GPLv2.
+
+All earlier versions of the alsa-lib topology source files must be
+considered LGPL-2.1 like the other source files in alsa-lib and also
+as specified in the alsa-lib COPYING file.
+
+Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+---
+ src/topology/builder.c | 17 +++++++++--------
+ src/topology/channel.c | 17 +++++++++--------
+ src/topology/ctl.c     | 17 +++++++++--------
+ src/topology/dapm.c    | 17 +++++++++--------
+ src/topology/data.c    | 17 +++++++++--------
+ src/topology/elem.c    | 17 +++++++++--------
+ src/topology/ops.c     | 17 +++++++++--------
+ src/topology/parser.c  | 17 +++++++++--------
+ src/topology/pcm.c     | 17 +++++++++--------
+ src/topology/text.c    | 17 +++++++++--------
+ 10 files changed, 90 insertions(+), 80 deletions(-)
+
+diff --git a/src/topology/builder.c b/src/topology/builder.c
+index 20fa925..dcd9e2a 100644
+--- a/src/topology/builder.c
++++ b/src/topology/builder.c
+@@ -2,14 +2,15 @@
+   Copyright(c) 2014-2015 Intel Corporation
+   All rights reserved.
+ 
+-  This program is free software; you can redistribute it and/or modify
+-  it under the terms of version 2 of the GNU General Public License as
+-  published by the Free Software Foundation.
+-
+-  This program is distributed in the hope that it will be useful, but
+-  WITHOUT ANY WARRANTY; without even the implied warranty of
+-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+-  General Public License for more details.
++  This library is free software; you can redistribute it and/or modify
++  it under the terms of the GNU Lesser General Public License as
++  published by the Free Software Foundation; either version 2.1 of
++  the License, or (at your option) any later version.
++
++  This program is distributed in the hope that it will be useful,
++  but WITHOUT ANY WARRANTY; without even the implied warranty of
++  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++  GNU Lesser General Public License for more details.
+ 
+   Authors: Mengdong Lin <mengdong.lin@intel.com>
+            Yao Jin <yao.jin@intel.com>
+diff --git a/src/topology/channel.c b/src/topology/channel.c
+index c2f1fea..8516b23 100644
+--- a/src/topology/channel.c
++++ b/src/topology/channel.c
+@@ -2,14 +2,15 @@
+   Copyright(c) 2014-2015 Intel Corporation
+   All rights reserved.
+ 
+-  This program is free software; you can redistribute it and/or modify
+-  it under the terms of version 2 of the GNU General Public License as
+-  published by the Free Software Foundation.
+-
+-  This program is distributed in the hope that it will be useful, but
+-  WITHOUT ANY WARRANTY; without even the implied warranty of
+-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+-  General Public License for more details.
++  This library is free software; you can redistribute it and/or modify
++  it under the terms of the GNU Lesser General Public License as
++  published by the Free Software Foundation; either version 2.1 of
++  the License, or (at your option) any later version.
++
++  This program is distributed in the hope that it will be useful,
++  but WITHOUT ANY WARRANTY; without even the implied warranty of
++  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++  GNU Lesser General Public License for more details.
+ 
+   Authors: Mengdong Lin <mengdong.lin@intel.com>
+            Yao Jin <yao.jin@intel.com>
+diff --git a/src/topology/ctl.c b/src/topology/ctl.c
+index 907a97f..1da3d18 100644
+--- a/src/topology/ctl.c
++++ b/src/topology/ctl.c
+@@ -2,14 +2,15 @@
+   Copyright(c) 2014-2015 Intel Corporation
+   All rights reserved.
+ 
+-  This program is free software; you can redistribute it and/or modify
+-  it under the terms of version 2 of the GNU General Public License as
+-  published by the Free Software Foundation.
+-
+-  This program is distributed in the hope that it will be useful, but
+-  WITHOUT ANY WARRANTY; without even the implied warranty of
+-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+-  General Public License for more details.
++  This library is free software; you can redistribute it and/or modify
++  it under the terms of the GNU Lesser General Public License as
++  published by the Free Software Foundation; either version 2.1 of
++  the License, or (at your option) any later version.
++
++  This program is distributed in the hope that it will be useful,
++  but WITHOUT ANY WARRANTY; without even the implied warranty of
++  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++  GNU Lesser General Public License for more details.
+ 
+   Authors: Mengdong Lin <mengdong.lin@intel.com>
+            Yao Jin <yao.jin@intel.com>
+diff --git a/src/topology/dapm.c b/src/topology/dapm.c
+index 8c585a7..eef72bb 100644
+--- a/src/topology/dapm.c
++++ b/src/topology/dapm.c
+@@ -2,14 +2,15 @@
+   Copyright(c) 2014-2015 Intel Corporation
+   All rights reserved.
+ 
+-  This program is free software; you can redistribute it and/or modify
+-  it under the terms of version 2 of the GNU General Public License as
+-  published by the Free Software Foundation.
+-
+-  This program is distributed in the hope that it will be useful, but
+-  WITHOUT ANY WARRANTY; without even the implied warranty of
+-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+-  General Public License for more details.
++  This library is free software; you can redistribute it and/or modify
++  it under the terms of the GNU Lesser General Public License as
++  published by the Free Software Foundation; either version 2.1 of
++  the License, or (at your option) any later version.
++
++  This program is distributed in the hope that it will be useful,
++  but WITHOUT ANY WARRANTY; without even the implied warranty of
++  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++  GNU Lesser General Public License for more details.
+ 
+   Authors: Mengdong Lin <mengdong.lin@intel.com>
+            Yao Jin <yao.jin@intel.com>
+diff --git a/src/topology/data.c b/src/topology/data.c
+index 0d5c430..e2aa38c 100644
+--- a/src/topology/data.c
++++ b/src/topology/data.c
+@@ -2,14 +2,15 @@
+   Copyright(c) 2014-2015 Intel Corporation
+   All rights reserved.
+ 
+-  This program is free software; you can redistribute it and/or modify
+-  it under the terms of version 2 of the GNU General Public License as
+-  published by the Free Software Foundation.
+-
+-  This program is distributed in the hope that it will be useful, but
+-  WITHOUT ANY WARRANTY; without even the implied warranty of
+-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+-  General Public License for more details.
++  This library is free software; you can redistribute it and/or modify
++  it under the terms of the GNU Lesser General Public License as
++  published by the Free Software Foundation; either version 2.1 of
++  the License, or (at your option) any later version.
++
++  This program is distributed in the hope that it will be useful,
++  but WITHOUT ANY WARRANTY; without even the implied warranty of
++  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++  GNU Lesser General Public License for more details.
+ 
+   Authors: Mengdong Lin <mengdong.lin@intel.com>
+            Yao Jin <yao.jin@intel.com>
+diff --git a/src/topology/elem.c b/src/topology/elem.c
+index db26483..efcf3e9 100644
+--- a/src/topology/elem.c
++++ b/src/topology/elem.c
+@@ -2,14 +2,15 @@
+   Copyright(c) 2014-2015 Intel Corporation
+   All rights reserved.
+ 
+-  This program is free software; you can redistribute it and/or modify
+-  it under the terms of version 2 of the GNU General Public License as
+-  published by the Free Software Foundation.
+-
+-  This program is distributed in the hope that it will be useful, but
+-  WITHOUT ANY WARRANTY; without even the implied warranty of
+-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+-  General Public License for more details.
++  This library is free software; you can redistribute it and/or modify
++  it under the terms of the GNU Lesser General Public License as
++  published by the Free Software Foundation; either version 2.1 of
++  the License, or (at your option) any later version.
++
++  This program is distributed in the hope that it will be useful,
++  but WITHOUT ANY WARRANTY; without even the implied warranty of
++  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++  GNU Lesser General Public License for more details.
+ 
+   Authors: Mengdong Lin <mengdong.lin@intel.com>
+            Yao Jin <yao.jin@intel.com>
+diff --git a/src/topology/ops.c b/src/topology/ops.c
+index 1b5c1e2..6f8dc1f 100644
+--- a/src/topology/ops.c
++++ b/src/topology/ops.c
+@@ -2,14 +2,15 @@
+   Copyright(c) 2014-2015 Intel Corporation
+   All rights reserved.
+ 
+-  This program is free software; you can redistribute it and/or modify
+-  it under the terms of version 2 of the GNU General Public License as
+-  published by the Free Software Foundation.
+-
+-  This program is distributed in the hope that it will be useful, but
+-  WITHOUT ANY WARRANTY; without even the implied warranty of
+-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+-  General Public License for more details.
++  This library is free software; you can redistribute it and/or modify
++  it under the terms of the GNU Lesser General Public License as
++  published by the Free Software Foundation; either version 2.1 of
++  the License, or (at your option) any later version.
++
++  This program is distributed in the hope that it will be useful,
++  but WITHOUT ANY WARRANTY; without even the implied warranty of
++  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++  GNU Lesser General Public License for more details.
+ 
+   Authors: Mengdong Lin <mengdong.lin@intel.com>
+            Yao Jin <yao.jin@intel.com>
+diff --git a/src/topology/parser.c b/src/topology/parser.c
+index c5f9757..cfc20e0 100644
+--- a/src/topology/parser.c
++++ b/src/topology/parser.c
+@@ -2,14 +2,15 @@
+   Copyright(c) 2014-2015 Intel Corporation
+   All rights reserved.
+ 
+-  This program is free software; you can redistribute it and/or modify
+-  it under the terms of version 2 of the GNU General Public License as
+-  published by the Free Software Foundation.
+-
+-  This program is distributed in the hope that it will be useful, but
+-  WITHOUT ANY WARRANTY; without even the implied warranty of
+-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+-  General Public License for more details.
++  This library is free software; you can redistribute it and/or modify
++  it under the terms of the GNU Lesser General Public License as
++  published by the Free Software Foundation; either version 2.1 of
++  the License, or (at your option) any later version.
++
++  This program is distributed in the hope that it will be useful,
++  but WITHOUT ANY WARRANTY; without even the implied warranty of
++  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++  GNU Lesser General Public License for more details.
+ 
+   Authors: Mengdong Lin <mengdong.lin@intel.com>
+            Yao Jin <yao.jin@intel.com>
+diff --git a/src/topology/pcm.c b/src/topology/pcm.c
+index 8f8a703..5568d57 100644
+--- a/src/topology/pcm.c
++++ b/src/topology/pcm.c
+@@ -2,14 +2,15 @@
+   Copyright(c) 2014-2015 Intel Corporation
+   All rights reserved.
+ 
+-  This program is free software; you can redistribute it and/or modify
+-  it under the terms of version 2 of the GNU General Public License as
+-  published by the Free Software Foundation.
+-
+-  This program is distributed in the hope that it will be useful, but
+-  WITHOUT ANY WARRANTY; without even the implied warranty of
+-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+-  General Public License for more details.
++  This library is free software; you can redistribute it and/or modify
++  it under the terms of the GNU Lesser General Public License as
++  published by the Free Software Foundation; either version 2.1 of
++  the License, or (at your option) any later version.
++
++  This program is distributed in the hope that it will be useful,
++  but WITHOUT ANY WARRANTY; without even the implied warranty of
++  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++  GNU Lesser General Public License for more details.
+ 
+   Authors: Mengdong Lin <mengdong.lin@intel.com>
+            Yao Jin <yao.jin@intel.com>
+diff --git a/src/topology/text.c b/src/topology/text.c
+index 303fbeb..cba6887 100644
+--- a/src/topology/text.c
++++ b/src/topology/text.c
+@@ -2,14 +2,15 @@
+   Copyright(c) 2014-2015 Intel Corporation
+   All rights reserved.
+ 
+-  This program is free software; you can redistribute it and/or modify
+-  it under the terms of version 2 of the GNU General Public License as
+-  published by the Free Software Foundation.
+-
+-  This program is distributed in the hope that it will be useful, but
+-  WITHOUT ANY WARRANTY; without even the implied warranty of
+-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+-  General Public License for more details.
++  This library is free software; you can redistribute it and/or modify
++  it under the terms of the GNU Lesser General Public License as
++  published by the Free Software Foundation; either version 2.1 of
++  the License, or (at your option) any later version.
++
++  This program is distributed in the hope that it will be useful,
++  but WITHOUT ANY WARRANTY; without even the implied warranty of
++  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++  GNU Lesser General Public License for more details.
+ 
+   Authors: Mengdong Lin <mengdong.lin@intel.com>
+            Yao Jin <yao.jin@intel.com>
+-- 
+2.9.3
+
+
+From 4dfa8f08fb834f7b087f35f9ba1746cd0c989d02 Mon Sep 17 00:00:00 2001
+From: Manohar Narkhede <Manohar.Narkhede@imgtec.com>
+Date: Wed, 25 Jan 2017 22:14:15 +0100
+Subject: [PATCH 20/37] conf/cards: add support for pistachio-card.
+
+The data sheet of the chip and technical reference manual can be found at https://docs.creatordev.io/ci40/guides/hardwaredocs/cXT200_datasheet2.pdf
+and https://docs.creatordev.io/ci40/guides/hardwaredocs/MIPS_Creator_cXT200_Technical_Reference_Manual_1.0.112.pdf.
+
+The additional information about the cards can be found in src/conf/cards/pistachio-card.conf file.
+
+Signed-off-by: Manohar Narkhede <Manohar.Narkhede@imgtec.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+---
+ src/conf/cards/Makefile.am         |  1 +
+ src/conf/cards/aliases.conf        |  1 +
+ src/conf/cards/pistachio-card.conf | 58 ++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 60 insertions(+)
+ create mode 100644 src/conf/cards/pistachio-card.conf
+
+diff --git a/src/conf/cards/Makefile.am b/src/conf/cards/Makefile.am
+index 008d399..60b5309 100644
+--- a/src/conf/cards/Makefile.am
++++ b/src/conf/cards/Makefile.am
+@@ -39,6 +39,7 @@ cfg_files = aliases.conf \
+ 	Maestro3.conf \
+ 	NFORCE.conf \
+ 	PC-Speaker.conf \
++	pistachio-card.conf \
+ 	PMac.conf \
+ 	PMacToonie.conf \
+ 	PS3.conf \
+diff --git a/src/conf/cards/aliases.conf b/src/conf/cards/aliases.conf
+index 4a92fb2..60f9d26 100644
+--- a/src/conf/cards/aliases.conf
++++ b/src/conf/cards/aliases.conf
+@@ -55,6 +55,7 @@ AV100 cards.CMI8788
+ AV200 cards.CMI8788
+ CMI8786 cards.CMI8788
+ CMI8787 cards.CMI8788
++pistachio cards.pistachio-card
+ 
+ <confdir:pcm/default.conf>
+ <confdir:pcm/dmix.conf>
+diff --git a/src/conf/cards/pistachio-card.conf b/src/conf/cards/pistachio-card.conf
+new file mode 100644
+index 0000000..59cd920
+--- /dev/null
++++ b/src/conf/cards/pistachio-card.conf
+@@ -0,0 +1,58 @@
++#
++# Configuration for the pistachio chip.
++#
++# The data sheet of the chip and technical reference manual can be 
++found at 
++https://docs.creatordev.io/ci40/guides/hardwaredocs/cXT200_datasheet2.p
++df # and 
++https://docs.creatordev.io/ci40/guides/hardwaredocs/MIPS_Creator_cXT200_Technical_Reference_Manual_1.0.112.pdf.
++#
++# The list of hardware devices is as per below:
++#
++#  root@OpenWrt:/# arecord -l
++# **** List of CAPTURE Hardware Devices **** card 0: pistachiocard [pistachio-card], device 1: pistachio-spdif-in snd-soc-dummy-dai-1 []
++#   Subdevices: 1/1
++#   Subdevice #0: subdevice #0
++# card 0: pistachiocard [pistachio-card], device 4: pistachio-i2s-in-0 snd-soc-dummy-dai-4 []
++#   Subdevices: 1/1
++#   Subdevice #0: subdevice #0
++#
++# root@OpenWrt:/# aplay -l
++# **** List of PLAYBACK Hardware Devices **** card 0: pistachiocard [pistachio-card], device 0: pistachio-spdif-out snd-soc-dummy-dai-0 []
++#   Subdevices: 1/1
++#   Subdevice #0: subdevice #0
++# card 0: pistachiocard [pistachio-card], device 2: pistachio-parallel-out pistachio_internal_dac-2 []
++#   Subdevices: 1/1
++#   Subdevice #0: subdevice #0
++# card 0: pistachiocard [pistachio-card], device 3: pistachio-i2s-out snd-soc-dummy-dai-3 []
++#   Subdevices: 1/1
++#   Subdevice #0: subdevice #0
++#
++
++pistachio-card.pcm.default{
++        @args [ CARD ]
++        @args.CARD {
++                type string
++                default "pistachio"
++        }
++        @args.DEVICE {
++                type integer
++                default 2
++        }
++
++        type asym
++        capture.pcm {
++                type multi
++                slaves.a.pcm "hw:0,4"
++                slaves.a.channels 12
++                bindings.0.slave a
++                bindings.0.channel 4
++                bindings.1.slave a
++                bindings.1.channel 5
++        }
++
++        playback.pcm {
++                type hw
++                card $CARD
++                device $DEVICE
++
+-- 
+2.9.3
+
+
+From e1143dd9ba350eb19d13d4e298eeb55179712a1e Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Fri, 27 Jan 2017 12:01:51 +0100
+Subject: [PATCH 21/37] pcm: multi: Drop the fixed slave_map[] in
+ snd_pcm_multi_open()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+slave_map[] in snd_pcm_multi_open() is a fixed size array and
+obviously we have no overflow check, and eventually the program gets
+an error when more than 64 channels are used.
+
+Although we can modify the code to allocate the array dynamically, it
+turned out that we can drop the whole slave_map[] thingy in this
+function when looking at the code closely.  In the past, it was used
+to identify the one-to-many mapping.  But the check was dropped, and
+now it's nothing more than a sanity check.
+
+Reported-by: Jörg Müller <joerg.mueller7744@gmail.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+---
+ src/pcm/pcm_multi.c | 3 ---
+ 1 file changed, 3 deletions(-)
+
+diff --git a/src/pcm/pcm_multi.c b/src/pcm/pcm_multi.c
+index c4b1fba..9e4be71 100644
+--- a/src/pcm/pcm_multi.c
++++ b/src/pcm/pcm_multi.c
+@@ -1015,7 +1015,6 @@ int snd_pcm_multi_open(snd_pcm_t **pcmp, const char *name,
+ 	snd_pcm_multi_t *multi;
+ 	unsigned int i;
+ 	snd_pcm_stream_t stream;
+-	char slave_map[64][64] = { { 0 } };
+ 	int err;
+ 
+ 	assert(pcmp);
+@@ -1059,8 +1058,6 @@ int snd_pcm_multi_open(snd_pcm_t **pcmp, const char *name,
+ 		bind->slave_channel = schannels[i];
+ 		if (sidxs[i] < 0)
+ 			continue;
+-		assert(!slave_map[sidxs[i]][schannels[i]]);
+-		slave_map[sidxs[i]][schannels[i]] = 1;
+ 	}
+ 	multi->channels_count = channels_count;
+ 
+-- 
+2.9.3
+
+
+From 53dc36f1f465e2a1f9ed37906a7f16a438f941e4 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 7 Feb 2017 14:25:17 +0100
+Subject: [PATCH 22/37] conf: Add card config for Intel HDMI/DP LPE audio
+
+It's a playback-only device with a single PCM dedicated for HDMI/DP
+output.  The dmix is working with the latest driver code, so enable it
+for default, while providing the hdmi PCM dev for the accesses with
+AES bits.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+---
+ src/conf/cards/HdmiLpeAudio.conf | 85 ++++++++++++++++++++++++++++++++++++++++
+ src/conf/cards/Makefile.am       |  1 +
+ 2 files changed, 86 insertions(+)
+ create mode 100644 src/conf/cards/HdmiLpeAudio.conf
+
+diff --git a/src/conf/cards/HdmiLpeAudio.conf b/src/conf/cards/HdmiLpeAudio.conf
+new file mode 100644
+index 0000000..f5836c0
+--- /dev/null
++++ b/src/conf/cards/HdmiLpeAudio.conf
+@@ -0,0 +1,85 @@
++#
++# Configuration for the Intel HDMI/DP LPE audio
++#
++
++<confdir:pcm/front.conf>
++
++HdmiLpeAudio.pcm.front.0 {
++	@args [ CARD ]
++	@args.CARD {
++		type string
++	}
++	type softvol
++	slave.pcm {
++		type hw
++		card $CARD
++	}
++	control {
++		name "PCM Playback Volume"
++		card $CARD
++	}
++}
++
++# default with dmix+softvol
++HdmiLpeAudio.pcm.default {
++	@args [ CARD ]
++	@args.CARD {
++		type string
++	}
++	type plug
++	slave.pcm {
++		type softvol
++		slave.pcm {
++			@func concat
++			strings [ "dmix:" $CARD ]
++		}
++		control {
++			name "PCM Playback Volume"
++			card $CARD
++		}
++	}
++}
++
++<confdir:pcm/surround40.conf>
++<confdir:pcm/surround21.conf>
++<confdir:pcm/surround41.conf>
++<confdir:pcm/surround50.conf>
++<confdir:pcm/surround51.conf>
++
++<confdir:pcm/hdmi.conf>
++
++HdmiLpeAudio.pcm.hdmi.0 {
++	@args [ CARD AES0 AES1 AES2 AES3 ]
++	@args.CARD {
++		type string
++	}
++	@args.AES0 {
++		type integer
++	}
++	@args.AES1 {
++		type integer
++	}
++	@args.AES2 {
++		type integer
++	}
++	@args.AES3 {
++		type integer
++	}
++	type hooks
++	slave.pcm {
++		type hw
++		card $CARD
++	}
++	hooks.0 {
++		type ctl_elems
++		hook_args [
++			{
++				interface PCM
++				name "IEC958 Playback Default"
++				lock true
++				preserve true
++				value [ $AES0 $AES1 $AES2 $AES3 ]
++			}
++		]
++	}
++}
+diff --git a/src/conf/cards/Makefile.am b/src/conf/cards/Makefile.am
+index 60b5309..e8b530e 100644
+--- a/src/conf/cards/Makefile.am
++++ b/src/conf/cards/Makefile.am
+@@ -30,6 +30,7 @@ cfg_files = aliases.conf \
+ 	FireWave.conf \
+ 	GUS.conf \
+ 	HDA-Intel.conf \
++	HdmiLpeAudio.conf \
+ 	ICE1712.conf \
+ 	ICE1724.conf \
+ 	ICH.conf \
+-- 
+2.9.3
+
+
+From b5a2c06f6c5d69fc71ef648af95a044ee1dc25d0 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Thu, 9 Feb 2017 17:23:22 +0100
+Subject: [PATCH 23/37] pcm: Avoid lock for snd_pcm_nonblock()
+
+snd_pcm_nonblock() is called as snd_pcm_abort().  Since
+snd_pcm_abort() is called often from a signal handler to clean things
+up (e.g. aplay does it), we may face a deadlock if the signal is
+raised during the locked operation.
+
+There can be some way to check the deadlock state, but they would cost
+much.  Since the race condition of snd_pcm_nonblock() is quite small,
+let's just drop the locking inside snd_pcm_nonblock() as a
+workaround.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+---
+ src/pcm/pcm.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c
+index 0cf740f..c136d55 100644
+--- a/src/pcm/pcm.c
++++ b/src/pcm/pcm.c
+@@ -759,7 +759,10 @@ int snd_pcm_nonblock(snd_pcm_t *pcm, int nonblock)
+ 	int err = 0;
+ 
+ 	assert(pcm);
+-	__snd_pcm_lock(pcm); /* forced lock due to pcm field change */
++	/* FIXME: __snd_pcm_lock() call below is commented out because of the
++	 * the possible deadlock in signal handler calling snd_pcm_abort()
++	 */
++	/* __snd_pcm_lock(pcm); */ /* forced lock due to pcm field change */
+ 	if ((err = pcm->ops->nonblock(pcm->op_arg, nonblock)) < 0)
+ 		goto unlock;
+ 	if (nonblock == 2) {
+@@ -775,7 +778,7 @@ int snd_pcm_nonblock(snd_pcm_t *pcm, int nonblock)
+ 			pcm->mode &= ~SND_PCM_NONBLOCK;
+ 	}
+  unlock:
+-	__snd_pcm_unlock(pcm);
++	/* __snd_pcm_unlock(pcm); */ /* FIXME: see above */
+ 	return err;
+ }
+ 
+-- 
+2.9.3
+
+
+From e31a3273df6eb619e35d10bf6a0fc0fded91d559 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Thu, 9 Feb 2017 17:29:21 +0100
+Subject: [PATCH 24/37] pcm: Disable locking in async mode
+
+When PCM is operated in async mode and an async handler calls some PCM
+functions with lock during other PCM operations, we may hit a
+deadlock.
+
+Although async mode is rarely used, it's still a possible use case.
+Disable the locking when the stream is opened in async mode or it's
+set to async mode via snd_pcm_async().
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+---
+ src/pcm/pcm.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c
+index c136d55..493e903 100644
+--- a/src/pcm/pcm.c
++++ b/src/pcm/pcm.c
+@@ -799,6 +799,8 @@ int snd_pcm_async(snd_pcm_t *pcm, int sig, pid_t pid)
+ 		sig = SIGIO;
+ 	if (pid == 0)
+ 		pid = getpid();
++	/* async handler may lead to a deadlock; suppose no multi thread */
++	pcm->lock_enabled = 0;
+ 	return pcm->ops->async(pcm->op_arg, sig, pid);
+ }
+ #endif
+@@ -2597,7 +2599,10 @@ int snd_pcm_new(snd_pcm_t **pcmp, snd_pcm_type_t type, const char *name,
+ 	 * each plugin may suppress this in its open call
+ 	 */
+ 	pcm->need_lock = 1;
+-	{
++	if (mode & SND_PCM_ASYNC) {
++		/* async handler may lead to a deadlock; suppose no MT */
++		pcm->lock_enabled = 0;
++	} else {
+ 		/* set lock_enabled field depending on $LIBASOUND_THREAD_SAFE */
+ 		static int do_lock_enable = -1; /* uninitialized */
+ 
+-- 
+2.9.3
+
+
+From 22eca6468b4aea47c783770ec0739d1e13bf3bfc Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Fri, 10 Feb 2017 12:16:12 +0100
+Subject: [PATCH 25/37] pcm: dmix: Allow disabling x86 optimizations
+
+The dmix plugin has some optimized implementations for x86 using the
+direct memory accesses, which was rather the original version, in
+addition to the "generic" implementation using the semaphore
+blocking.  The x86 implementation relies on the memory coherency *and*
+the fast read/write on it.
+
+For other architectures, this has been always disabled just because of
+memory coherency.  But, the recent LPE audio development revealed
+that, even on x86 platforms, the read/write performance might become
+extremely bad when the buffer is marked as uncached.  Some drivers
+already know the buffer is uncached, we need to switch to the generic
+mode in such a case.
+
+This patch introduces yet another flag to dmix configuration,
+direct_memory_access, that indicates whether the x86-specific
+optimization can be used or not.  Each driver can set the flag in its
+cards config namespace, and the default dmix config refers to it.
+
+As of this patch, only HDMI LPE Audio driver sets it.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+---
+ src/conf/cards/HdmiLpeAudio.conf |  3 +++
+ src/conf/pcm/dmix.conf           | 15 +++++++++++++++
+ src/pcm/pcm_direct.c             |  8 ++++++++
+ src/pcm/pcm_direct.h             |  2 ++
+ src/pcm/pcm_dmix.c               |  1 +
+ src/pcm/pcm_dmix_i386.c          |  5 +++++
+ src/pcm/pcm_dmix_x86_64.c        |  5 +++++
+ 7 files changed, 39 insertions(+)
+
+diff --git a/src/conf/cards/HdmiLpeAudio.conf b/src/conf/cards/HdmiLpeAudio.conf
+index f5836c0..61bdfea 100644
+--- a/src/conf/cards/HdmiLpeAudio.conf
++++ b/src/conf/cards/HdmiLpeAudio.conf
+@@ -20,6 +20,9 @@ HdmiLpeAudio.pcm.front.0 {
+ 	}
+ }
+ 
++# uncached memory reads have a high penalty
++HdmiLpeAudio.dmix.direct_memory_access false
++
+ # default with dmix+softvol
+ HdmiLpeAudio.pcm.default {
+ 	@args [ CARD ]
+diff --git a/src/conf/pcm/dmix.conf b/src/conf/pcm/dmix.conf
+index 7d0aa01..2d3b329 100644
+--- a/src/conf/pcm/dmix.conf
++++ b/src/conf/pcm/dmix.conf
+@@ -49,6 +49,21 @@ pcm.!dmix {
+ 		@func refer
+ 		name defaults.pcm.ipc_perm
+ 	}
++	direct_memory_access {
++		@func refer
++		name {
++			@func concat
++			strings [
++				"cards."
++				{
++					@func card_driver
++					card $CARD
++				}
++				".dmix.direct_memory_access"
++			]
++		}
++		default true
++	}
+ 	slave {
+ 		pcm {
+ 			type hw
+diff --git a/src/pcm/pcm_direct.c b/src/pcm/pcm_direct.c
+index e4bef78..364191b 100644
+--- a/src/pcm/pcm_direct.c
++++ b/src/pcm/pcm_direct.c
+@@ -1861,6 +1861,7 @@ int snd_pcm_direct_parse_open_conf(snd_config_t *root, snd_config_t *conf,
+ 	rec->slowptr = 1;
+ 	rec->max_periods = 0;
+ 	rec->var_periodsize = 1;
++	rec->direct_memory_access = 1;
+ 
+ 	/* read defaults */
+ 	if (snd_config_search(root, "defaults.pcm.dmix_max_periods", &n) >= 0) {
+@@ -1974,6 +1975,13 @@ int snd_pcm_direct_parse_open_conf(snd_config_t *root, snd_config_t *conf,
+ 			rec->var_periodsize = err;
+ 			continue;
+ 		}
++		if (strcmp(id, "direct_memory_access") == 0) {
++			err = snd_config_get_bool(n);
++			if (err < 0)
++				return err;
++			rec->direct_memory_access = err;
++			continue;
++		}
+ 		SNDERR("Unknown field %s", id);
+ 		return -EINVAL;
+ 	}
+diff --git a/src/pcm/pcm_direct.h b/src/pcm/pcm_direct.h
+index 66107ec..fba55fd 100644
+--- a/src/pcm/pcm_direct.h
++++ b/src/pcm/pcm_direct.h
+@@ -159,6 +159,7 @@ struct snd_pcm_direct {
+ 	unsigned int channels;		/* client's channels */
+ 	unsigned int *bindings;
+ 	unsigned int recoveries;	/* mirror of executed recoveries on slave */
++	int direct_memory_access;	/* use arch-optimized buffer RW */
+ 	union {
+ 		struct {
+ 			int shmid_sum;			/* IPC global sum ring buffer memory identification */
+@@ -340,6 +341,7 @@ struct snd_pcm_direct_open_conf {
+ 	int slowptr;
+ 	int max_periods;
+ 	int var_periodsize;
++	int direct_memory_access;
+ 	snd_config_t *slave;
+ 	snd_config_t *bindings;
+ };
+diff --git a/src/pcm/pcm_dmix.c b/src/pcm/pcm_dmix.c
+index 2ef6159..dd0356e 100644
+--- a/src/pcm/pcm_dmix.c
++++ b/src/pcm/pcm_dmix.c
+@@ -1065,6 +1065,7 @@ int snd_pcm_dmix_open(snd_pcm_t **pcmp, const char *name,
+ 	dmix->max_periods = opts->max_periods;
+ 	dmix->var_periodsize = opts->var_periodsize;
+ 	dmix->sync_ptr = snd_pcm_dmix_sync_ptr;
++	dmix->direct_memory_access = opts->direct_memory_access;
+ 
+  retry:
+ 	if (first_instance) {
+diff --git a/src/pcm/pcm_dmix_i386.c b/src/pcm/pcm_dmix_i386.c
+index dcc6b9a..1ab983a 100644
+--- a/src/pcm/pcm_dmix_i386.c
++++ b/src/pcm/pcm_dmix_i386.c
+@@ -87,6 +87,11 @@ static void mix_select_callbacks(snd_pcm_direct_t *dmix)
+ {
+ 	static int smp = 0, mmx = 0, cmov = 0;
+ 
++	if (!dmix->direct_memory_access) {
++		generic_mix_select_callbacks(dmix);
++		return;
++	}
++
+ 	if (!((1ULL<< dmix->shmptr->s.format) & i386_dmix_supported_format)) {
+ 		generic_mix_select_callbacks(dmix);
+ 		return;
+diff --git a/src/pcm/pcm_dmix_x86_64.c b/src/pcm/pcm_dmix_x86_64.c
+index 831046d..34c40d4 100644
+--- a/src/pcm/pcm_dmix_x86_64.c
++++ b/src/pcm/pcm_dmix_x86_64.c
+@@ -70,6 +70,11 @@ static void mix_select_callbacks(snd_pcm_direct_t *dmix)
+ {
+ 	static int smp = 0;
+ 	
++	if (!dmix->direct_memory_access) {
++		generic_mix_select_callbacks(dmix);
++		return;
++	}
++
+ 	if (!((1ULL<< dmix->shmptr->s.format) & x86_64_dmix_supported_format)) {
+ 		generic_mix_select_callbacks(dmix);
+ 		return;
+-- 
+2.9.3
+
+
+From df7694d80cdd7d273b34ead6841b9f32f5991966 Mon Sep 17 00:00:00 2001
+From: Timo Wischer <twischer@de.adit-jv.com>
+Date: Fri, 17 Feb 2017 12:45:36 +0530
+Subject: [PATCH 26/37] pcm: dmix_rewind corrupts application pointer fix
+
+sometimes pulseaudio stops with the following assertion in libasound.so:
+alsa-lib-1.0.29/src/pcm/pcm.c:2761:
+snd_pcm_area_copy: Assertion `dst < src || dst >= src + bytes' failed.
+Application pointer is handled properly, in cases of rewind operations.
+
+Signed-off-by: Timo Wischer <twischer@de.adit-jv.com>
+Signed-off-by: Ravikiran Polepalli <ravikiran_polepalli@mentor.com>
+Signed-off-by: Mikhail Durnev <mikhail_durnev@mentor.com>
+Signed-off-by: Mounesh Sutar <sutar.mounesh@gmail.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+---
+ src/pcm/pcm_dmix.c | 33 +++++++++++++++++++++++----------
+ 1 file changed, 23 insertions(+), 10 deletions(-)
+
+diff --git a/src/pcm/pcm_dmix.c b/src/pcm/pcm_dmix.c
+index dd0356e..46142e5 100644
+--- a/src/pcm/pcm_dmix.c
++++ b/src/pcm/pcm_dmix.c
+@@ -706,7 +706,7 @@ static snd_pcm_sframes_t snd_pcm_dmix_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t f
+ {
+ 	snd_pcm_direct_t *dmix = pcm->private_data;
+ 	snd_pcm_uframes_t slave_appl_ptr, slave_size;
+-	snd_pcm_uframes_t appl_ptr, size, transfer, result;
++	snd_pcm_uframes_t appl_ptr, size, transfer, result, frames_to_remix;
+ 	int err;
+ 	const snd_pcm_channel_area_t *src_areas, *dst_areas;
+ 
+@@ -717,6 +717,13 @@ static snd_pcm_sframes_t snd_pcm_dmix_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t f
+ 			return err;
+ 	}
+ 
++	/* (appl_ptr - last_appl_ptr) indicates the frames which are not
++	 * already mixed
++	 * (last_appl_ptr - hw_ptr)  indicates the frames which are already
++	 * mixed but not played yet.
++	 * So they can be remixed.
++	 */
++
+ 	if (dmix->last_appl_ptr < dmix->appl_ptr)
+ 		size = dmix->appl_ptr - dmix->last_appl_ptr;
+ 	else
+@@ -729,6 +736,9 @@ static snd_pcm_sframes_t snd_pcm_dmix_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t f
+ 		return size;
+ 	result = size;
+ 
++	/* Always at this point last_appl_ptr == appl_ptr
++	 * So (appl_ptr - hw_ptr) indicates the frames which can be remixed
++	 */
+ 	if (dmix->hw_ptr < dmix->appl_ptr)
+ 		size = dmix->appl_ptr - dmix->hw_ptr;
+ 	else
+@@ -741,9 +751,12 @@ static snd_pcm_sframes_t snd_pcm_dmix_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t f
+ 		slave_size = dmix->slave_appl_ptr + (pcm->boundary - dmix->slave_hw_ptr);
+ 	if (slave_size < size)
+ 		size = slave_size;
+-	frames -= size;
+-	result += size;
+-		
++
++	/* frames which should be remixed will be saved
++	 * to also backward the appl pointer on success
++	 */
++	frames_to_remix = size;
++
+ 	/* add sample areas here */
+ 	src_areas = snd_pcm_mmap_areas(pcm);
+ 	dst_areas = snd_pcm_mmap_areas(dmix->spcm);
+@@ -769,15 +782,15 @@ static snd_pcm_sframes_t snd_pcm_dmix_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t f
+ 		appl_ptr += transfer;
+ 		appl_ptr %= pcm->buffer_size;
+ 	}
+-	dmix->last_appl_ptr -= frames;
+-	dmix->last_appl_ptr %= pcm->boundary;
+-	dmix->slave_appl_ptr -= frames;
+-	dmix->slave_appl_ptr %= dmix->slave_boundary;
+ 	dmix_up_sem(dmix);
+ 
+-	snd_pcm_mmap_appl_backward(pcm, frames);
++	snd_pcm_mmap_appl_backward(pcm, frames_to_remix);
++	result += frames_to_remix;
++	/* At this point last_appl_ptr and appl_ptr has to indicate the
++	 * position of the first not mixed frame
++	 */
+ 
+-	return result + frames;
++	return result;
+ }
+ 
+ static snd_pcm_sframes_t snd_pcm_dmix_forwardable(snd_pcm_t *pcm)
+-- 
+2.9.3
+
+
+From 9219034301a3bf3d8de57ac5672bbc1c53f18049 Mon Sep 17 00:00:00 2001
+From: Andreas Pape <apape@de.adit-jv.com>
+Date: Fri, 17 Feb 2017 12:45:56 +0530
+Subject: [PATCH 27/37] pcm: direct: fix race on clearing timer events
+
+snd_timer handling is racy: plugins clear timer queue if avail_min
+is not reached to force a sleep on timer. The race can happen if
+the expected event arrives in between the avail check and the
+clearing of pending events. If this race happens, the user will
+unnecessarily wait for one more timer event. On low latency/realtime
+streams this can lead to xruns and must be avoided.
+
+As a fix we recheck avail after having cleared poll events.
+
+Signed-off-by: Andreas Pape <apape@de.adit-jv.com>
+Signed-off-by: Jiada Wang <jiada_wang@mentor.com>
+Signed-off-by: Mounesh Sutar <sutar.mounesh@gmail.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+---
+ src/pcm/pcm_direct.c | 23 +++++++++++++++++++----
+ src/pcm/pcm_direct.h |  2 +-
+ 2 files changed, 20 insertions(+), 5 deletions(-)
+
+diff --git a/src/pcm/pcm_direct.c b/src/pcm/pcm_direct.c
+index 364191b..8a75c42 100644
+--- a/src/pcm/pcm_direct.c
++++ b/src/pcm/pcm_direct.c
+@@ -515,10 +515,12 @@ int snd_pcm_direct_async(snd_pcm_t *pcm, int sig, pid_t pid)
+ }
+ 
+ /* empty the timer read queue */
+-void snd_pcm_direct_clear_timer_queue(snd_pcm_direct_t *dmix)
++int snd_pcm_direct_clear_timer_queue(snd_pcm_direct_t *dmix)
+ {
++	int changed = 0;
+ 	if (dmix->timer_need_poll) {
+ 		while (poll(&dmix->timer_fd, 1, 0) > 0) {
++			changed++;
+ 			/* we don't need the value */
+ 			if (dmix->tread) {
+ 				snd_timer_tread_t rbuf[4];
+@@ -533,15 +535,17 @@ void snd_pcm_direct_clear_timer_queue(snd_pcm_direct_t *dmix)
+ 			snd_timer_tread_t rbuf[4];
+ 			int len;
+ 			while ((len = snd_timer_read(dmix->timer, rbuf,
+-						     sizeof(rbuf))) > 0 &&
++						     sizeof(rbuf))) > 0
++						     && (++changed) &&
+ 			       len != sizeof(rbuf[0]))
+ 				;
+ 		} else {
+ 			snd_timer_read_t rbuf;
+ 			while (snd_timer_read(dmix->timer, &rbuf, sizeof(rbuf)) > 0)
+-				;
++				changed++;
+ 		}
+ 	}
++	return changed;
+ }
+ 
+ int snd_pcm_direct_timer_stop(snd_pcm_direct_t *dmix)
+@@ -693,6 +697,8 @@ int snd_pcm_direct_poll_revents(snd_pcm_t *pcm, struct pollfd *pfds, unsigned in
+ 	int empty = 0;
+ 
+ 	assert(pfds && nfds == 1 && revents);
++
++timer_changed:
+ 	events = pfds[0].revents;
+ 	if (events & POLLIN) {
+ 		snd_pcm_uframes_t avail;
+@@ -720,7 +726,16 @@ int snd_pcm_direct_poll_revents(snd_pcm_t *pcm, struct pollfd *pfds, unsigned in
+ 		break;
+ 	default:
+ 		if (empty) {
+-			snd_pcm_direct_clear_timer_queue(dmix);
++			/* here we have a race condition:
++			 * if period event arrived after the avail_update call
++			 * above we might clear this event with the following
++			 * clear_timer_queue.
++			 * There is no way to do this in atomic manner, so we
++			 * need to recheck avail_update if we successfully
++			 * cleared a poll event.
++			 */
++			if (snd_pcm_direct_clear_timer_queue(dmix))
++				goto timer_changed;
+ 			events &= ~(POLLOUT|POLLIN);
+ 			/* additional check */
+ 			switch (__snd_pcm_state(pcm)) {
+diff --git a/src/pcm/pcm_direct.h b/src/pcm/pcm_direct.h
+index fba55fd..24e85f0 100644
+--- a/src/pcm/pcm_direct.h
++++ b/src/pcm/pcm_direct.h
+@@ -322,7 +322,7 @@ int snd_pcm_direct_munmap(snd_pcm_t *pcm);
+ int snd_pcm_direct_prepare(snd_pcm_t *pcm);
+ int snd_pcm_direct_resume(snd_pcm_t *pcm);
+ int snd_pcm_direct_timer_stop(snd_pcm_direct_t *dmix);
+-void snd_pcm_direct_clear_timer_queue(snd_pcm_direct_t *dmix);
++int snd_pcm_direct_clear_timer_queue(snd_pcm_direct_t *dmix);
+ int snd_pcm_direct_set_timer_params(snd_pcm_direct_t *dmix);
+ int snd_pcm_direct_open_secondary_client(snd_pcm_t **spcmp, snd_pcm_direct_t *dmix, const char *client_name);
+ 
+-- 
+2.9.3
+
+
+From fe65b00f337dd08f8c14d54b0ce6b516424d78e8 Mon Sep 17 00:00:00 2001
+From: Timo Wischer <twischer@de.adit-jv.com>
+Date: Fri, 17 Feb 2017 12:47:17 +0530
+Subject: [PATCH 28/37] pcm: file: Enable file writing for capture path
+
+This commit reverts parts of commit 4081be0b87ab9fa53a8906e66bc240f18a7a9a54,
+because it is realy useful to use the file plugin in a capture path for
+debugging. Also it fixes the truncate issue mentioned in above commit.
+
+Additionally following MMAP access issue is considered:
+$ arecord -D teeraw -M -d5 arecord.wav
+Recording WAVE 'arecord.wav' : Unsigned 8 bit, Rate 8000 Hz, Mono
+ALSA lib pcm/pcm_file.c:358:(snd_pcm_file_write_bytes)
+write failed: Bad file descriptor
+ALSA lib pcm/pcm_file.c:358:(snd_pcm_file_write_bytes)
+write failed: Bad file descriptor
+arecord: pcm/pcm_file.c:397: snd_pcm_file_add_frames:
+Assertion `file->wbuf_used_bytes < file->wbuf_size_bytes' failed.
+Aborted by signal Aborted...
+
+Signed-off-by: Timo Wischer <twischer@de.adit-jv.com>
+Signed-off-by: Mounesh Sutar <sutar.mounesh@gmail.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+---
+ src/pcm/pcm_file.c | 12 ++++++++++--
+ 1 file changed, 10 insertions(+), 2 deletions(-)
+
+diff --git a/src/pcm/pcm_file.c b/src/pcm/pcm_file.c
+index 6d119d6..0363f84 100644
+--- a/src/pcm/pcm_file.c
++++ b/src/pcm/pcm_file.c
+@@ -544,6 +544,7 @@ static snd_pcm_sframes_t snd_pcm_file_writen(snd_pcm_t *pcm, void **bufs, snd_pc
+ static snd_pcm_sframes_t snd_pcm_file_readi(snd_pcm_t *pcm, void *buffer, snd_pcm_uframes_t size)
+ {
+ 	snd_pcm_file_t *file = pcm->private_data;
++	snd_pcm_channel_area_t areas[pcm->channels];
+ 	snd_pcm_sframes_t n;
+ 
+ 	n = _snd_pcm_readi(file->gen.slave, buffer, size);
+@@ -555,8 +556,10 @@ static snd_pcm_sframes_t snd_pcm_file_readi(snd_pcm_t *pcm, void *buffer, snd_pc
+ 		__snd_pcm_unlock(pcm);
+ 		if (n < 0)
+ 			return n;
+-		return n * 8 / pcm->frame_bits;
++		n = n * 8 / pcm->frame_bits;
+ 	}
++	snd_pcm_areas_from_buf(pcm, areas, buffer);
++	snd_pcm_file_add_frames(pcm, areas, 0, n);
+ 	return n;
+ }
+ 
+@@ -564,6 +567,7 @@ static snd_pcm_sframes_t snd_pcm_file_readi(snd_pcm_t *pcm, void *buffer, snd_pc
+ static snd_pcm_sframes_t snd_pcm_file_readn(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size)
+ {
+ 	snd_pcm_file_t *file = pcm->private_data;
++	snd_pcm_channel_area_t areas[pcm->channels];
+ 	snd_pcm_sframes_t n;
+ 
+ 	if (file->ifd >= 0) {
+@@ -572,6 +576,10 @@ static snd_pcm_sframes_t snd_pcm_file_readn(snd_pcm_t *pcm, void **bufs, snd_pcm
+ 	}
+ 
+ 	n = _snd_pcm_readn(file->gen.slave, bufs, size);
++	if (n > 0) {
++		snd_pcm_areas_from_bufs(pcm, areas, bufs);
++		snd_pcm_file_add_frames(pcm, areas, 0, n);
++	}
+ 	return n;
+ }
+ 
+@@ -635,7 +643,7 @@ static int snd_pcm_file_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params)
+ 		a->first = slave->sample_bits * channel;
+ 		a->step = slave->frame_bits;
+ 	}
+-	if ((file->fd < 0) && (pcm->stream == SND_PCM_STREAM_PLAYBACK)) {
++	if (file->fd < 0) {
+ 		err = snd_pcm_file_open_output_file(file);
+ 		if (err < 0) {
+ 			SYSERR("failed opening output file %s", file->fname);
+-- 
+2.9.3
+
+
+From a50496346f39e91ecd42cb09bc5c95321131be55 Mon Sep 17 00:00:00 2001
+From: Andreas Pape <apape@de.adit-jv.com>
+Date: Fri, 17 Feb 2017 12:47:36 +0530
+Subject: [PATCH 29/37] pcm: status dump fix timestamp formatting
+
+nanosecond part formatted with %06 will give incorrect/confusing results:
+
+trigger_time: 154.9748287
+trigger_time: 154.60109090
+trigger_time: 154.110425257
+
+time seems to run backwards...
+
+This patch converts to us before printing
+which gives the correct/expected result:
+
+trigger_time: 154.009748
+trigger_time: 154.060109
+trigger_time: 154.110425
+
+Signed-off-by: Andreas Pape <apape@de.adit-jv.com>
+Signed-off-by: Mounesh Sutar <sutar.mounesh@gmail.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+---
+ src/pcm/pcm.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c
+index 493e903..a16fd86 100644
+--- a/src/pcm/pcm.c
++++ b/src/pcm/pcm.c
+@@ -2194,9 +2194,10 @@ int snd_pcm_status_dump(snd_pcm_status_t *status, snd_output_t *out)
+ 	assert(status);
+ 	snd_output_printf(out, "  state       : %s\n", snd_pcm_state_name((snd_pcm_state_t) status->state));
+ 	snd_output_printf(out, "  trigger_time: %ld.%06ld\n",
+-		status->trigger_tstamp.tv_sec, status->trigger_tstamp.tv_nsec);
++			  status->trigger_tstamp.tv_sec,
++			  status->trigger_tstamp.tv_nsec / 1000);
+ 	snd_output_printf(out, "  tstamp      : %ld.%06ld\n",
+-		status->tstamp.tv_sec, status->tstamp.tv_nsec);
++		status->tstamp.tv_sec, status->tstamp.tv_nsec / 1000);
+ 	snd_output_printf(out, "  delay       : %ld\n", (long)status->delay);
+ 	snd_output_printf(out, "  avail       : %ld\n", (long)status->avail);
+ 	snd_output_printf(out, "  avail_max   : %ld\n", (long)status->avail_max);
+-- 
+2.9.3
+
+
+From fbb957138135e09ed9fd0180dcad549aad815465 Mon Sep 17 00:00:00 2001
+From: Awais Belal <awais_belal@mentor.com>
+Date: Fri, 17 Feb 2017 12:47:49 +0530
+Subject: [PATCH 30/37] pcm: extplug: refinement of masks in extplug
+
+It should be possible to use empty mask format with extplug.
+The refinement of mask via extplug is now modified,
+to accept empty masks as well to work properly.
+
+Signed-off-by: Awais Belal <awais_belal@mentor.com>
+Signed-off-by: Mounesh Sutar <sutar.mounesh@gmail.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+---
+ src/pcm/pcm_extplug.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/src/pcm/pcm_extplug.c b/src/pcm/pcm_extplug.c
+index a04f826..1004f54 100644
+--- a/src/pcm/pcm_extplug.c
++++ b/src/pcm/pcm_extplug.c
+@@ -172,6 +172,8 @@ int snd_ext_parm_mask_refine(snd_mask_t *mask, struct snd_ext_parm *parm, int ty
+ 	unsigned int i;
+ 
+ 	parm += type;
++	if (!parm->active)
++		return 0;
+ 	memset(&bits, 0, sizeof(bits));
+ 	for (i = 0; i < parm->num_list; i++)
+ 		bits.bits[parm->list[i] / 32] |= 1U << (parm->list[i] % 32);
+-- 
+2.9.3
+
+
+From 97be19cf6f44fc5084828114c53281dff6e365b4 Mon Sep 17 00:00:00 2001
+From: Alan Young <consult.awy@gmail.com>
+Date: Thu, 7 Apr 2016 09:15:04 +0100
+Subject: [PATCH 31/37] pcm: rate: Add capability to pass configuration node to
+ plugins
+
+If a rate plugin uses a node (compound) instead of a plain string for
+its "converter", and that compound is not a simple string array, then
+the compound will be passed as an additional parameter to the new plugin
+open() function (SND_PCM_RATE_PLUGIN_CONF_ENTRY(XXX)). The previous
+open() function (SND_PCM_RATE_PLUGIN_ENTRY(XXX)) will be called if the
+CONF version is not found. It is up to the plugin to determine whether
+the presence of the conf parameter is mandatory.
+
+Signed-off-by: Alan Young <consult.awy@gmail.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+---
+ include/pcm_rate.h |  5 +++-
+ src/pcm/pcm_rate.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++------
+ 2 files changed, 82 insertions(+), 10 deletions(-)
+
+diff --git a/include/pcm_rate.h b/include/pcm_rate.h
+index 4d70df2..da278ac 100644
+--- a/include/pcm_rate.h
++++ b/include/pcm_rate.h
+@@ -120,11 +120,14 @@ typedef struct snd_pcm_rate_ops {
+ typedef int (*snd_pcm_rate_open_func_t)(unsigned int version, void **objp,
+ 					snd_pcm_rate_ops_t *opsp);
+ 
++typedef int (*snd_pcm_rate_open_conf_func_t)(unsigned int version, void **objp,
++					snd_pcm_rate_ops_t *opsp, const snd_config_t *conf);
++
+ /**
+  * Define the object entry for external PCM rate-converter plugins
+  */
+ #define SND_PCM_RATE_PLUGIN_ENTRY(name) _snd_pcm_rate_##name##_open
+-
++#define SND_PCM_RATE_PLUGIN_CONF_ENTRY(name) _snd_pcm_rate_##name##_open_conf
+ 
+ #ifndef DOC_HIDDEN
+ /* old rate_ops for protocol version 0x010001 */
+diff --git a/src/pcm/pcm_rate.c b/src/pcm/pcm_rate.c
+index cbb7618..46eb797 100644
+--- a/src/pcm/pcm_rate.c
++++ b/src/pcm/pcm_rate.c
+@@ -1258,26 +1258,48 @@ static const char *const default_rate_plugins[] = {
+ 	"speexrate", "linear", NULL
+ };
+ 
+-static int rate_open_func(snd_pcm_rate_t *rate, const char *type, int verbose)
++static int rate_open_func(snd_pcm_rate_t *rate, const char *type, const snd_config_t *converter_conf, int verbose)
+ {
+-	char open_name[64], lib_name[128], *lib = NULL;
++	char open_name[64], open_conf_name[64], lib_name[128], *lib = NULL;
+ 	snd_pcm_rate_open_func_t open_func;
++	snd_pcm_rate_open_conf_func_t open_conf_func;
+ 	int err;
+ 
+ 	snprintf(open_name, sizeof(open_name), "_snd_pcm_rate_%s_open", type);
++	snprintf(open_conf_name, sizeof(open_conf_name), "_snd_pcm_rate_%s_open_conf", type);
+ 	if (!is_builtin_plugin(type)) {
+ 		snprintf(lib_name, sizeof(lib_name),
+ 				 "%s/libasound_module_rate_%s.so", ALSA_PLUGIN_DIR, type);
+ 		lib = lib_name;
+ 	}
++
++	rate->rate_min = SND_PCM_PLUGIN_RATE_MIN;
++	rate->rate_max = SND_PCM_PLUGIN_RATE_MAX;
++	rate->plugin_version = SND_PCM_RATE_PLUGIN_VERSION;
++
++	open_conf_func = snd_dlobj_cache_get(lib, open_conf_name, NULL, verbose && converter_conf != NULL);
++	if (open_conf_func) {
++		err = open_conf_func(SND_PCM_RATE_PLUGIN_VERSION,
++				     &rate->obj, &rate->ops, converter_conf);
++		if (!err) {
++			rate->plugin_version = rate->ops.version;
++			if (rate->ops.get_supported_rates)
++				rate->ops.get_supported_rates(rate->obj,
++							      &rate->rate_min,
++							      &rate->rate_max);
++			rate->open_func = open_conf_func;
++			return 0;
++		} else {
++			snd_dlobj_cache_put(open_conf_func);
++			return err;
++		}
++	}
++
+ 	open_func = snd_dlobj_cache_get(lib, open_name, NULL, verbose);
+ 	if (!open_func)
+ 		return -ENOENT;
+ 
+ 	rate->open_func = open_func;
+-	rate->rate_min = SND_PCM_PLUGIN_RATE_MIN;
+-	rate->rate_max = SND_PCM_PLUGIN_RATE_MAX;
+-	rate->plugin_version = SND_PCM_RATE_PLUGIN_VERSION;
+ 
+ 	err = open_func(SND_PCM_RATE_PLUGIN_VERSION, &rate->obj, &rate->ops);
+ 	if (!err) {
+@@ -1301,6 +1323,30 @@ static int rate_open_func(snd_pcm_rate_t *rate, const char *type, int verbose)
+ }
+ #endif
+ 
++/*
++ * If the conf is an array of alternatives then the id of
++ * the first element will be "0" (or maybe NULL). Otherwise assume it is
++ * a structure.
++ */
++static int is_string_array(const snd_config_t *conf)
++{
++	snd_config_iterator_t i;
++
++	if (snd_config_get_type(conf) != SND_CONFIG_TYPE_COMPOUND)
++		return 0;
++
++	i = snd_config_iterator_first(conf);
++	if (i && i != snd_config_iterator_end(conf)) {
++		snd_config_t *n = snd_config_iterator_entry(i);
++		const char *id;
++		snd_config_get_id(n, &id);
++		if (id && strcmp(id, "0") != 0)
++			return 0;
++	}
++
++	return 1;
++}
++
+ /**
+  * \brief Creates a new rate PCM
+  * \param pcmp Returns created PCM handle
+@@ -1353,24 +1399,42 @@ int snd_pcm_rate_open(snd_pcm_t **pcmp, const char *name,
+ 	if (!converter) {
+ 		const char *const *types;
+ 		for (types = default_rate_plugins; *types; types++) {
+-			err = rate_open_func(rate, *types, 0);
++			err = rate_open_func(rate, *types, NULL, 0);
+ 			if (!err) {
+ 				type = *types;
+ 				break;
+ 			}
+ 		}
+ 	} else if (!snd_config_get_string(converter, &type))
+-		err = rate_open_func(rate, type, 1);
+-	else if (snd_config_get_type(converter) == SND_CONFIG_TYPE_COMPOUND) {
++		err = rate_open_func(rate, type, NULL, 1);
++	else if (is_string_array(converter)) {
+ 		snd_config_iterator_t i, next;
+ 		snd_config_for_each(i, next, converter) {
+ 			snd_config_t *n = snd_config_iterator_entry(i);
+ 			if (snd_config_get_string(n, &type) < 0)
+ 				break;
+-			err = rate_open_func(rate, type, 0);
++			err = rate_open_func(rate, type, NULL, 0);
+ 			if (!err)
+ 				break;
+ 		}
++	} else if (snd_config_get_type(converter) == SND_CONFIG_TYPE_COMPOUND) {
++		snd_config_iterator_t i, next;
++		snd_config_for_each(i, next, converter) {
++			snd_config_t *n = snd_config_iterator_entry(i);
++			const char *id;
++			snd_config_get_id(n, &id);
++			if (strcmp(id, "name") != 0)
++				continue;
++			snd_config_get_string(n, &type);
++			break;
++		}
++		if (!type) {
++			SNDERR("No name given for rate converter");
++			snd_pcm_free(pcm);
++			free(rate);
++			return -EINVAL;
++		}
++		err = rate_open_func(rate, type, converter, 1);
+ 	} else {
+ 		SNDERR("Invalid type for rate converter");
+ 		snd_pcm_free(pcm);
+@@ -1439,6 +1503,11 @@ pcm.name {
+ 	converter [ STR1 STR2 ... ]	# optional
+ 				# Converter type, default is taken from
+ 				# defaults.pcm.rate_converter
++	# or
++	converter {		# optional
++		name STR	# Convertor type
++		xxx yyy		# optional convertor-specific configuration
++	}
+ }
+ \endcode
+ 
+-- 
+2.9.3
+
+
+From 3bad0a21b4d13d8d10691f382c836897fa7a7cb9 Mon Sep 17 00:00:00 2001
+From: Breno Leitao <leitao@debian.org>
+Date: Wed, 22 Feb 2017 16:45:00 -0300
+Subject: [PATCH 32/37] Drop ppc64-specific workaround for versioned symbols
+
+Currently aserver fails to build when using parameter
+--without-versioned, due to an workaround for ppc64
+(06221f86d207cb33ddd4867ca5301eeb247c4400).  This workaround is
+not required anymore on the ppc64 ABI v2, and, in fact is breaking the
+compilation. Reverting this commit
+
+Signed-off-by: Breno Leitao <leitao@debian.org>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+---
+ include/alsa-symbols.h | 17 -----------------
+ 1 file changed, 17 deletions(-)
+
+diff --git a/include/alsa-symbols.h b/include/alsa-symbols.h
+index 51cb982..eeacfdb 100644
+--- a/include/alsa-symbols.h
++++ b/include/alsa-symbols.h
+@@ -29,19 +29,10 @@
+ #define INTERNAL_CONCAT2_2(Pre, Post) Pre##Post
+ #define INTERNAL(Name) INTERNAL_CONCAT2_2(__, Name)
+ 
+-#ifdef __powerpc64__
+-# define symbol_version(real, name, version) 			\
+-	__asm__ (".symver " ASM_NAME(#real) "," ASM_NAME(#name) "@" #version);	\
+-	__asm__ (".symver ." ASM_NAME(#real) ",." ASM_NAME(#name) "@" #version)
+-# define default_symbol_version(real, name, version) 		\
+-	__asm__ (".symver " ASM_NAME(#real) "," ASM_NAME(#name) "@@" #version);	\
+-	__asm__ (".symver ." ASM_NAME(#real) ",." ASM_NAME(#name) "@@" #version)
+-#else
+ # define symbol_version(real, name, version) \
+ 	__asm__ (".symver " ASM_NAME(#real) "," ASM_NAME(#name) "@" #version)
+ # define default_symbol_version(real, name, version) \
+ 	__asm__ (".symver " ASM_NAME(#real) "," ASM_NAME(#name) "@@" #version)
+-#endif
+ 
+ #ifdef USE_VERSIONED_SYMBOLS
+ #define use_symbol_version(real, name, version) \
+@@ -50,13 +41,6 @@
+ 		default_symbol_version(real, name, version)
+ #else
+ #define use_symbol_version(real, name, version) /* nothing */
+-#ifdef __powerpc64__
+-#define use_default_symbol_version(real, name, version) \
+-	__asm__ (".weak " ASM_NAME(#name)); 			\
+-	__asm__ (".weak ." ASM_NAME(#name)); 			\
+-	__asm__ (".set " ASM_NAME(#name) "," ASM_NAME(#real));		\
+-	__asm__ (".set ." ASM_NAME(#name) ",." ASM_NAME(#real))
+-#else
+ #if defined(__alpha__) || defined(__mips__)
+ #define use_default_symbol_version(real, name, version) \
+         __asm__ (".weak " ASM_NAME(#name)); \
+@@ -67,6 +51,5 @@
+ 	__asm__ (".set " ASM_NAME(#name) "," ASM_NAME(#real))
+ #endif
+ #endif
+-#endif
+ 
+ #endif /* __ALSA_SYMBOLS_H */
+-- 
+2.9.3
+
+
+From b0e4652881f883023d2b190cf3897b7494d8d0ed Mon Sep 17 00:00:00 2001
+From: Jaroslav Kysela <perex@perex.cz>
+Date: Mon, 27 Feb 2017 09:25:24 +0100
+Subject: [PATCH 33/37] pcm_plugin: unify the snd_pcm_mmap_begin result value
+ checking
+
+---
+ src/pcm/pcm_plugin.c | 26 +++++++++++++++++++-------
+ 1 file changed, 19 insertions(+), 7 deletions(-)
+
+diff --git a/src/pcm/pcm_plugin.c b/src/pcm/pcm_plugin.c
+index ad4a102..aaea2ab 100644
+--- a/src/pcm/pcm_plugin.c
++++ b/src/pcm/pcm_plugin.c
+@@ -251,8 +251,12 @@ static snd_pcm_sframes_t snd_pcm_plugin_write_areas(snd_pcm_t *pcm,
+ 		snd_pcm_uframes_t slave_offset;
+ 		snd_pcm_uframes_t slave_frames = ULONG_MAX;
+ 		
+-		err = snd_pcm_mmap_begin(slave, &slave_areas, &slave_offset, &slave_frames);
+-		if (err < 0 || slave_frames == 0)
++		result = snd_pcm_mmap_begin(slave, &slave_areas, &slave_offset, &slave_frames);
++		if (result < 0) {
++			err = result;
++			goto error;
++		}
++		if (slave_frames == 0)
+ 			break;
+ 		frames = plugin->write(pcm, areas, offset, frames,
+ 				       slave_areas, slave_offset, &slave_frames);
+@@ -304,7 +308,11 @@ static snd_pcm_sframes_t snd_pcm_plugin_read_areas(snd_pcm_t *pcm,
+ 		snd_pcm_uframes_t slave_offset;
+ 		snd_pcm_uframes_t slave_frames = ULONG_MAX;
+ 		
+-		snd_pcm_mmap_begin(slave, &slave_areas, &slave_offset, &slave_frames);
++		result = snd_pcm_mmap_begin(slave, &slave_areas, &slave_offset, &slave_frames);
++		if (result < 0) {
++			err = result;
++			goto error;
++		}
+ 		if (slave_frames == 0)
+ 			break;
+ 		frames = (plugin->read)(pcm, areas, offset, frames,
+@@ -409,9 +417,11 @@ snd_pcm_plugin_mmap_commit(snd_pcm_t *pcm,
+ 		snd_pcm_uframes_t slave_frames = ULONG_MAX;
+ 		snd_pcm_sframes_t result;
+ 
+-		err = snd_pcm_mmap_begin(slave, &slave_areas, &slave_offset, &slave_frames);
+-		if (err < 0)
++		result = snd_pcm_mmap_begin(slave, &slave_areas, &slave_offset, &slave_frames);
++		if (result < 0) {
++			err = result;
+ 			goto error;
++		}
+ 		if (frames > cont)
+ 			frames = cont;
+ 		frames = plugin->write(pcm, areas, appl_offset, frames,
+@@ -481,9 +491,11 @@ static snd_pcm_sframes_t snd_pcm_plugin_avail_update(snd_pcm_t *pcm)
+ 			snd_pcm_uframes_t slave_frames = ULONG_MAX;
+ 			snd_pcm_sframes_t result;
+ 
+-			err = snd_pcm_mmap_begin(slave, &slave_areas, &slave_offset, &slave_frames);
+-			if (err < 0)
++			result = snd_pcm_mmap_begin(slave, &slave_areas, &slave_offset, &slave_frames);
++			if (result < 0) {
++				err = result;
+ 				goto error;
++			}
+ 			if (frames > cont)
+ 				frames = cont;
+ 			frames = (plugin->read)(pcm, areas, hw_offset, frames,
+-- 
+2.9.3
+
+
+From 8a38461fac67f6542308063ba8e9887a1a2fa84e Mon Sep 17 00:00:00 2001
+From: Jaroslav Kysela <perex@perex.cz>
+Date: Mon, 27 Feb 2017 09:26:33 +0100
+Subject: [PATCH 34/37] always handle return value from snd_config_get_id()
+ (coverity)
+
+---
+ src/pcm/pcm_rate.c  | 6 ++++--
+ src/topology/data.c | 4 ++--
+ 2 files changed, 6 insertions(+), 4 deletions(-)
+
+diff --git a/src/pcm/pcm_rate.c b/src/pcm/pcm_rate.c
+index 46eb797..f60b0ae 100644
+--- a/src/pcm/pcm_rate.c
++++ b/src/pcm/pcm_rate.c
+@@ -1339,7 +1339,8 @@ static int is_string_array(const snd_config_t *conf)
+ 	if (i && i != snd_config_iterator_end(conf)) {
+ 		snd_config_t *n = snd_config_iterator_entry(i);
+ 		const char *id;
+-		snd_config_get_id(n, &id);
++		if (snd_config_get_id(n, &id) < 0)
++			return 0;
+ 		if (id && strcmp(id, "0") != 0)
+ 			return 0;
+ 	}
+@@ -1422,7 +1423,8 @@ int snd_pcm_rate_open(snd_pcm_t **pcmp, const char *name,
+ 		snd_config_for_each(i, next, converter) {
+ 			snd_config_t *n = snd_config_iterator_entry(i);
+ 			const char *id;
+-			snd_config_get_id(n, &id);
++			if (snd_config_get_id(n, &id) < 0)
++				continue;
+ 			if (strcmp(id, "name") != 0)
+ 				continue;
+ 			snd_config_get_string(n, &type);
+diff --git a/src/topology/data.c b/src/topology/data.c
+index e2aa38c..8fe2342 100644
+--- a/src/topology/data.c
++++ b/src/topology/data.c
+@@ -653,8 +653,8 @@ static int parse_tuple_sets(snd_config_t *cfg,
+ 	int err;
+ 
+ 	if (snd_config_get_type(cfg) != SND_CONFIG_TYPE_COMPOUND) {
+-		snd_config_get_id(cfg, &id);
+-		SNDERR("error: compound type expected for %s", id);
++		if (snd_config_get_id(cfg, &id) >= 0)
++			SNDERR("error: compound type expected for %s", id);
+ 		return -EINVAL;
+ 	}
+ 
+-- 
+2.9.3
+
+
+From b96f6f47852aa145645fb8626d009ec532246e55 Mon Sep 17 00:00:00 2001
+From: Jaroslav Kysela <perex@perex.cz>
+Date: Mon, 27 Feb 2017 09:29:18 +0100
+Subject: [PATCH 35/37] pcm file plugin: handle snd_pcm_mmap_begin() error path
+ in snd_pcm_file_mmap_commit()
+
+---
+ src/pcm/pcm_file.c | 12 +++++++-----
+ 1 file changed, 7 insertions(+), 5 deletions(-)
+
+diff --git a/src/pcm/pcm_file.c b/src/pcm/pcm_file.c
+index 0363f84..8012251 100644
+--- a/src/pcm/pcm_file.c
++++ b/src/pcm/pcm_file.c
+@@ -593,11 +593,13 @@ static snd_pcm_sframes_t snd_pcm_file_mmap_commit(snd_pcm_t *pcm,
+ 	const snd_pcm_channel_area_t *areas;
+ 	snd_pcm_sframes_t result;
+ 
+-	snd_pcm_mmap_begin(file->gen.slave, &areas, &ofs, &siz);
+-	assert(ofs == offset && siz == size);
+-	result = snd_pcm_mmap_commit(file->gen.slave, ofs, siz);
+-	if (result > 0)
+-		snd_pcm_file_add_frames(pcm, areas, ofs, result);
++	result = snd_pcm_mmap_begin(file->gen.slave, &areas, &ofs, &siz);
++	if (result >= 0) {
++		assert(ofs == offset && siz == size);
++		result = snd_pcm_mmap_commit(file->gen.slave, ofs, siz);
++		if (result > 0)
++			snd_pcm_file_add_frames(pcm, areas, ofs, result);
++	}
+ 	return result;
+ }
+ 
+-- 
+2.9.3
+
+
+From db0e1dcfc22fb2e408a12993cda2d604e0fb10f8 Mon Sep 17 00:00:00 2001
+From: Jaroslav Kysela <perex@perex.cz>
+Date: Mon, 27 Feb 2017 09:46:18 +0100
+Subject: [PATCH 36/37] topology: coverity - remove dead code
+
+---
+ src/topology/ctl.c  |  5 ++---
+ src/topology/data.c |  2 +-
+ src/topology/pcm.c  | 17 +++++++----------
+ 3 files changed, 10 insertions(+), 14 deletions(-)
+
+diff --git a/src/topology/ctl.c b/src/topology/ctl.c
+index 1da3d18..c026c2a 100644
+--- a/src/topology/ctl.c
++++ b/src/topology/ctl.c
+@@ -173,7 +173,7 @@ static int tplg_build_enum_control(snd_tplg_t *tplg,
+ {
+ 	struct tplg_ref *ref;
+ 	struct list_head *base, *pos;
+-	int err = 0;
++	int err;
+ 
+ 	base = &elem->ref_list;
+ 
+@@ -198,8 +198,7 @@ static int tplg_build_enum_control(snd_tplg_t *tplg,
+ 			SNDERR("error: cannot find '%s' referenced by"
+ 				" control '%s'\n", ref->id, elem->id);
+ 			return -EINVAL;
+-		} else if (err < 0)
+-			return err;
++		}
+ 	}
+ 
+ 	return 0;
+diff --git a/src/topology/data.c b/src/topology/data.c
+index 8fe2342..31e4ee1 100644
+--- a/src/topology/data.c
++++ b/src/topology/data.c
+@@ -917,7 +917,7 @@ int tplg_build_manifest_data(snd_tplg_t *tplg)
+ 	list_for_each(pos, base) {
+ 
+ 		ref = list_entry(pos, struct tplg_ref, list);
+-		if (ref->id == NULL || ref->elem)
++		if (ref->elem)
+ 			continue;
+ 
+ 		if (ref->type == SND_TPLG_TYPE_DATA) {
+diff --git a/src/topology/pcm.c b/src/topology/pcm.c
+index 5568d57..50a373a 100644
+--- a/src/topology/pcm.c
++++ b/src/topology/pcm.c
+@@ -79,8 +79,8 @@ static int build_pcm(snd_tplg_t *tplg, struct tplg_elem *elem)
+ 	int err;
+ 
+ 	err = tplg_build_stream_caps(tplg, elem->id, elem->pcm->caps);
+-		if (err < 0)
+-			return err;
++	if (err < 0)
++		return err;
+ 
+ 	/* merge private data from the referenced data elements */
+ 	base = &elem->ref_list;
+@@ -96,8 +96,7 @@ static int build_pcm(snd_tplg_t *tplg, struct tplg_elem *elem)
+ 			SNDERR("error: cannot find '%s' referenced by"
+ 				" PCM '%s'\n", ref->id, elem->id);
+ 			return -EINVAL;
+-		} else if (err < 0)
+-			return err;
++		}
+ 	}
+ 
+ 	return 0;
+@@ -1208,12 +1207,10 @@ int tplg_add_link_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t)
+ 
+ 	/* ID and names */
+ 	link->id = link_tpl->id;
+-	if (link->name)
+-		elem_copy_text(link->name, link_tpl->name,
+-			       SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
+-	if (link->stream_name)
+-		elem_copy_text(link->stream_name, link_tpl->stream_name,
+-			       SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
++	elem_copy_text(link->name, link_tpl->name,
++		       SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
++	elem_copy_text(link->stream_name, link_tpl->stream_name,
++		       SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
+ 
+ 	/* stream configs */
+ 	if (link_tpl->num_streams > SND_SOC_TPLG_STREAM_CONFIG_MAX)
+-- 
+2.9.3
+
+
+From ad188bbf7813eab6f42dcdf617aa947107118857 Mon Sep 17 00:00:00 2001
+From: Jaroslav Kysela <perex@perex.cz>
+Date: Mon, 27 Feb 2017 09:53:26 +0100
+Subject: [PATCH 37/37] ucm parser: fix possible string overflow in
+ uc_mgr_import_master_config()
+
+---
+ src/ucm/parser.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/src/ucm/parser.c b/src/ucm/parser.c
+index 798bf48..b79b92d 100644
+--- a/src/ucm/parser.c
++++ b/src/ucm/parser.c
+@@ -1453,7 +1453,8 @@ int uc_mgr_import_master_config(snd_use_case_mgr_t *uc_mgr)
+ 		err = load_master_config(uc_mgr->card_name, &cfg);
+ 		if (err < 0)
+ 			return err;
+-		strcpy(uc_mgr->conf_file_name, uc_mgr->card_name);
++		strncpy(uc_mgr->conf_file_name, uc_mgr->card_name, MAX_CARD_LONG_NAME);
++		uc_mgr->conf_file_name[MAX_CARD_LONG_NAME-1] = '\0';
+ 	}
+ 
+ 	err = parse_master_file(uc_mgr, cfg);
+-- 
+2.9.3
+
diff --git a/SPECS/alsa-lib.spec b/SPECS/alsa-lib.spec
index a507780..babec3f 100644
--- a/SPECS/alsa-lib.spec
+++ b/SPECS/alsa-lib.spec
@@ -4,8 +4,8 @@
 
 Summary:  The Advanced Linux Sound Architecture (ALSA) library
 Name:     alsa-lib
-Version:  1.1.1
-Release:  1%{?prever_dot}%{?dist}
+Version:  1.1.3
+Release:  3%{?prever_dot}%{?dist}
 License:  LGPLv2+
 Group:    System Environment/Libraries
 URL:      http://www.alsa-project.org/
@@ -14,11 +14,11 @@ Source:   ftp://ftp.alsa-project.org/pub/lib/%{name}-%{version}%{?prever}%{?post
 Source10: asound.conf
 Source11: modprobe-dist-alsa.conf
 Source12: modprobe-dist-oss.conf
-Patch0:   alsa-lib-1.1.1-post.patch
+Patch0:   alsa-lib-1.1.3-post.patch
 Patch1:   alsa-lib-1.1.0-config.patch
-Patch2:   alsa-lib-1.0.16-no-dox-date.patch
 
 BuildRequires:  doxygen
+BuildRequires:  autoconf automake libtool
 Requires(post): /sbin/ldconfig, coreutils
 
 %description
@@ -46,7 +46,7 @@ against the ALSA libraries and interfaces.
 %setup -q -n %{name}-%{version}%{?prever}%{?postver}
 %patch0 -p1 -b .post
 %patch1 -p1 -b .config
-%patch2 -p1 -b .dox-date
+autoreconf -f -i
 
 %build
 %configure --disable-aload --with-plugindir=%{_libdir}/alsa-lib --disable-alisp
@@ -81,9 +81,11 @@ install -p -m 644 %{SOURCE12} %{buildroot}%{_defaultdocdir}/%{name}/modprobe-dis
 mkdir -p %{buildroot}/%{_datadir}/alsa/ucm
 # Remove all UCM files (should be selected by architecture)
 rm -rf %{buildroot}/%{_datadir}/alsa/ucm/*
+# Remove smixer .so modules
+rm -rf %{buildroot}/%{_libdir}/alsa-lib/smixer
 
 #Remove libtool archives.
-find %{buildroot} -name '*.la' -exec rm -f {} ';'
+find %{buildroot} -name '*.la' -delete
 
 %post -p /sbin/ldconfig
 
@@ -98,7 +100,7 @@ find %{buildroot} -name '*.la' -exec rm -f {} ';'
 %config %{_sysconfdir}/asound.conf
 /%{_lib}/libasound.so.*
 %{_bindir}/aserver
-%{_libdir}/alsa-lib/
+#%{_libdir}/alsa-lib/
 %{_datadir}/alsa/
 /lib/modprobe.d/dist-*
 
@@ -112,6 +114,10 @@ find %{buildroot} -name '*.la' -exec rm -f {} ';'
 %{_datadir}/aclocal/alsa.m4
 
 %changelog
+* Wed Mar  1 2017 Jaroslav Kysela <jkysela@redhat.com> - 1.1.3-3
+- Updated to 1.1.3
+- Resolves: rhbz#1399508
+
 * Mon Jun  6 2016 Jaroslav Kysela <jkysela@redhat.com> - 1.1.1-1
 - Updated to 1.1.1
 - Resolves: rhbz#1297932