Skip to content

Commit

Permalink
ASoC: SOF: partition audio-specific parts from the SOF core
Browse files Browse the repository at this point in the history
This patch makes elaborate changes to the SOF core device
structure and IPC RX/TX. At the high-level, the changes fall
into 3 main categories:

Audio-related members in the struct snd_sof_dev:
These are now partiioned into struct sof_audio_dev that is created
, maintained and used by the audio client. Along with these,
all the other topology related structs for such as snd_sof_widget,
snd_sof_route etc have all been moved to sof-audio.h. The snd_sof_dev
member in all the topology related structs has been replaced
with a member that represents the component driver that creates
the topology. The sof_audio_dev handle that is created by the audio
client is stored as private data in the MFD client struct but the
core should never touch this.

IPC TX/RX for MFD clients:
IPC TX/RX for MFD clients can be performed by calling the
sof_client_tx_message() API. If the clients want to receive
IPC's from the DSP, they should register for the type of IPC's
they'd like to receive.

Audio-specific PM sequence:
Previously, when the PCI device was resumed, the topology
was reconstructed in its resume callback. But this will now
be handled by the audio client device's resume callback. Also,
the audio client's suspend callback should handle suspending
streams.

Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
  • Loading branch information
ranj063 committed Sep 28, 2019
1 parent 8e3acba commit d72d3d1
Show file tree
Hide file tree
Showing 17 changed files with 1,299 additions and 1,121 deletions.
85 changes: 38 additions & 47 deletions sound/soc/sof/control.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

#include <linux/pm_runtime.h>
#include "sof-priv.h"
#include "sof-audio.h"

static inline u32 mixer_to_ipc(unsigned int value, u32 *volume_map, int size)
{
Expand Down Expand Up @@ -57,7 +58,7 @@ int snd_sof_volume_put(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 snd_soc_component *scomp = scontrol->scomp;
struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
unsigned int i, channels = scontrol->num_channels;

Expand All @@ -70,12 +71,10 @@ int snd_sof_volume_put(struct snd_kcontrol *kcontrol,
}

/* notify DSP of mixer updates */
if (pm_runtime_active(sdev->dev))
snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol,
SOF_IPC_COMP_SET_VALUE,
SOF_CTRL_TYPE_VALUE_CHAN_GET,
SOF_CTRL_CMD_VOLUME,
true);
snd_sof_ipc_set_get_comp_data(scomp, scontrol,
SOF_IPC_COMP_SET_VALUE,
SOF_CTRL_TYPE_VALUE_CHAN_GET,
SOF_CTRL_CMD_VOLUME, true);

return 0;
}
Expand All @@ -102,7 +101,7 @@ int snd_sof_switch_put(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 snd_soc_component *scomp = scontrol->scomp;
struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
unsigned int i, channels = scontrol->num_channels;

Expand All @@ -113,12 +112,10 @@ int snd_sof_switch_put(struct snd_kcontrol *kcontrol,
}

/* notify DSP of mixer updates */
if (pm_runtime_active(sdev->dev))
snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol,
SOF_IPC_COMP_SET_VALUE,
SOF_CTRL_TYPE_VALUE_CHAN_GET,
SOF_CTRL_CMD_SWITCH,
true);
snd_sof_ipc_set_get_comp_data(scomp, scontrol,
SOF_IPC_COMP_SET_VALUE,
SOF_CTRL_TYPE_VALUE_CHAN_GET,
SOF_CTRL_CMD_SWITCH, true);

return 0;
}
Expand All @@ -145,7 +142,7 @@ int snd_sof_enum_put(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 snd_soc_component *scomp = scontrol->scomp;
struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
unsigned int i, channels = scontrol->num_channels;

Expand All @@ -156,12 +153,10 @@ int snd_sof_enum_put(struct snd_kcontrol *kcontrol,
}

/* notify DSP of enum updates */
if (pm_runtime_active(sdev->dev))
snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol,
SOF_IPC_COMP_SET_VALUE,
SOF_CTRL_TYPE_VALUE_CHAN_GET,
SOF_CTRL_CMD_ENUM,
true);
snd_sof_ipc_set_get_comp_data(scomp, scontrol,
SOF_IPC_COMP_SET_VALUE,
SOF_CTRL_TYPE_VALUE_CHAN_GET,
SOF_CTRL_CMD_ENUM, true);

