]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
Merge remote-tracking branches 'asoc/topic/fsl-spdif', 'asoc/topic/img' and 'asoc...
authorMark Brown <broonie@kernel.org>
Wed, 23 Dec 2015 00:23:43 +0000 (00:23 +0000)
committerMark Brown <broonie@kernel.org>
Wed, 23 Dec 2015 00:23:43 +0000 (00:23 +0000)
1  2  3  4 
sound/soc/codecs/Kconfig
sound/soc/codecs/Makefile
sound/soc/fsl/fsl_spdif.c
sound/soc/intel/skylake/skl-topology.c

diff --combined sound/soc/codecs/Kconfig
index 05fb938c7704f17d010d99e82475dc38f2761312,cfdafc4c11ea9a64c465eef6d9ac4ed3520c159a,cfdafc4c11ea9a64c465eef6d9ac4ed3520c159a,8bba374b8860c8adb639e6e7ae08d88d930eb3c7..08433a8d9d40c9fee3f45c6aca3ce3ca1c4d3194
@@@@@ -55,11 -55,9 -55,9 -55,9 +55,11 @@@@@ config SND_SOC_ALL_CODEC
        select SND_SOC_CS4271_SPI if SPI_MASTER
        select SND_SOC_CS42XX8_I2C if I2C
        select SND_SOC_CS4349 if I2C
 +++    select SND_SOC_CS47L24 if MFD_CS47L24
        select SND_SOC_CX20442 if TTY
        select SND_SOC_DA7210 if SND_SOC_I2C_AND_SPI
        select SND_SOC_DA7213 if I2C
 +++    select SND_SOC_DA7218 if I2C
        select SND_SOC_DA7219 if I2C
        select SND_SOC_DA732X if I2C
        select SND_SOC_DA9055 if I2C
        select SND_SOC_ES8328_SPI if SPI_MASTER
        select SND_SOC_ES8328_I2C if I2C
        select SND_SOC_GTM601
+++     select SND_SOC_HDAC_HDMI
        select SND_SOC_ICS43432
        select SND_SOC_ISABELLE if I2C
        select SND_SOC_JZ4740_CODEC
        select SND_SOC_PCM1681 if I2C
        select SND_SOC_PCM1792A if SPI_MASTER
        select SND_SOC_PCM3008
 +++    select SND_SOC_PCM3168A_I2C if I2C
 +++    select SND_SOC_PCM3168A_SPI if SPI_MASTER
        select SND_SOC_PCM512x_I2C if I2C
        select SND_SOC_PCM512x_SPI if SPI_MASTER
        select SND_SOC_RT286 if I2C
@@@@@ -199,12 -195,10 -195,10 -196,10 +200,12 @@@@@ config SND_SOC_88PM860
    
    config SND_SOC_ARIZONA
        tristate
 +++    default y if SND_SOC_CS47L24=y
        default y if SND_SOC_WM5102=y
        default y if SND_SOC_WM5110=y
        default y if SND_SOC_WM8997=y
        default y if SND_SOC_WM8998=y
 +++    default m if SND_SOC_CS47L24=m
        default m if SND_SOC_WM5102=m
        default m if SND_SOC_WM5110=m
        default m if SND_SOC_WM8997=m
@@@@@ -217,12 -211,9 -211,9 -212,9 +218,12 @@@@@ config SND_SOC_WM_HUB
    
    config SND_SOC_WM_ADSP
        tristate
 +++    select SND_SOC_COMPRESS
 +++    default y if SND_SOC_CS47L24=y
        default y if SND_SOC_WM5102=y
        default y if SND_SOC_WM5110=y
        default y if SND_SOC_WM2200=y
 +++    default m if SND_SOC_CS47L24=m
        default m if SND_SOC_WM5102=m
        default m if SND_SOC_WM5110=m
        default m if SND_SOC_WM2200=m
@@@@@ -431,9 -422,6 -422,6 -423,6 +432,9 @@@@@ config SND_SOC_CS434
        tristate "Cirrus Logic CS4349 CODEC"
        depends on I2C
    
 +++config SND_SOC_CS47L24
 +++    tristate
 +++
    config SND_SOC_CX20442
        tristate
        depends on TTY
@@@@@ -451,9 -439,6 -439,6 -440,6 +452,9 @@@@@ config SND_SOC_DA721
    config SND_SOC_DA7213
            tristate
    
 +++config SND_SOC_DA7218
 +++    tristate
 +++
    config SND_SOC_DA7219
            tristate
    
@@@@@ -483,6 -468,6 -468,6 -469,11 +484,11 @@@@@ config SND_SOC_ES8328_SP
    config SND_SOC_GTM601
        tristate 'GTM601 UMTS modem audio codec'
    
+++ config SND_SOC_HDAC_HDMI
+++     tristate
+++     select SND_HDA_EXT_CORE
+++     select HDMI
+++ 
    config SND_SOC_ICS43432
        tristate
    
@@@@@ -521,21 -506,6 -506,6 -512,6 +527,21 @@@@@ config SND_SOC_PCM1792
    config SND_SOC_PCM3008
           tristate
    
 +++config SND_SOC_PCM3168A
 +++    tristate
 +++
 +++config SND_SOC_PCM3168A_I2C
 +++    tristate "Texas Instruments PCM3168A CODEC - I2C"
 +++    depends on I2C
 +++    select SND_SOC_PCM3168A
 +++    select REGMAP_I2C
 +++
 +++config SND_SOC_PCM3168A_SPI
 +++    tristate "Texas Instruments PCM3168A CODEC - SPI"
 +++    depends on SPI_MASTER
 +++    select SND_SOC_PCM3168A
 +++    select REGMAP_SPI
 +++
    config SND_SOC_PCM512x
        tristate
    
index 266c6be0c7f54eae2a9f67ab1fa74456d6c0105f,f632fc42f59f08d9d6c72f6aac045d9fe28176a1,f632fc42f59f08d9d6c72f6aac045d9fe28176a1,bcd5ad6b6fb0e8536bb095d2c31764bf84675da7..fdf5b31467746dbebf5f0a2d911d8aabb58ab0fb
@@@@@ -47,11 -47,9 -47,9 -47,9 +47,11 @@@@@ snd-soc-cs4271-spi-objs := cs4271-spi.
    snd-soc-cs42xx8-objs := cs42xx8.o
    snd-soc-cs42xx8-i2c-objs := cs42xx8-i2c.o
    snd-soc-cs4349-objs := cs4349.o
 +++snd-soc-cs47l24-objs := cs47l24.o
    snd-soc-cx20442-objs := cx20442.o
    snd-soc-da7210-objs := da7210.o
    snd-soc-da7213-objs := da7213.o
 +++snd-soc-da7218-objs := da7218.o
    snd-soc-da7219-objs := da7219.o da7219-aad.o
    snd-soc-da732x-objs := da732x.o
    snd-soc-da9055-objs := da9055.o
