diff --git a/sound/soc/sof/control.c b/sound/soc/sof/control.c index 6f73041760f861..3d9a042a0b0314 100644 --- a/sound/soc/sof/control.c +++ b/sound/soc/sof/control.c @@ -46,22 +46,8 @@ int snd_sof_volume_get(struct snd_kcontrol *kcontrol, struct soc_mixer_control *sm = (struct soc_mixer_control *)kcontrol->private_value; struct snd_sof_control *scontrol = sm->dobj.private; - struct snd_sof_dev *sdev = scontrol->sdev; struct sof_ipc_ctrl_data *cdata = scontrol->control_data; unsigned int i, channels = scontrol->num_channels; - int err, ret; - - ret = pm_runtime_get_sync(sdev->dev); - if (ret < 0) { - dev_err(sdev->dev, "error: volume get failed to resume %d\n", - ret); - return ret; - } - - /* get all the mixer data from DSP */ - snd_sof_ipc_get_comp_data(sdev->ipc, scontrol, SOF_IPC_COMP_GET_VALUE, - SOF_CTRL_TYPE_VALUE_CHAN_GET, - SOF_CTRL_CMD_VOLUME); /* read back each channel */ for (i = 0; i < channels; i++) @@ -69,11 +55,6 @@ int snd_sof_volume_get(struct snd_kcontrol *kcontrol, ipc_to_mixer(cdata->chanv[i].value, scontrol->volume_table, sm->max + 1); - pm_runtime_mark_last_busy(sdev->dev); - err = pm_runtime_put_autosuspend(sdev->dev); - if (err < 0) - dev_err(sdev->dev, "error: volume get failed to idle %d\n", - err); return 0; } @@ -86,14 +67,6 @@ int snd_sof_volume_put(struct snd_kcontrol *kcontrol, struct snd_sof_dev *sdev = scontrol->sdev; struct sof_ipc_ctrl_data *cdata = scontrol->control_data; unsigned int i, channels = scontrol->num_channels; - int ret, err; - - ret = pm_runtime_get_sync(sdev->dev); - if (ret < 0) { - dev_err(sdev->dev, "error: volume put failed to resume %d\n", - ret); - return ret; - } /* update each channel */ for (i = 0; i < channels; i++) { @@ -104,15 +77,11 @@ int snd_sof_volume_put(struct snd_kcontrol *kcontrol, } /* notify DSP of mixer updates */ - snd_sof_ipc_set_comp_data(sdev->ipc, scontrol, SOF_IPC_COMP_SET_VALUE, - SOF_CTRL_TYPE_VALUE_CHAN_GET, - SOF_CTRL_CMD_VOLUME); - - pm_runtime_mark_last_busy(sdev->dev); - err = pm_runtime_put_autosuspend(sdev->dev); - if (err < 0) - dev_err(sdev->dev, "error: volume put failed to idle %d\n", - err); + if (sdev->dev->power.runtime_status == RPM_ACTIVE) + snd_sof_ipc_set_comp_data(sdev->ipc, scontrol, + SOF_IPC_COMP_SET_VALUE, + SOF_CTRL_TYPE_VALUE_CHAN_GET, + SOF_CTRL_CMD_VOLUME); return 0; } @@ -122,32 +91,13 @@ int snd_sof_enum_get(struct snd_kcontrol *kcontrol, struct soc_enum *se = (struct soc_enum *)kcontrol->private_value; struct snd_sof_control *scontrol = se->dobj.private; - struct snd_sof_dev *sdev = scontrol->sdev; struct sof_ipc_ctrl_data *cdata = scontrol->control_data; unsigned int i, channels = scontrol->num_channels; - int err, ret; - - ret = pm_runtime_get_sync(sdev->dev); - if (ret < 0) { - dev_err(sdev->dev, "error: enum get failed to resume %d\n", - ret); - return ret; - } - - /* get all the mixer data from DSP */ - snd_sof_ipc_get_comp_data(sdev->ipc, scontrol, SOF_IPC_COMP_GET_VALUE, - SOF_CTRL_TYPE_VALUE_CHAN_GET, - SOF_CTRL_CMD_ENUM); /* read back each channel */ for (i = 0; i < channels; i++) ucontrol->value.integer.value[i] = cdata->chanv[i].value; - pm_runtime_mark_last_busy(sdev->dev); - err = pm_runtime_put_autosuspend(sdev->dev); - if (err < 0) - dev_err(sdev->dev, "error: enum get failed to idle %d\n", - ret); return 0; } @@ -160,29 +110,18 @@ int snd_sof_enum_put(struct snd_kcontrol *kcontrol, struct snd_sof_dev *sdev = scontrol->sdev; struct sof_ipc_ctrl_data *cdata = scontrol->control_data; unsigned int i, channels = scontrol->num_channels; - int ret, err; - - ret = pm_runtime_get_sync(sdev->dev); - if (ret < 0) { - dev_err(sdev->dev, "error: enum put failed to resume %d\n", - ret); - return ret; - } /* update each channel */ for (i = 0; i < channels; i++) cdata->chanv[i].value = ucontrol->value.integer.value[i]; /* notify DSP of mixer updates */ - snd_sof_ipc_set_comp_data(sdev->ipc, scontrol, SOF_IPC_COMP_SET_VALUE, - SOF_CTRL_TYPE_VALUE_CHAN_SET, - SOF_CTRL_CMD_ENUM); + if (sdev->dev->power.runtime_status == RPM_ACTIVE) + snd_sof_ipc_set_comp_data(sdev->ipc, scontrol, + SOF_IPC_COMP_SET_VALUE, + SOF_CTRL_TYPE_VALUE_CHAN_SET, + SOF_CTRL_CMD_ENUM); - pm_runtime_mark_last_busy(sdev->dev); - err = pm_runtime_put_autosuspend(sdev->dev); - if (err < 0) - dev_err(sdev->dev, "error: enum put failed to idle %d\n", - err); return 0; } @@ -196,18 +135,8 @@ int snd_sof_bytes_get(struct snd_kcontrol *kcontrol, struct sof_ipc_ctrl_data *cdata = scontrol->control_data; struct sof_abi_hdr *data = cdata->data; size_t size; - int ret, err; - - ret = pm_runtime_get_sync(sdev->dev); - if (ret < 0) { - dev_err(sdev->dev, "error: bytes get failed to resume %d\n", - ret); - return ret; - } + int ret; - /* get all the mixer data from DSP */ - snd_sof_ipc_get_comp_data(sdev->ipc, scontrol, SOF_IPC_COMP_GET_DATA, - SOF_CTRL_TYPE_DATA_GET, scontrol->cmd); size = data->size + sizeof(*data); if (size > be->max) { dev_err(sdev->dev, "error: DSP sent %zu bytes max is %d\n", @@ -220,11 +149,6 @@ int snd_sof_bytes_get(struct snd_kcontrol *kcontrol, memcpy(ucontrol->value.bytes.data, data, size); out: - pm_runtime_mark_last_busy(sdev->dev); - err = pm_runtime_put_autosuspend(sdev->dev); - if (err < 0) - dev_err(sdev->dev, "error: bytes get failed to idle %d\n", - err); return ret; } @@ -237,14 +161,7 @@ int snd_sof_bytes_put(struct snd_kcontrol *kcontrol, struct snd_sof_dev *sdev = scontrol->sdev; struct sof_ipc_ctrl_data *cdata = scontrol->control_data; struct sof_abi_hdr *data = cdata->data; - int ret, err; - - ret = pm_runtime_get_sync(sdev->dev); - if (ret < 0) { - dev_err(sdev->dev, "error: bytes put failed to resume %d\n", - ret); - return ret; - } + int ret; if (data->size > be->max) { dev_err(sdev->dev, "error: size too big %d bytes max is %d\n", @@ -257,15 +174,13 @@ int snd_sof_bytes_put(struct snd_kcontrol *kcontrol, memcpy(data, ucontrol->value.bytes.data, data->size); /* notify DSP of mixer updates */ - snd_sof_ipc_set_comp_data(sdev->ipc, scontrol, SOF_IPC_COMP_SET_DATA, - SOF_CTRL_TYPE_DATA_SET, scontrol->cmd); + if (sdev->dev->power.runtime_status == RPM_ACTIVE) + snd_sof_ipc_set_comp_data(sdev->ipc, scontrol, + SOF_IPC_COMP_SET_DATA, + SOF_CTRL_TYPE_DATA_SET, + scontrol->cmd); out: - pm_runtime_mark_last_busy(sdev->dev); - err = pm_runtime_put_autosuspend(sdev->dev); - if (err < 0) - dev_err(sdev->dev, "error: volume get failed to idle %d\n", - err); return ret; } diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index 976b01c3e8fae0..b394e846c80052 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -285,6 +285,7 @@ static int sof_control_load_volume(struct snd_soc_component *scomp, scontrol->comp_id = sdev->next_comp_id; scontrol->num_channels = le32_to_cpu(mc->num_channels); + dev_dbg(sdev->dev, "tplg: load kcontrol index %d chans %d\n", scontrol->comp_id, scontrol->num_channels); @@ -2362,6 +2363,48 @@ int snd_sof_complete_pipeline(struct snd_sof_dev *sdev, return 1; } +static int snd_sof_get_kcontrol_val(struct snd_sof_dev *sdev) +{ + struct snd_sof_control *scontrol = NULL; + int ipc_cmd, ctrl_type; + int ret = 0; + + list_for_each_entry(scontrol, &sdev->kcontrol_list, list) { + + /* notify DSP of kcontrol values */ + switch (scontrol->cmd) { + case SOF_CTRL_CMD_VOLUME: + case SOF_CTRL_CMD_ENUM: + ipc_cmd = SOF_IPC_COMP_GET_VALUE; + ctrl_type = SOF_CTRL_TYPE_VALUE_CHAN_GET; + ret = snd_sof_ipc_get_comp_data(sdev->ipc, scontrol, + ipc_cmd, ctrl_type, + scontrol->cmd); + break; + case SOF_CTRL_CMD_BINARY: + ipc_cmd = SOF_IPC_COMP_GET_DATA; + ctrl_type = SOF_CTRL_TYPE_DATA_GET; + ret = snd_sof_ipc_get_comp_data(sdev->ipc, scontrol, + ipc_cmd, ctrl_type, + scontrol->cmd); + break; + + default: + dev_err(sdev->dev, + "error: Invalid scontrol->cmd: %d\n", + scontrol->cmd); + return -EINVAL; + } + if (ret < 0) { + dev_warn(sdev->dev, + "error: failed kcontrol value get for widget: %d\n", + scontrol->comp_id); + } + } + + return ret; +} + /* completion - called at completion of firmware loading */ static void sof_complete(struct snd_soc_component *scomp) { @@ -2382,6 +2425,7 @@ static void sof_complete(struct snd_soc_component *scomp) break; } } + snd_sof_get_kcontrol_val(sdev); } /* manifest - optional to inform component of manifest */