Merge remote-tracking branch 'asoc/topic/intel' into asoc-next
authorMark Brown <broonie@kernel.org>
Sun, 30 Apr 2017 13:15:41 +0000 (22:15 +0900)
committerMark Brown <broonie@kernel.org>
Sun, 30 Apr 2017 13:15:41 +0000 (22:15 +0900)
1  2 
include/sound/soc.h
sound/soc/codecs/hdac_hdmi.c
sound/soc/intel/boards/bytcr_rt5640.c
sound/soc/intel/skylake/skl-topology.c
sound/soc/soc-core.c

diff --combined include/sound/soc.h
index ee838b0d5db8d4b1acdbf6339989420d350f825e,915c06cb2b325205ba347d520d7473684c2ce655..786765fc630bd440596afa38bed9e4dde1bd3e76
@@@ -497,7 -497,15 +497,15 @@@ void snd_soc_runtime_deactivate(struct 
  int snd_soc_runtime_set_dai_fmt(struct snd_soc_pcm_runtime *rtd,
        unsigned int dai_fmt);
  
+ #ifdef CONFIG_DMI
  int snd_soc_set_dmi_name(struct snd_soc_card *card, const char *flavour);
+ #else
+ static inline int snd_soc_set_dmi_name(struct snd_soc_card *card,
+                                      const char *flavour)
+ {
+       return 0;
+ }
+ #endif
  
  /* Utility functions to get clock rates from various things */
  int snd_soc_calc_frame_size(int sample_size, int channels, int tdm_slots);
@@@ -812,6 -820,7 +820,6 @@@ struct snd_soc_component 
  
        unsigned int ignore_pmdown_time:1; /* pmdown_time is ignored at stop */
        unsigned int registered_as_component:1;
 -      unsigned int auxiliary:1; /* for auxiliary component of the card */
        unsigned int suspended:1; /* is in suspend PM state */
  
        struct list_head list;
index fd272a40485b077039c68f786671218a7f4204e2,5b7694721ef79f2bb7c32aaa24c9f358de9a2c3a..bc2e74ff3b2deddf653f1823329d22bf3449f8b6
@@@ -469,7 -469,7 +469,7 @@@ static int hdac_hdmi_set_hw_params(stru
  
        format = snd_hdac_calc_stream_format(params_rate(hparams),
                        params_channels(hparams), params_format(hparams),
-                       24, 0);
+                       dai->driver->playback.sig_bits, 0);
  
        pcm = hdac_hdmi_get_pcm_from_cvt(hdmi, dai_map->cvt);
        if (!pcm)
@@@ -1419,8 -1419,8 +1419,8 @@@ static int hdac_hdmi_create_dais(struc
                hdmi_dais[i].playback.rate_min = rate_min;
                hdmi_dais[i].playback.channels_min = 2;
                hdmi_dais[i].playback.channels_max = 2;
+               hdmi_dais[i].playback.sig_bits = bps;
                hdmi_dais[i].ops = &hdmi_dai_ops;
                i++;
        }
  
@@@ -1534,20 -1534,21 +1534,20 @@@ static void hdac_hdmi_eld_notify_cb(voi
                        pin->mst_capable = false;
                        /* if not MST, default is port[0] */
                        hport = &pin->ports[0];
 -                      goto out;
                } else {
                        for (i = 0; i < pin->num_ports; i++) {
                                pin->mst_capable = true;
                                if (pin->ports[i].id == pipe) {
                                        hport = &pin->ports[i];
 -                                      goto out;
 +                                      break;
                                }
                        }
                }
 +
 +              if (hport)
 +                      hdac_hdmi_present_sense(pin, hport);
        }
  
 -out:
 -      if (pin && hport)
 -              hdac_hdmi_present_sense(pin, hport);
  }
  
  static struct i915_audio_component_audio_ops aops = {
@@@ -1997,7 -1998,7 +1997,7 @@@ static int hdac_hdmi_dev_remove(struct 
        struct hdac_hdmi_pin *pin, *pin_next;
        struct hdac_hdmi_cvt *cvt, *cvt_next;
        struct hdac_hdmi_pcm *pcm, *pcm_next;
 -      struct hdac_hdmi_port *port;
 +      struct hdac_hdmi_port *port, *port_next;
        int i;
  
        snd_soc_unregister_codec(&edev->hdac.dev);
                if (list_empty(&pcm->port_list))
                        continue;
  
 -              list_for_each_entry(port, &pcm->port_list, head)
 -                      port = NULL;
 +              list_for_each_entry_safe(port, port_next,
 +                                      &pcm->port_list, head)
 +                      list_del(&port->head);
  
                list_del(&pcm->head);
                kfree(pcm);
index 9e2a3404a836bf919f68b6cbd33c8f569b3c8843,f063368edef95be9933ab18536aa235a343c4a99..4a76b099a508954c4cd3e6b3a3bfdfda1755b0fe
@@@ -19,6 -19,7 +19,7 @@@
  
  #include <linux/init.h>
  #include <linux/module.h>
+ #include <linux/moduleparam.h>
  #include <linux/platform_device.h>
  #include <linux/acpi.h>
  #include <linux/device.h>
@@@ -56,35 -57,88 +57,88 @@@ enum 
  struct byt_rt5640_private {
        struct clk *mclk;
  };
+ static bool is_bytcr;
  
  static unsigned long byt_rt5640_quirk = BYT_RT5640_MCLK_EN;
+ static unsigned int quirk_override;
+ module_param_named(quirk, quirk_override, uint, 0444);
+ MODULE_PARM_DESC(quirk, "Board-specific quirk override");
  
  static void log_quirks(struct device *dev)
  {
-       if (BYT_RT5640_MAP(byt_rt5640_quirk) == BYT_RT5640_DMIC1_MAP)
-               dev_info(dev, "quirk DMIC1_MAP enabled");
-       if (BYT_RT5640_MAP(byt_rt5640_quirk) == BYT_RT5640_DMIC2_MAP)
-               dev_info(dev, "quirk DMIC2_MAP enabled");
-       if (BYT_RT5640_MAP(byt_rt5640_quirk) == BYT_RT5640_IN1_MAP)
-               dev_info(dev, "quirk IN1_MAP enabled");
-       if (BYT_RT5640_MAP(byt_rt5640_quirk) == BYT_RT5640_IN3_MAP)
-               dev_info(dev, "quirk IN3_MAP enabled");
-       if (byt_rt5640_quirk & BYT_RT5640_DMIC_EN)
-               dev_info(dev, "quirk DMIC enabled");
+       int map;
+       bool has_dmic = false;
+       bool has_mclk = false;
+       bool has_ssp0 = false;
+       bool has_ssp0_aif1 = false;
+       bool has_ssp0_aif2 = false;
+       bool has_ssp2_aif2 = false;
+       map = BYT_RT5640_MAP(byt_rt5640_quirk);
+       switch (map) {
+       case BYT_RT5640_DMIC1_MAP:
+               dev_info(dev, "quirk DMIC1_MAP enabled\n");
+               has_dmic = true;
+               break;
+       case BYT_RT5640_DMIC2_MAP:
+               dev_info(dev, "quirk DMIC2_MAP enabled\n");
+               has_dmic = true;
+               break;
+       case BYT_RT5640_IN1_MAP:
+               dev_info(dev, "quirk IN1_MAP enabled\n");
+               break;
+       case BYT_RT5640_IN3_MAP:
+               dev_info(dev, "quirk IN3_MAP enabled\n");
+               break;
+       default:
+               dev_err(dev, "quirk map 0x%x is not supported, microphone input will not work\n", map);
+               break;
+       }
+       if (byt_rt5640_quirk & BYT_RT5640_DMIC_EN) {
+               if (has_dmic)
+                       dev_info(dev, "quirk DMIC enabled\n");
+               else
+                       dev_err(dev, "quirk DMIC enabled but no DMIC input set, will be ignored\n");
+       }
        if (byt_rt5640_quirk & BYT_RT5640_MONO_SPEAKER)
-               dev_info(dev, "quirk MONO_SPEAKER enabled");
-       if (byt_rt5640_quirk & BYT_RT5640_DIFF_MIC)
-               dev_info(dev, "quirk DIFF_MIC enabled");
-       if (byt_rt5640_quirk & BYT_RT5640_SSP2_AIF2)
-               dev_info(dev, "quirk SSP2_AIF2 enabled");
-       if (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1)
-               dev_info(dev, "quirk SSP0_AIF1 enabled");
-       if (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2)
-               dev_info(dev, "quirk SSP0_AIF2 enabled");
-       if (byt_rt5640_quirk & BYT_RT5640_MCLK_EN)
-               dev_info(dev, "quirk MCLK_EN enabled");
-       if (byt_rt5640_quirk & BYT_RT5640_MCLK_25MHZ)
-               dev_info(dev, "quirk MCLK_25MHZ enabled");
+               dev_info(dev, "quirk MONO_SPEAKER enabled\n");
+       if (byt_rt5640_quirk & BYT_RT5640_DIFF_MIC) {
+               if (!has_dmic)
+                       dev_info(dev, "quirk DIFF_MIC enabled\n");
+               else
+                       dev_info(dev, "quirk DIFF_MIC enabled but DMIC input selected, will be ignored\n");
+       }
+       if (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) {
+               dev_info(dev, "quirk SSP0_AIF1 enabled\n");
+               has_ssp0 = true;
+               has_ssp0_aif1 = true;
+       }
+       if (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2) {
+               dev_info(dev, "quirk SSP0_AIF2 enabled\n");
+               has_ssp0 = true;
+               has_ssp0_aif2 = true;
+       }
+       if (byt_rt5640_quirk & BYT_RT5640_SSP2_AIF2) {
+               dev_info(dev, "quirk SSP2_AIF2 enabled\n");
+               has_ssp2_aif2 = true;
+       }
+       if (is_bytcr && !has_ssp0)
+               dev_err(dev, "Invalid routing, bytcr detected but no SSP0-based quirk, audio cannot work with SSP2 on bytcr\n");
+       if (has_ssp0_aif1 && has_ssp0_aif2)
+               dev_err(dev, "Invalid routing, SSP0 cannot be connected to both AIF1 and AIF2\n");
+       if (has_ssp0 && has_ssp2_aif2)
+               dev_err(dev, "Invalid routing, cannot have both SSP0 and SSP2 connected to codec\n");
+       if (byt_rt5640_quirk & BYT_RT5640_MCLK_EN) {
+               dev_info(dev, "quirk MCLK_EN enabled\n");
+               has_mclk = true;
+       }
+       if (byt_rt5640_quirk & BYT_RT5640_MCLK_25MHZ) {
+               if (has_mclk)
+                       dev_info(dev, "quirk MCLK_25MHZ enabled\n");
+               else
+                       dev_err(dev, "quirk MCLK_25MHZ enabled but quirk MCLK not selected, will be ignored\n");
+       }
  }
  
  
@@@ -128,7 -182,7 +182,7 @@@ static int platform_clock_control(struc
                        ret = clk_prepare_enable(priv->mclk);
                        if (ret < 0) {
                                dev_err(card->dev,
-                                       "could not configure MCLK state");
+                                       "could not configure MCLK state\n");
                                return ret;
                        }
                }
@@@ -621,7 -675,7 +675,7 @@@ static struct snd_soc_dai_link byt_rt56
                .codec_dai_name = "snd-soc-dummy-dai",
                .codec_name = "snd-soc-dummy",
                .platform_name = "sst-mfld-platform",
 -              .ignore_suspend = 1,
 +              .nonatomic = true,
                .dynamic = 1,
                .dpcm_playback = 1,
                .dpcm_capture = 1,
                .codec_dai_name = "snd-soc-dummy-dai",
                .codec_name = "snd-soc-dummy",
                .platform_name = "sst-mfld-platform",
 -              .ignore_suspend = 1,
                .nonatomic = true,
                .dynamic = 1,
                .dpcm_playback = 1,
                                                | SND_SOC_DAIFMT_CBS_CFS,
                .be_hw_params_fixup = byt_rt5640_codec_fixup,
                .ignore_suspend = 1,
 +              .nonatomic = true,
                .dpcm_playback = 1,
                .dpcm_capture = 1,
                .init = byt_rt5640_init,
@@@ -710,8 -764,8 +764,8 @@@ static int snd_byt_rt5640_mc_probe(stru
        int i;
        int dai_index;
        struct byt_rt5640_private *priv;
-       bool is_bytcr = false;
  
+       is_bytcr = false;
        priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_ATOMIC);
        if (!priv)
                return -ENOMEM;
  
        /* check quirks before creating card */
        dmi_check_system(byt_rt5640_quirk_table);
+       if (quirk_override) {
+               dev_info(&pdev->dev, "Overriding quirk 0x%x => 0x%x\n",
+                        (unsigned int)byt_rt5640_quirk, quirk_override);
+               byt_rt5640_quirk = quirk_override;
+       }
        log_quirks(&pdev->dev);
  
        if ((byt_rt5640_quirk & BYT_RT5640_SSP2_AIF2) ||
index 2dbfb1b24ef4a629ecdac8004630fc66aeb529fc,29f68713a23137773d36130ae49b3325dde4c8aa..3a99712e44a80df81f7ad27d52e69501f617e948
@@@ -299,8 -299,6 +299,6 @@@ static void skl_tplg_update_buffer_size
  {
        int multiplier = 1;
        struct skl_module_fmt *in_fmt, *out_fmt;
-       int in_rate, out_rate;
  
        /* Since fixups is applied to pin 0 only, ibs, obs needs
         * change for pin 0 only
        if (mcfg->m_type == SKL_MODULE_TYPE_SRCINT)
                multiplier = 5;
  
-       if (in_fmt->s_freq % 1000)
-               in_rate = (in_fmt->s_freq / 1000) + 1;
-       else
-               in_rate = (in_fmt->s_freq / 1000);
-       mcfg->ibs = in_rate * (mcfg->in_fmt->channels) *
-                       (mcfg->in_fmt->bit_depth >> 3) *
+       mcfg->ibs = DIV_ROUND_UP(in_fmt->s_freq, 1000) *
+                       in_fmt->channels * (in_fmt->bit_depth >> 3) *
                        multiplier;
  
-       if (mcfg->out_fmt->s_freq % 1000)
-               out_rate = (mcfg->out_fmt->s_freq / 1000) + 1;
-       else
-               out_rate = (mcfg->out_fmt->s_freq / 1000);
-       mcfg->obs = out_rate * (mcfg->out_fmt->channels) *
-                       (mcfg->out_fmt->bit_depth >> 3) *
+       mcfg->obs = DIV_ROUND_UP(out_fmt->s_freq, 1000) *
+                       out_fmt->channels * (out_fmt->bit_depth >> 3) *
                        multiplier;
  }
  
@@@ -512,7 -500,7 +500,7 @@@ static int skl_tplg_set_module_init_dat
                        if (bc->set_params != SKL_PARAM_INIT)
                                continue;
  
 -                      mconfig->formats_config.caps = (u32 *)&bc->params;
 +                      mconfig->formats_config.caps = (u32 *)bc->params;
                        mconfig->formats_config.caps_size = bc->size;
  
                        break;
@@@ -551,6 -539,7 +539,7 @@@ skl_tplg_init_pipe_modules(struct skl *
        int ret = 0;
  
        list_for_each_entry(w_module, &pipe->w_list, node) {
+               uuid_le *uuid_mod;
                w = w_module->w;
                mconfig = w->priv;
  
                 * FE/BE params
                 */
                skl_tplg_update_module_params(w, ctx);
-               mconfig->id.pvt_id = skl_get_pvt_id(ctx, mconfig);
+               uuid_mod = (uuid_le *)mconfig->guid;
+               mconfig->id.pvt_id = skl_get_pvt_id(ctx, uuid_mod,
+                                               mconfig->id.instance_id);
                if (mconfig->id.pvt_id < 0)
                        return ret;
                skl_tplg_set_module_init_data(w);
                ret = skl_init_module(ctx, mconfig);
                if (ret < 0) {
-                       skl_put_pvt_id(ctx, mconfig);
+                       skl_put_pvt_id(ctx, uuid_mod, &mconfig->id.pvt_id);
                        return ret;
                }
                skl_tplg_alloc_pipe_mcps(skl, mconfig);
@@@ -614,7 -605,9 +605,9 @@@ static int skl_tplg_unload_pipe_modules
        struct skl_module_cfg *mconfig = NULL;
  
        list_for_each_entry(w_module, &pipe->w_list, node) {
+               uuid_le *uuid_mod;
                mconfig  = w_module->w->priv;
+               uuid_mod = (uuid_le *)mconfig->guid;
  
                if (mconfig->is_loadable && ctx->dsp->fw_ops.unload_mod &&
                        mconfig->m_state > SKL_MODULE_UNINIT) {
                        if (ret < 0)
                                return -EIO;
                }
-               skl_put_pvt_id(ctx, mconfig);
+               skl_put_pvt_id(ctx, uuid_mod, &mconfig->id.pvt_id);
        }
  
        /* no modules to unload in this path, so return */
@@@ -645,8 -638,9 +638,9 @@@ static int skl_tplg_mixer_dapm_pre_pmu_
        struct skl_module_cfg *mconfig = w->priv;
        struct skl_pipe_module *w_module;
        struct skl_pipe *s_pipe = mconfig->pipe;
-       struct skl_module_cfg *src_module = NULL, *dst_module;
+       struct skl_module_cfg *src_module = NULL, *dst_module, *module;
        struct skl_sst *ctx = skl->skl_sst;
+       struct skl_module_deferred_bind *modules;
  
        /* check resource available */
        if (!skl_is_pipe_mcps_avail(skl, mconfig))
                src_module = dst_module;
        }
  
+       /*
+        * When the destination module is initialized, check for these modules
+        * in deferred bind list. If found, bind them.
+        */
+       list_for_each_entry(w_module, &s_pipe->w_list, node) {
+               if (list_empty(&skl->bind_list))
+                       break;
+               list_for_each_entry(modules, &skl->bind_list, node) {
+                       module = w_module->w->priv;
+                       if (modules->dst == module)
+                               skl_bind_modules(ctx, modules->src,
+                                                       modules->dst);
+               }
+       }
        return 0;
  }
  
- static int skl_fill_sink_instance_id(struct skl_sst *ctx,
-                               struct skl_algo_data *alg_data)
+ static int skl_fill_sink_instance_id(struct skl_sst *ctx, u32 *params,
+                               int size, struct skl_module_cfg *mcfg)
  {
-       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;
+       if (mcfg->m_type == SKL_MODULE_TYPE_KPB) {
+               struct skl_kpb_params *kpb_params =
+                               (struct skl_kpb_params *)params;
+               struct skl_mod_inst_map *inst = kpb_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++;
+               for (i = 0; i < kpb_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.
@@@ -726,6 -739,7 +739,7 @@@ static int skl_tplg_set_module_bind_par
        struct soc_bytes_ext *sb;
        struct skl_algo_data *bc;
        struct skl_specific_cfg *sp_cfg;
+       u32 *params;
  
        /*
         * check all out/in pins are in bind state.
                        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);
+                               params = kzalloc(bc->max, GFP_KERNEL);
+                               if (!params)
+                                       return -ENOMEM;
+                               memcpy(params, bc->params, bc->max);
+                               skl_fill_sink_instance_id(ctx, params, bc->max,
+                                                               mconfig);
+                               ret = skl_set_module_params(ctx, params,
+                                               bc->max, bc->param_id, mconfig);
+                               kfree(params);
                                if (ret < 0)
                                        return ret;
                        }
        return 0;
  }
  
+ static int skl_tplg_module_add_deferred_bind(struct skl *skl,
+       struct skl_module_cfg *src, struct skl_module_cfg *dst)
+ {
+       struct skl_module_deferred_bind *m_list, *modules;
+       int i;
+       /* only supported for module with static pin connection */
+       for (i = 0; i < dst->max_in_queue; i++) {
+               struct skl_module_pin *pin = &dst->m_in_pin[i];
+               if (pin->is_dynamic)
+                       continue;
+               if ((pin->id.module_id  == src->id.module_id) &&
+                       (pin->id.instance_id  == src->id.instance_id)) {
+                       if (!list_empty(&skl->bind_list)) {
+                               list_for_each_entry(modules, &skl->bind_list, node) {
+                                       if (modules->src == src && modules->dst == dst)
+                                               return 0;
+                               }
+                       }
+                       m_list = kzalloc(sizeof(*m_list), GFP_KERNEL);
+                       if (!m_list)
+                               return -ENOMEM;
+                       m_list->src = src;
+                       m_list->dst = dst;
+                       list_add(&m_list->node, &skl->bind_list);
+               }
+       }
+       return 0;
+ }
  static int skl_tplg_bind_sinks(struct snd_soc_dapm_widget *w,
                                struct skl *skl,
                                struct snd_soc_dapm_widget *src_w,
                        sink = p->sink;
                        sink_mconfig = sink->priv;
  
+                       /*
+                        * Modules other than PGA leaf can be connected
+                        * directly or via switch to a module in another
+                        * pipeline. EX: reference path
+                        * when the path is enabled, the dst module that needs
+                        * to be bound may not be initialized. if the module is
+                        * not initialized, add these modules in the deferred
+                        * bind list and when the dst module is initialised,
+                        * bind this module to the dst_module in deferred list.
+                        */
+                       if (((src_mconfig->m_state == SKL_MODULE_INIT_DONE)
+                               && (sink_mconfig->m_state == SKL_MODULE_UNINIT))) {
+                               ret = skl_tplg_module_add_deferred_bind(skl,
+                                               src_mconfig, sink_mconfig);
+                               if (ret < 0)
+                                       return ret;
+                       }
                        if (src_mconfig->m_state == SKL_MODULE_UNINIT ||
                                sink_mconfig->m_state == SKL_MODULE_UNINIT)
                                continue;
@@@ -985,15 -1066,6 +1066,6 @@@ static int skl_tplg_mixer_dapm_pre_pmd_
                        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);
@@@ -1019,6 -1091,7 +1091,7 @@@ static int skl_tplg_mixer_dapm_post_pmd
        struct skl_module_cfg *src_module = NULL, *dst_module;
        struct skl_sst *ctx = skl->skl_sst;
        struct skl_pipe *s_pipe = mconfig->pipe;
+       struct skl_module_deferred_bind *modules, *tmp;
  
        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) {
+               if (list_empty(&skl->bind_list))
+                       break;
+               src_module = w_module->w->priv;
+               list_for_each_entry_safe(modules, tmp, &skl->bind_list, node) {
+                       /*
+                        * When the destination module is deleted, Unbind the
+                        * modules from deferred bind list.
+                        */
+                       if (modules->dst == src_module) {
+                               skl_unbind_modules(ctx, modules->src,
+                                               modules->dst);
+                       }
+                       /*
+                        * When the source module is deleted, remove this entry
+                        * from the deferred bind list.
+                        */
+                       if (modules->src == src_module) {
+                               list_del(&modules->node);
+                               modules->src = NULL;
+                               modules->dst = NULL;
+                               kfree(modules);
+                       }
+               }
+       }
        list_for_each_entry(w_module, &s_pipe->w_list, node) {
                dst_module = w_module->w->priv;
  
  
        skl_delete_pipe(ctx, mconfig->pipe);
  
+       list_for_each_entry(w_module, &s_pipe->w_list, node) {
+               src_module = w_module->w->priv;
+               src_module->m_state = SKL_MODULE_UNINIT;
+       }
        return skl_tplg_unload_pipe_modules(ctx, s_pipe);
  }
  
@@@ -1082,36 -1189,6 +1189,6 @@@ static int skl_tplg_pga_dapm_post_pmd_e
        return ret;
  }
  
- /*
-  * In modelling, we assume there will be ONLY one mixer in a pipeline.  If
-  * mixer is not required then it is treated as static mixer aka vmixer with
-  * a hard path to source module
-  * So we don't need to check if source is started or not as hard path puts
-  * dependency on each other
-  */
- static int skl_tplg_vmixer_event(struct snd_soc_dapm_widget *w,
-                               struct snd_kcontrol *k, int event)
- {
-       struct snd_soc_dapm_context *dapm = w->dapm;
-       struct skl *skl = get_skl_ctx(dapm->dev);
-       switch (event) {
-       case SND_SOC_DAPM_PRE_PMU:
-               return skl_tplg_mixer_dapm_pre_pmu_event(w, skl);
-       case SND_SOC_DAPM_POST_PMU:
-               return skl_tplg_mixer_dapm_post_pmu_event(w, skl);
-       case SND_SOC_DAPM_PRE_PMD:
-               return skl_tplg_mixer_dapm_pre_pmd_event(w, skl);
-       case SND_SOC_DAPM_POST_PMD:
-               return skl_tplg_mixer_dapm_post_pmd_event(w, skl);
-       }
-       return 0;
- }
  /*
   * In modelling, we assume there will be ONLY one mixer in a pipeline. If a
   * second one is required that is created as another pipe entity.
@@@ -1252,10 -1329,12 +1329,12 @@@ static void skl_tplg_fill_dma_id(struc
                case SKL_DEVICE_HDALINK:
                        pipe->p_params->link_dma_id = params->link_dma_id;
                        pipe->p_params->link_index = params->link_index;
+                       pipe->p_params->link_bps = params->link_bps;
                        break;
  
                case SKL_DEVICE_HDAHOST:
                        pipe->p_params->host_dma_id = params->host_dma_id;
+                       pipe->p_params->host_bps = params->host_bps;
                        break;
  
                default:
@@@ -1578,7 -1657,7 +1657,7 @@@ int skl_tplg_be_update_params(struct sn
  
  static const struct snd_soc_tplg_widget_events skl_tplg_widget_ops[] = {
        {SKL_MIXER_EVENT, skl_tplg_mixer_event},
-       {SKL_VMIXER_EVENT, skl_tplg_vmixer_event},
+       {SKL_VMIXER_EVENT, skl_tplg_mixer_event},
        {SKL_PGA_EVENT, skl_tplg_pga_event},
  };
  
@@@ -1632,7 -1711,7 +1711,7 @@@ static int skl_tplg_add_pipe(struct dev
        list_for_each_entry(ppl, &skl->ppl_list, node) {
                if (ppl->pipe->ppl_id == tkn_elem->value) {
                        mconfig->pipe = ppl->pipe;
-                       return EEXIST;
+                       return -EEXIST;
                }
        }
  
@@@ -1924,11 -2003,13 +2003,13 @@@ static int skl_tplg_get_token(struct de
                ret = skl_tplg_add_pipe(dev,
                                mconfig, skl, tkn_elem);
  
-               if (ret < 0)
+               if (ret < 0) {
+                       if (ret == -EEXIST) {
+                               is_pipe_exists = 1;
+                               break;
+                       }
                        return is_pipe_exists;
-               if (ret == EEXIST)
-                       is_pipe_exists = 1;
+               }
  
                break;
  
diff --combined sound/soc/soc-core.c
index 9ee4d4a56eec0fab49e77b2e05651154de5b5311,05c4d9564b0b27405fd876973ff1b46a935d4815..f45748ef9f13a8e805b72f9b90025fe83dedf73e
@@@ -1776,6 -1776,7 +1776,6 @@@ static int soc_bind_aux_dev(struct snd_
        }
  
        component->init = aux_dev->init;
 -      component->auxiliary = 1;
        list_add(&component->card_aux_list, &card->aux_comp_list);
  
        return 0;
@@@ -1787,13 -1788,14 +1787,13 @@@ err_defer
  
  static int soc_probe_aux_devices(struct snd_soc_card *card)
  {
 -      struct snd_soc_component *comp, *tmp;
 +      struct snd_soc_component *comp;
        int order;
        int ret;
  
        for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST;
                order++) {
 -              list_for_each_entry_safe(comp, tmp, &card->aux_comp_list,
 -                                       card_aux_list) {
 +              list_for_each_entry(comp, &card->aux_comp_list, card_aux_list) {
                        if (comp->driver->probe_order == order) {
                                ret = soc_probe_component(card, comp);
                                if (ret < 0) {
                                                comp->name, ret);
                                        return ret;
                                }
 -                              list_del(&comp->card_aux_list);
                        }
                }
        }
@@@ -1817,12 -1820,14 +1817,12 @@@ static void soc_remove_aux_devices(stru
        for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST;
                order++) {
                list_for_each_entry_safe(comp, _comp,
 -                      &card->component_dev_list, card_list) {
 -
 -                      if (!comp->auxiliary)
 -                              continue;
 +                      &card->aux_comp_list, card_aux_list) {
  
                        if (comp->driver->remove_order == order) {
                                soc_remove_component(comp);
 -                              comp->auxiliary = 0;
 +                              /* remove it from the card's aux_comp_list */
 +                              list_del(&comp->card_aux_list);
                        }
                }
        }
