diff --git a/sound/soc/sof/control.c b/sound/soc/sof/control.c index 7b72361c3baee1..2daf55fe79b1b9 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 (pm_runtime_active(sdev->dev)) + 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); - - 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); + if (pm_runtime_active(sdev->dev)) + snd_sof_ipc_set_comp_data(sdev->ipc, scontrol, + SOF_IPC_COMP_SET_VALUE, + SOF_CTRL_TYPE_VALUE_CHAN_SET, + SOF_CTRL_CMD_ENUM); + 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 = 0; - /* 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 = 0; 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 (pm_runtime_active(sdev->dev)) + 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; } @@ -280,19 +195,11 @@ int snd_sof_bytes_ext_put(struct snd_kcontrol *kcontrol, struct sof_ipc_ctrl_data *cdata = scontrol->control_data; struct snd_ctl_tlv header; struct snd_ctl_tlv *tlvd = (struct snd_ctl_tlv *)binary_data; - int ret; - int err; + int ret = 0; int max_length = SOF_IPC_MSG_MAX_SIZE - sizeof(const struct sof_ipc_ctrl_data) - sizeof(const struct sof_abi_hdr); - 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; - } - /* The beginning of bytes data contains a header from where * the length (as bytes) is needed to know the correct copy * length of data from tlvd->tlv. @@ -330,15 +237,13 @@ int snd_sof_bytes_ext_put(struct snd_kcontrol *kcontrol, cdata->data->comp_abi = SOF_ABI_VERSION; /* 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 (pm_runtime_active(sdev->dev)) + 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: failed to idle %d\n", err); - return ret; } @@ -356,14 +261,7 @@ int snd_sof_bytes_ext_get(struct snd_kcontrol *kcontrol, int max_length = SOF_IPC_MSG_MAX_SIZE - sizeof(const struct sof_ipc_ctrl_data) - sizeof(const struct sof_abi_hdr); - int ret; - - 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 = 0; /* Decrement size to fit the ext bytes header and get the the * upper limit from ext bytes control size from topology and @@ -388,11 +286,6 @@ int snd_sof_bytes_ext_get(struct snd_kcontrol *kcontrol, cdata->data->abi = SOF_ABI_VERSION; cdata->data->comp_abi = SOF_ABI_VERSION; - /* get all the component data from DSP */ - ret = snd_sof_ipc_get_comp_data(sdev->ipc, scontrol, - SOF_IPC_COMP_GET_DATA, - SOF_CTRL_TYPE_DATA_GET, scontrol->cmd); - header.numid = scontrol->cmd; header.length = size; if (copy_to_user(tlvd, &header, sizeof(const struct snd_ctl_tlv))) @@ -402,7 +295,5 @@ int snd_sof_bytes_ext_get(struct snd_kcontrol *kcontrol, return -EFAULT; out: - pm_runtime_mark_last_busy(sdev->dev); - pm_runtime_put_autosuspend(sdev->dev); return ret; } diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index 02ef68d64a8092..780607a0af68cc 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -2360,6 +2360,51 @@ int snd_sof_complete_pipeline(struct snd_sof_dev *sdev, return 1; } +/* Function to read the initial value of SOF kcontrols. + * The value will be stored in scontrol->control_data + */ +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: 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) { @@ -2380,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 */