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;
+
+       if (bc->params) {
+               if (copy_to_user(data, &bc->param_id, sizeof(u32)))
+                       return -EFAULT;
+               if (copy_to_user(data + sizeof(u32), &size, sizeof(u32)))
+                       return -EFAULT;
+               if (copy_to_user(data + 2 * sizeof(u32), 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
        {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
        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 */