ASoC: SOF: Add widget_kcontrol_setup control ops for IPC3
authorPeter Ujfalusi <peter.ujfalusi@linux.intel.com>
Tue, 5 Apr 2022 17:27:06 +0000 (10:27 -0700)
committerMark Brown <broonie@kernel.org>
Mon, 11 Apr 2022 18:18:00 +0000 (19:18 +0100)
Define and set the widget_kcontrol_setup control IPC ops for IPC3.

The widget_kcontrol_setup callback can be used to set up all
kcontrols associated with the swidget.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Reviewed-by: Daniel Baluta <daniel.baluta@nxp.com>
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
Link: https://lore.kernel.org/r/20220405172708.122168-14-ranjani.sridharan@linux.intel.com
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/sof/ipc3-control.c
sound/soc/sof/sof-audio.h

index cdd5ad8..4e64714 100644 (file)
@@ -578,6 +578,43 @@ static void sof_ipc3_control_update(struct snd_sof_dev *sdev, void *ipc_control_
        snd_ctl_notify_one(swidget->scomp->card->snd_card, SNDRV_CTL_EVENT_MASK_VALUE, kc, 0);
 }
 
+static int sof_ipc3_widget_kcontrol_setup(struct snd_sof_dev *sdev,
+                                         struct snd_sof_widget *swidget)
+{
+       struct snd_sof_control *scontrol;
+       int ret;
+
+       /* set up all controls for the widget */
+       list_for_each_entry(scontrol, &sdev->kcontrol_list, list)
+               if (scontrol->comp_id == swidget->comp_id) {
+                       /* set kcontrol data in DSP */
+                       ret = snd_sof_ipc_set_get_comp_data(scontrol, true);
+                       if (ret < 0) {
+                               dev_err(sdev->dev,
+                                       "kcontrol %d set up failed for widget %s\n",
+                                       scontrol->comp_id, swidget->widget->name);
+                               return ret;
+                       }
+
+                       /*
+                        * Read back the data from the DSP for static widgets.
+                        * This is particularly useful for binary kcontrols
+                        * associated with static pipeline widgets to initialize
+                        * the data size to match that in the DSP.
+                        */
+                       if (swidget->dynamic_pipeline_widget)
+                               continue;
+
+                       ret = snd_sof_ipc_set_get_comp_data(scontrol, false);
+                       if (ret < 0)
+                               dev_warn(sdev->dev,
+                                        "kcontrol %d read failed for widget %s\n",
+                                        scontrol->comp_id, swidget->widget->name);
+               }
+
+       return 0;
+}
+
 const struct sof_ipc_tplg_control_ops tplg_ipc3_control_ops = {
        .volume_put = sof_ipc3_volume_put,
        .volume_get = sof_ipc3_volume_get,
@@ -591,4 +628,5 @@ const struct sof_ipc_tplg_control_ops tplg_ipc3_control_ops = {
        .bytes_ext_get = sof_ipc3_bytes_ext_get,
        .bytes_ext_volatile_get = sof_ipc3_bytes_ext_volatile_get,
        .update = sof_ipc3_control_update,
+       .widget_kcontrol_setup = sof_ipc3_widget_kcontrol_setup,
 };
index 4a8cd7f..c85461d 100644 (file)
@@ -86,6 +86,8 @@ struct sof_ipc_tplg_control_ops {
                             const unsigned int __user *binary_data, unsigned int size);
        /* update control data based on notification from the DSP */
        void (*update)(struct snd_sof_dev *sdev, void *ipc_control_message);
+       /* Optional callback to setup kcontrols associated with an swidget */
+       int (*widget_kcontrol_setup)(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget);
 };
 
 /**