@@@@@ -61,6 -59,6 -59,6 -59,7 +61,7 @@@@@ snd-soc-es8328-objs := es8328.
    snd-soc-es8328-i2c-objs := es8328-i2c.o
    snd-soc-es8328-spi-objs := es8328-spi.o
    snd-soc-gtm601-objs := gtm601.o
+++ snd-soc-hdac-hdmi-objs := hdac_hdmi.o
    snd-soc-ics43432-objs := ics43432.o
    snd-soc-isabelle-objs := isabelle.o
    snd-soc-jz4740-codec-objs := jz4740.o
@@@@@ -80,9 -78,6 -78,6 -79,6 +81,9 @@@@@ snd-soc-nau8825-objs := nau8825.
    snd-soc-pcm1681-objs := pcm1681.o
    snd-soc-pcm1792a-codec-objs := pcm1792a.o
    snd-soc-pcm3008-objs := pcm3008.o
 +++snd-soc-pcm3168a-objs := pcm3168a.o
 +++snd-soc-pcm3168a-i2c-objs := pcm3168a-i2c.o
 +++snd-soc-pcm3168a-spi-objs := pcm3168a-spi.o
    snd-soc-pcm512x-objs := pcm512x.o
    snd-soc-pcm512x-i2c-objs := pcm512x-i2c.o
    snd-soc-pcm512x-spi-objs := pcm512x-spi.o
@@@@@ -247,11 -242,9 -242,9 -243,9 +248,11 @@@@@ obj-$(CONFIG_SND_SOC_CS4271_SPI)       += snd
    obj-$(CONFIG_SND_SOC_CS42XX8)       += snd-soc-cs42xx8.o
    obj-$(CONFIG_SND_SOC_CS42XX8_I2C) += snd-soc-cs42xx8-i2c.o
    obj-$(CONFIG_SND_SOC_CS4349)        += snd-soc-cs4349.o
 +++obj-$(CONFIG_SND_SOC_CS47L24)       += snd-soc-cs47l24.o
    obj-$(CONFIG_SND_SOC_CX20442)       += snd-soc-cx20442.o
    obj-$(CONFIG_SND_SOC_DA7210)        += snd-soc-da7210.o
    obj-$(CONFIG_SND_SOC_DA7213)        += snd-soc-da7213.o
 +++obj-$(CONFIG_SND_SOC_DA7218)        += snd-soc-da7218.o
    obj-$(CONFIG_SND_SOC_DA7219)        += snd-soc-da7219.o
    obj-$(CONFIG_SND_SOC_DA732X)        += snd-soc-da732x.o
    obj-$(CONFIG_SND_SOC_DA9055)        += snd-soc-da9055.o
@@@@@ -261,6 -254,6 -254,6 -255,7 +262,7 @@@@@ obj-$(CONFIG_SND_SOC_ES8328)     += snd-soc
    obj-$(CONFIG_SND_SOC_ES8328_I2C)+= snd-soc-es8328-i2c.o
    obj-$(CONFIG_SND_SOC_ES8328_SPI)+= snd-soc-es8328-spi.o
    obj-$(CONFIG_SND_SOC_GTM601)    += snd-soc-gtm601.o
+++ obj-$(CONFIG_SND_SOC_HDAC_HDMI) += snd-soc-hdac-hdmi.o
    obj-$(CONFIG_SND_SOC_ICS43432)      += snd-soc-ics43432.o
    obj-$(CONFIG_SND_SOC_ISABELLE)      += snd-soc-isabelle.o
    obj-$(CONFIG_SND_SOC_JZ4740_CODEC)  += snd-soc-jz4740-codec.o
@@@@@ -280,9 -273,6 -273,6 -275,6 +282,9 @@@@@ obj-$(CONFIG_SND_SOC_NAU8825)   += snd-
    obj-$(CONFIG_SND_SOC_PCM1681)       += snd-soc-pcm1681.o
    obj-$(CONFIG_SND_SOC_PCM1792A)      += snd-soc-pcm1792a-codec.o
    obj-$(CONFIG_SND_SOC_PCM3008)       += snd-soc-pcm3008.o
 +++obj-$(CONFIG_SND_SOC_PCM3168A)      += snd-soc-pcm3168a.o
 +++obj-$(CONFIG_SND_SOC_PCM3168A_I2C)  += snd-soc-pcm3168a-i2c.o
 +++obj-$(CONFIG_SND_SOC_PCM3168A_SPI)  += snd-soc-pcm3168a-spi.o
    obj-$(CONFIG_SND_SOC_PCM512x)       += snd-soc-pcm512x.o
    obj-$(CONFIG_SND_SOC_PCM512x_I2C)   += snd-soc-pcm512x-i2c.o
    obj-$(CONFIG_SND_SOC_PCM512x_SPI)   += snd-soc-pcm512x-spi.o
index 28a88233690474d83a49cb0de268803b2280e19d,fa36e6753799bc13f8a354a3e82a68d0cc5ebf8c,3d59bb6719f2b6fea0d7ed7137940bac88d99d6b,3d59bb6719f2b6fea0d7ed7137940bac88d99d6b..151849f7986396b335863222e1a3e599557bcd62
@@@@@ -88,6 -88,7 -88,6 -88,6 +88,7 @@@@@ struct spdif_mixer_control 
     * @rxclk: rx clock sources for capture
     * @coreclk: core clock for register access via DMA
     * @sysclk: system clock for rx clock rate measurement
+ ++ * @spbaclk: SPBA clock (optional, depending on SoC design)
     * @dma_params_tx: DMA parameters for transmit channel
     * @dma_params_rx: DMA parameters for receive channel
     */
@@@@@ -106,6 -107,7 -106,6 -106,6 +107,7 @@@@@ struct fsl_spdif_priv 
        struct clk *rxclk;
        struct clk *coreclk;
        struct clk *sysclk;
+ ++    struct clk *spbaclk;
        struct snd_dmaengine_dai_dma_data dma_params_tx;
        struct snd_dmaengine_dai_dma_data dma_params_rx;
        /* regcache for SRPC */
@@@@@ -474,6 -476,14 -474,6 -474,6 +476,14 @@@@@ static int fsl_spdif_startup(struct snd
                        return ret;
                }
    
