aboutsummaryrefslogtreecommitdiff
path: root/sound/soc/sof/ipc3-topology.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/sof/ipc3-topology.c')
-rw-r--r--sound/soc/sof/ipc3-topology.c65
1 files changed, 40 insertions, 25 deletions
diff --git a/sound/soc/sof/ipc3-topology.c b/sound/soc/sof/ipc3-topology.c
index dceb78bfe17c..fc1eb8e2de2c 100644
--- a/sound/soc/sof/ipc3-topology.c
+++ b/sound/soc/sof/ipc3-topology.c
@@ -1627,7 +1627,6 @@ static void sof_ipc3_widget_free_comp_dai(struct snd_sof_widget *swidget)
static int sof_ipc3_route_setup(struct snd_sof_dev *sdev, struct snd_sof_route *sroute)
{
struct sof_ipc_pipe_comp_connect connect;
- struct sof_ipc_reply reply;
int ret;
connect.hdr.size = sizeof(connect);
@@ -1640,7 +1639,7 @@ static int sof_ipc3_route_setup(struct snd_sof_dev *sdev, struct snd_sof_route *
sroute->sink_widget->widget->name);
/* send ipc */
- ret = sof_ipc_tx_message(sdev->ipc, &connect, sizeof(connect), &reply, sizeof(reply));
+ ret = sof_ipc_tx_message_no_reply(sdev->ipc, &connect, sizeof(connect));
if (ret < 0)
dev_err(sdev->dev, "%s: route %s -> %s failed\n", __func__,
sroute->src_widget->widget->name, sroute->sink_widget->widget->name);
@@ -1789,7 +1788,7 @@ static int sof_ipc3_control_free(struct snd_sof_dev *sdev, struct snd_sof_contro
fcomp.id = scontrol->comp_id;
/* send IPC to the DSP */
- return sof_ipc_tx_message(sdev->ipc, &fcomp, sizeof(fcomp), NULL, 0);
+ return sof_ipc_tx_message_no_reply(sdev->ipc, &fcomp, sizeof(fcomp));
}
/* send pcm params ipc */
@@ -1797,7 +1796,6 @@ static int sof_ipc3_keyword_detect_pcm_params(struct snd_sof_widget *swidget, in
{
struct snd_soc_component *scomp = swidget->scomp;
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
- struct sof_ipc_pcm_params_reply ipc_params_reply;
struct snd_pcm_hw_params *params;
struct sof_ipc_pcm_params pcm;
struct snd_sof_pcm *spcm;
@@ -1841,8 +1839,7 @@ static int sof_ipc3_keyword_detect_pcm_params(struct snd_sof_widget *swidget, in
}
/* send IPC to the DSP */
- ret = sof_ipc_tx_message(sdev->ipc, &pcm, sizeof(pcm),
- &ipc_params_reply, sizeof(ipc_params_reply));
+ ret = sof_ipc_tx_message_no_reply(sdev->ipc, &pcm, sizeof(pcm));
if (ret < 0)
dev_err(scomp->dev, "%s: PCM params failed for %s\n", __func__,
swidget->widget->name);
@@ -1856,7 +1853,6 @@ static int sof_ipc3_keyword_detect_trigger(struct snd_sof_widget *swidget, int c
struct snd_soc_component *scomp = swidget->scomp;
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
struct sof_ipc_stream stream;
- struct sof_ipc_reply reply;
int ret;
/* set IPC stream params */
@@ -1865,7 +1861,7 @@ static int sof_ipc3_keyword_detect_trigger(struct snd_sof_widget *swidget, int c
stream.comp_id = swidget->comp_id;
/* send IPC to the DSP */
- ret = sof_ipc_tx_message(sdev->ipc, &stream, sizeof(stream), &reply, sizeof(reply));
+ ret = sof_ipc_tx_message_no_reply(sdev->ipc, &stream, sizeof(stream));
if (ret < 0)
dev_err(scomp->dev, "%s: Failed to trigger %s\n", __func__, swidget->widget->name);
@@ -1982,7 +1978,6 @@ static int sof_ipc3_widget_bind_event(struct snd_soc_component *scomp,
static int sof_ipc3_complete_pipeline(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget)
{
struct sof_ipc_pipe_ready ready;
- struct sof_ipc_reply reply;
int ret;
dev_dbg(sdev->dev, "tplg: complete pipeline %s id %d\n",
@@ -1993,7 +1988,7 @@ static int sof_ipc3_complete_pipeline(struct snd_sof_dev *sdev, struct snd_sof_w
ready.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_PIPE_COMPLETE;
ready.comp_id = swidget->comp_id;
- ret = sof_ipc_tx_message(sdev->ipc, &ready, sizeof(ready), &reply, sizeof(reply));
+ ret = sof_ipc_tx_message_no_reply(sdev->ipc, &ready, sizeof(ready));
if (ret < 0)
return ret;
@@ -2009,7 +2004,6 @@ static int sof_ipc3_widget_free(struct snd_sof_dev *sdev, struct snd_sof_widget
},
.id = swidget->comp_id,
};
- struct sof_ipc_reply reply;
int ret;
if (!swidget->private)
@@ -2029,8 +2023,7 @@ static int sof_ipc3_widget_free(struct snd_sof_dev *sdev, struct snd_sof_widget
break;
}
- ret = sof_ipc_tx_message(sdev->ipc, &ipc_free, sizeof(ipc_free),
- &reply, sizeof(reply));
+ ret = sof_ipc_tx_message_no_reply(sdev->ipc, &ipc_free, sizeof(ipc_free));
if (ret < 0)
dev_err(sdev->dev, "failed to free widget %s\n", swidget->widget->name);
@@ -2044,7 +2037,6 @@ static int sof_ipc3_dai_config(struct snd_sof_dev *sdev, struct snd_sof_widget *
struct snd_sof_dai *dai = swidget->private;
struct sof_dai_private_data *private;
struct sof_ipc_dai_config *config;
- struct sof_ipc_reply reply;
int ret = 0;
if (!dai || !dai->private) {
@@ -2081,7 +2073,9 @@ static int sof_ipc3_dai_config(struct snd_sof_dev *sdev, struct snd_sof_widget *
break;
case SOF_DAI_INTEL_ALH:
if (data) {
- config->dai_index = data->dai_index;
+ /* save the dai_index during hw_params and reuse it for hw_free */
+ if (flags & SOF_DAI_CONFIG_FLAGS_HW_PARAMS)
+ config->dai_index = data->dai_index;
config->alh.stream_id = data->dai_data;
}
break;
@@ -2089,14 +2083,39 @@ static int sof_ipc3_dai_config(struct snd_sof_dev *sdev, struct snd_sof_widget *
break;
}
- config->flags = flags;
+ /*
+ * The dai_config op is invoked several times and the flags argument varies as below:
+ * BE DAI hw_params: When the op is invoked during the BE DAI hw_params, flags contains
+ * SOF_DAI_CONFIG_FLAGS_HW_PARAMS along with quirks
+ * FE DAI hw_params: When invoked during FE DAI hw_params after the DAI widget has
+ * just been set up in the DSP, flags is set to SOF_DAI_CONFIG_FLAGS_HW_PARAMS with no
+ * quirks
+ * BE DAI trigger: When invoked during the BE DAI trigger, flags is set to
+ * SOF_DAI_CONFIG_FLAGS_PAUSE and contains no quirks
+ * BE DAI hw_free: When invoked during the BE DAI hw_free, flags is set to
+ * SOF_DAI_CONFIG_FLAGS_HW_FREE and contains no quirks
+ * FE DAI hw_free: When invoked during the FE DAI hw_free, flags is set to
+ * SOF_DAI_CONFIG_FLAGS_HW_FREE and contains no quirks
+ *
+ * The DAI_CONFIG IPC is sent to the DSP, only after the widget is set up during the FE
+ * DAI hw_params. But since the BE DAI hw_params precedes the FE DAI hw_params, the quirks
+ * need to be preserved when assigning the flags before sending the IPC.
+ * For the case of PAUSE/HW_FREE, since there are no quirks, flags can be used as is.
+ */
+
+ if (flags & SOF_DAI_CONFIG_FLAGS_HW_PARAMS)
+ config->flags |= flags;
+ else
+ config->flags = flags;
/* only send the IPC if the widget is set up in the DSP */
if (swidget->use_count > 0) {
- ret = sof_ipc_tx_message(sdev->ipc, config, config->hdr.size,
- &reply, sizeof(reply));
+ ret = sof_ipc_tx_message_no_reply(sdev->ipc, config, config->hdr.size);
if (ret < 0)
dev_err(sdev->dev, "Failed to set dai config for %s\n", dai->name);
+
+ /* clear the flags once the IPC has been sent even if it fails */
+ config->flags = SOF_DAI_CONFIG_FLAGS_NONE;
}
return ret;
@@ -2104,7 +2123,6 @@ static int sof_ipc3_dai_config(struct snd_sof_dev *sdev, struct snd_sof_widget *
static int sof_ipc3_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget)
{
- struct sof_ipc_comp_reply reply;
int ret;
if (!swidget->private)
@@ -2118,8 +2136,7 @@ static int sof_ipc3_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget
struct sof_dai_private_data *dai_data = dai->private;
struct sof_ipc_comp *comp = &dai_data->comp_dai->comp;
- ret = sof_ipc_tx_message(sdev->ipc, dai_data->comp_dai,
- comp->hdr.size, &reply, sizeof(reply));
+ ret = sof_ipc_tx_message_no_reply(sdev->ipc, dai_data->comp_dai, comp->hdr.size);
break;
}
case snd_soc_dapm_scheduler:
@@ -2127,8 +2144,7 @@ static int sof_ipc3_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget
struct sof_ipc_pipe_new *pipeline;
pipeline = swidget->private;
- ret = sof_ipc_tx_message(sdev->ipc, pipeline, sizeof(*pipeline),
- &reply, sizeof(reply));
+ ret = sof_ipc_tx_message_no_reply(sdev->ipc, pipeline, sizeof(*pipeline));
break;
}
default:
@@ -2136,8 +2152,7 @@ static int sof_ipc3_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget
struct sof_ipc_cmd_hdr *hdr;
hdr = swidget->private;
- ret = sof_ipc_tx_message(sdev->ipc, swidget->private, hdr->size,
- &reply, sizeof(reply));
+ ret = sof_ipc_tx_message_no_reply(sdev->ipc, swidget->private, hdr->size);
break;
}
}