The following commits has been backported from kernel 4.9
with local modification to fit to kernel 4.4:
e4e2d2f45284f620eeb9eea25570838b2a42c968
f7590d4f1565b0d609d25113c37b9bea8a13e9f7

Signed-off-by: Guoqing Zhang <guoqing.zh...@intel.com>
---
 include/uapi/sound/asoc.h                    |   44 +-
 include/uapi/sound/snd_sst_tokens.h          |  214 ++++
 sound/soc/intel/skylake/skl-pcm.c            |   60 +-
 sound/soc/intel/skylake/skl-sst-dsp.h        |   14 +-
 sound/soc/intel/skylake/skl-sst-utils.c      |  249 ++++-
 sound/soc/intel/skylake/skl-topology.c       | 1343 ++++++++++++++++++++------
 sound/soc/intel/skylake/skl-topology.h       |   22 +-
 sound/soc/intel/skylake/skl-tplg-interface.h |   25 +-
 sound/soc/intel/skylake/skl.h                |    3 +
 9 files changed, 1670 insertions(+), 304 deletions(-)
 create mode 100644 include/uapi/sound/snd_sst_tokens.h

diff --git a/include/uapi/sound/asoc.h b/include/uapi/sound/asoc.h
index c4cc1e4..e4701a3 100644
--- a/include/uapi/sound/asoc.h
+++ b/include/uapi/sound/asoc.h
@@ -116,6 +116,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.
@@ -132,6 +140,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
@@ -139,7 +176,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));
 
 /*
@@ -383,7 +423,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/include/uapi/sound/snd_sst_tokens.h 
b/include/uapi/sound/snd_sst_tokens.h
new file mode 100644
index 0000000..1ee2e94
--- /dev/null
+++ b/include/uapi/sound/snd_sst_tokens.h
@@ -0,0 +1,214 @@
+/*
+ * snd_sst_tokens.h - Intel SST tokens definition
+ *
+ * Copyright (C) 2016 Intel Corp
+ * Author: Shreyas NC <shreyas...@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 __SND_SST_TOKENS_H__
+#define __SND_SST_TOKENS_H__
+
+/**
+ * %SKL_TKN_UUID:               Module UUID
+ *
+ * %SKL_TKN_U8_BLOCK_TYPE:      Type of the private data block.Can be:
+ *                              tuples, bytes, short and words
+ *
+ * %SKL_TKN_U8_IN_PIN_TYPE:     Input pin type,
+ *                              homogenous=0, heterogenous=1
+ *
+ * %SKL_TKN_U8_OUT_PIN_TYPE:    Output pin type,
+ *                              homogenous=0, heterogenous=1
+ * %SKL_TKN_U8_DYN_IN_PIN:      Configure Input pin dynamically
+ *                              if true
+ *
+ * %SKL_TKN_U8_DYN_OUT_PIN:     Configure Output pin dynamically
+ *                              if true
+ *
+ * %SKL_TKN_U8_IN_QUEUE_COUNT:  Store the number of Input pins
+ *
+ * %SKL_TKN_U8_OUT_QUEUE_COUNT: Store the number of Output pins
+ *
+ * %SKL_TKN_U8_TIME_SLOT:       TDM slot number
+ *
+ * %SKL_TKN_U8_CORE_ID:         Stores module affinity value.Can take
+ *                              the values:
+ *                              SKL_AFFINITY_CORE_0 = 0,
+ *                              SKL_AFFINITY_CORE_1,
+ *                              SKL_AFFINITY_CORE_MAX
+ *
+ * %SKL_TKN_U8_MOD_TYPE:        Module type value.
+ *
+ * %SKL_TKN_U8_CONN_TYPE:       Module connection type can be a FE,
+ *                              BE or NONE as defined :
+ *                              SKL_PIPE_CONN_TYPE_NONE = 0,
+ *                              SKL_PIPE_CONN_TYPE_FE = 1 (HOST_DMA)
+ *                              SKL_PIPE_CONN_TYPE_BE = 2 (LINK_DMA)
+ *
+ * %SKL_TKN_U8_DEV_TYPE:        Type of device to which the module is
+ *                              connected
+ *                              Can take the values:
+ *                              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
+ *
+ * %SKL_TKN_U8_HW_CONN_TYPE:    Connection type of the HW to which the
+ *                              module is connected
+ *                              SKL_CONN_NONE = 0,
+ *                              SKL_CONN_SOURCE = 1,
+ *                              SKL_CONN_SINK = 2
+ *
+ * %SKL_TKN_U16_PIN_INST_ID:    Stores the pin instance id
+ *
+ * %SKL_TKN_U16_MOD_INST_ID:    Stores the mdule instance id
+ *
+ * %SKL_TKN_U32_MAX_MCPS:       Module max mcps value
+ *
+ * %SKL_TKN_U32_MEM_PAGES:      Module resource pages
+ *
+ * %SKL_TKN_U32_OBS:            Stores Output Buffer size
+ *
+ * %SKL_TKN_U32_IBS:            Stores input buffer size
+ *
+ * %SKL_TKN_U32_VBUS_ID:        Module VBUS_ID. PDM=0, SSP0=0,
+ *                              SSP1=1,SSP2=2,
+ *                              SSP3=3, SSP4=4,
+ *                              SSP5=5, SSP6=6,INVALID
+ *
+ * %SKL_TKN_U32_PARAMS_FIXUP:   Module Params fixup mask
+ * %SKL_TKN_U32_CONVERTER:      Module params converter mask
+ * %SKL_TKN_U32_PIPE_ID:        Stores the pipe id
+ *
+ * %SKL_TKN_U32_PIPE_CONN_TYPE: Type of the token to which the pipe is
+ *                              connected to. It can be
+ *                              SKL_PIPE_CONN_TYPE_NONE = 0,
+ *                              SKL_PIPE_CONN_TYPE_FE = 1 (HOST_DMA),
+ *                              SKL_PIPE_CONN_TYPE_BE = 2 (LINK_DMA),
+ *
+ * %SKL_TKN_U32_PIPE_PRIORITY:  Pipe priority value
+ * %SKL_TKN_U32_PIPE_MEM_PGS:   Pipe resource pages
+ *
+ * %SKL_TKN_U32_DIR_PIN_COUNT:  Value for the direction to set input/output
+ *                              formats and the pin count.
+ *                              The first 4 bits have the direction
+ *                              value and the next 4 have
+ *                              the pin count value.
+ *                              SKL_DIR_IN = 0, SKL_DIR_OUT = 1.
+ *                              The input and output formats
+ *                              share the same set of tokens
+ *                              with the distinction between input
+ *                              and output made by reading direction
+ *                              token.
+ *
+ * %SKL_TKN_U32_FMT_CH:         Supported channel count
+ *
+ * %SKL_TKN_U32_FMT_FREQ:       Supported frequency/sample rate
+ *
+ * %SKL_TKN_U32_FMT_BIT_DEPTH:  Supported container size
+ *
+ * %SKL_TKN_U32_FMT_SAMPLE_SIZE:Number of samples in the container
+ *
+ * %SKL_TKN_U32_FMT_CH_CONFIG:  Supported channel configurations for the
+ *                              input/output.
+ *
+ * %SKL_TKN_U32_FMT_INTERLEAVE: Interleaving style which can be per
+ *                              channel or per sample. The values can be :
+ *                              SKL_INTERLEAVING_PER_CHANNEL = 0,
+ *                              SKL_INTERLEAVING_PER_SAMPLE = 1,
+ *
+ * %SKL_TKN_U32_FMT_SAMPLE_TYPE:
+ *                              Specifies the sample type. Can take the
+ *                              values: 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
+ *
+ * %SKL_TKN_U32_CH_MAP:         Channel map values
+ * %SKL_TKN_U32_MOD_SET_PARAMS: It can take these values:
+ *                              SKL_PARAM_DEFAULT, SKL_PARAM_INIT,
+ *                              SKL_PARAM_SET, SKL_PARAM_BIND
+ *
+ * %SKL_TKN_U32_MOD_PARAM_ID:   ID of the module params
+ *
+ * %SKL_TKN_U32_CAPS_SET_PARAMS:
+ *                              Set params value
+ *
+ * %SKL_TKN_U32_CAPS_PARAMS_ID: Params ID
+ *
+ * %SKL_TKN_U32_CAPS_SIZE:      Caps size
+ *
+ * %SKL_TKN_U32_PROC_DOMAIN:    Specify processing domain
+ *
+ * %SKL_TKN_U32_LIB_COUNT:      Specifies the number of libraries
+ *
+ * %SKL_TKN_STR_LIB_NAME:       Specifies the library name
+ *
+ * module_id and loadable flags dont have tokens as these values will be
+ * read from the DSP FW manifest
+ */
+enum SKL_TKNS {
+       SKL_TKN_UUID = 1,
+       SKL_TKN_U8_NUM_BLOCKS,
+       SKL_TKN_U8_BLOCK_TYPE,
+       SKL_TKN_U8_IN_PIN_TYPE,
+       SKL_TKN_U8_OUT_PIN_TYPE,
+       SKL_TKN_U8_DYN_IN_PIN,
+       SKL_TKN_U8_DYN_OUT_PIN,
+       SKL_TKN_U8_IN_QUEUE_COUNT,
+       SKL_TKN_U8_OUT_QUEUE_COUNT,
+       SKL_TKN_U8_TIME_SLOT,
+       SKL_TKN_U8_CORE_ID,
+       SKL_TKN_U8_MOD_TYPE,
+       SKL_TKN_U8_CONN_TYPE,
+       SKL_TKN_U8_DEV_TYPE,
+       SKL_TKN_U8_HW_CONN_TYPE,
+       SKL_TKN_U16_MOD_INST_ID,
+       SKL_TKN_U16_BLOCK_SIZE,
+       SKL_TKN_U32_MAX_MCPS,
+       SKL_TKN_U32_MEM_PAGES,
+       SKL_TKN_U32_OBS,
+       SKL_TKN_U32_IBS,
+       SKL_TKN_U32_VBUS_ID,
+       SKL_TKN_U32_PARAMS_FIXUP,
+       SKL_TKN_U32_CONVERTER,
+       SKL_TKN_U32_PIPE_ID,
+       SKL_TKN_U32_PIPE_CONN_TYPE,
+       SKL_TKN_U32_PIPE_PRIORITY,
+       SKL_TKN_U32_PIPE_MEM_PGS,
+       SKL_TKN_U32_DIR_PIN_COUNT,
+       SKL_TKN_U32_FMT_CH,
+       SKL_TKN_U32_FMT_FREQ,
+       SKL_TKN_U32_FMT_BIT_DEPTH,
+       SKL_TKN_U32_FMT_SAMPLE_SIZE,
+       SKL_TKN_U32_FMT_CH_CONFIG,
+       SKL_TKN_U32_FMT_INTERLEAVE,
+       SKL_TKN_U32_FMT_SAMPLE_TYPE,
+       SKL_TKN_U32_FMT_CH_MAP,
+       SKL_TKN_U32_PIN_MOD_ID,
+       SKL_TKN_U32_PIN_INST_ID,
+       SKL_TKN_U32_MOD_SET_PARAMS,
+       SKL_TKN_U32_MOD_PARAM_ID,
+       SKL_TKN_U32_CAPS_SET_PARAMS,
+       SKL_TKN_U32_CAPS_PARAMS_ID,
+       SKL_TKN_U32_CAPS_SIZE,
+       SKL_TKN_U32_PROC_DOMAIN,
+       SKL_TKN_U32_LIB_COUNT,
+       SKL_TKN_STR_LIB_NAME,
+       SKL_TKN_MAX = SKL_TKN_STR_LIB_NAME,
+};
+
+#endif
diff --git a/sound/soc/intel/skylake/skl-pcm.c 
b/sound/soc/intel/skylake/skl-pcm.c
index 7c81b31..acbc219 100644
--- a/sound/soc/intel/skylake/skl-pcm.c
+++ b/sound/soc/intel/skylake/skl-pcm.c
@@ -219,7 +219,6 @@ static int skl_be_prepare(struct snd_pcm_substream 
*substream,
        mconfig = skl_tplg_be_get_cpr_module(dai, substream->stream);
        if (mconfig == NULL)
                return -EINVAL;
-
        return skl_dsp_set_dma_control(ctx, mconfig);
 }
 