+ ++            if (!IS_ERR(spdif_priv->spbaclk)) {
+ ++                    ret = clk_prepare_enable(spdif_priv->spbaclk);
+ ++                    if (ret) {
+ ++                            dev_err(&pdev->dev, "failed to enable spba clock\n");
+ ++                            goto err_spbaclk;
+ ++                    }
+ ++            }
+ ++
                ret = spdif_softreset(spdif_priv);
                if (ret) {
                        dev_err(&pdev->dev, "failed to soft reset\n");
@@@@@ -515,6 -525,9 -515,6 -515,6 +525,9 @@@@@ disable_txclk
        for (i--; i >= 0; i--)
                clk_disable_unprepare(spdif_priv->txclk[i]);
    err:
+ ++    if (!IS_ERR(spdif_priv->spbaclk))
+ ++            clk_disable_unprepare(spdif_priv->spbaclk);
+ ++err_spbaclk:
        clk_disable_unprepare(spdif_priv->coreclk);
    
        return ret;
@@@@@ -548,6 -561,8 -548,6 -548,6 +561,8 @@@@@ static void fsl_spdif_shutdown(struct s
                spdif_intr_status_clear(spdif_priv);
                regmap_update_bits(regmap, REG_SPDIF_SCR,
                                SCR_LOW_POWER, SCR_LOW_POWER);
+ ++            if (!IS_ERR(spdif_priv->spbaclk))
+ ++                    clk_disable_unprepare(spdif_priv->spbaclk);
                clk_disable_unprepare(spdif_priv->coreclk);
        }
    }
@@@@@ -1006,14 -1021,12 -1006,12 -1006,12 +1021,14 @@@@@ static const struct snd_soc_component_d
    
    /* FSL SPDIF REGMAP */
    static const struct reg_default fsl_spdif_reg_defaults[] = {
 ---    {0x0,  0x00000400},
 ---    {0x4,  0x00000000},
 ---    {0xc,  0x00000000},
 ---    {0x34, 0x00000000},
 ---    {0x38, 0x00000000},
 ---    {0x50, 0x00020f00},
 +++    {REG_SPDIF_SCR,    0x00000400},
 +++    {REG_SPDIF_SRCD,   0x00000000},
 +++    {REG_SPDIF_SIE,    0x00000000},
 +++    {REG_SPDIF_STL,    0x00000000},
 +++    {REG_SPDIF_STR,    0x00000000},
 +++    {REG_SPDIF_STCSCH, 0x00000000},
 +++    {REG_SPDIF_STCSCL, 0x00000000},
 +++    {REG_SPDIF_STC,    0x00020f00},
    };
    
    static bool fsl_spdif_readable_reg(struct device *dev, unsigned int reg)
