Add the switch_get/put control IPC ops for IPC3.
Signed-off-by: Ranjani Sridharan ranjani.sridharan@linux.intel.com Reviewed-by: Péter Ujfalusi peter.ujfalusi@linux.intel.com Reviewed-by: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com --- sound/soc/sof/control.c | 39 +++++++++------------------- sound/soc/sof/ipc3-control.c | 50 ++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 27 deletions(-)
diff --git a/sound/soc/sof/control.c b/sound/soc/sof/control.c index 9eb54b7024b3..f9f8bd37b480 100644 --- a/sound/soc/sof/control.c +++ b/sound/soc/sof/control.c @@ -127,17 +127,14 @@ int snd_sof_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info int snd_sof_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct soc_mixer_control *sm = - (struct soc_mixer_control *)kcontrol->private_value; + struct soc_mixer_control *sm = (struct soc_mixer_control *)kcontrol->private_value; struct snd_sof_control *scontrol = sm->dobj.private; - struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; - unsigned int i, channels = scontrol->num_channels; - - snd_sof_refresh_control(scontrol); + struct snd_soc_component *scomp = scontrol->scomp; + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); + const struct sof_ipc_tplg_ops *tplg_ops = sdev->ipc->ops->tplg;
- /* read back each channel */ - for (i = 0; i < channels; i++) - ucontrol->value.integer.value[i] = cdata->chanv[i].value; + if (tplg_ops->control->switch_get) + return tplg_ops->control->switch_get(scontrol, ucontrol);
return 0; } @@ -145,31 +142,19 @@ int snd_sof_switch_get(struct snd_kcontrol *kcontrol, int snd_sof_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct soc_mixer_control *sm = - (struct soc_mixer_control *)kcontrol->private_value; + struct soc_mixer_control *sm = (struct soc_mixer_control *)kcontrol->private_value; struct snd_sof_control *scontrol = sm->dobj.private; struct snd_soc_component *scomp = scontrol->scomp; - struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; - unsigned int i, channels = scontrol->num_channels; - bool change = false; - u32 value; - - /* update each channel */ - for (i = 0; i < channels; i++) { - value = ucontrol->value.integer.value[i]; - change = change || (value != cdata->chanv[i].value); - cdata->chanv[i].channel = i; - cdata->chanv[i].value = value; - } + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); + const struct sof_ipc_tplg_ops *tplg_ops = sdev->ipc->ops->tplg;
if (scontrol->led_ctl.use_led) update_mute_led(scontrol, kcontrol, ucontrol);
- /* notify DSP of mixer updates */ - if (pm_runtime_active(scomp->dev)) - snd_sof_ipc_set_get_comp_data(scontrol, true); + if (tplg_ops->control->switch_put) + return tplg_ops->control->switch_put(scontrol, ucontrol);
- return change; + return false; }
int snd_sof_enum_get(struct snd_kcontrol *kcontrol, diff --git a/sound/soc/sof/ipc3-control.c b/sound/soc/sof/ipc3-control.c index 12aeb3ae4e52..ba9cde011b5a 100644 --- a/sound/soc/sof/ipc3-control.c +++ b/sound/soc/sof/ipc3-control.c @@ -109,6 +109,54 @@ static bool sof_ipc3_volume_put(struct snd_sof_control *scontrol, return change; }
+static int sof_ipc3_switch_get(struct snd_sof_control *scontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; + unsigned int channels = scontrol->num_channels; + unsigned int i; + + snd_sof_refresh_control(scontrol); + + /* read back each channel */ + for (i = 0; i < channels; i++) + ucontrol->value.integer.value[i] = cdata->chanv[i].value; + + return 0; +} + +static bool sof_ipc3_switch_put(struct snd_sof_control *scontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; + struct snd_soc_component *scomp = scontrol->scomp; + unsigned int channels = scontrol->num_channels; + unsigned int i; + bool change = false; + u32 value; + + /* update each channel */ + for (i = 0; i < channels; i++) { + value = ucontrol->value.integer.value[i]; + change = change || (value != cdata->chanv[i].value); + cdata->chanv[i].channel = i; + cdata->chanv[i].value = value; + } + + /* notify DSP of mixer updates */ + if (pm_runtime_active(scomp->dev)) { + int ret = snd_sof_ipc_set_get_comp_data(scontrol, true); + + if (ret < 0) { + dev_err(scomp->dev, "Failed to set mixer updates for %s\n", + scontrol->name); + return false; + } + } + + return change; +} + static void snd_sof_update_control(struct snd_sof_control *scontrol, struct sof_ipc_ctrl_data *cdata) { @@ -252,5 +300,7 @@ static void sof_ipc3_control_update(struct snd_sof_dev *sdev, void *ipc_control_ const struct sof_ipc_tplg_control_ops tplg_ipc3_control_ops = { .volume_put = sof_ipc3_volume_put, .volume_get = sof_ipc3_volume_get, + .switch_put = sof_ipc3_switch_put, + .switch_get = sof_ipc3_switch_get, .update = sof_ipc3_control_update, };