Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
119 changes: 17 additions & 102 deletions sound/soc/sof/control.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,34 +46,15 @@ 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++)
ucontrol->value.integer.value[i] =
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;
}

Expand All @@ -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++) {
Expand All @@ -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;
}

Expand All @@ -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;
}

Expand All @@ -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;
}

Expand All @@ -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",
Expand All @@ -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;
}

Expand All @@ -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",
Expand All @@ -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;
}

Expand Down
44 changes: 44 additions & 0 deletions sound/soc/sof/topology.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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)
{
Expand All @@ -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 */
Expand Down