From a0d667822f2fa885ae3cce3c629361c470de18d2 Mon Sep 17 00:00:00 2001 From: Bard liao Date: Fri, 28 Sep 2018 09:50:21 +0800 Subject: [PATCH] ASoC: SOF: dont wake dsp up in kcontrol set/get Cache the kcontrol value in host. Always get kcontrol value from cache, set kcontrol value to DSP when DSP is active. Kcontrol values will be restored when DSP is boot. Signed-off-by: Bard liao --- sound/soc/sof/control.c | 119 ++++++--------------------------------- sound/soc/sof/topology.c | 44 +++++++++++++++ 2 files changed, 61 insertions(+), 102 deletions(-) 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 */