@@@@@ -1051,6 -1064,8 -1049,8 -1049,8 +1066,6 @@@@@ static bool fsl_spdif_volatile_reg(stru
        case REG_SPDIF_SRCSL:
        case REG_SPDIF_SRU:
        case REG_SPDIF_SRQ:
 ---    case REG_SPDIF_STL:
 ---    case REG_SPDIF_STR:
        case REG_SPDIF_SRFM:
                return true;
        default:
@@@@@ -1261,6 -1276,10 -1261,6 -1261,6 +1276,10 @@@@@ static int fsl_spdif_probe(struct platf
                return PTR_ERR(spdif_priv->coreclk);
        }
    
+ ++    spdif_priv->spbaclk = devm_clk_get(&pdev->dev, "spba");
+ ++    if (IS_ERR(spdif_priv->spbaclk))
+ ++            dev_warn(&pdev->dev, "no spba clock in devicetree\n");
+ ++
        /* Select clock source for rx/tx clock */
        spdif_priv->rxclk = devm_clk_get(&pdev->dev, "rxtx1");
        if (IS_ERR(spdif_priv->rxclk)) {
index ffea427aeca8eab29809f049c53ba27f71b54393,a7854c8fc523e832f6137437c6e7737cc5eee46c,a7854c8fc523e832f6137437c6e7737cc5eee46c,34f2f7351f66ff924eca8061e2afd436c70512b5..5315b7422b98bc2c984dab9f5ce823c24bb02ac3
    #include "skl-topology.h"
    #include "skl.h"
    #include "skl-tplg-interface.h"
+++ #include "../common/sst-dsp.h"
+++ #include "../common/sst-dsp-priv.h"
    
    #define SKL_CH_FIXUP_MASK           (1 << 0)
    #define SKL_RATE_FIXUP_MASK         (1 << 1)
@@@@@ -129,17 -129,17 -129,17 -131,15 +131,15 @@@@@ static void skl_dump_mconfig(struct skl
    {
        dev_dbg(ctx->dev, "Dumping config\n");
        dev_dbg(ctx->dev, "Input Format:\n");
---     dev_dbg(ctx->dev, "channels = %d\n", mcfg->in_fmt.channels);
---     dev_dbg(ctx->dev, "s_freq = %d\n", mcfg->in_fmt.s_freq);
---     dev_dbg(ctx->dev, "ch_cfg = %d\n", mcfg->in_fmt.ch_cfg);
---     dev_dbg(ctx->dev, "valid bit depth = %d\n",
---                     mcfg->in_fmt.valid_bit_depth);
+++     dev_dbg(ctx->dev, "channels = %d\n", mcfg->in_fmt[0].channels);
+++     dev_dbg(ctx->dev, "s_freq = %d\n", mcfg->in_fmt[0].s_freq);
+++     dev_dbg(ctx->dev, "ch_cfg = %d\n", mcfg->in_fmt[0].ch_cfg);
+++     dev_dbg(ctx->dev, "valid bit depth = %d\n", mcfg->in_fmt[0].valid_bit_depth);
        dev_dbg(ctx->dev, "Output Format:\n");
---     dev_dbg(ctx->dev, "channels = %d\n", mcfg->out_fmt.channels);
---     dev_dbg(ctx->dev, "s_freq = %d\n", mcfg->out_fmt.s_freq);
---     dev_dbg(ctx->dev, "valid bit depth = %d\n",
---                     mcfg->out_fmt.valid_bit_depth);
---     dev_dbg(ctx->dev, "ch_cfg = %d\n", mcfg->out_fmt.ch_cfg);
+++     dev_dbg(ctx->dev, "channels = %d\n", mcfg->out_fmt[0].channels);
+++     dev_dbg(ctx->dev, "s_freq = %d\n", mcfg->out_fmt[0].s_freq);
+++     dev_dbg(ctx->dev, "valid bit depth = %d\n", mcfg->out_fmt[0].valid_bit_depth);
+++     dev_dbg(ctx->dev, "ch_cfg = %d\n", mcfg->out_fmt[0].ch_cfg);
    }
    
    static void skl_tplg_update_params(struct skl_module_fmt *fmt,
                fmt->s_freq = params->s_freq;
        if (fixup & SKL_CH_FIXUP_MASK)
                fmt->channels = params->ch;
---     if (fixup & SKL_FMT_FIXUP_MASK)
---             fmt->valid_bit_depth = params->s_fmt;
+++     if (fixup & SKL_FMT_FIXUP_MASK) {
+++             fmt->valid_bit_depth = skl_get_bit_depth(params->s_fmt);
+++ 
+++             /*
+++              * 16 bit is 16 bit container whereas 24 bit is in 32 bit
+++              * container so update bit depth accordingly
+++              */
+++             switch (fmt->valid_bit_depth) {
+++             case SKL_DEPTH_16BIT:
+++                     fmt->bit_depth = fmt->valid_bit_depth;
+++                     break;
+++ 
+++             default:
+++                     fmt->bit_depth = SKL_DEPTH_32BIT;
+++                     break;
+++             }
+++     }
+++ 
    }
    
    /*
@@@@@ -171,8 -171,8 -171,8 -187,9 +187,9 @@@@@ static void skl_tplg_update_params_fixu
        int in_fixup, out_fixup;
        struct skl_module_fmt *in_fmt, *out_fmt;
    
---     in_fmt = &m_cfg->in_fmt;
---     out_fmt = &m_cfg->out_fmt;
+++     /* Fixups will be applied to pin 0 only */
+++     in_fmt = &m_cfg->in_fmt[0];
+++     out_fmt = &m_cfg->out_fmt[0];
    
        if (params->stream == SNDRV_PCM_STREAM_PLAYBACK) {
                if (is_fe) {
@@@@@ -209,18 -209,18 -209,18 -226,25 +226,25 @@@@@ static void skl_tplg_update_buffer_size
                                struct skl_module_cfg *mcfg)
    {
        int multiplier = 1;
+++     struct skl_module_fmt *in_fmt, *out_fmt;
+++ 
+++ 
+++     /* Since fixups is applied to pin 0 only, ibs, obs needs
+++      * change for pin 0 only
+++      */
+++     in_fmt = &mcfg->in_fmt[0];
+++     out_fmt = &mcfg->out_fmt[0];
    
        if (mcfg->m_type == SKL_MODULE_TYPE_SRCINT)
                multiplier = 5;
--- 
---     mcfg->ibs = (mcfg->in_fmt.s_freq / 1000) *
---                             (mcfg->in_fmt.channels) *
---                             (mcfg->in_fmt.bit_depth >> 3) *
+++     mcfg->ibs = (in_fmt->s_freq / 1000) *
+++                             (mcfg->in_fmt->channels) *
+++                             (mcfg->in_fmt->bit_depth >> 3) *
                                multiplier;
    
---     mcfg->obs = (mcfg->out_fmt.s_freq / 1000) *
---                             (mcfg->out_fmt.channels) *
---                             (mcfg->out_fmt.bit_depth >> 3) *
+++     mcfg->obs = (mcfg->out_fmt->s_freq / 1000) *
+++                             (mcfg->out_fmt->channels) *
+++                             (mcfg->out_fmt->bit_depth >> 3) *
                                multiplier;
    }
    
@@@@@ -291,6 -291,6 -291,6 -315,83 +315,83 @@@@@ static int skl_tplg_alloc_pipe_widget(s
        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.
+++  */
+++ static int skl_tplg_set_module_params(struct snd_soc_dapm_widget *w,
+++                                             struct skl_sst *ctx)
+++ {
+++     int i, ret;
+++     struct skl_module_cfg *mconfig = w->priv;
+++     const struct snd_kcontrol_new *k;
+++     struct soc_bytes_ext *sb;
+++     struct skl_algo_data *bc;
+++     struct skl_specific_cfg *sp_cfg;
+++ 
+++     if (mconfig->formats_config.caps_size > 0 &&
+++             mconfig->formats_config.set_params == SKL_PARAM_SET) {
+++             sp_cfg = &mconfig->formats_config;
+++             ret = skl_set_module_params(ctx, sp_cfg->caps,
+++                                     sp_cfg->caps_size,
+++                                     sp_cfg->param_id, mconfig);
+++             if (ret < 0)
+++                     return ret;
+++     }
+++ 
+++     for (i = 0; i < w->num_kcontrols; i++) {
+++             k = &w->kcontrol_news[i];
+++             if (k->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) {
+++                     sb = (void *) k->private_value;
+++                     bc = (struct skl_algo_data *)sb->dobj.private;
+++ 
+++                     if (bc->set_params == SKL_PARAM_SET) {
+++                             ret = skl_set_module_params(ctx,
+++                                             (u32 *)bc->params, bc->max,
+++                                             bc->param_id, mconfig);
+++                             if (ret < 0)
+++                                     return ret;
+++                     }
+++             }
+++     }
+++ 
+++     return 0;
+++ }
+++ 
+++ /*
+++  * some module param can set from user control and this is required as
+++  * when module is initailzed. if module param is required in init it is
+++  * identifed by set_param flag. if set_param flag is not set, then this
+++  * parameter needs to set as part of module init.
+++  */
+++ static int skl_tplg_set_module_init_data(struct snd_soc_dapm_widget *w)
+++ {
+++     const struct snd_kcontrol_new *k;
+++     struct soc_bytes_ext *sb;
+++     struct skl_algo_data *bc;
+++     struct skl_module_cfg *mconfig = w->priv;
+++     int i;
+++ 
+++     for (i = 0; i < w->num_kcontrols; i++) {
+++             k = &w->kcontrol_news[i];
+++             if (k->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) {
+++                     sb = (struct soc_bytes_ext *)k->private_value;
+++                     bc = (struct skl_algo_data *)sb->dobj.private;
+++ 
+++                     if (bc->set_params != SKL_PARAM_INIT)
+++                             continue;
+++ 
+++                     mconfig->formats_config.caps = (u32 *)&bc->params;
+++                     mconfig->formats_config.caps_size = bc->max;
+++ 
+++                     break;
+++             }
+++     }
+++ 
+++     return 0;
+++ }
+++ 
    /*
     * Inside a pipe instance, we can have various modules. These modules need
     * to instantiated in DSP by invoking INIT_MODULE IPC, which is achieved by
@@@@@ -313,12 -313,12 -313,12 -414,25 +414,25 @@@@@ skl_tplg_init_pipe_modules(struct skl *
                if (!skl_tplg_alloc_pipe_mcps(skl, mconfig))
                        return -ENOMEM;
    
+++             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);
+++                     if (ret < 0)
+++                             return ret;
+++             }
+++ 
                /*
                 * apply fix/conversion to module params based on
                 * FE/BE params
                 */
                skl_tplg_update_module_params(w, ctx);
---             ret = skl_init_module(ctx, mconfig, NULL);
+++ 
+++             skl_tplg_set_module_init_data(w);
+++             ret = skl_init_module(ctx, mconfig);
+++             if (ret < 0)
+++                     return ret;
+++ 
+++             ret = skl_tplg_set_module_params(w, ctx);
                if (ret < 0)
                        return ret;
        }
        return 0;
    }
    
+++ static int skl_tplg_unload_pipe_modules(struct skl_sst *ctx,
+++      struct skl_pipe *pipe)
+++ {
+++     struct skl_pipe_module *w_module = NULL;
+++     struct skl_module_cfg *mconfig = NULL;
+++ 
+++     list_for_each_entry(w_module, &pipe->w_list, node) {
+++             mconfig  = w_module->w->priv;
+++ 
+++             if (mconfig->is_loadable && ctx->dsp->fw_ops.unload_mod)
+++                     return ctx->dsp->fw_ops.unload_mod(ctx->dsp,
+++                                             mconfig->id.module_id);
+++     }
+++ 
+++     /* no modules to unload in this path, so return */
+++     return 0;
+++ }
+++ 
    /*
     * Mixer module represents a pipeline. So in the Pre-PMU event of mixer we
     * need create the pipeline. So we do following:
@@@@@ -397,41 -397,41 -397,41 -529,24 +529,24 @@@@@ static int skl_tplg_mixer_dapm_pre_pmu_
        return 0;
    }
    
--- /*
---  * A PGA represents a module in a pipeline. So in the Pre-PMU event of PGA
---  * we need to do following:
---  *   - Bind to sink pipeline
---  *      Since the sink pipes can be running and we don't get mixer event on
---  *      connect for already running mixer, we need to find the sink pipes
---  *      here and bind to them. This way dynamic connect works.
---  *   - Start sink pipeline, if not running
---  *   - Then run current pipe
---  */
--- static int skl_tplg_pga_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w,
---                                                     struct skl *skl)
+++ static int skl_tplg_bind_sinks(struct snd_soc_dapm_widget *w,
+++                             struct skl *skl,
+++                             struct skl_module_cfg *src_mconfig)
    {
        struct snd_soc_dapm_path *p;
---     struct skl_dapm_path_list *path_list;
---     struct snd_soc_dapm_widget *source, *sink;
---     struct skl_module_cfg *src_mconfig, *sink_mconfig;
+++     struct snd_soc_dapm_widget *sink = NULL, *next_sink = NULL;
+++     struct skl_module_cfg *sink_mconfig;
        struct skl_sst *ctx = skl->skl_sst;
---     int ret = 0;
--- 
---     source = w;
---     src_mconfig = source->priv;
+++     int ret;
    
---     /*
---      * find which sink it is connected to, bind with the sink,
---      * if sink is not started, start sink pipe first, then start
---      * this pipe
---      */
---     snd_soc_dapm_widget_for_each_source_path(w, p) {
+++     snd_soc_dapm_widget_for_each_sink_path(w, p) {
                if (!p->connect)
                        continue;
    
                dev_dbg(ctx->dev, "%s: src widget=%s\n", __func__, w->name);
                dev_dbg(ctx->dev, "%s: sink widget=%s\n", __func__, p->sink->name);
    
+++             next_sink = p->sink;
                /*
                 * here we will check widgets in sink pipelines, so that
                 * can be any widgets type and we are only interested if
                                        is_skl_dsp_widget_type(p->sink)) {
    
                        sink = p->sink;
---                     src_mconfig = source->priv;
                        sink_mconfig = sink->priv;
    
                        /* Bind source to sink, mixin is always source */
    
                        /* Start sinks pipe first */
                        if (sink_mconfig->pipe->state != SKL_PIPE_STARTED) {
---                             ret = skl_run_pipe(ctx, sink_mconfig->pipe);
+++                             if (sink_mconfig->pipe->conn_type !=
+++                                                     SKL_PIPE_CONN_TYPE_FE)
+++                                     ret = skl_run_pipe(ctx,
+++                                                     sink_mconfig->pipe);
                                if (ret)
                                        return ret;
                        }
--- 
---                     path_list = kzalloc(
---                                     sizeof(struct skl_dapm_path_list),
---                                     GFP_KERNEL);
---                     if (path_list == NULL)
---                             return -ENOMEM;
--- 
---                     /* Add connected path to one global list */
---                     path_list->dapm_path = p;
---                     list_add_tail(&path_list->node, &skl->dapm_path_list);
---                     break;
                }
        }
    
---     /* Start source pipe last after starting all sinks */
---     ret = skl_run_pipe(ctx, src_mconfig->pipe);
+++     if (!sink)
+++             return skl_tplg_bind_sinks(next_sink, skl, src_mconfig);
+++ 
+++     return 0;
+++ }
+++ 
+++ /*
+++  * A PGA represents a module in a pipeline. So in the Pre-PMU event of PGA
+++  * we need to do following:
+++  *   - Bind to sink pipeline
+++  *      Since the sink pipes can be running and we don't get mixer event on
+++  *      connect for already running mixer, we need to find the sink pipes
+++  *      here and bind to them. This way dynamic connect works.
+++  *   - Start sink pipeline, if not running
+++  *   - Then run current pipe
+++  */
+++ static int skl_tplg_pga_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w,
+++                                                             struct skl *skl)
+++ {
+++     struct skl_module_cfg *src_mconfig;
+++     struct skl_sst *ctx = skl->skl_sst;
+++     int ret = 0;
+++ 
+++     src_mconfig = w->priv;
+++ 
+++     /*
+++      * find which sink it is connected to, bind with the sink,
+++      * if sink is not started, start sink pipe first, then start
+++      * this pipe
+++      */
+++     ret = skl_tplg_bind_sinks(w, skl, src_mconfig);
        if (ret)
                return ret;
    
+++     /* Start source pipe last after starting all sinks */
+++     if (src_mconfig->pipe->conn_type != SKL_PIPE_CONN_TYPE_FE)
+++             return skl_run_pipe(ctx, src_mconfig->pipe);
+++ 
        return 0;
    }
    
+++ static struct snd_soc_dapm_widget *skl_get_src_dsp_widget(
+++             struct snd_soc_dapm_widget *w, struct skl *skl)
+++ {
+++     struct snd_soc_dapm_path *p;
+++     struct snd_soc_dapm_widget *src_w = NULL;
+++     struct skl_sst *ctx = skl->skl_sst;
+++ 
+++     snd_soc_dapm_widget_for_each_source_path(w, p) {
+++             src_w = p->source;
+++             if (!p->connect)
+++                     continue;
+++ 
+++             dev_dbg(ctx->dev, "sink widget=%s\n", w->name);
+++             dev_dbg(ctx->dev, "src widget=%s\n", p->source->name);
+++ 
+++             /*
+++              * here we will check widgets in sink pipelines, so that can
+++              * be any widgets type and we are only interested if they are
+++              * ones used for SKL so check that first
+++              */
+++             if ((p->source->priv != NULL) &&
+++                                     is_skl_dsp_widget_type(p->source)) {
+++                     return p->source;
+++             }
+++     }
+++ 
+++     if (src_w != NULL)
+++             return skl_get_src_dsp_widget(src_w, skl);
+++ 
+++     return NULL;
+++ }
+++ 
    /*
     * in the Post-PMU event of mixer we need to do following:
     *   - Check if this pipe is running
@@@@@ -490,7 -490,7 -490,7 -661,6 +661,6 @@@@@ static int skl_tplg_mixer_dapm_post_pmu
                                                        struct skl *skl)
    {
        int ret = 0;
---     struct snd_soc_dapm_path *p;
        struct snd_soc_dapm_widget *source, *sink;
        struct skl_module_cfg *src_mconfig, *sink_mconfig;
        struct skl_sst *ctx = skl->skl_sst;
         * one more sink before this sink got connected, Since source is
         * started, bind this sink to source and start this pipe.
         */
---     snd_soc_dapm_widget_for_each_sink_path(w, p) {
---             if (!p->connect)
---                     continue;
--- 
---             dev_dbg(ctx->dev, "sink widget=%s\n", w->name);
---             dev_dbg(ctx->dev, "src widget=%s\n", p->source->name);
+++     source = skl_get_src_dsp_widget(w, skl);
+++     if (source != NULL) {
+++             src_mconfig = source->priv;
+++             sink_mconfig = sink->priv;
+++             src_pipe_started = 1;
    
                /*
---              * here we will check widgets in sink pipelines, so that
---              * can be any widgets type and we are only interested if
---              * they are ones used for SKL so check that first
+++              * check pipe state, then no need to bind or start the
+++              * pipe
                 */
---             if ((p->source->priv != NULL) &&
---                                     is_skl_dsp_widget_type(p->source)) {
---                     source = p->source;
---                     src_mconfig = source->priv;
---                     sink_mconfig = sink->priv;
---                     src_pipe_started = 1;
--- 
---                     /*
---                      * check pipe state, then no need to bind or start
---                      * the pipe
---                      */
---                     if (src_mconfig->pipe->state != SKL_PIPE_STARTED)
---                             src_pipe_started = 0;
---             }
+++             if (src_mconfig->pipe->state != SKL_PIPE_STARTED)
+++                     src_pipe_started = 0;
        }
    
        if (src_pipe_started) {
                if (ret)
                        return ret;
    
---             ret = skl_run_pipe(ctx, sink_mconfig->pipe);
+++             if (sink_mconfig->pipe->conn_type != SKL_PIPE_CONN_TYPE_FE)
+++                     ret = skl_run_pipe(ctx, sink_mconfig->pipe);
        }
    
        return ret;
    static int skl_tplg_mixer_dapm_pre_pmd_event(struct snd_soc_dapm_widget *w,
                                                        struct skl *skl)
    {
---     struct snd_soc_dapm_widget *source, *sink;
        struct skl_module_cfg *src_mconfig, *sink_mconfig;
---     int ret = 0, path_found = 0;
---     struct skl_dapm_path_list *path_list, *tmp_list;
+++     int ret = 0, i;
        struct skl_sst *ctx = skl->skl_sst;
    
---     sink = w;
---     sink_mconfig = sink->priv;
+++     sink_mconfig = w->priv;
    
        /* Stop the pipe */
        ret = skl_stop_pipe(ctx, sink_mconfig->pipe);
        if (ret)
                return ret;
    
---     /*
---      * This list, dapm_path_list handling here does not need any locks
---      * as we are under dapm lock while handling widget events.
---      * List can be manipulated safely only under dapm widgets handler
---      * routines
---      */
---     list_for_each_entry_safe(path_list, tmp_list,
---                             &skl->dapm_path_list, node) {
---             if (path_list->dapm_path->sink == sink) {
---                     dev_dbg(ctx->dev, "Path found = %s\n",
---                                     path_list->dapm_path->name);
---                     source = path_list->dapm_path->source;
---                     src_mconfig = source->priv;
---                     path_found = 1;
--- 
---                     list_del(&path_list->node);
---                     kfree(path_list);
---                     break;
---             }
---     }
--- 
---     /*
---      * If path_found == 1, that means pmd for source pipe has
---      * not occurred, source is connected to some other sink.
---      * so its responsibility of sink to unbind itself from source.
---      */
---     if (path_found) {
---             ret = skl_stop_pipe(ctx, src_mconfig->pipe);
---             if (ret < 0)
---                     return ret;
+++     for (i = 0; i < sink_mconfig->max_in_queue; i++) {
+++             if (sink_mconfig->m_in_pin[i].pin_state == SKL_PIN_BIND_DONE) {
+++                     src_mconfig = sink_mconfig->m_in_pin[i].tgt_mcfg;
+++                     if (!src_mconfig)
+++                             continue;
+++                     /*
+++                      * If path_found == 1, that means pmd for source
+++                      * pipe has not occurred, source is connected to
+++                      * some other sink. so its responsibility of sink
+++                      * to unbind itself from source.
+++                      */
+++                     ret = skl_stop_pipe(ctx, src_mconfig->pipe);
+++                     if (ret < 0)
+++                             return ret;
    
---             ret = skl_unbind_modules(ctx, src_mconfig, sink_mconfig);
+++                     ret = skl_unbind_modules(ctx,
+++                                             src_mconfig, sink_mconfig);
+++             }
        }
    
        return ret;
@@@@@ -622,10 -622,10 -622,10 -762,12 +762,12 @@@@@ static int skl_tplg_mixer_dapm_post_pmd
        int ret = 0;
    
        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 (src_module == NULL) {
                        src_module = dst_module;
                        continue;
        }
    
        ret = skl_delete_pipe(ctx, mconfig->pipe);
---     skl_tplg_free_pipe_mem(skl, mconfig);
    
---     return ret;
+++     return skl_tplg_unload_pipe_modules(ctx, s_pipe);
    }
    
    /*
    static int skl_tplg_pga_dapm_post_pmd_event(struct snd_soc_dapm_widget *w,
                                                                struct skl *skl)
    {
---     struct snd_soc_dapm_widget *source, *sink;
        struct skl_module_cfg *src_mconfig, *sink_mconfig;
---     int ret = 0, path_found = 0;
---     struct skl_dapm_path_list *path_list, *tmp_path_list;
+++     int ret = 0, i;
        struct skl_sst *ctx = skl->skl_sst;
    
---     source = w;
---     src_mconfig = source->priv;
+++     src_mconfig = w->priv;
    
---     skl_tplg_free_pipe_mcps(skl, src_mconfig);
        /* Stop the pipe since this is a mixin module */
        ret = skl_stop_pipe(ctx, src_mconfig->pipe);
        if (ret)
                return ret;
    
---     list_for_each_entry_safe(path_list, tmp_path_list, &skl->dapm_path_list, node) {
---             if (path_list->dapm_path->source == source) {
---                     dev_dbg(ctx->dev, "Path found = %s\n",
---                                     path_list->dapm_path->name);
---                     sink = path_list->dapm_path->sink;
---                     sink_mconfig = sink->priv;
---                     path_found = 1;
--- 
---                     list_del(&path_list->node);
---                     kfree(path_list);
---                     break;
+++     for (i = 0; i < src_mconfig->max_out_queue; i++) {
+++             if (src_mconfig->m_out_pin[i].pin_state == SKL_PIN_BIND_DONE) {
+++                     sink_mconfig = src_mconfig->m_out_pin[i].tgt_mcfg;
+++                     if (!sink_mconfig)
+++                             continue;
+++                     /*
+++                      * This is a connecter and if path is found that means
+++                      * unbind between source and sink has not happened yet
+++                      */
+++                     ret = skl_stop_pipe(ctx, sink_mconfig->pipe);
+++                     if (ret < 0)
+++                             return ret;
+++                     ret = skl_unbind_modules(ctx, src_mconfig,
+++                                                     sink_mconfig);
                }
        }
    
---     /*
---      * This is a connector and if path is found that means
---      * unbind between source and sink has not happened yet
---      */
---     if (path_found) {
---             ret = skl_stop_pipe(ctx, src_mconfig->pipe);
---             if (ret < 0)
---                     return ret;
--- 
---             ret = skl_unbind_modules(ctx, src_mconfig, sink_mconfig);
---     }
--- 
        return ret;
    }
    
@@@@@ -774,6 -774,6 -774,6 -902,67 +902,67 @@@@@ static int skl_tplg_pga_event(struct sn
        return 0;
    }
    
+++ static int skl_tplg_tlv_control_get(struct snd_kcontrol *kcontrol,
+++                     unsigned int __user *data, unsigned int size)
+++ {
+++     struct soc_bytes_ext *sb =
+++                     (struct soc_bytes_ext *)kcontrol->private_value;
+++     struct skl_algo_data *bc = (struct skl_algo_data *)sb->dobj.private;
+++     struct snd_soc_dapm_widget *w = snd_soc_dapm_kcontrol_widget(kcontrol);
+++     struct skl_module_cfg *mconfig = w->priv;
+++     struct skl *skl = get_skl_ctx(w->dapm->dev);
+++ 
+++     if (w->power)
+++             skl_get_module_params(skl->skl_sst, (u32 *)bc->params,
+++                                   bc->max, bc->param_id, mconfig);
+++ 
+++     if (bc->params) {
+++             if (copy_to_user(data, &bc->param_id, sizeof(u32)))
+++                     return -EFAULT;
+++             if (copy_to_user(data + 1, &size, sizeof(u32)))
+++                     return -EFAULT;
+++             if (copy_to_user(data + 2, bc->params, size))
+++                     return -EFAULT;
+++     }
+++ 
+++     return 0;
+++ }
+++ 
+++ #define SKL_PARAM_VENDOR_ID 0xff
+++ 
+++ static int skl_tplg_tlv_control_set(struct snd_kcontrol *kcontrol,
+++                     const unsigned int __user *data, unsigned int size)
+++ {
+++     struct snd_soc_dapm_widget *w = snd_soc_dapm_kcontrol_widget(kcontrol);
+++     struct skl_module_cfg *mconfig = w->priv;
+++     struct soc_bytes_ext *sb =
+++                     (struct soc_bytes_ext *)kcontrol->private_value;
+++     struct skl_algo_data *ac = (struct skl_algo_data *)sb->dobj.private;
+++     struct skl *skl = get_skl_ctx(w->dapm->dev);
+++ 
+++     if (ac->params) {
+++             /*
+++              * if the param_is is of type Vendor, firmware expects actual
+++              * parameter id and size from the control.
+++              */
+++             if (ac->param_id == SKL_PARAM_VENDOR_ID) {
+++                     if (copy_from_user(ac->params, data, size))
+++                             return -EFAULT;
+++             } else {
+++                     if (copy_from_user(ac->params,
+++                                        data + 2 * sizeof(u32), size))
+++                             return -EFAULT;
+++             }
+++ 
+++             if (w->power)
+++                     return skl_set_module_params(skl->skl_sst,
+++                                             (u32 *)ac->params, ac->max,
+++                                             ac->param_id, mconfig);
+++     }
+++ 
+++     return 0;
+++ }
+++ 
    /*
     * 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
@@@@@ -790,9 -790,9 -790,9 -979,9 +979,9 @@@@@ int skl_tplg_update_pipe_params(struct 
        memcpy(pipe->p_params, params, sizeof(*params));
    
        if (params->stream == SNDRV_PCM_STREAM_PLAYBACK)
---             format = &mconfig->in_fmt;
+++             format = &mconfig->in_fmt[0];
        else
---             format = &mconfig->out_fmt;
+++             format = &mconfig->out_fmt[0];
    
        /* set the hw_params */
        format->s_freq = params->s_freq;
                break;
    
        case SKL_DEPTH_24BIT:
+++     case SKL_DEPTH_32BIT:
                format->bit_depth = SKL_DEPTH_32BIT;
                break;
    
@@@@@ -846,7 -846,7 -846,7 -1036,7 +1036,7 @@@@@ skl_tplg_fe_get_cpr_module(struct snd_s
                w = dai->playback_widget;
                snd_soc_dapm_widget_for_each_sink_path(w, p) {
                        if (p->connect && p->sink->power &&
---                                     is_skl_dsp_widget_type(p->sink))
+++                                     !is_skl_dsp_widget_type(p->sink))
                                continue;
    
                        if (p->sink->priv) {
                w = dai->capture_widget;
                snd_soc_dapm_widget_for_each_source_path(w, p) {
                        if (p->connect && p->source->power &&
---                                     is_skl_dsp_widget_type(p->source))
+++                                     !is_skl_dsp_widget_type(p->source))
                                continue;
    
                        if (p->source->priv) {
@@@@@ -920,6 -920,6 -920,6 -1110,9 +1110,9 @@@@@ static int skl_tplg_be_fill_pipe_params
    
        memcpy(pipe->p_params, params, sizeof(*params));
    
+++     if (link_type == NHLT_LINK_HDA)
+++             return 0;
+++ 
        /* update the blob based on virtual bus_id*/
        cfg = skl_get_ep_blob(skl, mconfig->vbus_id, link_type,
                                        params->s_fmt, params->ch,
@@@@@ -950,18 -950,18 -950,18 -1143,13 +1143,13 @@@@@ static int skl_tplg_be_set_src_pipe_par
                if (p->connect && is_skl_dsp_widget_type(p->source) &&
                                                p->source->priv) {
    
---                     if (!p->source->power) {
---                             ret = skl_tplg_be_fill_pipe_params(
---                                             dai, p->source->priv,
---                                             params);
---                             if (ret < 0)
---                                     return ret;
---                     } else {
---                             return -EBUSY;
---                     }
+++                     ret = skl_tplg_be_fill_pipe_params(dai,
+++                                             p->source->priv, params);
+++                     if (ret < 0)
+++                             return ret;
                } else {
---                     ret = skl_tplg_be_set_src_pipe_params(
---                                             dai, p->source, params);
+++                     ret = skl_tplg_be_set_src_pipe_params(dai,
+++                                             p->source, params);
                        if (ret < 0)
                                return ret;
                }
@@@@@ -980,15 -980,15 -980,15 -1168,10 +1168,10 @@@@@ static int skl_tplg_be_set_sink_pipe_pa
                if (p->connect && is_skl_dsp_widget_type(p->sink) &&
                                                p->sink->priv) {
    
---                     if (!p->sink->power) {
---                             ret = skl_tplg_be_fill_pipe_params(
---                                             dai, p->sink->priv, params);
---                             if (ret < 0)
---                                     return ret;
---                     } else {
---                             return -EBUSY;
---                     }
--- 
+++                     ret = skl_tplg_be_fill_pipe_params(dai,
+++                                             p->sink->priv, params);
+++                     if (ret < 0)
+++                             return ret;
                } else {
                        ret = skl_tplg_be_set_sink_pipe_params(
                                                dai, p->sink, params);
@@@@@ -1030,6 -1030,6 -1030,6 -1213,11 +1213,11 @@@@@ static const struct snd_soc_tplg_widget
        {SKL_PGA_EVENT, skl_tplg_pga_event},
    };
    
+++ static const struct snd_soc_tplg_bytes_ext_ops skl_tlv_ops[] = {
+++     {SKL_CONTROL_TYPE_BYTE_TLV, skl_tplg_tlv_control_get,
+++                                     skl_tplg_tlv_control_set},
+++ };
+++ 
    /*
     * The topology binary passes the pin info for a module so initialize the pin
     * info passed into module instance
@@@@@ -1045,6 -1045,6 -1045,6 -1233,7 +1233,7 @@@@@ static void skl_fill_module_pin_info(st
                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;
        }
    }
    
@@@@@ -1092,6 -1092,6 -1092,6 -1281,24 +1281,24 @@@@@ static struct skl_pipe *skl_tplg_add_pi
        return ppl->pipe;
    }
    
+++ static void skl_tplg_fill_fmt(struct skl_module_fmt *dst_fmt,
+++                             struct skl_dfw_module_fmt *src_fmt,
+++                             int pins)
+++ {
+++     int i;
+++ 
+++     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;
+++     }
+++ }
+++ 
    /*
     * Topology core widget load callback
     *
@@@@@ -1130,22 -1130,22 -1130,22 -1337,16 +1337,16 @@@@@ static int skl_tplg_widget_load(struct 
        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;
---     mconfig->in_fmt.channels = dfw_config->in_fmt.channels;
---     mconfig->in_fmt.s_freq = dfw_config->in_fmt.freq;
---     mconfig->in_fmt.bit_depth = dfw_config->in_fmt.bit_depth;
---     mconfig->in_fmt.valid_bit_depth =
---                             dfw_config->in_fmt.valid_bit_depth;
---     mconfig->in_fmt.ch_cfg = dfw_config->in_fmt.ch_cfg;
---     mconfig->out_fmt.channels = dfw_config->out_fmt.channels;
---     mconfig->out_fmt.s_freq = dfw_config->out_fmt.freq;
---     mconfig->out_fmt.bit_depth = dfw_config->out_fmt.bit_depth;
---     mconfig->out_fmt.valid_bit_depth =
---                             dfw_config->out_fmt.valid_bit_depth;
---     mconfig->out_fmt.ch_cfg = dfw_config->out_fmt.ch_cfg;
+++     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->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 (dfw_config->is_loadable)
+++             memcpy(mconfig->guid, dfw_config->uuid,
+++                                     ARRAY_SIZE(dfw_config->uuid));
+++ 
+++     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;
    
                return -ENOMEM;
    
        memcpy(mconfig->formats_config.caps, dfw_config->caps.caps,
---                                      dfw_config->caps.caps_size);
+++                                              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;
    
    bind_event:
        if (tplg_w->event_type == 0) {
        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;
+++ 
+++     if (ac->max) {
+++             ac->params = (char *) devm_kzalloc(dev, ac->max, GFP_KERNEL);
+++             if (!ac->params)
+++                     return -ENOMEM;
+++ 
+++             if (dfw_ac->params)
+++                     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 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),
    };
    
    /* This will be read from topology manifest, currently defined here */
@@@@@ -1240,7 -1240,6 -1240,6 -1508,6 +1508,7 @@@@@ int skl_tplg_init(struct snd_soc_platfo
         */
        ret = snd_soc_tplg_component_load(&platform->component,
                                        &skl_tplg_ops, fw, 0);
 +++    release_firmware(fw);
        if (ret < 0) {
                dev_err(bus->dev, "tplg component load failed%d\n", ret);
                return -EINVAL;