@@@ -1913,6 -1918,7 +1913,7 @@@ int snd_soc_runtime_set_dai_fmt(struct 
  EXPORT_SYMBOL_GPL(snd_soc_runtime_set_dai_fmt);
  
  
+ #ifdef CONFIG_DMI
  /* Trim special characters, and replace '-' with '_' since '-' is used to
   * separate different DMI fields in the card long name. Only number and
   * alphabet characters and a few separator characters are kept.
@@@ -2044,6 -2050,7 +2045,7 @@@ int snd_soc_set_dmi_name(struct snd_soc
        return 0;
  }
  EXPORT_SYMBOL_GPL(snd_soc_set_dmi_name);
+ #endif /* CONFIG_DMI */
  
  static int snd_soc_instantiate_card(struct snd_soc_card *card)
  {
                snd_soc_dapm_add_routes(&card->dapm, card->of_dapm_routes,
                                        card->num_of_dapm_routes);
  
+       /* try to set some sane longname if DMI is available */
+       snd_soc_set_dmi_name(card, NULL);
        snprintf(card->snd_card->shortname, sizeof(card->snd_card->shortname),
                 "%s", card->name);
        snprintf(card->snd_card->longname, sizeof(card->snd_card->longname),
@@@ -3134,7 -3144,7 +3139,7 @@@ static int snd_soc_component_initialize
        component->suspend = component->driver->suspend;
        component->resume = component->driver->resume;
        component->pcm_new = component->driver->pcm_new;
 -      component->pcm_free= component->driver->pcm_free;
 +      component->pcm_free = component->driver->pcm_free;
  
        dapm = &component->dapm;
        dapm->dev = dev;
@@@ -3321,10 -3331,7 +3326,10 @@@ static int snd_soc_platform_drv_pcm_new
  {
        struct snd_soc_platform *platform = rtd->platform;
  
 -      return platform->driver->pcm_new(rtd);
 +      if (platform->driver->pcm_new)
 +              return platform->driver->pcm_new(rtd);
 +      else
 +              return 0;
  }
  
  static void snd_soc_platform_drv_pcm_free(struct snd_pcm *pcm)
        struct snd_soc_pcm_runtime *rtd = pcm->private_data;
        struct snd_soc_platform *platform = rtd->platform;
  
 -      platform->driver->pcm_free(pcm);
 +      if (platform->driver->pcm_free)
 +              platform->driver->pcm_free(pcm);
  }
  
  /**