@@ -227,11 +226,14 @@ static int skl_pcm_prepare(struct snd_pcm_substream 
*substream,
                struct snd_soc_dai *dai)
 {
        struct hdac_ext_stream *stream = get_hdac_ext_stream(substream);
+       struct skl *skl = get_skl_ctx(dai->dev);
        unsigned int format_val;
        int err;
+       struct skl_module_cfg *mconfig;
 
        dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
 
+       mconfig = skl_tplg_fe_get_cpr_module(dai, substream->stream);
        format_val = skl_get_format(substream, dai);
        dev_dbg(dai->dev, "stream_tag=%d formatvalue=%d\n",
                                hdac_stream(stream)->stream_tag, format_val);
@@ -338,7 +340,6 @@ static int skl_be_hw_params(struct snd_pcm_substream 
*substream,
                                struct snd_soc_dai *dai)
 {
        struct skl_pipe_params p_params = {0};
-
        p_params.s_fmt = snd_pcm_format_width(params_format(params));
        p_params.ch = params_channels(params);
        p_params.s_freq = params_rate(params);
@@ -520,6 +521,8 @@ static int skl_link_pcm_prepare(struct snd_pcm_substream 
*substream,
        unsigned int format_val = 0;
        struct skl_dma_params *dma_params;
        struct snd_soc_dai *codec_dai = rtd->codec_dai;
+       struct skl *skl = get_skl_ctx(dai->dev);
+       struct skl_module_cfg *mconfig = NULL;
        struct hdac_ext_link *link;
 
        dma_params  = (struct skl_dma_params *)
@@ -535,6 +538,7 @@ static int skl_link_pcm_prepare(struct snd_pcm_substream 
*substream,
 
        snd_hdac_ext_link_stream_reset(link_dev);
 
+       mconfig = skl_tplg_be_get_cpr_module(dai, substream->stream);
        snd_hdac_ext_link_stream_setup(link_dev, format_val);
 
        snd_hdac_ext_link_set_stream_id(link, 
hdac_stream(link_dev)->stream_tag);
@@ -890,6 +894,17 @@ static struct snd_soc_dai_driver skl_platform_dai[] = {
        },
 },
 {
+       .name = "DMIC23 Pin",
+       .ops = &skl_dmic_dai_ops,
+       .capture = {
+               .stream_name = "DMIC23 Rx",
+               .channels_min = HDA_MONO,
+               .channels_max = HDA_QUAD,
+               .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
+       },
+},
+{
        .name = "HD-Codec Pin",
        .ops = &skl_link_dai_ops,
        .playback = {
@@ -1025,7 +1040,6 @@ static int skl_get_delay_from_lpib(struct hdac_ext_bus 
*ebus,
                delay = pos - lpib_pos;
        else
                delay = lpib_pos - pos;
-
        if (delay < 0) {
                if (delay >= hstream->delay_negative_threshold)
                        delay = 0;
@@ -1037,12 +1051,12 @@ static int skl_get_delay_from_lpib(struct hdac_ext_bus 
*ebus,
                delay = 0;
 
        if (delay >= hstream->period_bytes) {
-               dev_info(bus->dev,
+               /* The following line add extra delay to ring buffer updates, 
remove it */
+               /*dev_info(bus->dev,
                         "Unstable LPIB (%d >= %d); disabling LPIB delay 
counting\n",
-                        delay, hstream->period_bytes);
+                        delay, hstream->period_bytes);*/
                delay = 0;
        }
-
        return bytes_to_frames(substream->runtime, delay);
 }
 
@@ -1177,13 +1191,44 @@ static int skl_pcm_new(struct snd_soc_pcm_runtime *rtd)
        return retval;
 }
 
+
+static int skl_populate_modules(struct skl *skl)
+{
+       struct skl_pipeline *p;
+       struct skl_pipe_module *m;
+       struct snd_soc_dapm_widget *w;
+       struct skl_module_cfg *mconfig;
+       int ret;
+
+       list_for_each_entry(p, &skl->ppl_list, node) {
+               list_for_each_entry(m, &p->pipe->w_list, node) {
+                       w = m->w;
+                       mconfig = w->priv;
+                       ret = snd_skl_get_module_info(skl->skl_sst, mconfig);
+                       if (ret < 0) {
+                               dev_err(skl->skl_sst->dev,
+                                       "query module info failed:%d\n", ret);
+                               goto err;
+                       }
+               }
+       }
+err:
+       return ret;
+}
+
+
 static int skl_platform_soc_probe(struct snd_soc_platform *platform)
 {
        struct hdac_ext_bus *ebus = dev_get_drvdata(platform->dev);
 
+       int ret = 0;
+       struct skl *skl = ebus_to_skl(ebus);
        if (ebus->ppcap)
-               return skl_tplg_init(platform, ebus);
+               ret = skl_tplg_init(platform, ebus);
+       if (ret)
+               return ret;
 
+       skl_populate_modules(skl);
        return 0;
 }
 static struct snd_soc_platform_driver skl_platform_drv  = {
@@ -1204,7 +1249,6 @@ int skl_platform_register(struct device *dev)
        struct skl *skl = ebus_to_skl(ebus);
 
        INIT_LIST_HEAD(&skl->ppl_list);
-
        ret = snd_soc_register_platform(dev, &skl_platform_drv);
        if (ret) {
                dev_err(dev, "soc platform registration failed %d\n", ret);
diff --git a/sound/soc/intel/skylake/skl-sst-dsp.h 
b/sound/soc/intel/skylake/skl-sst-dsp.h
index 7efaf64..1690a74 100644
--- a/sound/soc/intel/skylake/skl-sst-dsp.h
+++ b/sound/soc/intel/skylake/skl-sst-dsp.h
@@ -20,6 +20,7 @@
 #include <sound/memalloc.h>
 #include "skl-sst-cldma.h"
 #include "skl-tplg-interface.h"
+#include "skl-topology.h"
 
 struct sst_dsp;
 struct skl_sst;
@@ -176,9 +177,18 @@ int bxt_sst_dsp_init(struct device *dev, void __iomem 
*mmio_base, int irq,
 void skl_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx);
 void bxt_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx);
 
-int snd_skl_get_module_info(struct skl_sst *ctx, u8 *uuid,
-               struct skl_dfw_module *dfw_config);
+int snd_skl_get_module_info(struct skl_sst *ctx, struct skl_module_cfg 
*mconfig);
+
 int snd_skl_parse_uuids(struct sst_dsp *ctx, unsigned int offset);
+
+int skl_get_pvt_id(struct skl_sst *ctx,
+                               struct skl_module_cfg *mconfig);
+int skl_put_pvt_id(struct skl_sst *ctx,
+                               struct skl_module_cfg *mconfig);
+int skl_get_pvt_instance_id_map(struct skl_sst *ctx,
+                               int module_id, int instance_id);
+
+
 void skl_freeup_uuid_list(struct skl_sst *ctx);
 
 int skl_dsp_strip_extended_manifest(struct firmware *fw);
diff --git a/sound/soc/intel/skylake/skl-sst-utils.c 
b/sound/soc/intel/skylake/skl-sst-utils.c
index 25fcb79..d906701 100644
--- a/sound/soc/intel/skylake/skl-sst-utils.c
+++ b/sound/soc/intel/skylake/skl-sst-utils.c
@@ -28,11 +28,6 @@
 /* FW Extended Manifest Header id = $AE1 */
 #define SKL_EXT_MANIFEST_HEADER_MAGIC   0x31454124
 
-struct skl_dfw_module_mod {
-       char name[100];
-       struct skl_dfw_module skl_dfw_mod;
-};
-
 struct UUID {
        u8 id[16];
 };
@@ -99,10 +94,15 @@ struct adsp_fw_hdr {
        u32 load_offset;
 } __packed;
 
+#define MAX_INSTANCE_BUFF 2
+
 struct uuid_module {
        uuid_le uuid;
        int id;
        int is_loadable;
+       int max_instance;
+       u64 pvt_id[MAX_INSTANCE_BUFF];
+       int *instance_id;
 
        struct list_head list;
 };
@@ -115,19 +115,26 @@ struct skl_ext_manifest_hdr {
        u32 entries;
 };
 
-int snd_skl_get_module_info(struct skl_sst *ctx, u8 *uuid,
-                       struct skl_dfw_module *dfw_config)
+int snd_skl_get_module_info(struct skl_sst *ctx, struct skl_module_cfg 
*mconfig)
 {
        struct uuid_module *module;
        uuid_le *uuid_mod;
 
-       uuid_mod = (uuid_le *)uuid;
+       uuid_mod = (uuid_le *)mconfig->guid;
+
+       if (list_empty(&ctx->uuid_list)) {
+               dev_err(ctx->dev, "Module list is empty\n");
+               return -EINVAL;
+       }
 
        list_for_each_entry(module, &ctx->uuid_list, list) {
-               if (uuid_le_cmp(*uuid_mod, module->uuid) == 0) {
-                       dfw_config->module_id = module->id;
-                       dfw_config->is_loadable = module->is_loadable;
+               dev_dbg(ctx->dev,
+                       "uuid_tplg :%pUL   uuid_fw:%pUL\n",
+                       uuid_mod, &module->uuid );
 
+               if (uuid_le_cmp(*uuid_mod, module->uuid) == 0) {
+                       mconfig->id.module_id = module->id;
+                       mconfig->is_loadable = module->is_loadable;
                        return 0;
                }
        }
@@ -136,6 +143,219 @@ int snd_skl_get_module_info(struct skl_sst *ctx, u8 *uuid,
 }
 EXPORT_SYMBOL_GPL(snd_skl_get_module_info);
 
+static int skl_get_pvtid_map(struct uuid_module *module, int instance_id)
+{
+       int pvt_id;
+
+       for (pvt_id = 0; pvt_id < module->max_instance; pvt_id++) {
+               if (module->instance_id[pvt_id] == instance_id)
+                       return pvt_id;
+       }
+       return -EINVAL;
+}
+
+int skl_get_pvt_instance_id_map(struct skl_sst *ctx,
+                               int module_id, int instance_id)
+{
+       struct uuid_module *module;
+
+       list_for_each_entry(module, &ctx->uuid_list, list) {
+               if (module->id == module_id)
+                       return skl_get_pvtid_map(module, instance_id);
+       }
+
+       return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(skl_get_pvt_instance_id_map);
+
+static inline int skl_getid_32(struct uuid_module *module, u64 *val,
+                               int word1_mask, int word2_mask)
+{
+       int index, max_inst, pvt_id;
+       u32 mask_val;
+
+       max_inst =  module->max_instance;
+       mask_val = (u32)(*val >> word1_mask);
+       if (mask_val != 0xffffffff) {
+               index = ffz(mask_val);
+               pvt_id = index + word1_mask + word2_mask;
+               if (pvt_id <= (max_inst - 1)) {
+                       *val |= 1 << (index + word1_mask);
+                       return pvt_id;
+               }
+       }
+
+       return -EINVAL;
+}
+
+static inline int skl_pvtid_128(struct uuid_module *module)
+{
+       int j, i, word1_mask, word2_mask = 0, pvt_id;
+
+       for (j = 0; j < MAX_INSTANCE_BUFF; j++) {
+               word1_mask = 0;
+
+               for (i = 0; i < 2; i++) {
+                       pvt_id = skl_getid_32(module, &module->pvt_id[j],
+                                               word1_mask, word2_mask);
+                       if (pvt_id >= 0)
+                               return pvt_id;
+
+                       word1_mask += 32;
+                       if ((word1_mask + word2_mask) >= module->max_instance)
+                               return -EINVAL;
+               }
+
+               word2_mask += 64;
+               if (word2_mask >= module->max_instance)
+                       return -EINVAL;
+       }
+
+       return -EINVAL;
+}
+
+/**
+ * skl_get_pvt_id: generate a private id for use as module id
+ *
+ * @ctx: driver context
+ * @mconfig: module configuration data
+ *
+ * This generates a 128 bit private unique id for a module TYPE so that
+ * module instance is unique
+ */
+int skl_get_pvt_id(struct skl_sst *ctx, struct skl_module_cfg *mconfig)
+{
+       struct uuid_module *module;
+       uuid_le *uuid_mod;
+       int pvt_id;
+
+       uuid_mod = (uuid_le *)mconfig->guid;
+
+       list_for_each_entry(module, &ctx->uuid_list, list) {
+               if (uuid_le_cmp(*uuid_mod, module->uuid) == 0) {
+                       pvt_id = skl_pvtid_128(module);
+                       if (pvt_id >= 0) {
+                               module->instance_id[pvt_id] =
+                                               mconfig->id.instance_id;
+                               return pvt_id;
+                       }
+               }
+       }
+
+       return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(skl_get_pvt_id);
+
+/**
+ * skl_put_pvt_id: free up the private id allocated
+ *
+ * @ctx: driver context
+ * @mconfig: module configuration data
+ *
+ * This frees a 128 bit private unique id previously generated
+ */
+int skl_put_pvt_id(struct skl_sst *ctx, struct skl_module_cfg *mconfig)
+{
+       int i;
+       uuid_le *uuid_mod;
+       struct uuid_module *module;
+
+       uuid_mod = (uuid_le *)mconfig->guid;
+       list_for_each_entry(module, &ctx->uuid_list, list) {
+               if (uuid_le_cmp(*uuid_mod, module->uuid) == 0) {
+
+                       if (mconfig->id.pvt_id != 0)
+                               i = (mconfig->id.pvt_id) / 64;
+                       else
+                               i = 0;
+
+                       module->pvt_id[i] &= ~(1 << (mconfig->id.pvt_id));
+                       mconfig->id.pvt_id = -1;
+                       return 0;
+               }
+       }
+
+       return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(skl_put_pvt_id);
+
+/*
+ * Parse the firmware binary to get the UUID, module id
+ * and loadable flags
+ */
+/*int snd_skl_parse_uuids(struct sst_dsp *ctx, const struct firmware *fw,
+                       unsigned int offset, int index)
+{
+       struct adsp_fw_hdr *adsp_hdr;
+       struct adsp_module_entry *mod_entry;
+       int i, num_entry, size;
+       uuid_le *uuid_bin;
+       const char *buf;
+       struct skl_sst *skl = ctx->thread_context;
+       struct uuid_module *module;
+       struct firmware stripped_fw;
+       unsigned int safe_file;
+
+       stripped_fw.data = fw->data;
+       stripped_fw.size = fw->size;
+
+       skl_dsp_strip_extended_manifest(&stripped_fw);
+
+       buf = stripped_fw.data;
+
+       safe_file = sizeof(*adsp_hdr) + offset;
+       if (stripped_fw.size <= safe_file) {
+               dev_err(ctx->dev, "Small fw file size, No space for hdr\n");
+               return -EINVAL;
+       }
+
+       adsp_hdr = (struct adsp_fw_hdr *)(buf + offset);
+
+       safe_file += adsp_hdr->len + sizeof(*mod_entry);
+       if (stripped_fw.size <= safe_file) {
+               dev_err(ctx->dev, "Small fw file size, No module entry\n");
+               return -EINVAL;
+       }
+
+       mod_entry = (struct adsp_module_entry *)
+               (buf + offset + adsp_hdr->len);
+
+       num_entry = adsp_hdr->num_modules;
+
+       safe_file += num_entry * sizeof(*mod_entry);
+       if (stripped_fw.size <= safe_file) {
+               dev_err(ctx->dev, "Small fw file size, No modules\n");
+               return -EINVAL;
+       }
+
+
+
+       for (i = 0; i < num_entry; i++, mod_entry++) {
+               module = kzalloc(sizeof(*module), GFP_KERNEL);
+               if (!module)
+                       return -ENOMEM;
+
+               uuid_bin = (uuid_le *)mod_entry->uuid.id;
+               memcpy(&module->uuid, uuid_bin, sizeof(module->uuid));
+
+               module->id = (i | (index << 12));
+               module->is_loadable = mod_entry->type.load_type;
+               module->max_instance = mod_entry->instance_max_count;
+               size = sizeof(int) * mod_entry->instance_max_count;
+               module->instance_id = devm_kzalloc(ctx->dev, size, GFP_KERNEL);
+               if (!module->instance_id)
+                       return -ENOMEM;
+
+               list_add_tail(&module->list, &skl->uuid_list);
+
+               dev_dbg(ctx->dev,
+                       "Adding uuid :%pUL   mod id: %d  Loadable: %d\n",
+                       &module->uuid, module->id, module->is_loadable);
+       }
+
+       return 0;
+}*/
+
 /*
  * Parse the firmware binary to get the UUID, module id
  * and loadable flags
@@ -144,7 +364,7 @@ int snd_skl_parse_uuids(struct sst_dsp *ctx, unsigned int 
offset)
 {
        struct adsp_fw_hdr *adsp_hdr;
        struct adsp_module_entry *mod_entry;
-       int i, num_entry;
+       int i, num_entry, size;
        uuid_le *uuid_bin;
        const char *buf;
        struct skl_sst *skl = ctx->thread_context;
@@ -207,6 +427,11 @@ int snd_skl_parse_uuids(struct sst_dsp *ctx, unsigned int 
offset)
 
                module->id = i;
                module->is_loadable = mod_entry->type.load_type;
+               module->max_instance = mod_entry->instance_max_count;
+               size = sizeof(int) * mod_entry->instance_max_count;
+               module->instance_id = devm_kzalloc(ctx->dev, size, GFP_KERNEL);
+               if (!module->instance_id)
+                       return -ENOMEM;
 
                list_add_tail(&module->list, &skl->uuid_list);
 
diff --git a/sound/soc/intel/skylake/skl-topology.c 
b/sound/soc/intel/skylake/skl-topology.c
index 44b62e1..7e93d4f 100644
--- a/sound/soc/intel/skylake/skl-topology.c
+++ b/sound/soc/intel/skylake/skl-topology.c
@@ -21,6 +21,7 @@
 #include <linux/firmware.h>
 #include <sound/soc.h>
 #include <sound/soc-topology.h>
+#include <uapi/sound/snd_sst_tokens.h>
 #include "skl-sst-dsp.h"
 #include "skl-sst-ipc.h"
 #include "skl-topology.h"
@@ -32,6 +33,8 @@
 #define SKL_CH_FIXUP_MASK              (1 << 0)
 #define SKL_RATE_FIXUP_MASK            (1 << 1)
 #define SKL_FMT_FIXUP_MASK             (1 << 2)
+#define SKL_IN_DIR_BIT_MASK            BIT(0)
+#define SKL_PIN_COUNT_MASK             GENMASK(7, 4)
 
 /*
  * SKL DSP driver modelling uses only few DAPM widgets so for rest we will
@@ -297,7 +300,6 @@ static int skl_tplg_update_be_blob(struct 
snd_soc_dapm_widget *w,
        u32 ch, s_freq, s_fmt;
        struct nhlt_specific_cfg *cfg;
        struct skl *skl = get_skl_ctx(ctx->dev);
-
        /* check if we already have blob */
        if (m_cfg->formats_config.caps_size > 0)
                return 0;
@@ -379,43 +381,6 @@ static void skl_tplg_update_module_params(struct 
snd_soc_dapm_widget *w,
 }
 
 /*
- * A pipe can have multiple modules, each of them will be a DAPM widget as
- * well. While managing a pipeline we need to get the list of all the
- * widgets in a pipelines, so this helper - skl_tplg_get_pipe_widget() helps
- * to get the SKL type widgets in that pipeline
- */
-static int skl_tplg_alloc_pipe_widget(struct device *dev,
-       struct snd_soc_dapm_widget *w, struct skl_pipe *pipe)
-{
-       struct skl_module_cfg *src_module = NULL;
-       struct snd_soc_dapm_path *p = NULL;
-       struct skl_pipe_module *p_module = NULL;
-
-       p_module = devm_kzalloc(dev, sizeof(*p_module), GFP_KERNEL);
-       if (!p_module)
-               return -ENOMEM;
-
-       p_module->w = w;
-       list_add_tail(&p_module->node, &pipe->w_list);
-
-       snd_soc_dapm_widget_for_each_sink_path(w, p) {
-               if ((p->sink->priv == NULL)
-                               && (!is_skl_dsp_widget_type(w)))
-                       continue;
-
-               if ((p->sink->priv != NULL) && p->connect
-                               && is_skl_dsp_widget_type(p->sink)) {
-
-                       src_module = p->sink->priv;
-                       if (pipe->ppl_id == src_module->pipe->ppl_id)
-                               skl_tplg_alloc_pipe_widget(dev,
-                                                       p->sink, pipe);
-               }
-       }
-       return 0;
-}
-
-/*
  * some modules can have multiple params set from user control and
  * need to be set after module is initialized. If set_param flag is
  * set module params will be done after module is initialised.
@@ -448,7 +413,7 @@ static int skl_tplg_set_module_params(struct 
snd_soc_dapm_widget *w,
 
                        if (bc->set_params == SKL_PARAM_SET) {
                                ret = skl_set_module_params(ctx,
-                                               (u32 *)bc->params, bc->max,
+                                               (u32 *)bc->params, bc->size,
                                                bc->param_id, mconfig);
                                if (ret < 0)
                                        return ret;
@@ -483,7 +448,7 @@ static int skl_tplg_set_module_init_data(struct 
snd_soc_dapm_widget *w)
                                continue;
 
                        mconfig->formats_config.caps = (u32 *)&bc->params;
-                       mconfig->formats_config.caps_size = bc->max;
+                       mconfig->formats_config.caps_size = bc->size;
 
                        break;
                }
@@ -509,13 +474,22 @@ skl_tplg_init_pipe_modules(struct skl *skl, struct 
skl_pipe *pipe)
        list_for_each_entry(w_module, &pipe->w_list, node) {
                w = w_module->w;
                mconfig = w->priv;
+               /* check if module ids are populated */
+               if (mconfig->id.module_id < 0) {
+                       dev_err(skl->skl_sst->dev,
+                                       "module %pUL id not populated\n",
+                                       (uuid_le *)mconfig->guid);
+                       return -EIO;
+               } else {
+                       dev_err(skl->skl_sst->dev,
+                                       "module %pUL id is  populated\n",
+                                       (uuid_le *)mconfig->guid);
 
+               }
                /* check resource available */
                if (!skl_is_pipe_mcps_avail(skl, mconfig))
                        return -ENOMEM;
 
-               skl_tplg_alloc_pipe_mcps(skl, mconfig);
-
                if (mconfig->is_loadable && ctx->dsp->fw_ops.load_mod) {
                        ret = ctx->dsp->fw_ops.load_mod(ctx->dsp,
                                mconfig->id.module_id, mconfig->guid);
@@ -533,13 +507,21 @@ skl_tplg_init_pipe_modules(struct skl *skl, struct 
skl_pipe *pipe)
                 * FE/BE params
                 */
                skl_tplg_update_module_params(w, ctx);
+               mconfig->id.pvt_id = skl_get_pvt_id(ctx, mconfig);
 
+               if (mconfig->id.pvt_id < 0)
+                       return ret;
                skl_tplg_set_module_init_data(w);
+
                ret = skl_init_module(ctx, mconfig);
-               if (ret < 0)
+               if (ret < 0) {
+                       skl_put_pvt_id(ctx, mconfig);
                        return ret;
+               }
 
+               skl_tplg_alloc_pipe_mcps(skl, mconfig);
                ret = skl_tplg_set_module_params(w, ctx);
+
                if (ret < 0)
                        return ret;
        }
@@ -550,6 +532,7 @@ skl_tplg_init_pipe_modules(struct skl *skl, struct skl_pipe 
*pipe)
 static int skl_tplg_unload_pipe_modules(struct skl_sst *ctx,
         struct skl_pipe *pipe)
 {
+       int ret;
        struct skl_pipe_module *w_module = NULL;
        struct skl_module_cfg *mconfig = NULL;
 
@@ -557,9 +540,13 @@ static int skl_tplg_unload_pipe_modules(struct skl_sst 
*ctx,
                mconfig  = w_module->w->priv;
 
                if (mconfig->is_loadable && ctx->dsp->fw_ops.unload_mod &&
-                       mconfig->m_state > SKL_MODULE_UNINIT)
-                       return ctx->dsp->fw_ops.unload_mod(ctx->dsp,
+                       mconfig->m_state > SKL_MODULE_UNINIT) {
+                       ret = ctx->dsp->fw_ops.unload_mod(ctx->dsp,
                                                mconfig->id.module_id);
+                       if (ret < 0)
+                               return -EIO;
+               }
+               skl_put_pvt_id(ctx, mconfig);
        }
 
        /* no modules to unload in this path, so return */
@@ -591,9 +578,6 @@ static int skl_tplg_mixer_dapm_pre_pmu_event(struct 
snd_soc_dapm_widget *w,
        if (!skl_is_pipe_mem_avail(skl, mconfig))
                return -ENOMEM;
 
-       skl_tplg_alloc_pipe_mem(skl, mconfig);
-       skl_tplg_alloc_pipe_mcps(skl, mconfig);
-
        /*
         * Create a list of modules for pipe.
         * This list contains modules from source to sink
@@ -602,19 +586,8 @@ static int skl_tplg_mixer_dapm_pre_pmu_event(struct 
snd_soc_dapm_widget *w,
        if (ret < 0)
                return ret;
 
-       /*
-        * we create a w_list of all widgets in that pipe. This list is not
-        * freed on PMD event as widgets within a pipe are static. This
-        * saves us cycles to get widgets in pipe every time.
-        *
-        * So if we have already initialized all the widgets of a pipeline
-        * we skip, so check for list_empty and create the list if empty
-        */
-       if (list_empty(&s_pipe->w_list)) {
-               ret = skl_tplg_alloc_pipe_widget(ctx->dev, w, s_pipe);
-               if (ret < 0)
-                       return ret;
-       }
+       skl_tplg_alloc_pipe_mem(skl, mconfig);
+       skl_tplg_alloc_pipe_mcps(skl, mconfig);
 
        /* Init all pipe modules from source to sink */
        ret = skl_tplg_init_pipe_modules(skl, s_pipe);
@@ -640,6 +613,26 @@ static int skl_tplg_mixer_dapm_pre_pmu_event(struct 
snd_soc_dapm_widget *w,
        return 0;
 }
 
+static int skl_fill_sink_instance_id(struct skl_sst *ctx,
+                               struct skl_algo_data *alg_data)
+{
+       struct skl_kpb_params *params = (struct skl_kpb_params 
*)alg_data->params;
+       struct skl_mod_inst_map *inst;
+       int i, pvt_id;
+
+       inst = params->map;
+
+       for (i = 0; i < params->num_modules; i++) {
+               pvt_id = skl_get_pvt_instance_id_map(ctx,
+                                       inst->mod_id, inst->inst_id);
+               if (pvt_id < 0)
+                       return -EINVAL;
+               inst->inst_id = pvt_id;
+               inst++;
+       }
+       return 0;
+}
+
 /*
  * Some modules require params to be set after the module is bound to
  * all pins connected.
@@ -688,6 +681,8 @@ static int skl_tplg_set_module_bind_params(struct 
snd_soc_dapm_widget *w,
                        bc = (struct skl_algo_data *)sb->dobj.private;
 
                        if (bc->set_params == SKL_PARAM_BIND) {
+                               if (mconfig->m_type == SKL_MODULE_TYPE_KPB)
+                                       skl_fill_sink_instance_id(ctx, bc);
                                ret = skl_set_module_params(ctx,
                                                (u32 *)bc->params, bc->max,
                                                bc->param_id, mconfig);
@@ -781,7 +776,6 @@ static int skl_tplg_pga_dapm_pre_pmu_event(struct 
snd_soc_dapm_widget *w,
        struct skl_module_cfg *src_mconfig;
        struct skl_sst *ctx = skl->skl_sst;
        int ret = 0;
-
        src_mconfig = w->priv;
 
        /*
@@ -949,13 +943,17 @@ static int skl_tplg_mixer_dapm_post_pmd_event(struct 
snd_soc_dapm_widget *w,
        struct skl_pipe *s_pipe = mconfig->pipe;
        int ret = 0;
 
+       if (s_pipe->state == SKL_PIPE_INVALID)
+               return -EINVAL;
+
        skl_tplg_free_pipe_mcps(skl, mconfig);
        skl_tplg_free_pipe_mem(skl, mconfig);
 
        list_for_each_entry(w_module, &s_pipe->w_list, node) {
                dst_module = w_module->w->priv;
 
-               skl_tplg_free_pipe_mcps(skl, dst_module);
+               if (mconfig->m_state >= SKL_MODULE_INIT_DONE)
+                       skl_tplg_free_pipe_mcps(skl, dst_module);
                if (src_module == NULL) {
                        src_module = dst_module;
                        continue;
@@ -1102,7 +1100,7 @@ static int skl_tplg_tlv_control_get(struct snd_kcontrol 
*kcontrol,
 
        if (w->power)
                skl_get_module_params(skl->skl_sst, (u32 *)bc->params,
-                                     bc->max, bc->param_id, mconfig);
+                                     bc->size, bc->param_id, mconfig);
 
        /* decrement size for TLV header */
        size -= 2 * sizeof(u32);
@@ -1136,6 +1134,10 @@ static int skl_tplg_tlv_control_set(struct snd_kcontrol 
*kcontrol,
        struct skl *skl = get_skl_ctx(w->dapm->dev);
 
        if (ac->params) {
+               if (size > ac->max)
+                       return -EINVAL;
+
+               ac->size = size;
                /*
                 * if the param_is is of type Vendor, firmware expects actual
                 * parameter id and size from the control.
@@ -1151,7 +1153,7 @@ static int skl_tplg_tlv_control_set(struct snd_kcontrol 
*kcontrol,
 
                if (w->power)
                        return skl_set_module_params(skl->skl_sst,
-                                               (u32 *)ac->params, ac->max,
+                                               (u32 *)ac->params, ac->size,
                                                ac->param_id, mconfig);
        }
 
@@ -1159,6 +1161,39 @@ static int skl_tplg_tlv_control_set(struct snd_kcontrol 
*kcontrol,
 }
 
 /*
+ * Fill the dma id for host and link. In case of passthrough
+ * pipeline, this will both host and link in the same
+ * pipeline, so need to copy the link and host based on dev_type
+ */
+static void skl_tplg_fill_dma_id(struct skl_module_cfg *mcfg,
+                               struct skl_pipe_params *params)
+{
+       struct skl_pipe *pipe = mcfg->pipe;
+
+       if (pipe->passthru) {
+               switch (mcfg->dev_type) {
+               case SKL_DEVICE_HDALINK:
+                       pipe->p_params->link_dma_id = params->link_dma_id;
+                       break;
+
+               case SKL_DEVICE_HDAHOST:
+                       pipe->p_params->host_dma_id = params->host_dma_id;
+                       break;
+
+               default:
+                       break;
+               }
+               pipe->p_params->s_fmt = params->s_fmt;
+               pipe->p_params->ch = params->ch;
+               pipe->p_params->s_freq = params->s_freq;
+               pipe->p_params->stream = params->stream;
+
+       } else {
+               memcpy(pipe->p_params, params, sizeof(*params));
+       }
+}
+
+/*
  * The FE params are passed by hw_params of the DAI.
  * On hw_params, the params are stored in Gateway module of the FE and we
  * need to calculate the format in DSP module configuration, that
@@ -1168,10 +1203,9 @@ int skl_tplg_update_pipe_params(struct device *dev,
                        struct skl_module_cfg *mconfig,
                        struct skl_pipe_params *params)
 {
-       struct skl_pipe *pipe = mconfig->pipe;
        struct skl_module_fmt *format = NULL;
 
-       memcpy(pipe->p_params, params, sizeof(*params));
+       skl_tplg_fill_dma_id(mconfig, params);
 
        if (params->stream == SNDRV_PCM_STREAM_PLAYBACK)
                format = &mconfig->in_fmt[0];
@@ -1358,12 +1392,12 @@ static int skl_tplg_be_fill_pipe_params(struct 
snd_soc_dai *dai,
                                struct skl_module_cfg *mconfig,
                                struct skl_pipe_params *params)
 {
-       struct skl_pipe *pipe = mconfig->pipe;
        struct nhlt_specific_cfg *cfg;
        struct skl *skl = get_skl_ctx(dai->dev);
        int link_type = skl_tplg_be_link_type(mconfig->dev_type);
+       u32 *ssp_blob;
 
-       memcpy(pipe->p_params, params, sizeof(*params));
+       skl_tplg_fill_dma_id(mconfig, params);
 
        if (link_type == NHLT_LINK_HDA)
                return 0;
@@ -1383,6 +1417,14 @@ static int skl_tplg_be_fill_pipe_params(struct 
snd_soc_dai *dai,
                                 params->ch, params->s_freq, params->s_fmt);
                return -EINVAL;
        }
+                if ((link_type == NHLT_LINK_SSP) &&  (mconfig->vbus_id == 0)) 
{         /*Assuming you are using SSP0 */
+                        dev_info(dai->dev, "%s:overridimg MDIVR to bypass MCLK 
division\n", __func__);
+                        ssp_blob = (u32*)mconfig->formats_config.caps;
+                        /* Set bypass in mdivr */
+                       ssp_blob[9] = 0x83D00337; // 4 channel, 24 data size
+                        ssp_blob[20] = 0xFFF;
+                       ssp_blob[12] = ssp_blob[12] & 0xFFFFFFFC;
+                }
 
        return 0;
 }
@@ -1450,7 +1492,6 @@ int skl_tplg_be_update_params(struct snd_soc_dai *dai,
 
        if (params->stream == SNDRV_PCM_STREAM_PLAYBACK) {
                w = dai->playback_widget;
-
                return skl_tplg_be_set_src_pipe_params(dai, w, params);
 
        } else {
@@ -1473,297 +1514,1041 @@ static const struct snd_soc_tplg_bytes_ext_ops 
skl_tlv_ops[] = {
                                        skl_tplg_tlv_control_set},
 };
 
-/*
- * The topology binary passes the pin info for a module so initialize the pin
- * info passed into module instance
- */
-static void skl_fill_module_pin_info(struct skl_dfw_module_pin *dfw_pin,
-                                               struct skl_module_pin *m_pin,
-                                               bool is_dynamic, int max_pin)
+static int skl_tplg_fill_pipe_tkn(struct device *dev,
+                       struct skl_pipe *pipe, u32 tkn,
+                       u32 tkn_val)
 {
-       int i;
 
-       for (i = 0; i < max_pin; i++) {
-               m_pin[i].id.module_id = dfw_pin[i].module_id;
-               m_pin[i].id.instance_id = dfw_pin[i].instance_id;
-               m_pin[i].in_use = false;
-               m_pin[i].is_dynamic = is_dynamic;
-               m_pin[i].pin_state = SKL_PIN_UNBIND;
+       switch (tkn) {
+       case SKL_TKN_U32_PIPE_CONN_TYPE:
+               pipe->conn_type = tkn_val;
+               break;
+
+       case SKL_TKN_U32_PIPE_PRIORITY:
+               pipe->pipe_priority = tkn_val;
+               break;
+
+       case SKL_TKN_U32_PIPE_MEM_PGS:
+               pipe->memory_pages = tkn_val;
+               break;
+
+       default:
+               dev_err(dev, "Token not handled %d\n", tkn);
+               return -EINVAL;
        }
+
+       return 0;
 }
 
 /*
- * Add pipeline from topology binary into driver pipeline list
- *
- * If already added we return that instance
- * Otherwise we create a new instance and add into driver list
+ * Add pipeline by parsing the relevant tokens
+ * Return an existing pipe if the pipe already exists.
  */
-static struct skl_pipe *skl_tplg_add_pipe(struct device *dev,
-                       struct skl *skl, struct skl_dfw_pipe *dfw_pipe)
+static int skl_tplg_add_pipe(struct device *dev,
+               struct skl_module_cfg *mconfig, struct skl *skl,
+               struct snd_soc_tplg_vendor_value_elem *tkn_elem)
 {
        struct skl_pipeline *ppl;
        struct skl_pipe *pipe;
        struct skl_pipe_params *params;
 
        list_for_each_entry(ppl, &skl->ppl_list, node) {
-               if (ppl->pipe->ppl_id == dfw_pipe->pipe_id)
-                       return ppl->pipe;
+               if (ppl->pipe->ppl_id == tkn_elem->value) {
+                       mconfig->pipe = ppl->pipe;
+                       return EEXIST;
+               }
        }
 
        ppl = devm_kzalloc(dev, sizeof(*ppl), GFP_KERNEL);
        if (!ppl)
-               return NULL;
+               return -ENOMEM;
 
        pipe = devm_kzalloc(dev, sizeof(*pipe), GFP_KERNEL);
        if (!pipe)
-               return NULL;
+               return -ENOMEM;
 
        params = devm_kzalloc(dev, sizeof(*params), GFP_KERNEL);
        if (!params)
-               return NULL;
+               return -ENOMEM;
 
-       pipe->ppl_id = dfw_pipe->pipe_id;
-       pipe->memory_pages = dfw_pipe->memory_pages;
-       pipe->pipe_priority = dfw_pipe->pipe_priority;
-       pipe->conn_type = dfw_pipe->conn_type;
-       pipe->state = SKL_PIPE_INVALID;
        pipe->p_params = params;
+       pipe->ppl_id = tkn_elem->value;
        INIT_LIST_HEAD(&pipe->w_list);
 
        ppl->pipe = pipe;
        list_add(&ppl->node, &skl->ppl_list);
 
-       return ppl->pipe;
+       mconfig->pipe = pipe;
+       mconfig->pipe->state = SKL_PIPE_INVALID;
+
+       return 0;
 }
 
-static void skl_tplg_fill_fmt(struct skl_module_fmt *dst_fmt,
-                               struct skl_dfw_module_fmt *src_fmt,
-                               int pins)
+static int skl_tplg_fill_pin(struct device *dev, u32 tkn,
+                       struct skl_module_pin *m_pin,
+                       int pin_index, u32 value)
 {
-       int i;
+       switch (tkn) {
+       case SKL_TKN_U32_PIN_MOD_ID:
+               m_pin[pin_index].id.module_id = value;
+               break;
+
+       case SKL_TKN_U32_PIN_INST_ID:
+               m_pin[pin_index].id.instance_id = value;
+               break;
 
-       for (i = 0; i < pins; i++) {
-               dst_fmt[i].channels  = src_fmt[i].channels;
-               dst_fmt[i].s_freq = src_fmt[i].freq;
-               dst_fmt[i].bit_depth = src_fmt[i].bit_depth;
-               dst_fmt[i].valid_bit_depth = src_fmt[i].valid_bit_depth;
-               dst_fmt[i].ch_cfg = src_fmt[i].ch_cfg;
-               dst_fmt[i].ch_map = src_fmt[i].ch_map;
-               dst_fmt[i].interleaving_style = src_fmt[i].interleaving_style;
-               dst_fmt[i].sample_type = src_fmt[i].sample_type;
+       default:
+               dev_err(dev, "%d Not a pin token\n", value);
+               return -EINVAL;
        }
+
+       return 0;
 }
 
 /*
- * Topology core widget load callback
- *
- * This is used to save the private data for each widget which gives
- * information to the driver about module and pipeline parameters which DSP
- * FW expects like ids, resource values, formats etc
+ * Parse for pin config specific tokens to fill up the
+ * module private data
  */
-static int skl_tplg_widget_load(struct snd_soc_component *cmpnt,
-                               struct snd_soc_dapm_widget *w,
-                               struct snd_soc_tplg_dapm_widget *tplg_w)
+static int skl_tplg_fill_pins_info(struct device *dev,
+               struct skl_module_cfg *mconfig,
+               struct snd_soc_tplg_vendor_value_elem *tkn_elem,
+               int dir, int pin_count)
 {
        int ret;
-       struct hdac_ext_bus *ebus = snd_soc_component_get_drvdata(cmpnt);
-       struct skl *skl = ebus_to_skl(ebus);
-       struct hdac_bus *bus = ebus_to_hbus(ebus);
-       struct skl_module_cfg *mconfig;
-       struct skl_pipe *pipe;
-       struct skl_dfw_module *dfw_config =
-                               (struct skl_dfw_module *)tplg_w->priv.data;
+       struct skl_module_pin *m_pin;
 
-       if (!tplg_w->priv.size)
-               goto bind_event;
+       switch (dir) {
+       case SKL_DIR_IN:
+               m_pin = mconfig->m_in_pin;
+               break;
 
-       mconfig = devm_kzalloc(bus->dev, sizeof(*mconfig), GFP_KERNEL);
+       case SKL_DIR_OUT:
+               m_pin = mconfig->m_out_pin;
+               break;
 
-       if (!mconfig)
-               return -ENOMEM;
+       default:
+               dev_err(dev, "Invalid direction value\n");
+               return -EINVAL;
+       }
 
-       w->priv = mconfig;
-       memcpy(&mconfig->guid, &dfw_config->uuid, 16);
+       ret = skl_tplg_fill_pin(dev, tkn_elem->token,
+                       m_pin, pin_count, tkn_elem->value);
 
-       ret = snd_skl_get_module_info(skl->skl_sst, mconfig->guid, dfw_config);
        if (ret < 0)
                return ret;
 
-       mconfig->id.module_id = dfw_config->module_id;
-       mconfig->id.instance_id = dfw_config->instance_id;
-       mconfig->mcps = dfw_config->max_mcps;
-       mconfig->ibs = dfw_config->ibs;
-       mconfig->obs = dfw_config->obs;
-       mconfig->core_id = dfw_config->core_id;
-       mconfig->max_in_queue = dfw_config->max_in_queue;
-       mconfig->max_out_queue = dfw_config->max_out_queue;
-       mconfig->is_loadable = dfw_config->is_loadable;
-       skl_tplg_fill_fmt(mconfig->in_fmt, dfw_config->in_fmt,
-                                               MODULE_MAX_IN_PINS);
-       skl_tplg_fill_fmt(mconfig->out_fmt, dfw_config->out_fmt,
-                                               MODULE_MAX_OUT_PINS);
-
-       mconfig->params_fixup = dfw_config->params_fixup;
-       mconfig->converter = dfw_config->converter;
-       mconfig->m_type = dfw_config->module_type;
-       mconfig->vbus_id = dfw_config->vbus_id;
-       mconfig->mem_pages = dfw_config->mem_pages;
-
-       pipe = skl_tplg_add_pipe(bus->dev, skl, &dfw_config->pipe);
-       if (pipe)
-               mconfig->pipe = pipe;
-
-       mconfig->dev_type = dfw_config->dev_type;
-       mconfig->hw_conn_type = dfw_config->hw_conn_type;
-       mconfig->time_slot = dfw_config->time_slot;
-       mconfig->formats_config.caps_size = dfw_config->caps.caps_size;
-
-       mconfig->m_in_pin = devm_kzalloc(bus->dev, (mconfig->max_in_queue) *
-                                               sizeof(*mconfig->m_in_pin),
-                                               GFP_KERNEL);
-       if (!mconfig->m_in_pin)
-               return -ENOMEM;
+       m_pin[pin_count].in_use = false;
+       m_pin[pin_count].pin_state = SKL_PIN_UNBIND;
 
-       mconfig->m_out_pin = devm_kzalloc(bus->dev, (mconfig->max_out_queue) *
-                                               sizeof(*mconfig->m_out_pin),
-                                               GFP_KERNEL);
-       if (!mconfig->m_out_pin)
-               return -ENOMEM;
+       return 0;
+}
 
-       skl_fill_module_pin_info(dfw_config->in_pin, mconfig->m_in_pin,
-                                               dfw_config->is_dynamic_in_pin,
-                                               mconfig->max_in_queue);
+/*
+ * Fill up input/output module config format based
+ * on the direction
+ */
+static int skl_tplg_fill_fmt(struct device *dev,
+               struct skl_module_cfg *mconfig, u32 tkn,
+               u32 value, u32 dir, u32 pin_count)
+{
+       struct skl_module_fmt *dst_fmt;
 
-       skl_fill_module_pin_info(dfw_config->out_pin, mconfig->m_out_pin,
-                                                dfw_config->is_dynamic_out_pin,
-                                                       mconfig->max_out_queue);
+       switch (dir) {
+       case SKL_DIR_IN:
+               dst_fmt = mconfig->in_fmt;
+               dst_fmt += pin_count;
+               break;
 
+       case SKL_DIR_OUT:
+               dst_fmt = mconfig->out_fmt;
+               dst_fmt += pin_count;
+               break;
 
-       if (mconfig->formats_config.caps_size == 0)
-               goto bind_event;
+       default:
+               dev_err(dev, "Invalid direction value\n");
+               return -EINVAL;
+       }
 
-       mconfig->formats_config.caps = (u32 *)devm_kzalloc(bus->dev,
-                       mconfig->formats_config.caps_size, GFP_KERNEL);
+       switch (tkn) {
+       case SKL_TKN_U32_FMT_CH:
+               dst_fmt->channels  = value;
+               break;
 
-       if (mconfig->formats_config.caps == NULL)
-               return -ENOMEM;
+       case SKL_TKN_U32_FMT_FREQ:
+               dst_fmt->s_freq = value;
+               break;
 
-       memcpy(mconfig->formats_config.caps, dfw_config->caps.caps,
-                                                dfw_config->caps.caps_size);
-       mconfig->formats_config.param_id = dfw_config->caps.param_id;
-       mconfig->formats_config.set_params = dfw_config->caps.set_params;
+       case SKL_TKN_U32_FMT_BIT_DEPTH:
+               dst_fmt->bit_depth = value;
+               break;
 
-bind_event:
-       if (tplg_w->event_type == 0) {
-               dev_dbg(bus->dev, "ASoC: No event handler required\n");
-               return 0;
+       case SKL_TKN_U32_FMT_SAMPLE_SIZE:
+               dst_fmt->valid_bit_depth = value;
+               break;
+
+       case SKL_TKN_U32_FMT_CH_CONFIG:
+               dst_fmt->ch_cfg = value;
+               break;
+
+       case SKL_TKN_U32_FMT_INTERLEAVE:
+               dst_fmt->interleaving_style = value;
+               break;
+
+       case SKL_TKN_U32_FMT_SAMPLE_TYPE:
+               dst_fmt->sample_type = value;
+               break;
+
+       case SKL_TKN_U32_FMT_CH_MAP:
+               dst_fmt->ch_map = value;
+               break;
+
+       default:
+               dev_err(dev, "Invalid token %d\n", tkn);
+               return -EINVAL;
        }
 
-       ret = snd_soc_tplg_widget_bind_event(w, skl_tplg_widget_ops,
-                                       ARRAY_SIZE(skl_tplg_widget_ops),
-                                       tplg_w->event_type);
+       return 0;
+}
 
-       if (ret) {
-               dev_err(bus->dev, "%s: No matching event handlers found for 
%d\n",
-                                       __func__, tplg_w->event_type);
+static int skl_tplg_get_uuid(struct device *dev, struct skl_module_cfg 
*mconfig,
+             struct snd_soc_tplg_vendor_uuid_elem *uuid_tkn)
+{
+       if (uuid_tkn->token == SKL_TKN_UUID)
+               memcpy(&mconfig->guid, &uuid_tkn->uuid, 16);
+       else {
+               dev_err(dev, "Not an UUID token tkn %d\n", uuid_tkn->token);
                return -EINVAL;
        }
 
        return 0;
 }
 
-static int skl_init_algo_data(struct device *dev, struct soc_bytes_ext *be,
-                                       struct snd_soc_tplg_bytes_control *bc)
+static void skl_tplg_fill_pin_dynamic_val(
+               struct skl_module_pin *mpin, u32 pin_count, u32 value)
 {
-       struct skl_algo_data *ac;
-       struct skl_dfw_algo_data *dfw_ac =
-                               (struct skl_dfw_algo_data *)bc->priv.data;
+       int i;
 
-       ac = devm_kzalloc(dev, sizeof(*ac), GFP_KERNEL);
-       if (!ac)
-               return -ENOMEM;
+       for (i = 0; i < pin_count; i++)
+               mpin[i].is_dynamic = value;
+}
 
-       /* Fill private data */
-       ac->max = dfw_ac->max;
-       ac->param_id = dfw_ac->param_id;
-       ac->set_params = dfw_ac->set_params;
+/*
+ * Parse tokens to fill up the module private data
+ */
+static int skl_tplg_get_token(struct device *dev,
+               struct snd_soc_tplg_vendor_value_elem *tkn_elem,
+               struct skl *skl, struct skl_module_cfg *mconfig)
+{
+       int tkn_count = 0;
+       int ret;
+       static int is_pipe_exists;
+       static int pin_index, dir;
+       if (tkn_elem->token > SKL_TKN_MAX)
+               return -EINVAL;
 
-       if (ac->max) {
-               ac->params = (char *) devm_kzalloc(dev, ac->max, GFP_KERNEL);
-               if (!ac->params)
+       switch (tkn_elem->token) {
+       case SKL_TKN_U8_IN_QUEUE_COUNT:
+               mconfig->max_in_queue = tkn_elem->value;
+               mconfig->m_in_pin = devm_kzalloc(dev, mconfig->max_in_queue *
+                                       sizeof(*mconfig->m_in_pin),
+                                       GFP_KERNEL);
+               if (!mconfig->m_in_pin)
                        return -ENOMEM;
 
-               memcpy(ac->params, dfw_ac->params, ac->max);
-       }
+               break;
 
-       be->dobj.private  = ac;
-       return 0;
-}
+       case SKL_TKN_U8_OUT_QUEUE_COUNT:
+               mconfig->max_out_queue = tkn_elem->value;
+               mconfig->m_out_pin = devm_kzalloc(dev, mconfig->max_out_queue *
+                                       sizeof(*mconfig->m_out_pin),
+                                       GFP_KERNEL);
 
-static int skl_tplg_control_load(struct snd_soc_component *cmpnt,
-                               struct snd_kcontrol_new *kctl,
-                               struct snd_soc_tplg_ctl_hdr *hdr)
-{
-       struct soc_bytes_ext *sb;
-       struct snd_soc_tplg_bytes_control *tplg_bc;
-       struct hdac_ext_bus *ebus  = snd_soc_component_get_drvdata(cmpnt);
-       struct hdac_bus *bus = ebus_to_hbus(ebus);
+               if (!mconfig->m_out_pin)
+                       return -ENOMEM;
 
-       switch (hdr->ops.info) {
-       case SND_SOC_TPLG_CTL_BYTES:
-               tplg_bc = container_of(hdr,
-                               struct snd_soc_tplg_bytes_control, hdr);
-               if (kctl->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) {
-                       sb = (struct soc_bytes_ext *)kctl->private_value;
-                       if (tplg_bc->priv.size)
-                               return skl_init_algo_data(
-                                               bus->dev, sb, tplg_bc);
-               }
                break;
 
-       default:
-               dev_warn(bus->dev, "Control load not supported %d:%d:%d\n",
-                       hdr->ops.get, hdr->ops.put, hdr->ops.info);
+       case SKL_TKN_U8_DYN_IN_PIN:
+               if (!mconfig->m_in_pin)
+                       return -ENOMEM;
+
+               skl_tplg_fill_pin_dynamic_val(mconfig->m_in_pin,
+                       mconfig->max_in_queue, tkn_elem->value);
+
                break;
-       }
 
-       return 0;
-}
+       case SKL_TKN_U8_DYN_OUT_PIN:
+               if (!mconfig->m_out_pin)
+                       return -ENOMEM;
 
-static struct snd_soc_tplg_ops skl_tplg_ops  = {
-       .widget_load = skl_tplg_widget_load,
-       .control_load = skl_tplg_control_load,
-       .bytes_ext_ops = skl_tlv_ops,
-       .bytes_ext_ops_count = ARRAY_SIZE(skl_tlv_ops),
-};
+               skl_tplg_fill_pin_dynamic_val(mconfig->m_out_pin,
+                       mconfig->max_out_queue, tkn_elem->value);
 
-/* This will be read from topology manifest, currently defined here */
-#define SKL_MAX_MCPS 30000000
-#define SKL_FW_MAX_MEM 1000000
+               break;
 
-/*
- * SKL topology init routine
- */
-int skl_tplg_init(struct snd_soc_platform *platform, struct hdac_ext_bus *ebus)
-{
-       int ret;
-       const struct firmware *fw;
-       struct hdac_bus *bus = ebus_to_hbus(ebus);
-       struct skl *skl = ebus_to_skl(ebus);
+       case SKL_TKN_U8_TIME_SLOT:
+               mconfig->time_slot = tkn_elem->value;
+               break;
 
-       ret = request_firmware(&fw, skl->tplg_name, bus->dev);
-       if (ret < 0) {
-               dev_err(bus->dev, "tplg fw %s load failed with %d\n",
-                               skl->tplg_name, ret);
-               ret = request_firmware(&fw, "dfw_sst.bin", bus->dev);
-               if (ret < 0) {
-                       dev_err(bus->dev, "Fallback tplg fw %s load failed with 
%d\n",
-                                       "dfw_sst.bin", ret);
-                       return ret;
-               }
-       }
+       case SKL_TKN_U8_CORE_ID:
+               mconfig->core_id = tkn_elem->value;
 
-       /*
+       case SKL_TKN_U8_MOD_TYPE:
+               mconfig->m_type = tkn_elem->value;
+               break;
+
+       case SKL_TKN_U8_DEV_TYPE:
+               mconfig->dev_type = tkn_elem->value;
+               break;
+
+       case SKL_TKN_U8_HW_CONN_TYPE:
+               mconfig->hw_conn_type = tkn_elem->value;
+               break;
+
+       case SKL_TKN_U16_MOD_INST_ID:
+               mconfig->id.instance_id =
+               tkn_elem->value;
+               break;
+
+       case SKL_TKN_U32_MEM_PAGES:
+               mconfig->mem_pages = tkn_elem->value;
+               break;
+
+       case SKL_TKN_U32_MAX_MCPS:
+               mconfig->mcps = tkn_elem->value;
+               break;
+
+       case SKL_TKN_U32_OBS:
+               mconfig->obs = tkn_elem->value;
+               break;
+
+       case SKL_TKN_U32_IBS:
+               mconfig->ibs = tkn_elem->value;
+               break;
+
+       case SKL_TKN_U32_VBUS_ID:
+               mconfig->vbus_id = tkn_elem->value;
+               break;
+
+       case SKL_TKN_U32_PARAMS_FIXUP:
+               mconfig->params_fixup = tkn_elem->value;
+               break;
+
+       case SKL_TKN_U32_CONVERTER:
+               mconfig->converter = tkn_elem->value;
+               break;
+
+       case SKL_TKN_U32_PIPE_ID:
+               ret = skl_tplg_add_pipe(dev,
+                               mconfig, skl, tkn_elem);
+
+               if (ret < 0)
+                       return is_pipe_exists;
+
+               if (ret == EEXIST)
+                       is_pipe_exists = 1;
+
+               break;
+
+       case SKL_TKN_U32_PIPE_CONN_TYPE:
+       case SKL_TKN_U32_PIPE_PRIORITY:
+       case SKL_TKN_U32_PIPE_MEM_PGS:
+               if (is_pipe_exists) {
+                       ret = skl_tplg_fill_pipe_tkn(dev, mconfig->pipe,
+                                       tkn_elem->token, tkn_elem->value);
+                       if (ret < 0)
+                               return ret;
+               }
+
+               break;
+
+       /*
+        * SKL_TKN_U32_DIR_PIN_COUNT token has the value for both
+        * direction and the pin count. The first four bits represent
+        * direction and next four the pin count.
+        */
+       case SKL_TKN_U32_DIR_PIN_COUNT:
+               dir = tkn_elem->value & SKL_IN_DIR_BIT_MASK;
+               pin_index = (tkn_elem->value &
+                       SKL_PIN_COUNT_MASK) >> 4;
+
+               break;
+
+       case SKL_TKN_U32_FMT_CH:
+       case SKL_TKN_U32_FMT_FREQ:
+       case SKL_TKN_U32_FMT_BIT_DEPTH:
+       case SKL_TKN_U32_FMT_SAMPLE_SIZE:
+       case SKL_TKN_U32_FMT_CH_CONFIG:
+       case SKL_TKN_U32_FMT_INTERLEAVE:
+       case SKL_TKN_U32_FMT_SAMPLE_TYPE:
+       case SKL_TKN_U32_FMT_CH_MAP:
+               ret = skl_tplg_fill_fmt(dev, mconfig, tkn_elem->token,
+                               tkn_elem->value, dir, pin_index);
+
+               if (ret < 0)
+                       return ret;
+
+               break;
+
+       case SKL_TKN_U32_PIN_MOD_ID:
+       case SKL_TKN_U32_PIN_INST_ID:
+               ret = skl_tplg_fill_pins_info(dev,
+                               mconfig, tkn_elem, dir,
+                               pin_index);
+               if (ret < 0)
+                       return ret;
+
+               break;
+
+       case SKL_TKN_U32_CAPS_SIZE:
+               mconfig->formats_config.caps_size =
+                       tkn_elem->value;
+
+               break;
+
+       case SKL_TKN_U32_PROC_DOMAIN:
+               mconfig->domain =
+                       tkn_elem->value;
+
+               break;
+
+       case SKL_TKN_U8_IN_PIN_TYPE:
+       case SKL_TKN_U8_OUT_PIN_TYPE:
+       case SKL_TKN_U8_CONN_TYPE:
+               break;
+
+       default:
+               dev_err(dev, "Token %d not handled\n",
+                               tkn_elem->token);
+               return -EINVAL;
+       }
+
+       tkn_count++;
+
+       return tkn_count;
+}
+
+/*
+ * Parse the vendor array for specific tokens to construct
+ * module private data
+ */
+static int skl_tplg_get_tokens(struct device *dev,
+               char *pvt_data, struct skl *skl,
+               struct skl_module_cfg *mconfig, int block_size)
+{
+       struct snd_soc_tplg_vendor_array *array;
+       struct snd_soc_tplg_vendor_value_elem *tkn_elem;
+       int tkn_count = 0, ret;
+       int off = 0, tuple_size = 0;
+       if (block_size <= 0)
+               return -EINVAL;
+
+       while (tuple_size < block_size) {
+               array = (struct snd_soc_tplg_vendor_array *)(pvt_data + off);
+
+               off += array->size;
+
+               switch (array->type) {
+               case SND_SOC_TPLG_TUPLE_TYPE_STRING:
+                       dev_warn(dev, "no string tokens expected for skl 
tplg\n");
+                       continue;
+
+               case SND_SOC_TPLG_TUPLE_TYPE_UUID:
+                       ret = skl_tplg_get_uuid(dev, mconfig, array->uuid);
+                       if (ret < 0)
+                               return ret;
+
+                       tuple_size += sizeof(*array->uuid);
+
+                       continue;
+
+               default:
+                       tkn_elem = array->value;
+                       tkn_count = 0;
+                       break;
+               }
+
+               while (tkn_count <= (array->num_elems - 1)) {
+                       ret = skl_tplg_get_token(dev, tkn_elem,
+                                       skl, mconfig);
+
+                       if (ret < 0)
+                               return ret;
+
+                       tkn_count = tkn_count + ret;
+                       tkn_elem++;
+               }
+
+               tuple_size += tkn_count * sizeof(*tkn_elem);
+       }
+
+       return 0;
+}
+
+/*
+ * Every data block is preceded by a descriptor to read the number
+ * of data blocks, they type of the block and it's size
+ */
+static int skl_tplg_get_desc_blocks(struct device *dev,
+               struct snd_soc_tplg_vendor_array *array)
+{
+       struct snd_soc_tplg_vendor_value_elem *tkn_elem;
+
+       tkn_elem = array->value;
+
+       switch (tkn_elem->token) {
+       case SKL_TKN_U8_NUM_BLOCKS:
+       case SKL_TKN_U8_BLOCK_TYPE:
+       case SKL_TKN_U16_BLOCK_SIZE:
+               return tkn_elem->value;
+
+       default:
+               dev_err(dev, "Invalid descriptor token %d\n", tkn_elem->token);
+               break;
+       }
+
+       return -EINVAL;
+}
+
+/*
+ * Parse the private data for the token and corresponding value.
+ * The private data can have multiple data blocks. So, a data block
+ * is preceded by a descriptor for number of blocks and a descriptor
+ * for the type and size of the suceeding data block.
+ */
+static int skl_tplg_get_pvt_data(struct snd_soc_tplg_dapm_widget *tplg_w,
+                               struct skl *skl, struct device *dev,
+                               struct skl_module_cfg *mconfig)
+{
+       struct snd_soc_tplg_vendor_array *array;
+       int num_blocks, block_size = 0, block_type, off = 0;
+       char *data;
+       int ret;
+       /* Read the NUM_DATA_BLOCKS descriptor */
+       array = (struct snd_soc_tplg_vendor_array *)tplg_w->priv.data;
+       ret = skl_tplg_get_desc_blocks(dev, array);
+       if (ret < 0)
+               return ret;
+       num_blocks = ret;
+
+       off += array->size;
+       array = (struct snd_soc_tplg_vendor_array *)(tplg_w->priv.data + off);
+
+       /* Read the BLOCK_TYPE and BLOCK_SIZE descriptor */
+       while (num_blocks > 0) {
+               ret = skl_tplg_get_desc_blocks(dev, array);
+
+               if (ret < 0)
+                       return ret;
+               block_type = ret;
+               off += array->size;
+
+               array = (struct snd_soc_tplg_vendor_array *)
+                       (tplg_w->priv.data + off);
+
+               ret = skl_tplg_get_desc_blocks(dev, array);
+
+               if (ret < 0)
+                       return ret;
+               block_size = ret;
+               off += array->size;
+
+               array = (struct snd_soc_tplg_vendor_array *)
+                       (tplg_w->priv.data + off);
+
+               data = (tplg_w->priv.data + off);
+
+               if (block_type == SKL_TYPE_TUPLE) {
+                       ret = skl_tplg_get_tokens(dev, data,
+                                       skl, mconfig, block_size);
+
+                       if (ret < 0)
+                               return ret;
+
+                       --num_blocks;
+               } else {
+                       if (mconfig->formats_config.caps_size > 0)
+                               memcpy(mconfig->formats_config.caps, data,
+                                       mconfig->formats_config.caps_size);
+                       --num_blocks;
+               }
+       }
+
+       return 0;
+}
+
+static void skl_clear_pin_config(struct snd_soc_platform *platform,
+                               struct snd_soc_dapm_widget *w)
+{
+       int i;
+       struct skl_module_cfg *mconfig;
+       struct skl_pipe *pipe;
+
+       if (!strncmp(w->dapm->component->name, platform->component.name,
+                                       strlen(platform->component.name))) {
+               mconfig = w->priv;
+               pipe = mconfig->pipe;
+               for (i = 0; i < mconfig->max_in_queue; i++) {
+                       mconfig->m_in_pin[i].in_use = false;
+                       mconfig->m_in_pin[i].pin_state = SKL_PIN_UNBIND;
+               }
+               for (i = 0; i < mconfig->max_out_queue; i++) {
+                       mconfig->m_out_pin[i].in_use = false;
+                       mconfig->m_out_pin[i].pin_state = SKL_PIN_UNBIND;
+               }
+               pipe->state = SKL_PIPE_INVALID;
+               mconfig->m_state = SKL_MODULE_UNINIT;
+       }
+}
+
+void skl_cleanup_resources(struct skl *skl)
+{
+       struct skl_sst *ctx = skl->skl_sst;
+       struct snd_soc_platform *soc_platform = skl->platform;
+       struct snd_soc_dapm_widget *w;
+       struct snd_soc_card *card;
+
+       if (soc_platform == NULL)
+               return;
+
+       card = soc_platform->component.card;
+       if (!card || !card->instantiated)
+               return;
+
+       skl->resource.mem = 0;
+       skl->resource.mcps = 0;
+
+       list_for_each_entry(w, &card->widgets, list) {
+               if (is_skl_dsp_widget_type(w) && (w->priv != NULL))
+                       skl_clear_pin_config(soc_platform, w);
+       }
+
+       //skl_clear_module_cnt(ctx->dsp);
+}
+
+/*
+ * Topology core widget load callback
+ *
+ * This is used to save the private data for each widget which gives
+ * information to the driver about module and pipeline parameters which DSP
+ * FW expects like ids, resource values, formats etc
+ */
+static int skl_tplg_widget_load(struct snd_soc_component *cmpnt,
+                               struct snd_soc_dapm_widget *w,
+                               struct snd_soc_tplg_dapm_widget *tplg_w)
+{
+       int ret;
+       struct hdac_ext_bus *ebus = snd_soc_component_get_drvdata(cmpnt);
+       struct skl *skl = ebus_to_skl(ebus);
+       struct hdac_bus *bus = ebus_to_hbus(ebus);
+       struct skl_module_cfg *mconfig;
+
+       if (!tplg_w->priv.size)
+               goto bind_event;
+
+       mconfig = devm_kzalloc(bus->dev, sizeof(*mconfig), GFP_KERNEL);
+
+       if (!mconfig)
+               return -ENOMEM;
+
+       w->priv = mconfig;
+
+       /*
+        * module binary can be loaded later, so set it to query when
+        * module is load for a use case
+        */
+       mconfig->id.module_id = -1;
+       /* Parse private data for tuples */
+       ret = skl_tplg_get_pvt_data(tplg_w, skl, bus->dev, mconfig);
+       if (ret < 0)
+               return ret;
+bind_event:
+       if (tplg_w->event_type == 0) {
+               dev_dbg(bus->dev, "ASoC: No event handler required\n");
+               return 0;
+       }
+
+       ret = snd_soc_tplg_widget_bind_event(w, skl_tplg_widget_ops,
+                                       ARRAY_SIZE(skl_tplg_widget_ops),
+                                       tplg_w->event_type);
+
+       if (ret) {
+               dev_err(bus->dev, "%s: No matching event handlers found for 
%d\n",
+                                       __func__, tplg_w->event_type);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int skl_init_algo_data(struct device *dev, struct soc_bytes_ext *be,
+                                       struct snd_soc_tplg_bytes_control *bc)
+{
+       struct skl_algo_data *ac;
+       struct skl_dfw_algo_data *dfw_ac =
+                               (struct skl_dfw_algo_data *)bc->priv.data;
+
+       ac = devm_kzalloc(dev, sizeof(*ac), GFP_KERNEL);
+       if (!ac)
+               return -ENOMEM;
+
+       /* Fill private data */
+       ac->max = dfw_ac->max;
+       ac->param_id = dfw_ac->param_id;
+       ac->set_params = dfw_ac->set_params;
+       ac->size = dfw_ac->max;
+
+       if (ac->max) {
+               ac->params = (char *) devm_kzalloc(dev, ac->max, GFP_KERNEL);
+               if (!ac->params)
+                       return -ENOMEM;
+
+               memcpy(ac->params, dfw_ac->params, ac->max);
+       }
+
+       be->dobj.private  = ac;
+       return 0;
+}
+
+static int skl_tplg_control_load(struct snd_soc_component *cmpnt,
+                               struct snd_kcontrol_new *kctl,
+                               struct snd_soc_tplg_ctl_hdr *hdr)
+{
+       struct soc_bytes_ext *sb;
+       struct snd_soc_tplg_bytes_control *tplg_bc;
+       struct hdac_ext_bus *ebus  = snd_soc_component_get_drvdata(cmpnt);
+       struct hdac_bus *bus = ebus_to_hbus(ebus);
+
+       switch (hdr->ops.info) {
+       case SND_SOC_TPLG_CTL_BYTES:
+               tplg_bc = container_of(hdr,
+                               struct snd_soc_tplg_bytes_control, hdr);
+               if (kctl->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) {
+                       sb = (struct soc_bytes_ext *)kctl->private_value;
+                       if (tplg_bc->priv.size)
+                               return skl_init_algo_data(
+                                               bus->dev, sb, tplg_bc);
+               }
+               break;
+
+       default:
+               dev_warn(bus->dev, "Control load not supported %d:%d:%d\n",
+                       hdr->ops.get, hdr->ops.put, hdr->ops.info);
+               break;
+       }
+
+       return 0;
+}
+
+static int skl_tplg_fill_str_mfest_tkn(struct device *dev,
+               struct snd_soc_tplg_vendor_string_elem *str_elem,
+               struct skl_dfw_manifest *minfo)
+{
+       int tkn_count = 0;
+       static int ref_count;
+
+       switch (str_elem->token) {
+       case SKL_TKN_STR_LIB_NAME:
+               if (ref_count > minfo->lib_count - 1) {
+                       ref_count = 0;
+                       return -EINVAL;
+               }
+
+               strncpy(minfo->lib[ref_count].name, str_elem->string,
+                               ARRAY_SIZE(minfo->lib[ref_count].name));
+               ref_count++;
+               tkn_count++;
+               break;
+
+       default:
+               dev_err(dev, "Not a string token %d\n", str_elem->token);
+               break;
+       }
+
+       return tkn_count;
+}
+
+static int skl_tplg_get_str_tkn(struct device *dev,
+               struct snd_soc_tplg_vendor_array *array,
+               struct skl_dfw_manifest *minfo)
+{
+       int tkn_count = 0, ret;
+       struct snd_soc_tplg_vendor_string_elem *str_elem;
+
+       str_elem = (struct snd_soc_tplg_vendor_string_elem *)array->value;
+       while (tkn_count < array->num_elems) {
+               ret = skl_tplg_fill_str_mfest_tkn(dev, str_elem, minfo);
+               str_elem++;
+
+               if (ret < 0)
+                       return ret;
+
+               tkn_count = tkn_count + ret;
+       }
+
+       return tkn_count;
+}
+
+static int skl_tplg_get_int_tkn(struct device *dev,
+               struct snd_soc_tplg_vendor_value_elem *tkn_elem,
+               struct skl_dfw_manifest *minfo)
+{
+       int tkn_count = 0;
+
+       switch (tkn_elem->token) {
+       case SKL_TKN_U32_LIB_COUNT:
+               minfo->lib_count = tkn_elem->value;
+               tkn_count++;
+               break;
+
+       default:
+               dev_err(dev, "Not a manifest token %d\n", tkn_elem->token);
+               return -EINVAL;
+       }
+
+       return tkn_count;
+}
+
+/*
+ * Fill the manifest structure by parsing the tokens based on the
+ * type.
+ */
+static int skl_tplg_get_manifest_tkn(struct device *dev,
+               char *pvt_data, struct skl_dfw_manifest *minfo,
+               int block_size)
+{
+       int tkn_count = 0, ret;
+       int off = 0, tuple_size = 0;
+       struct snd_soc_tplg_vendor_array *array;
+       struct snd_soc_tplg_vendor_value_elem *tkn_elem;
+
+       if (block_size <= 0)
+               return -EINVAL;
+
+       while (tuple_size < block_size) {
+               array = (struct snd_soc_tplg_vendor_array *)(pvt_data + off);
+               off += array->size;
+               switch (array->type) {
+               case SND_SOC_TPLG_TUPLE_TYPE_STRING:
+                       ret = skl_tplg_get_str_tkn(dev, array, minfo);
+
+                       if (ret < 0)
+                               return ret;
+                       tkn_count += ret;
+
+                       tuple_size += tkn_count *
+                               sizeof(struct snd_soc_tplg_vendor_string_elem);
+                       continue;
+
+               case SND_SOC_TPLG_TUPLE_TYPE_UUID:
+                       dev_warn(dev, "no uuid tokens for skl tplf manifest\n");
+                       continue;
+
+               default:
+                       tkn_elem = array->value;
+                       tkn_count = 0;
+                       break;
+               }
+
+               while (tkn_count <= array->num_elems - 1) {
+                       ret = skl_tplg_get_int_tkn(dev,
+                                       tkn_elem, minfo);
+                       if (ret < 0)
+                               return ret;
+
+                       tkn_count = tkn_count + ret;
+                       tkn_elem++;
+                       tuple_size += tkn_count *
+                               sizeof(struct snd_soc_tplg_vendor_value_elem);
+                       break;
+               }
+               tkn_count = 0;
+       }
+
+       return 0;
+}
+
+/*
+ * Parse manifest private data for tokens. The private data block is
+ * preceded by descriptors for type and size of data block.
+ */
+static int skl_tplg_get_manifest_data(struct snd_soc_tplg_manifest *manifest,
+                       struct device *dev, struct skl_dfw_manifest *minfo)
+{
+       struct snd_soc_tplg_vendor_array *array;
+       int num_blocks, block_size = 0, block_type, off = 0;
+       char *data;
+       int ret;
+
+       /* Read the NUM_DATA_BLOCKS descriptor */
+       array = (struct snd_soc_tplg_vendor_array *)manifest->priv.data;
+       ret = skl_tplg_get_desc_blocks(dev, array);
+       if (ret < 0)
+               return ret;
+       num_blocks = ret;
+
+       off += array->size;
+       array = (struct snd_soc_tplg_vendor_array *)
+                       (manifest->priv.data + off);
+
+       /* Read the BLOCK_TYPE and BLOCK_SIZE descriptor */
+       while (num_blocks > 0) {
+               ret = skl_tplg_get_desc_blocks(dev, array);
+
+               if (ret < 0)
+                       return ret;
+               block_type = ret;
+               off += array->size;
+
+               array = (struct snd_soc_tplg_vendor_array *)
+                       (manifest->priv.data + off);
+
+               ret = skl_tplg_get_desc_blocks(dev, array);
+
+               if (ret < 0)
+                       return ret;
+               block_size = ret;
+               off += array->size;
+
+               array = (struct snd_soc_tplg_vendor_array *)
+                       (manifest->priv.data + off);
+
+               data = (manifest->priv.data + off);
+
+               if (block_type == SKL_TYPE_TUPLE) {
+                       ret = skl_tplg_get_manifest_tkn(dev, data, minfo,
+                                       block_size);
+
+                       if (ret < 0)
+                               return ret;
+
+                       --num_blocks;
+               } else {
+                       return -EINVAL;
+               }
+       }
+
+       return 0;
+}
+
+static struct skl_dfw_manifest gManifest;
+
+static int skl_manifest_load(struct snd_soc_component *cmpnt,
+                               struct snd_soc_tplg_manifest *manifest)
+{
+       struct skl_dfw_manifest *minfo;
+       struct hdac_ext_bus *ebus = snd_soc_component_get_drvdata(cmpnt);
+       struct hdac_bus *bus = ebus_to_hbus(ebus);
+       struct skl *skl = ebus_to_skl(ebus);
+       int ret = 0;
+
+       /* proceed only if we have private data defined */
+       if (manifest->priv.size == 0)
+               return 0;
+
+       minfo = &gManifest; //skl->skl_sst->manifest;
+
+       skl_tplg_get_manifest_data(manifest, bus->dev, minfo);
+
+       if (minfo->lib_count > HDA_MAX_LIB) {
+               dev_err(bus->dev, "Exceeding max Library count. Got:%d\n",
+                                       minfo->lib_count);
+               ret = -EINVAL;
+       }
+
+       return ret;
+}
+
+static struct snd_soc_tplg_ops skl_tplg_ops  = {
+       .widget_load = skl_tplg_widget_load,
+       .control_load = skl_tplg_control_load,
+       .bytes_ext_ops = skl_tlv_ops,
+       .bytes_ext_ops_count = ARRAY_SIZE(skl_tlv_ops),
+       .manifest = skl_manifest_load,
+};
+
+/*
+ * A pipe can have multiple modules, each of them will be a DAPM widget as
+ * well. While managing a pipeline we need to get the list of all the
+ * widgets in a pipelines, so this helper - skl_tplg_create_pipe_widget_list()
+ * helps to get the SKL type widgets in that pipeline
+ */
+static int skl_tplg_create_pipe_widget_list(struct snd_soc_platform *platform)
+{
+       struct snd_soc_dapm_widget *w;
+       struct skl_module_cfg *mcfg = NULL;
+       struct skl_pipe_module *p_module = NULL;
+       struct skl_pipe *pipe;
+
+       list_for_each_entry(w, &platform->component.card->widgets, list) {
+               if (is_skl_dsp_widget_type(w) && w->priv != NULL) {
+                       mcfg = w->priv;
+                       pipe = mcfg->pipe;
+
+                       p_module = devm_kzalloc(platform->dev,
+                                               sizeof(*p_module), GFP_KERNEL);
+                       if (!p_module)
+                               return -ENOMEM;
+
+                       p_module->w = w;
+                       list_add_tail(&p_module->node, &pipe->w_list);
+               }
+       }
+
+       return 0;
+}
+
+static void skl_tplg_set_pipe_type(struct skl *skl, struct skl_pipe *pipe)
+{
+       struct skl_pipe_module *w_module;
+       struct snd_soc_dapm_widget *w;
+       struct skl_module_cfg *mconfig;
+       bool host_found = false, link_found = false;
+
+       list_for_each_entry(w_module, &pipe->w_list, node) {
+               w = w_module->w;
+               mconfig = w->priv;
+
+               if (mconfig->dev_type == SKL_DEVICE_HDAHOST)
+                       host_found = true;
+               else if (mconfig->dev_type != SKL_DEVICE_NONE)
+                       link_found = true;
+       }
+
+       if (host_found && link_found)
+               pipe->passthru = true;
+       else
+               pipe->passthru = false;
+}
+
+/* This will be read from topology manifest, currently defined here */
+#define SKL_MAX_MCPS 30000000
+#define SKL_FW_MAX_MEM 1000000
+
+/*
+ * SKL topology init routine
+ */
+int skl_tplg_init(struct snd_soc_platform *platform, struct hdac_ext_bus *ebus)
+{
+       int ret;
+       const struct firmware *fw;
+       struct hdac_bus *bus = ebus_to_hbus(ebus);
+       struct skl *skl = ebus_to_skl(ebus);
+       struct skl_pipeline *ppl;
+
+       ret = request_firmware(&fw, skl->tplg_name, bus->dev);
+       if (ret < 0) {
+               dev_err(bus->dev, "tplg fw %s load failed with %d\n",
+                               skl->tplg_name, ret);
+               ret = request_firmware(&fw, "dfw_sst.bin", bus->dev);
+               if (ret < 0) {
+                       dev_err(bus->dev, "Fallback tplg fw %s load failed with 
%d\n",
+                                       "dfw_sst.bin", ret);
+                       return ret;
+               }
+       }
+
+       /*
         * The complete tplg for SKL is loaded as index 0, we don't use
         * any other index
         */
@@ -1779,6 +2564,12 @@ int skl_tplg_init(struct snd_soc_platform *platform, 
struct hdac_ext_bus *ebus)
        skl->resource.max_mem = SKL_FW_MAX_MEM;
 
        skl->tplg = fw;
+       ret = skl_tplg_create_pipe_widget_list(platform);
+       if (ret < 0)
+               return ret;
+
+       list_for_each_entry(ppl, &skl->ppl_list, node)
+               skl_tplg_set_pipe_type(skl, ppl->pipe);
 
        return 0;
 }
diff --git a/sound/soc/intel/skylake/skl-topology.h 
b/sound/soc/intel/skylake/skl-topology.h
index e4b399c..a519360 100644
--- a/sound/soc/intel/skylake/skl-topology.h
+++ b/sound/soc/intel/skylake/skl-topology.h
@@ -133,7 +133,7 @@ struct skl_i2s_config_blob {
 struct skl_dma_control {
        u32 node_id;
        u32 config_length;
-       u32 config_data[1];
+       u32 config_data[0];
 } __packed;
 
 struct skl_cpr_cfg {
@@ -215,9 +215,20 @@ struct skl_module_fmt {
 
 struct skl_module_cfg;
 
+struct skl_mod_inst_map {
+       u16 mod_id;
+       u16 inst_id;
+};
+
+struct skl_kpb_params {
+       u32 num_modules;
+       struct skl_mod_inst_map map[0];
+};
+
 struct skl_module_inst_id {
-       u32 module_id;
+       int module_id;
        u32 instance_id;
+       int pvt_id;
 };
 
 enum skl_module_pin_state {
@@ -244,7 +255,8 @@ enum skl_pipe_state {
        SKL_PIPE_INVALID = 0,
        SKL_PIPE_CREATED = 1,
        SKL_PIPE_PAUSED = 2,
-       SKL_PIPE_STARTED = 3
+       SKL_PIPE_STARTED = 3,
+       SKL_PIPE_RESET = 4
 };
 
 struct skl_pipe_module {
@@ -270,6 +282,7 @@ struct skl_pipe {
        struct skl_pipe_params *p_params;
        enum skl_pipe_state state;
        struct list_head w_list;
+       bool passthru;
 };
 
 enum skl_module_state {
@@ -319,6 +332,7 @@ struct skl_algo_data {
        u32 param_id;
        u32 set_params;
        u32 max;
+       u32 size;
        char *params;
 };
 
@@ -357,6 +371,8 @@ int skl_delete_pipe(struct skl_sst *ctx, struct skl_pipe 
*pipe);
 
 int skl_stop_pipe(struct skl_sst *ctx, struct skl_pipe *pipe);
 
+int skl_reset_pipe(struct skl_sst *ctx, struct skl_pipe *pipe);
+
 int skl_init_module(struct skl_sst *ctx, struct skl_module_cfg *module_config);
 
 int skl_bind_modules(struct skl_sst *ctx, struct skl_module_cfg
diff --git a/sound/soc/intel/skylake/skl-tplg-interface.h 
b/sound/soc/intel/skylake/skl-tplg-interface.h
index a32e5e9..44f723c 100644
--- a/sound/soc/intel/skylake/skl-tplg-interface.h
+++ b/sound/soc/intel/skylake/skl-tplg-interface.h
@@ -80,7 +80,8 @@ enum skl_module_type {
        SKL_MODULE_TYPE_UPDWMIX,
        SKL_MODULE_TYPE_SRCINT,
        SKL_MODULE_TYPE_ALGO,
-       SKL_MODULE_TYPE_BASE_OUTFMT
+       SKL_MODULE_TYPE_BASE_OUTFMT,
+       SKL_MODULE_TYPE_KPB,
 };
 
 enum skl_core_affinity {
@@ -228,4 +229,26 @@ struct skl_dfw_algo_data {
        char params[0];
 } __packed;
 
+#define LIB_NAME_LENGTH        128
+#define HDA_MAX_LIB    16
+
+struct lib_info {
+       char name[LIB_NAME_LENGTH];
+} __packed;
+
+struct skl_dfw_manifest {
+       u32 lib_count;
+       struct lib_info lib[HDA_MAX_LIB];
+} __packed;
+
+enum skl_tkn_dir {
+       SKL_DIR_IN,
+       SKL_DIR_OUT
+};
+
+enum skl_tuple_type {
+       SKL_TYPE_TUPLE,
+       SKL_TYPE_DATA
+};
+
 #endif
diff --git a/sound/soc/intel/skylake/skl.h b/sound/soc/intel/skylake/skl.h
index 4b4b387..3ddf1b3 100644
--- a/sound/soc/intel/skylake/skl.h
+++ b/sound/soc/intel/skylake/skl.h
@@ -66,6 +66,7 @@ struct skl {
        struct platform_device *dmic_dev;
        struct platform_device *i2s_dev;
 
+       struct snd_soc_platform *platform;
        struct nhlt_acpi_table *nhlt; /* nhlt ptr */
        struct skl_sst *skl_sst; /* sst skl ctx */
 
@@ -113,4 +114,6 @@ int skl_init_dsp(struct skl *skl);
 int skl_free_dsp(struct skl *skl);
 int skl_suspend_dsp(struct skl *skl);
 int skl_resume_dsp(struct skl *skl);
+
+void skl_cleanup_resources(struct skl *skl);
 #endif /* __SOUND_SOC_SKL_H */
-- 
2.5.0

-- 
_______________________________________________
linux-yocto mailing list
linux-yocto@yoctoproject.org
https://lists.yoctoproject.org/listinfo/linux-yocto

Reply via email to