summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/sound/sof/dai.h5
-rw-r--r--include/sound/sof/topology.h8
-rw-r--r--sound/soc/sof/intel/hda-dai.c27
-rw-r--r--sound/soc/sof/intel/hda.c39
-rw-r--r--sound/soc/sof/ipc.c12
-rw-r--r--sound/soc/sof/pcm.c77
-rw-r--r--sound/soc/sof/sof-audio.c45
-rw-r--r--sound/soc/sof/sof-audio.h21
-rw-r--r--sound/soc/sof/sof-priv.h12
-rw-r--r--sound/soc/sof/topology.c200
10 files changed, 267 insertions, 179 deletions
diff --git a/include/sound/sof/dai.h b/include/sound/sof/dai.h
index 59ee50ac7705..a818a0f0a226 100644
--- a/include/sound/sof/dai.h
+++ b/include/sound/sof/dai.h
@@ -116,4 +116,9 @@ struct sof_ipc_dai_config {
};
} __packed;
+struct sof_dai_private_data {
+ struct sof_ipc_comp_dai *comp_dai;
+ struct sof_ipc_dai_config *dai_config;
+};
+
#endif
diff --git a/include/sound/sof/topology.h b/include/sound/sof/topology.h
index adee6afd1490..88560281d420 100644
--- a/include/sound/sof/topology.h
+++ b/include/sound/sof/topology.h
@@ -87,9 +87,6 @@ struct sof_ipc_comp {
*/
#define SOF_BUF_UNDERRUN_PERMITTED BIT(1)
-/* the UUID size in bytes, shared between FW and host */
-#define SOF_UUID_SIZE 16
-
/* create new component buffer - SOF_IPC_TPLG_BUFFER_NEW */
struct sof_ipc_buffer {
struct sof_ipc_comp comp;
@@ -303,9 +300,4 @@ enum sof_event_types {
SOF_KEYWORD_DETECT_DAPM_EVENT,
};
-/* extended data struct for UUID components */
-struct sof_ipc_comp_ext {
- uint8_t uuid[SOF_UUID_SIZE];
-} __packed;
-
#endif
diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c
index 75063140ed0c..9b78eea8d76b 100644
--- a/sound/soc/sof/intel/hda-dai.c
+++ b/sound/soc/sof/intel/hda-dai.c
@@ -167,6 +167,7 @@ static struct sof_ipc_dai_config *hda_dai_update_config(struct snd_soc_dapm_widg
int channel)
{
struct snd_sof_widget *swidget = w->dobj.private;
+ struct sof_dai_private_data *private;
struct sof_ipc_dai_config *config;
struct snd_sof_dai *sof_dai;
@@ -175,12 +176,19 @@ static struct sof_ipc_dai_config *hda_dai_update_config(struct snd_soc_dapm_widg
sof_dai = swidget->private;
- if (!sof_dai || !sof_dai->dai_config) {
- dev_err(swidget->scomp->dev, "error: No config for DAI %s\n", w->name);
+ if (!sof_dai || !sof_dai->private) {
+ dev_err(swidget->scomp->dev, "%s: No private data for DAI %s\n", __func__,
+ w->name);
return NULL;
}
- config = &sof_dai->dai_config[sof_dai->current_config];
+ private = sof_dai->private;
+ if (!private->dai_config) {
+ dev_err(swidget->scomp->dev, "%s: No config for DAI %s\n", __func__, w->name);
+ return NULL;
+ }
+
+ config = &private->dai_config[sof_dai->current_config];
/* update config with stream tag */
config->hda.link_dma_ch = channel;
@@ -294,6 +302,7 @@ static int hda_link_dai_config_pause_push_ipc(struct snd_soc_dapm_widget *w)
struct snd_sof_widget *swidget = w->dobj.private;
struct snd_soc_component *component = swidget->scomp;
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
+ struct sof_dai_private_data *private;
struct sof_ipc_dai_config *config;
struct snd_sof_dai *sof_dai;
struct sof_ipc_reply reply;
@@ -301,12 +310,18 @@ static int hda_link_dai_config_pause_push_ipc(struct snd_soc_dapm_widget *w)
sof_dai = swidget->private;
- if (!sof_dai || !sof_dai->dai_config) {
- dev_err(sdev->dev, "No config for DAI %s\n", w->name);
+ if (!sof_dai || !sof_dai->private) {
+ dev_err(sdev->dev, "%s: No private data for DAI %s\n", __func__, w->name);
+ return -EINVAL;
+ }
+
+ private = sof_dai->private;
+ if (!private->dai_config) {
+ dev_err(sdev->dev, "%s: No config for DAI %s\n", __func__, w->name);
return -EINVAL;
}
- config = &sof_dai->dai_config[sof_dai->current_config];
+ config = &private->dai_config[sof_dai->current_config];
/* set PAUSE command flag */
config->flags = FIELD_PREP(SOF_DAI_CONFIG_FLAGS_CMD_MASK, SOF_DAI_CONFIG_FLAGS_PAUSE);
diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c
index 07d8686632a5..7403b9848a56 100644
--- a/sound/soc/sof/intel/hda.c
+++ b/sound/soc/sof/intel/hda.c
@@ -47,14 +47,21 @@ int hda_ctrl_dai_widget_setup(struct snd_soc_dapm_widget *w, unsigned int quirk_
struct snd_soc_component *component = swidget->scomp;
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
struct sof_ipc_dai_config *config;
+ struct sof_dai_private_data *private;
struct snd_sof_dai *sof_dai;
struct sof_ipc_reply reply;
int ret;
sof_dai = swidget->private;
- if (!sof_dai || !sof_dai->dai_config) {
- dev_err(sdev->dev, "No config for DAI %s\n", w->name);
+ if (!sof_dai || !sof_dai->private) {
+ dev_err(sdev->dev, "%s: No private data for DAI %s\n", __func__, w->name);
+ return -EINVAL;
+ }
+
+ private = sof_dai->private;
+ if (!private->dai_config) {
+ dev_err(sdev->dev, "%s: No config for DAI %s\n", __func__, w->name);
return -EINVAL;
}
@@ -65,7 +72,7 @@ int hda_ctrl_dai_widget_setup(struct snd_soc_dapm_widget *w, unsigned int quirk_
return ret;
}
- config = &sof_dai->dai_config[sof_dai->current_config];
+ config = &private->dai_config[sof_dai->current_config];
/*
* For static pipelines, the DAI widget would already be set up and calling
@@ -101,6 +108,7 @@ int hda_ctrl_dai_widget_free(struct snd_soc_dapm_widget *w, unsigned int quirk_f
struct snd_sof_widget *swidget = w->dobj.private;
struct snd_soc_component *component = swidget->scomp;
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
+ struct sof_dai_private_data *private;
struct sof_ipc_dai_config *config;
struct snd_sof_dai *sof_dai;
struct sof_ipc_reply reply;
@@ -108,8 +116,14 @@ int hda_ctrl_dai_widget_free(struct snd_soc_dapm_widget *w, unsigned int quirk_f
sof_dai = swidget->private;
- if (!sof_dai || !sof_dai->dai_config) {
- dev_err(sdev->dev, "error: No config to free DAI %s\n", w->name);
+ if (!sof_dai || !sof_dai->private) {
+ dev_err(sdev->dev, "%s: No private data for DAI %s\n", __func__, w->name);
+ return -EINVAL;
+ }
+
+ private = sof_dai->private;
+ if (!private->dai_config) {
+ dev_err(sdev->dev, "%s: No config for DAI %s\n", __func__, w->name);
return -EINVAL;
}
@@ -117,7 +131,7 @@ int hda_ctrl_dai_widget_free(struct snd_soc_dapm_widget *w, unsigned int quirk_f
if (!sof_dai->configured)
return 0;
- config = &sof_dai->dai_config[sof_dai->current_config];
+ config = &private->dai_config[sof_dai->current_config];
/* set HW_FREE flag along with any quirks */
config->flags = SOF_DAI_CONFIG_FLAGS_HW_FREE |
@@ -154,6 +168,7 @@ static int sdw_dai_config_ipc(struct snd_sof_dev *sdev,
int link_id, int alh_stream_id, int dai_id, bool setup)
{
struct snd_sof_widget *swidget = w->dobj.private;
+ struct sof_dai_private_data *private;
struct sof_ipc_dai_config *config;
struct snd_sof_dai *sof_dai;
@@ -164,12 +179,18 @@ static int sdw_dai_config_ipc(struct snd_sof_dev *sdev,
sof_dai = swidget->private;
- if (!sof_dai || !sof_dai->dai_config) {
- dev_err(sdev->dev, "error: No config for DAI %s\n", w->name);
+ if (!sof_dai || !sof_dai->private) {
+ dev_err(sdev->dev, "%s: No private data for DAI %s\n", __func__, w->name);
+ return -EINVAL;
+ }
+
+ private = sof_dai->private;
+ if (!private->dai_config) {
+ dev_err(sdev->dev, "%s: No config for DAI %s\n", __func__, w->name);
return -EINVAL;
}
- config = &sof_dai->dai_config[sof_dai->current_config];
+ config = &private->dai_config[sof_dai->current_config];
/* update config with link and stream ID */
config->dai_index = (link_id << 8) | dai_id;
diff --git a/sound/soc/sof/ipc.c b/sound/soc/sof/ipc.c
index c729bb7bf8c8..34084e0008f1 100644
--- a/sound/soc/sof/ipc.c
+++ b/sound/soc/sof/ipc.c
@@ -27,18 +27,6 @@ static void ipc_stream_message(struct snd_sof_dev *sdev, void *msg_buf);
* IPC message Tx/Rx message handling.
*/
-/* SOF generic IPC data */
-struct snd_sof_ipc {
- struct snd_sof_dev *sdev;
-
- /* protects messages and the disable flag */
- struct mutex tx_mutex;
- /* disables further sending of ipc's */
- bool disable_ipc_tx;
-
- struct snd_sof_ipc_msg msg;
-};
-
struct sof_ipc_ctrl_data_params {
size_t msg_bytes;
size_t hdr_bytes;
diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c
index 1d04f75e6d32..4628bc642fda 100644
--- a/sound/soc/sof/pcm.c
+++ b/sound/soc/sof/pcm.c
@@ -670,7 +670,9 @@ static void ssp_dai_config_pcm_params_match(struct snd_sof_dev *sdev, const char
if (!dai->name || strcmp(link_name, dai->name))
continue;
for (i = 0; i < dai->number_configs; i++) {
- config = &dai->dai_config[i];
+ struct sof_dai_private_data *private = dai->private;
+
+ config = &private->dai_config[i];
if (config->ssp.fsync_rate == params_rate(params)) {
dev_dbg(sdev->dev, "DAI config %d matches pcm hw params\n", i);
dai->current_config = i;
@@ -693,6 +695,7 @@ int sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_pa
struct snd_sof_dai *dai =
snd_sof_find_dai(component, (char *)rtd->dai_link->name);
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
+ struct sof_dai_private_data *private = dai->private;
struct snd_soc_dpcm *dpcm;
/* no topology exists for this BE, try a common configuration */
@@ -717,7 +720,7 @@ int sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_pa
/* read format from topology */
snd_mask_none(fmt);
- switch (dai->comp_dai->config.frame_fmt) {
+ switch (private->comp_dai->config.frame_fmt) {
case SOF_IPC_FRAME_S16_LE:
snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S16_LE);
break;
@@ -733,15 +736,15 @@ int sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_pa
}
/* read rate and channels from topology */
- switch (dai->dai_config->type) {
+ switch (private->dai_config->type) {
case SOF_DAI_INTEL_SSP:
/* search for config to pcm params match, if not found use default */
ssp_dai_config_pcm_params_match(sdev, (char *)rtd->dai_link->name, params);
- rate->min = dai->dai_config[dai->current_config].ssp.fsync_rate;
- rate->max = dai->dai_config[dai->current_config].ssp.fsync_rate;
- channels->min = dai->dai_config[dai->current_config].ssp.tdm_slots;
- channels->max = dai->dai_config[dai->current_config].ssp.tdm_slots;
+ rate->min = private->dai_config[dai->current_config].ssp.fsync_rate;
+ rate->max = private->dai_config[dai->current_config].ssp.fsync_rate;
+ channels->min = private->dai_config[dai->current_config].ssp.tdm_slots;
+ channels->max = private->dai_config[dai->current_config].ssp.tdm_slots;
dev_dbg(component->dev,
"rate_min: %d rate_max: %d\n", rate->min, rate->max);
@@ -752,11 +755,11 @@ int sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_pa
break;
case SOF_DAI_INTEL_DMIC:
/* DMIC only supports 16 or 32 bit formats */
- if (dai->comp_dai->config.frame_fmt == SOF_IPC_FRAME_S24_4LE) {
+ if (private->comp_dai->config.frame_fmt == SOF_IPC_FRAME_S24_4LE) {
dev_err(component->dev,
"error: invalid fmt %d for DAI type %d\n",
- dai->comp_dai->config.frame_fmt,
- dai->dai_config->type);
+ private->comp_dai->config.frame_fmt,
+ private->dai_config->type);
}
break;
case SOF_DAI_INTEL_HDA:
@@ -776,14 +779,14 @@ int sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_pa
* Dai could run with different channel count compared with
* front end, so get dai channel count from topology
*/
- channels->min = dai->dai_config->alh.channels;
- channels->max = dai->dai_config->alh.channels;
+ channels->min = private->dai_config->alh.channels;
+ channels->max = private->dai_config->alh.channels;
break;
case SOF_DAI_IMX_ESAI:
- rate->min = dai->dai_config->esai.fsync_rate;
- rate->max = dai->dai_config->esai.fsync_rate;
- channels->min = dai->dai_config->esai.tdm_slots;
- channels->max = dai->dai_config->esai.tdm_slots;
+ rate->min = private->dai_config->esai.fsync_rate;
+ rate->max = private->dai_config->esai.fsync_rate;
+ channels->min = private->dai_config->esai.tdm_slots;
+ channels->max = private->dai_config->esai.tdm_slots;
dev_dbg(component->dev,
"rate_min: %d rate_max: %d\n", rate->min, rate->max);
@@ -792,10 +795,10 @@ int sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_pa
channels->min, channels->max);
break;
case SOF_DAI_MEDIATEK_AFE:
- rate->min = dai->dai_config->afe.rate;
- rate->max = dai->dai_config->afe.rate;
- channels->min = dai->dai_config->afe.channels;
- channels->max = dai->dai_config->afe.channels;
+ rate->min = private->dai_config->afe.rate;
+ rate->max = private->dai_config->afe.rate;
+ channels->min = private->dai_config->afe.channels;
+ channels->max = private->dai_config->afe.channels;
dev_dbg(component->dev,
"rate_min: %d rate_max: %d\n", rate->min, rate->max);
@@ -804,10 +807,10 @@ int sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_pa
channels->min, channels->max);
break;
case SOF_DAI_IMX_SAI:
- rate->min = dai->dai_config->sai.fsync_rate;
- rate->max = dai->dai_config->sai.fsync_rate;
- channels->min = dai->dai_config->sai.tdm_slots;
- channels->max = dai->dai_config->sai.tdm_slots;
+ rate->min = private->dai_config->sai.fsync_rate;
+ rate->max = private->dai_config->sai.fsync_rate;
+ channels->min = private->dai_config->sai.tdm_slots;
+ channels->max = private->dai_config->sai.tdm_slots;
dev_dbg(component->dev,
"rate_min: %d rate_max: %d\n", rate->min, rate->max);
@@ -816,10 +819,10 @@ int sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_pa
channels->min, channels->max);
break;
case SOF_DAI_AMD_BT:
- rate->min = dai->dai_config->acpbt.fsync_rate;
- rate->max = dai->dai_config->acpbt.fsync_rate;
- channels->min = dai->dai_config->acpbt.tdm_slots;
- channels->max = dai->dai_config->acpbt.tdm_slots;
+ rate->min = private->dai_config->acpbt.fsync_rate;
+ rate->max = private->dai_config->acpbt.fsync_rate;
+ channels->min = private->dai_config->acpbt.tdm_slots;
+ channels->max = private->dai_config->acpbt.tdm_slots;
dev_dbg(component->dev,
"AMD_BT rate_min: %d rate_max: %d\n", rate->min, rate->max);
@@ -828,10 +831,10 @@ int sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_pa
channels->min, channels->max);
break;
case SOF_DAI_AMD_SP:
- rate->min = dai->dai_config->acpsp.fsync_rate;
- rate->max = dai->dai_config->acpsp.fsync_rate;
- channels->min = dai->dai_config->acpsp.tdm_slots;
- channels->max = dai->dai_config->acpsp.tdm_slots;
+ rate->min = private->dai_config->acpsp.fsync_rate;
+ rate->max = private->dai_config->acpsp.fsync_rate;
+ channels->min = private->dai_config->acpsp.tdm_slots;
+ channels->max = private->dai_config->acpsp.tdm_slots;
dev_dbg(component->dev,
"AMD_SP rate_min: %d rate_max: %d\n", rate->min, rate->max);
@@ -840,10 +843,10 @@ int sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_pa
channels->min, channels->max);
break;
case SOF_DAI_AMD_DMIC:
- rate->min = dai->dai_config->acpdmic.fsync_rate;
- rate->max = dai->dai_config->acpdmic.fsync_rate;
- channels->min = dai->dai_config->acpdmic.tdm_slots;
- channels->max = dai->dai_config->acpdmic.tdm_slots;
+ rate->min = private->dai_config->acpdmic.fsync_rate;
+ rate->max = private->dai_config->acpdmic.fsync_rate;
+ channels->min = private->dai_config->acpdmic.tdm_slots;
+ channels->max = private->dai_config->acpdmic.tdm_slots;
dev_dbg(component->dev,
"AMD_DMIC rate_min: %d rate_max: %d\n", rate->min, rate->max);
@@ -853,7 +856,7 @@ int sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_pa
break;
default:
dev_err(component->dev, "error: invalid DAI type %d\n",
- dai->dai_config->type);
+ private->dai_config->type);
break;
}
diff --git a/sound/soc/sof/sof-audio.c b/sound/soc/sof/sof-audio.c
index b49d8e348077..15c36a51f89f 100644
--- a/sound/soc/sof/sof-audio.c
+++ b/sound/soc/sof/sof-audio.c
@@ -29,11 +29,12 @@ static int sof_kcontrol_setup(struct snd_sof_dev *sdev, struct snd_sof_control *
static int sof_dai_config_setup(struct snd_sof_dev *sdev, struct snd_sof_dai *dai)
{
+ struct sof_dai_private_data *private = dai->private;
struct sof_ipc_dai_config *config;
struct sof_ipc_reply reply;
int ret;
- config = &dai->dai_config[dai->current_config];
+ config = &private->dai_config[dai->current_config];
if (!config) {
dev_err(sdev->dev, "error: no config for DAI %s\n", dai->name);
return -EINVAL;
@@ -191,12 +192,16 @@ int sof_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget)
switch (swidget->id) {
case snd_soc_dapm_dai_in:
case snd_soc_dapm_dai_out:
+ {
+ struct sof_dai_private_data *dai_data;
+
dai = swidget->private;
- comp = &dai->comp_dai->comp;
+ dai_data = dai->private;
+ comp = &dai_data->comp_dai->comp;
dai->configured = false;
- ret = sof_ipc_tx_message(sdev->ipc, comp->hdr.cmd, dai->comp_dai, comp->hdr.size,
- &r, sizeof(r));
+ ret = sof_ipc_tx_message(sdev->ipc, comp->hdr.cmd, dai_data->comp_dai,
+ comp->hdr.size, &r, sizeof(r));
if (ret < 0) {
dev_err(sdev->dev, "error: failed to load widget %s\n",
swidget->widget->name);
@@ -216,6 +221,7 @@ int sof_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget)
return ret;
}
break;
+ }
case snd_soc_dapm_scheduler:
pipeline = swidget->private;
ret = sof_ipc_tx_message(sdev->ipc, pipeline->hdr.cmd, pipeline,
@@ -259,28 +265,25 @@ EXPORT_SYMBOL(sof_widget_setup);
static int sof_route_setup_ipc(struct snd_sof_dev *sdev, struct snd_sof_route *sroute)
{
- struct sof_ipc_pipe_comp_connect *connect;
+ struct sof_ipc_pipe_comp_connect connect;
struct sof_ipc_reply reply;
int ret;
- /* skip if there's no private data */
- if (!sroute->private)
- return 0;
-
/* nothing to do if route is already set up */
if (sroute->setup)
return 0;
- connect = sroute->private;
+ connect.hdr.size = sizeof(connect);
+ connect.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_COMP_CONNECT;
+ connect.source_id = sroute->src_widget->comp_id;
+ connect.sink_id = sroute->sink_widget->comp_id;
dev_dbg(sdev->dev, "setting up route %s -> %s\n",
sroute->src_widget->widget->name,
sroute->sink_widget->widget->name);
/* send ipc */
- ret = sof_ipc_tx_message(sdev->ipc,
- connect->hdr.cmd,
- connect, sizeof(*connect),
+ ret = sof_ipc_tx_message(sdev->ipc, connect.hdr.cmd, &connect, sizeof(connect),
&reply, sizeof(reply));
if (ret < 0) {
dev_err(sdev->dev, "%s: route setup failed %d\n", __func__, ret);
@@ -623,12 +626,13 @@ int sof_set_up_pipelines(struct snd_sof_dev *sdev, bool verify)
/* update DAI config. The IPC will be sent in sof_widget_setup() */
if (WIDGET_IS_DAI(swidget->id)) {
struct snd_sof_dai *dai = swidget->private;
+ struct sof_dai_private_data *private = dai->private;
struct sof_ipc_dai_config *config;
- if (!dai || !dai->dai_config)
+ if (!dai || !private || !private->dai_config)
continue;
- config = dai->dai_config;
+ config = private->dai_config;
/*
* The link DMA channel would be invalidated for running
* streams but not for streams that were in the PAUSED
@@ -914,18 +918,19 @@ static int sof_dai_get_clk(struct snd_soc_pcm_runtime *rtd, int clk_type)
snd_soc_rtdcom_lookup(rtd, SOF_AUDIO_PCM_DRV_NAME);
struct snd_sof_dai *dai =
snd_sof_find_dai(component, (char *)rtd->dai_link->name);
+ struct sof_dai_private_data *private = dai->private;
/* use the tplg configured mclk if existed */
- if (!dai || !dai->dai_config)
+ if (!dai || !private || !private->dai_config)
return 0;
- switch (dai->dai_config->type) {
+ switch (private->dai_config->type) {
case SOF_DAI_INTEL_SSP:
switch (clk_type) {
case SOF_DAI_CLK_INTEL_SSP_MCLK:
- return dai->dai_config->ssp.mclk_rate;
+ return private->dai_config->ssp.mclk_rate;
case SOF_DAI_CLK_INTEL_SSP_BCLK:
- return dai->dai_config->ssp.bclk_rate;
+ return private->dai_config->ssp.bclk_rate;
default:
dev_err(rtd->dev, "fail to get SSP clk %d rate\n",
clk_type);
@@ -935,7 +940,7 @@ static int sof_dai_get_clk(struct snd_soc_pcm_runtime *rtd, int clk_type)
default:
/* not yet implemented for platforms other than the above */
dev_err(rtd->dev, "DAI type %d not supported yet!\n",
- dai->dai_config->type);
+ private->dai_config->type);
return -EINVAL;
}
}
diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h
index a8eeffc12b24..450ee9977c55 100644
--- a/sound/soc/sof/sof-audio.h
+++ b/sound/soc/sof/sof-audio.h
@@ -30,6 +30,18 @@
#define WIDGET_IS_DAI(id) ((id) == snd_soc_dapm_dai_in || (id) == snd_soc_dapm_dai_out)
+/** struct snd_sof_tuple - Tuple info
+ * @token: Token ID
+ * @value: union of a string or a u32 values
+ */
+struct snd_sof_tuple {
+ u32 token;
+ union {
+ u32 v;
+ const char *s;
+ } value;
+};
+
/* PCM stream, mapped to FW component */
struct snd_sof_pcm_stream {
u32 comp_id;
@@ -110,8 +122,10 @@ struct snd_sof_widget {
struct list_head list; /* list in sdev widget list */
struct snd_sof_widget *pipe_widget;
- /* extended data for UUID components */
- struct sof_ipc_comp_ext comp_ext;
+ const guid_t uuid;
+
+ int num_tuples;
+ struct snd_sof_tuple *tuples;
void *private; /* core does not touch this */
};
@@ -134,12 +148,11 @@ struct snd_sof_dai {
struct snd_soc_component *scomp;
const char *name;
- struct sof_ipc_comp_dai *comp_dai;
int number_configs;
int current_config;
bool configured; /* DAI configured during BE hw_params */
- struct sof_ipc_dai_config *dai_config;
struct list_head list; /* list in sdev dai list */
+ void *private;
};
/*
diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h
index 2e19ac619ad5..7f0514db4d06 100644
--- a/sound/soc/sof/sof-priv.h
+++ b/sound/soc/sof/sof-priv.h
@@ -345,6 +345,18 @@ struct snd_sof_ipc_msg {
bool ipc_complete;
};
+/* SOF generic IPC data */
+struct snd_sof_ipc {
+ struct snd_sof_dev *sdev;
+
+ /* protects messages and the disable flag */
+ struct mutex tx_mutex;
+ /* disables further sending of ipc's */
+ bool disable_ipc_tx;
+
+ struct snd_sof_ipc_msg msg;
+};
+
/*
* SOF Device Level.
*/
diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c
index 41927e99ace2..afd9eda67631 100644
--- a/sound/soc/sof/topology.c
+++ b/sound/soc/sof/topology.c
@@ -743,7 +743,7 @@ static const struct sof_topology_token core_tokens[] = {
static const struct sof_topology_token comp_ext_tokens[] = {
{SOF_TKN_COMP_UUID,
SND_SOC_TPLG_TUPLE_TYPE_UUID, get_token_uuid,
- offsetof(struct sof_ipc_comp_ext, uuid)},
+ offsetof(struct snd_sof_widget, uuid)},
};
/*
@@ -807,12 +807,21 @@ static const struct sof_topology_token afe_tokens[] = {
offsetof(struct sof_ipc_dai_mtk_afe_params, format)},
};
+/**
+ * sof_parse_uuid_tokens - Parse multiple sets of UUID tokens
+ * @scomp: pointer to soc component
+ * @object: target ipc struct for parsed values
+ * @offset: offset within the object pointer
+ * @tokens: array of struct sof_topology_token containing the tokens to be matched
+ * @num_tokens: number of tokens in tokens array
+ * @array: source pointer to consecutive vendor arrays in topology
+ *
+ * This function parses multiple sets of string type tokens in vendor arrays
+ */
static int sof_parse_uuid_tokens(struct snd_soc_component *scomp,
- void *object,
- const struct sof_topology_token *tokens,
- int count,
- struct snd_soc_tplg_vendor_array *array,
- size_t offset)
+ void *object, size_t offset,
+ const struct sof_topology_token *tokens, int num_tokens,
+ struct snd_soc_tplg_vendor_array *array)
{
struct snd_soc_tplg_vendor_uuid_elem *elem;
int found = 0;
@@ -823,7 +832,7 @@ static int sof_parse_uuid_tokens(struct snd_soc_component *scomp,
elem = &array->uuid[i];
/* search for token */
- for (j = 0; j < count; j++) {
+ for (j = 0; j < num_tokens; j++) {
/* match token type */
if (tokens[j].type != SND_SOC_TPLG_TUPLE_TYPE_UUID)
continue;
@@ -843,12 +852,21 @@ static int sof_parse_uuid_tokens(struct snd_soc_component *scomp,
return found;
}
+/**
+ * sof_parse_string_tokens - Parse multiple sets of tokens
+ * @scomp: pointer to soc component
+ * @object: target ipc struct for parsed values
+ * @offset: offset within the object pointer
+ * @tokens: array of struct sof_topology_token containing the tokens to be matched
+ * @num_tokens: number of tokens in tokens array
+ * @array: source pointer to consecutive vendor arrays in topology
+ *
+ * This function parses multiple sets of string type tokens in vendor arrays
+ */
static int sof_parse_string_tokens(struct snd_soc_component *scomp,
- void *object,
- const struct sof_topology_token *tokens,
- int count,
- struct snd_soc_tplg_vendor_array *array,
- size_t offset)
+ void *object, int offset,
+ const struct sof_topology_token *tokens, int num_tokens,
+ struct snd_soc_tplg_vendor_array *array)
{
struct snd_soc_tplg_vendor_string_elem *elem;
int found = 0;
@@ -859,7 +877,7 @@ static int sof_parse_string_tokens(struct snd_soc_component *scomp,
elem = &array->string[i];
/* search for token */
- for (j = 0; j < count; j++) {
+ for (j = 0; j < num_tokens; j++) {
/* match token type */
if (tokens[j].type != SND_SOC_TPLG_TUPLE_TYPE_STRING)
continue;
@@ -878,12 +896,21 @@ static int sof_parse_string_tokens(struct snd_soc_component *scomp,
return found;
}
+/**
+ * sof_parse_word_tokens - Parse multiple sets of tokens
+ * @scomp: pointer to soc component
+ * @object: target ipc struct for parsed values
+ * @offset: offset within the object pointer
+ * @tokens: array of struct sof_topology_token containing the tokens to be matched
+ * @num_tokens: number of tokens in tokens array
+ * @array: source pointer to consecutive vendor arrays in topology
+ *
+ * This function parses multiple sets of word type tokens in vendor arrays
+ */
static int sof_parse_word_tokens(struct snd_soc_component *scomp,
- void *object,
- const struct sof_topology_token *tokens,
- int count,
- struct snd_soc_tplg_vendor_array *array,
- size_t offset)
+ void *object, int offset,
+ const struct sof_topology_token *tokens, int num_tokens,
+ struct snd_soc_tplg_vendor_array *array)
{
struct snd_soc_tplg_vendor_value_elem *elem;
int found = 0;
@@ -894,7 +921,7 @@ static int sof_parse_word_tokens(struct snd_soc_component *scomp,
elem = &array->value[i];
/* search for token */
- for (j = 0; j < count; j++) {
+ for (j = 0; j < num_tokens; j++) {
/* match token type */
if (!(tokens[j].type == SND_SOC_TPLG_TUPLE_TYPE_WORD ||
tokens[j].type == SND_SOC_TPLG_TUPLE_TYPE_SHORT ||
@@ -907,8 +934,7 @@ static int sof_parse_word_tokens(struct snd_soc_component *scomp,
continue;
/* load token */
- tokens[j].get_token(elem, object,
- offset + tokens[j].offset);
+ tokens[j].get_token(elem, object, offset + tokens[j].offset);
found++;
}
@@ -923,27 +949,26 @@ static int sof_parse_word_tokens(struct snd_soc_component *scomp,
* @object: target ipc struct for parsed values
* @tokens: token definition array describing what tokens to parse
* @count: number of tokens in definition array
- * @array: source pointer to consecutive vendor arrays to be parsed
- * @priv_size: total size of the consecutive source arrays
- * @sets: number of similar token sets to be parsed, 1 set has count elements
+ * @array: source pointer to consecutive vendor arrays in topology
+ * @array_size: total size of @array
+ * @token_instance_num: number of times the same tokens needs to be parsed i.e. the function
+ * looks for @token_instance_num of each token in the @tokens
* @object_size: offset to next target ipc struct with multiple sets
*
* This function parses multiple sets of tokens in vendor arrays into
* consecutive ipc structs.
*/
static int sof_parse_token_sets(struct snd_soc_component *scomp,
- void *object,
- const struct sof_topology_token *tokens,
- int count,
- struct snd_soc_tplg_vendor_array *array,
- int priv_size, int sets, size_t object_size)
+ void *object, const struct sof_topology_token *tokens,
+ int count, struct snd_soc_tplg_vendor_array *array,
+ int array_size, int token_instance_num, size_t object_size)
{
size_t offset = 0;
int found = 0;
int total = 0;
int asize;
- while (priv_size > 0 && total < count * sets) {
+ while (array_size > 0 && total < count * token_instance_num) {
asize = le32_to_cpu(array->size);
/* validate asize */
@@ -954,8 +979,8 @@ static int sof_parse_token_sets(struct snd_soc_component *scomp,
}
/* make sure there is enough data before parsing */
- priv_size -= asize;
- if (priv_size < 0) {
+ array_size -= asize;
+ if (array_size < 0) {
dev_err(scomp->dev, "error: invalid array size 0x%x\n",
asize);
return -EINVAL;
@@ -964,19 +989,19 @@ static int sof_parse_token_sets(struct snd_soc_component *scomp,
/* call correct parser depending on type */
switch (le32_to_cpu(array->type)) {
case SND_SOC_TPLG_TUPLE_TYPE_UUID:
- found += sof_parse_uuid_tokens(scomp, object, tokens,
- count, array, offset);
+ found += sof_parse_uuid_tokens(scomp, object, offset, tokens, count,
+ array);
break;
case SND_SOC_TPLG_TUPLE_TYPE_STRING:
- found += sof_parse_string_tokens(scomp, object, tokens,
- count, array, offset);
+ found += sof_parse_string_tokens(scomp, object, offset, tokens, count,
+ array);
break;
case SND_SOC_TPLG_TUPLE_TYPE_BOOL:
case SND_SOC_TPLG_TUPLE_TYPE_BYTE:
case SND_SOC_TPLG_TUPLE_TYPE_WORD:
case SND_SOC_TPLG_TUPLE_TYPE_SHORT:
- found += sof_parse_word_tokens(scomp, object, tokens,
- count, array, offset);
+ found += sof_parse_word_tokens(scomp, object, offset, tokens, count,
+ array);
break;
default:
dev_err(scomp->dev, "error: unknown token type %d\n",
@@ -999,12 +1024,23 @@ static int sof_parse_token_sets(struct snd_soc_component *scomp,
return 0;
}
-static int sof_parse_tokens(struct snd_soc_component *scomp,
- void *object,
- const struct sof_topology_token *tokens,
- int count,
+/**
+ * sof_parse_tokens - Parse one set of tokens
+ * @scomp: pointer to soc component
+ * @object: target ipc struct for parsed values
+ * @tokens: token definition array describing what tokens to parse
+ * @num_tokens: number of tokens in definition array
+ * @array: source pointer to consecutive vendor arrays in topology
+ * @array_size: total size of @array
+ *
+ * This function parses a single set of tokens in vendor arrays into
+ * consecutive ipc structs.
+ */
+static int sof_parse_tokens(struct snd_soc_component *scomp, void *object,
+ const struct sof_topology_token *tokens, int num_tokens,
struct snd_soc_tplg_vendor_array *array,
- int priv_size)
+ int array_size)
+
{
/*
* sof_parse_tokens is used when topology contains only a single set of
@@ -1012,8 +1048,8 @@ static int sof_parse_tokens(struct snd_soc_component *scomp,
* sof_parse_token_sets are sets = 1 (only 1 set) and
* object_size = 0 (irrelevant).
*/
- return sof_parse_token_sets(scomp, object, tokens, count, array,
- priv_size, 1, 0);
+ return sof_parse_token_sets(scomp, object, tokens, num_tokens, array,
+ array_size, 1, 0);
}
static void sof_dbg_comp_config(struct snd_soc_component *scomp,
@@ -1419,16 +1455,16 @@ static int sof_connect_dai_widget(struct snd_soc_component *scomp,
*
* Return: The pointer to the new allocated component, NULL if failed.
*/
-static struct sof_ipc_comp *sof_comp_alloc(struct snd_sof_widget *swidget,
- size_t *ipc_size, int index)
+static struct sof_ipc_comp *sof_comp_alloc(struct snd_sof_widget *swidget, size_t *ipc_size,
+ int index)
{
- u8 nil_uuid[SOF_UUID_SIZE] = {0};
struct sof_ipc_comp *comp;
size_t total_size = *ipc_size;
+ size_t ext_size = sizeof(swidget->uuid);
/* only non-zero UUID is valid */
- if (memcmp(&swidget->comp_ext, nil_uuid, SOF_UUID_SIZE))
- total_size += sizeof(swidget->comp_ext);
+ if (!guid_is_null(&swidget->uuid))
+ total_size += ext_size;
comp = kzalloc(total_size, GFP_KERNEL);
if (!comp)
@@ -1444,8 +1480,8 @@ static struct sof_ipc_comp *sof_comp_alloc(struct snd_sof_widget *swidget,
/* handle the extended data if needed */
if (total_size > *ipc_size) {
/* append extended data to the end of the component */
- memcpy((u8 *)comp + *ipc_size, &swidget->comp_ext, sizeof(swidget->comp_ext));
- comp->ext_data_length = sizeof(swidget->comp_ext);
+ memcpy((u8 *)comp + *ipc_size, &swidget->uuid, ext_size);
+ comp->ext_data_length = ext_size;
}
/* update ipc_size and return */
@@ -1459,14 +1495,21 @@ static int sof_widget_load_dai(struct snd_soc_component *scomp, int index,
struct snd_sof_dai *dai)
{
struct snd_soc_tplg_private *private = &tw->priv;
+ struct sof_dai_private_data *dai_data;
struct sof_ipc_comp_dai *comp_dai;
size_t ipc_size = sizeof(*comp_dai);
int ret;
+ dai_data = kzalloc(sizeof(*dai_data), GFP_KERNEL);
+ if (!dai_data)
+ return -ENOMEM;
+
comp_dai = (struct sof_ipc_comp_dai *)
sof_comp_alloc(swidget, &ipc_size, index);
- if (!comp_dai)
- return -ENOMEM;
+ if (!comp_dai) {
+ ret = -ENOMEM;
+ goto free;
+ }
/* configure dai IPC message */
comp_dai->comp.type = SOF_COMP_DAI;
@@ -1478,7 +1521,7 @@ static int sof_widget_load_dai(struct snd_soc_component *scomp, int index,
if (ret != 0) {
dev_err(scomp->dev, "error: parse dai tokens failed %d\n",
le32_to_cpu(private->size));
- return ret;
+ goto free;
}
ret = sof_parse_tokens(scomp, &comp_dai->config, comp_tokens,
@@ -1487,7 +1530,7 @@ static int sof_widget_load_dai(struct snd_soc_component *scomp, int index,
if (ret != 0) {
dev_err(scomp->dev, "error: parse dai.cfg tokens failed %d\n",
private->size);
- return ret;
+ goto free;
}
dev_dbg(scomp->dev, "dai %s: type %d index %d\n",
@@ -1496,9 +1539,14 @@ static int sof_widget_load_dai(struct snd_soc_component *scomp, int index,
if (dai) {
dai->scomp = scomp;
- dai->comp_dai = comp_dai;
+ dai_data->comp_dai = comp_dai;
+ dai->private = dai_data;
}
+ return 0;
+
+free:
+ kfree(dai_data);
return ret;
}
@@ -2276,9 +2324,8 @@ static int sof_widget_ready(struct snd_soc_component *scomp, int index,
swidget->core = comp.core;
- ret = sof_parse_tokens(scomp, &swidget->comp_ext, comp_ext_tokens,
- ARRAY_SIZE(comp_ext_tokens), tw->priv.array,
- le32_to_cpu(tw->priv.size));
+ ret = sof_parse_tokens(scomp, swidget, comp_ext_tokens, ARRAY_SIZE(comp_ext_tokens),
+ tw->priv.array, le32_to_cpu(tw->priv.size));
if (ret != 0) {
dev_err(scomp->dev, "error: parsing comp_ext_tokens failed %d\n",
ret);
@@ -2421,9 +2468,11 @@ static int sof_widget_unload(struct snd_soc_component *scomp,
dai = swidget->private;
if (dai) {
- kfree(dai->comp_dai);
- /* free dai config */
- kfree(dai->dai_config);
+ struct sof_dai_private_data *dai_data = dai->private;
+
+ kfree(dai_data->comp_dai);
+ kfree(dai_data->dai_config);
+ kfree(dai_data);
list_del(&dai->list);
}
break;
@@ -2645,11 +2694,13 @@ static int sof_set_dai_config_multi(struct snd_sof_dev *sdev, u32 size,
struct sof_ipc_dai_config *config,
int num_conf, int curr_conf)
{
+ struct sof_dai_private_data *dai_data;
struct snd_sof_dai *dai;
int found = 0;
int i;
list_for_each_entry(dai, &sdev->dai_list, list) {
+ dai_data = dai->private;
if (!dai->name)
continue;
@@ -2661,15 +2712,15 @@ static int sof_set_dai_config_multi(struct snd_sof_dev *sdev, u32 size,
* dai_index.
*/
for (i = 0; i < num_conf; i++)
- config[i].dai_index = dai->comp_dai->dai_index;
+ config[i].dai_index = dai_data->comp_dai->dai_index;
dev_dbg(sdev->dev, "set DAI config for %s index %d\n",
dai->name, config[curr_conf].dai_index);
dai->number_configs = num_conf;
dai->current_config = curr_conf;
- dai->dai_config = kmemdup(config, size * num_conf, GFP_KERNEL);
- if (!dai->dai_config)
+ dai_data->dai_config = kmemdup(config, size * num_conf, GFP_KERNEL);
+ if (!dai_data->dai_config)
return -ENOMEM;
found = 1;
@@ -3323,7 +3374,6 @@ static int sof_route_load(struct snd_soc_component *scomp, int index,
struct snd_soc_dapm_route *route)
{
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
- struct sof_ipc_pipe_comp_connect *connect;
struct snd_sof_widget *source_swidget, *sink_swidget;
struct snd_soc_dobj *dobj = &route->dobj;
struct snd_sof_route *sroute;
@@ -3335,16 +3385,6 @@ static int sof_route_load(struct snd_soc_component *scomp, int index,
return -ENOMEM;
sroute->scomp = scomp;
-
- connect = kzalloc(sizeof(*connect), GFP_KERNEL);
- if (!connect) {
- kfree(sroute);
- return -ENOMEM;
- }
-
- connect->hdr.size = sizeof(*connect);
- connect->hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_COMP_CONNECT;
-
dev_dbg(scomp->dev, "sink %s control %s source %s\n",
route->sink, route->control ? route->control : "none",
route->source);
@@ -3368,8 +3408,6 @@ static int sof_route_load(struct snd_soc_component *scomp, int index,
source_swidget->id == snd_soc_dapm_output)
goto err;
- connect->source_id = source_swidget->comp_id;
-
/* sink component */
sink_swidget = snd_sof_find_swidget(scomp, (char *)route->sink);
if (!sink_swidget) {
@@ -3387,8 +3425,6 @@ static int sof_route_load(struct snd_soc_component *scomp, int index,
sink_swidget->id == snd_soc_dapm_output)
goto err;
- connect->sink_id = sink_swidget->comp_id;
-
/*
* For virtual routes, both sink and source are not
* buffer. Since only buffer linked to component is supported by
@@ -3403,7 +3439,6 @@ static int sof_route_load(struct snd_soc_component *scomp, int index,
} else {
sroute->route = route;
dobj->private = sroute;
- sroute->private = connect;
sroute->src_widget = source_swidget;
sroute->sink_widget = sink_swidget;
@@ -3414,7 +3449,6 @@ static int sof_route_load(struct snd_soc_component *scomp, int index,
}
err:
- kfree(connect);
kfree(sroute);
return ret;
}