return 0;
}
Expand All @@ -172,22 +167,22 @@ int snd_sof_bytes_get(struct snd_kcontrol *kcontrol,
struct soc_bytes_ext *be =
(struct soc_bytes_ext *)kcontrol->private_value;
struct snd_sof_control *scontrol = be->dobj.private;
struct snd_sof_dev *sdev = scontrol->sdev;
struct snd_soc_component *scomp = scontrol->scomp;
struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
struct sof_abi_hdr *data = cdata->data;
size_t size;
int ret = 0;

if (be->max > sizeof(ucontrol->value.bytes.data)) {
dev_err_ratelimited(sdev->dev,
dev_err_ratelimited(scomp->dev,
"error: data max %d exceeds ucontrol data array size\n",
be->max);
return -EINVAL;
}

size = data->size + sizeof(*data);
if (size > be->max) {
dev_err_ratelimited(sdev->dev,
dev_err_ratelimited(scomp->dev,
"error: DSP sent %zu bytes max is %d\n",
size, be->max);
ret = -EINVAL;
Expand All @@ -207,20 +202,20 @@ int snd_sof_bytes_put(struct snd_kcontrol *kcontrol,
struct soc_bytes_ext *be =
(struct soc_bytes_ext *)kcontrol->private_value;
struct snd_sof_control *scontrol = be->dobj.private;
struct snd_sof_dev *sdev = scontrol->sdev;
struct snd_soc_component *scomp = scontrol->scomp;
struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
struct sof_abi_hdr *data = cdata->data;
size_t size = data->size + sizeof(*data);

if (be->max > sizeof(ucontrol->value.bytes.data)) {
dev_err_ratelimited(sdev->dev,
dev_err_ratelimited(scomp->dev,
"error: data max %d exceeds ucontrol data array size\n",
be->max);
return -EINVAL;
}

if (size > be->max) {
dev_err_ratelimited(sdev->dev,
dev_err_ratelimited(scomp->dev,
"error: size too big %zu bytes max is %d\n",
size, be->max);
return -EINVAL;
Expand All @@ -230,12 +225,10 @@ int snd_sof_bytes_put(struct snd_kcontrol *kcontrol,
memcpy(data, ucontrol->value.bytes.data, size);

/* notify DSP of byte control updates */
if (pm_runtime_active(sdev->dev))
snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol,
SOF_IPC_COMP_SET_DATA,
SOF_CTRL_TYPE_DATA_SET,
scontrol->cmd,
true);
snd_sof_ipc_set_get_comp_data(scomp, scontrol,
SOF_IPC_COMP_SET_DATA,
SOF_CTRL_TYPE_DATA_SET,
scontrol->cmd, true);

return 0;
}
Expand All @@ -247,7 +240,7 @@ int snd_sof_bytes_ext_put(struct snd_kcontrol *kcontrol,
struct soc_bytes_ext *be =
(struct soc_bytes_ext *)kcontrol->private_value;
struct snd_sof_control *scontrol = be->dobj.private;
struct snd_sof_dev *sdev = scontrol->sdev;
struct snd_soc_component *scomp = scontrol->scomp;
struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
struct snd_ctl_tlv header;
const struct snd_ctl_tlv __user *tlvd =
Expand All @@ -263,14 +256,14 @@ int snd_sof_bytes_ext_put(struct snd_kcontrol *kcontrol,

/* be->max is coming from topology */
if (header.length > be->max) {
dev_err_ratelimited(sdev->dev, "error: Bytes data size %d exceeds max %d.\n",
dev_err_ratelimited(scomp->dev, "error: Bytes data size %d exceeds max %d.\n",
header.length, be->max);
return -EINVAL;
}

/* Check that header id matches the command */
if (header.numid != scontrol->cmd) {
dev_err_ratelimited(sdev->dev,
dev_err_ratelimited(scomp->dev,
"error: incorrect numid %d\n",
header.numid);
return -EINVAL;
Expand All @@ -280,30 +273,28 @@ int snd_sof_bytes_ext_put(struct snd_kcontrol *kcontrol,
return -EFAULT;

if (cdata->data->magic != SOF_ABI_MAGIC) {
dev_err_ratelimited(sdev->dev,
dev_err_ratelimited(scomp->dev,
"error: Wrong ABI magic 0x%08x.\n",
cdata->data->magic);
return -EINVAL;
}

if (SOF_ABI_VERSION_INCOMPATIBLE(SOF_ABI_VERSION, cdata->data->abi)) {
dev_err_ratelimited(sdev->dev, "error: Incompatible ABI version 0x%08x.\n",
dev_err_ratelimited(scomp->dev, "error: Incompatible ABI version 0x%08x.\n",
cdata->data->abi);
return -EINVAL;
}

if (cdata->data->size + sizeof(const struct sof_abi_hdr) > be->max) {
dev_err_ratelimited(sdev->dev, "error: Mismatch in ABI data size (truncated?).\n");
dev_err_ratelimited(scomp->dev, "error: Mismatch in ABI data size (truncated?).\n");
return -EINVAL;
}

/* notify DSP of byte control updates */
if (pm_runtime_active(sdev->dev))
snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol,
SOF_IPC_COMP_SET_DATA,
SOF_CTRL_TYPE_DATA_SET,
scontrol->cmd,
true);
snd_sof_ipc_set_get_comp_data(scomp, scontrol,
SOF_IPC_COMP_SET_DATA,
SOF_CTRL_TYPE_DATA_SET,
scontrol->cmd, true);

return 0;
}
Expand All @@ -315,7 +306,7 @@ int snd_sof_bytes_ext_get(struct snd_kcontrol *kcontrol,
struct soc_bytes_ext *be =
(struct soc_bytes_ext *)kcontrol->private_value;
struct snd_sof_control *scontrol = be->dobj.private;
struct snd_sof_dev *sdev = scontrol->sdev;
struct snd_soc_component *scomp = scontrol->scomp;
struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
struct snd_ctl_tlv header;
struct snd_ctl_tlv __user *tlvd =
Expand All @@ -338,7 +329,7 @@ int snd_sof_bytes_ext_get(struct snd_kcontrol *kcontrol,

/* check data size doesn't exceed max coming from topology */
if (data_size > be->max) {
dev_err_ratelimited(sdev->dev, "error: user data size %d exceeds max size %d.\n",
dev_err_ratelimited(scomp->dev, "error: user data size %d exceeds max size %d.\n",
data_size, be->max);
ret = -EINVAL;
goto out;
Expand Down

0 comments on commit d72d3d1

Please sign in to comment.