ASoC: Intel: Skylake: Add support to configure module params
authorJeeja KP <jeeja.kp@intel.com>
Sat, 28 Nov 2015 09:31:49 +0000 (15:01 +0530)
committerMark Brown <broonie@kernel.org>
Tue, 1 Dec 2015 22:17:00 +0000 (22:17 +0000)
This adds support to configure module parameter during module
initialization or after module init using set module param
required by the DSP firmware sequence.

Signed-off-by: Jeeja KP <jeeja.kp@intel.com>
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/intel/skylake/skl-topology.c
sound/soc/intel/skylake/skl-topology.h

index 7a03bea48a9ad36870a56868c7798d8ce1fc67cb..bfc138df56bc5e1599341569b1744dd8bb5d3627 100644 (file)
@@ -313,6 +313,83 @@ static int skl_tplg_alloc_pipe_widget(struct device *dev,
        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) {
+               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) {
+                               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)
+                               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
@@ -340,9 +417,15 @@ skl_tplg_init_pipe_modules(struct skl *skl, struct skl_pipe *pipe)
                 * FE/BE params
                 */
                skl_tplg_update_module_params(w, ctx);
+
+               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;
@@ -1215,7 +1298,9 @@ static int skl_tplg_widget_load(struct snd_soc_component *cmpnt,
                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) {
index 0a66fab5982861d51621cbb683791ef717c533e2..51e785424a37a391a7fdf8fb09b68425d06a320e 100644 (file)
@@ -206,6 +206,8 @@ struct skl_module_pin {
 };
 
 struct skl_specific_cfg {
+       bool set_params;
+       u32 param_id;
        u32 caps_size;
        u32 *caps;
 };
@@ -284,6 +286,13 @@ struct skl_module_cfg {
        struct skl_specific_cfg formats_config;
 };
 
+struct skl_algo_data {
+       u32 param_id;
+       bool set_params;
+       u32 max;
+       char *params;
+};
+
 struct skl_pipeline {
        struct skl_pipe *pipe;
        struct list_head node;