summaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2022-04-05 11:24:59 +0200
committerMark Brown <broonie@kernel.org>2022-04-05 11:24:59 +0200
commit5f6c3f90845343316d32a08bafea9faddbdfa6de (patch)
treee5f41351cc3d5c0b2ef4e7c408aa6f0cf3ed05d7 /sound
parentASoC: mediatek: Add support for MT8195 sound card with max98390 and rt5682 (diff)
parentASoC: SOF: Remove redundant return statements (diff)
downloadlinux-5f6c3f90845343316d32a08bafea9faddbdfa6de.tar.xz
linux-5f6c3f90845343316d32a08bafea9faddbdfa6de.zip
ASoC: SOF: Miscellaneous fixes for IPC and trace
Merge series from Ranjani Sridharan <ranjani.sridharan@linux.intel.com>: This series includes some miscellaenous fixes pertaining to IPC, DMA buffer and DMA trace.
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/sof/compress.c8
-rw-r--r--sound/soc/sof/debug.c2
-rw-r--r--sound/soc/sof/intel/hda-dsp.c8
-rw-r--r--sound/soc/sof/intel/hda-loader.c12
-rw-r--r--sound/soc/sof/intel/tgl.c6
-rw-r--r--sound/soc/sof/ipc.c76
-rw-r--r--sound/soc/sof/ipc3-pcm.c8
-rw-r--r--sound/soc/sof/ipc3-topology.c25
-rw-r--r--sound/soc/sof/ipc3.c4
-rw-r--r--sound/soc/sof/pcm.c5
-rw-r--r--sound/soc/sof/pm.c20
-rw-r--r--sound/soc/sof/sof-audio.c3
-rw-r--r--sound/soc/sof/sof-audio.h1
-rw-r--r--sound/soc/sof/sof-client.c2
-rw-r--r--sound/soc/sof/sof-priv.h26
-rw-r--r--sound/soc/sof/trace.c61
16 files changed, 131 insertions, 136 deletions
diff --git a/sound/soc/sof/compress.c b/sound/soc/sof/compress.c
index a8e908e50101..47639b6344c8 100644
--- a/sound/soc/sof/compress.c
+++ b/sound/soc/sof/compress.c
@@ -147,8 +147,7 @@ static int sof_compr_free(struct snd_soc_component *component,
stream.comp_id = spcm->stream[cstream->direction].comp_id;
if (spcm->prepared[cstream->direction]) {
- ret = sof_ipc_tx_message(sdev->ipc, stream.hdr.cmd,
- &stream, sizeof(stream),
+ ret = sof_ipc_tx_message(sdev->ipc, &stream, sizeof(stream),
&reply, sizeof(reply));
if (!ret)
spcm->prepared[cstream->direction] = false;
@@ -209,7 +208,7 @@ static int sof_compr_set_params(struct snd_soc_component *component,
snd_pcm_format_physical_width(SNDRV_PCM_FORMAT_S32) >> 3;
pcm.params.host_period_bytes = params->buffer.fragment_size;
- ret = sof_ipc_tx_message(sdev->ipc, pcm.hdr.cmd, &pcm, sizeof(pcm),
+ ret = sof_ipc_tx_message(sdev->ipc, &pcm, sizeof(pcm),
&ipc_params_reply, sizeof(ipc_params_reply));
if (ret < 0) {
dev_err(component->dev, "error ipc failed\n");
@@ -268,8 +267,7 @@ static int sof_compr_trigger(struct snd_soc_component *component,
break;
}
- return sof_ipc_tx_message(sdev->ipc, stream.hdr.cmd,
- &stream, sizeof(stream),
+ return sof_ipc_tx_message(sdev->ipc, &stream, sizeof(stream),
&reply, sizeof(reply));
}
diff --git a/sound/soc/sof/debug.c b/sound/soc/sof/debug.c
index 7b1139961a99..8a77245b5182 100644
--- a/sound/soc/sof/debug.c
+++ b/sound/soc/sof/debug.c
@@ -236,7 +236,7 @@ static int memory_info_update(struct snd_sof_dev *sdev, char *buf, size_t buff_s
goto error;
}
- ret = sof_ipc_tx_message(sdev->ipc, msg.cmd, &msg, msg.size, reply, SOF_IPC_MSG_MAX_SIZE);
+ ret = sof_ipc_tx_message(sdev->ipc, &msg, msg.size, reply, SOF_IPC_MSG_MAX_SIZE);
pm_runtime_mark_last_busy(sdev->dev);
pm_runtime_put_autosuspend(sdev->dev);
if (ret < 0 || reply->rhdr.error < 0) {
diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c
index 8ddde60c56b3..ad11df345be7 100644
--- a/sound/soc/sof/intel/hda-dsp.c
+++ b/sound/soc/sof/intel/hda-dsp.c
@@ -363,9 +363,8 @@ static int hda_dsp_send_pm_gate_ipc(struct snd_sof_dev *sdev, u32 flags)
pm_gate.flags = flags;
/* send pm_gate ipc to dsp */
- return sof_ipc_tx_message_no_pm(sdev->ipc, pm_gate.hdr.cmd,
- &pm_gate, sizeof(pm_gate), &reply,
- sizeof(reply));
+ return sof_ipc_tx_message_no_pm(sdev->ipc, &pm_gate, sizeof(pm_gate),
+ &reply, sizeof(reply));
}
static int hda_dsp_update_d0i3c_register(struct snd_sof_dev *sdev, u8 value)
@@ -985,8 +984,7 @@ int hda_dsp_core_get(struct snd_sof_dev *sdev, int core)
return 0;
/* Now notify DSP for secondary cores */
- ret = sof_ipc_tx_message(sdev->ipc, pm_core_config.hdr.cmd,
- &pm_core_config, sizeof(pm_core_config),
+ ret = sof_ipc_tx_message(sdev->ipc, &pm_core_config, sizeof(pm_core_config),
&pm_core_config, sizeof(pm_core_config));
if (ret < 0) {
dev_err(sdev->dev, "failed to enable secondary core '%d' failed with %d\n",
diff --git a/sound/soc/sof/intel/hda-loader.c b/sound/soc/sof/intel/hda-loader.c
index 2ac5d9d0719b..697d18a41a6e 100644
--- a/sound/soc/sof/intel/hda-loader.c
+++ b/sound/soc/sof/intel/hda-loader.c
@@ -313,6 +313,7 @@ int hda_dsp_cl_boot_firmware_iccmax(struct snd_sof_dev *sdev)
struct hdac_ext_stream *iccmax_stream;
struct hdac_bus *bus = sof_to_bus(sdev);
struct firmware stripped_firmware;
+ struct snd_dma_buffer dmab_bdl;
int ret, ret1;
u8 original_gb;
@@ -328,7 +329,7 @@ int hda_dsp_cl_boot_firmware_iccmax(struct snd_sof_dev *sdev)
/* prepare capture stream for ICCMAX */
iccmax_stream = cl_stream_prepare(sdev, HDA_CL_STREAM_FORMAT, stripped_firmware.size,
- &sdev->dmab_bdl, SNDRV_PCM_STREAM_CAPTURE);
+ &dmab_bdl, SNDRV_PCM_STREAM_CAPTURE);
if (IS_ERR(iccmax_stream)) {
dev_err(sdev->dev, "error: dma prepare for ICCMAX stream failed\n");
return PTR_ERR(iccmax_stream);
@@ -340,7 +341,7 @@ int hda_dsp_cl_boot_firmware_iccmax(struct snd_sof_dev *sdev)
* Perform iccmax stream cleanup. This should be done even if firmware loading fails.
* If the cleanup also fails, we return the initial error
*/
- ret1 = cl_cleanup(sdev, &sdev->dmab_bdl, iccmax_stream);
+ ret1 = cl_cleanup(sdev, &dmab_bdl, iccmax_stream);
if (ret1 < 0) {
dev_err(sdev->dev, "error: ICCMAX stream cleanup failed\n");
@@ -395,6 +396,7 @@ int hda_dsp_cl_boot_firmware(struct snd_sof_dev *sdev)
const struct sof_intel_dsp_desc *chip_info;
struct hdac_ext_stream *hext_stream;
struct firmware stripped_firmware;
+ struct snd_dma_buffer dmab;
int ret, ret1, i;
if ((sdev->fw_ready.flags & SOF_IPC_INFO_D3_PERSISTENT) &&
@@ -419,13 +421,13 @@ int hda_dsp_cl_boot_firmware(struct snd_sof_dev *sdev)
/* prepare DMA for code loader stream */
hext_stream = cl_stream_prepare(sdev, HDA_CL_STREAM_FORMAT, stripped_firmware.size,
- &sdev->dmab, SNDRV_PCM_STREAM_PLAYBACK);
+ &dmab, SNDRV_PCM_STREAM_PLAYBACK);
if (IS_ERR(hext_stream)) {
dev_err(sdev->dev, "error: dma prepare for fw loading failed\n");
return PTR_ERR(hext_stream);
}
- memcpy(sdev->dmab.area, stripped_firmware.data,
+ memcpy(dmab.area, stripped_firmware.data,
stripped_firmware.size);
/* try ROM init a few times before giving up */
@@ -486,7 +488,7 @@ cleanup:
* This should be done even if firmware loading fails.
* If the cleanup also fails, we return the initial error
*/
- ret1 = cl_cleanup(sdev, &sdev->dmab, hext_stream);
+ ret1 = cl_cleanup(sdev, &dmab, hext_stream);
if (ret1 < 0) {
dev_err(sdev->dev, "error: Code loader DSP cleanup failed\n");
diff --git a/sound/soc/sof/intel/tgl.c b/sound/soc/sof/intel/tgl.c
index cb1c319d5bee..72d92ff6cef5 100644
--- a/sound/soc/sof/intel/tgl.c
+++ b/sound/soc/sof/intel/tgl.c
@@ -35,8 +35,7 @@ static int tgl_dsp_core_get(struct snd_sof_dev *sdev, int core)
return hda_dsp_enable_core(sdev, BIT(core));
/* notify DSP for secondary cores */
- return sof_ipc_tx_message(sdev->ipc, pm_core_config.hdr.cmd,
- &pm_core_config, sizeof(pm_core_config),
+ return sof_ipc_tx_message(sdev->ipc, &pm_core_config, sizeof(pm_core_config),
&pm_core_config, sizeof(pm_core_config));
}
@@ -55,8 +54,7 @@ static int tgl_dsp_core_put(struct snd_sof_dev *sdev, int core)
return hda_dsp_core_reset_power_down(sdev, BIT(core));
/* notify DSP for secondary cores */
- return sof_ipc_tx_message(sdev->ipc, pm_core_config.hdr.cmd,
- &pm_core_config, sizeof(pm_core_config),
+ return sof_ipc_tx_message(sdev->ipc, &pm_core_config, sizeof(pm_core_config),
&pm_core_config, sizeof(pm_core_config));
}
diff --git a/sound/soc/sof/ipc.c b/sound/soc/sof/ipc.c
index 5f5753608c79..17dd51d342cf 100644
--- a/sound/soc/sof/ipc.c
+++ b/sound/soc/sof/ipc.c
@@ -341,9 +341,8 @@ static int sof_ipc_tx_message_unlocked(struct snd_sof_ipc *ipc,
}
/* send IPC message from host to DSP */
-int sof_ipc_tx_message(struct snd_sof_ipc *ipc, u32 header,
- void *msg_data, size_t msg_bytes, void *reply_data,
- size_t reply_bytes)
+int sof_ipc_tx_message(struct snd_sof_ipc *ipc, void *msg_data, size_t msg_bytes,
+ void *reply_data, size_t reply_bytes)
{
const struct sof_dsp_power_state target_state = {
.state = SOF_DSP_PM_D0,
@@ -357,7 +356,7 @@ int sof_ipc_tx_message(struct snd_sof_ipc *ipc, u32 header,
return ret;
}
- return sof_ipc_tx_message_no_pm(ipc, header, msg_data, msg_bytes,
+ return sof_ipc_tx_message_no_pm(ipc, msg_data, msg_bytes,
reply_data, reply_bytes);
}
EXPORT_SYMBOL(sof_ipc_tx_message);
@@ -367,14 +366,13 @@ EXPORT_SYMBOL(sof_ipc_tx_message);
* This will be used for IPC's that can be handled by the DSP
* even in a low-power D0 substate.
*/
-int sof_ipc_tx_message_no_pm(struct snd_sof_ipc *ipc, u32 header,
- void *msg_data, size_t msg_bytes,
+int sof_ipc_tx_message_no_pm(struct snd_sof_ipc *ipc, void *msg_data, size_t msg_bytes,
void *reply_data, size_t reply_bytes)
{
int ret;
- if (msg_bytes > SOF_IPC_MSG_MAX_SIZE ||
- reply_bytes > SOF_IPC_MSG_MAX_SIZE)
+ if (msg_bytes > ipc->max_payload_size ||
+ reply_bytes > ipc->max_payload_size)
return -ENOBUFS;
/* Serialise IPC TX */
@@ -393,7 +391,7 @@ EXPORT_SYMBOL(sof_ipc_tx_message_no_pm);
void snd_sof_ipc_get_reply(struct snd_sof_dev *sdev)
{
struct snd_sof_ipc_msg *msg = sdev->msg;
- struct sof_ipc_reply reply;
+ struct sof_ipc_reply *reply;
int ret = 0;
/*
@@ -407,13 +405,12 @@ void snd_sof_ipc_get_reply(struct snd_sof_dev *sdev)
}
/* get the generic reply */
- snd_sof_dsp_mailbox_read(sdev, sdev->host_box.offset, &reply,
- sizeof(reply));
+ reply = msg->reply_data;
+ snd_sof_dsp_mailbox_read(sdev, sdev->host_box.offset, reply, sizeof(*reply));
- if (reply.error < 0) {
- memcpy(msg->reply_data, &reply, sizeof(reply));
- ret = reply.error;
- } else if (!reply.hdr.size) {
+ if (reply->error < 0) {
+ ret = reply->error;
+ } else if (!reply->hdr.size) {
/* Reply should always be >= sizeof(struct sof_ipc_reply) */
if (msg->reply_size)
dev_err(sdev->dev,
@@ -424,24 +421,27 @@ void snd_sof_ipc_get_reply(struct snd_sof_dev *sdev)
ret = -EINVAL;
} else if (msg->reply_size > 0) {
- if (reply.hdr.size == msg->reply_size) {
+ if (reply->hdr.size == msg->reply_size) {
ret = 0;
- } else if (reply.hdr.size < msg->reply_size) {
+ } else if (reply->hdr.size < msg->reply_size) {
dev_dbg(sdev->dev,
"reply size (%u) is less than expected (%zu)\n",
- reply.hdr.size, msg->reply_size);
+ reply->hdr.size, msg->reply_size);
- msg->reply_size = reply.hdr.size;
+ msg->reply_size = reply->hdr.size;
ret = 0;
} else {
dev_err(sdev->dev,
"reply size (%u) exceeds the buffer size (%zu)\n",
- reply.hdr.size, msg->reply_size);
+ reply->hdr.size, msg->reply_size);
ret = -EINVAL;
}
- /* get the full message if reply.hdr.size <= msg->reply_size */
- if (!ret)
+ /*
+ * get the full message if reply->hdr.size <= msg->reply_size
+ * and the reply->hdr.size > sizeof(struct sof_ipc_reply)
+ */
+ if (!ret && msg->reply_size > sizeof(*reply))
snd_sof_dsp_mailbox_read(sdev, sdev->host_box.offset,
msg->reply_data, msg->reply_size);
}
@@ -699,8 +699,7 @@ int snd_sof_ipc_stream_posn(struct snd_soc_component *scomp,
stream.comp_id = spcm->stream[direction].comp_id;
/* send IPC to the DSP */
- err = sof_ipc_tx_message(sdev->ipc,
- stream.hdr.cmd, &stream, sizeof(stream), posn,
+ err = sof_ipc_tx_message(sdev->ipc, &stream, sizeof(stream), posn,
sizeof(*posn));
if (err < 0) {
dev_err(sdev->dev, "error: failed to get stream %d position\n",
@@ -823,7 +822,6 @@ int snd_sof_ipc_set_get_comp_data(struct snd_sof_control *scontrol, bool set)
enum sof_ipc_ctrl_type ctrl_type;
struct snd_sof_widget *swidget;
bool widget_found = false;
- size_t send_bytes;
u32 ipc_cmd;
int err;
@@ -847,27 +845,6 @@ int snd_sof_ipc_set_get_comp_data(struct snd_sof_control *scontrol, bool set)
if (!swidget->use_count)
return 0;
- /* read or write firmware volume */
- if (scontrol->readback_offset != 0) {
- /* write/read value header via mmaped region */
- send_bytes = sizeof(struct sof_ipc_ctrl_value_chan) *
- cdata->num_elems;
- if (set)
- err = snd_sof_dsp_block_write(sdev, SOF_FW_BLK_TYPE_IRAM,
- scontrol->readback_offset,
- cdata->chanv, send_bytes);
-
- else
- err = snd_sof_dsp_block_read(sdev, SOF_FW_BLK_TYPE_IRAM,
- scontrol->readback_offset,
- cdata->chanv, send_bytes);
-
- if (err)
- dev_err_once(sdev->dev, "error: %s TYPE_IRAM failed\n",
- set ? "write to" : "read from");
- return err;
- }
-
/*
* Select the IPC cmd and the ctrl_type based on the ctrl_cmd and the
* direction
@@ -913,9 +890,8 @@ int snd_sof_ipc_set_get_comp_data(struct snd_sof_control *scontrol, bool set)
/* send normal size ipc in one part */
if (cdata->rhdr.hdr.size <= SOF_IPC_MSG_MAX_SIZE) {
- err = sof_ipc_tx_message(sdev->ipc, cdata->rhdr.hdr.cmd, cdata,
- cdata->rhdr.hdr.size, cdata,
- cdata->rhdr.hdr.size);
+ err = sof_ipc_tx_message(sdev->ipc, cdata, cdata->rhdr.hdr.size,
+ cdata, cdata->rhdr.hdr.size);
if (err < 0)
dev_err(sdev->dev, "error: set/get ctrl ipc comp %d\n",
@@ -1005,6 +981,8 @@ int sof_ipc_init_msg_memory(struct snd_sof_dev *sdev)
if (!msg->reply_data)
return -ENOMEM;
+ sdev->ipc->max_payload_size = SOF_IPC_MSG_MAX_SIZE;
+
return 0;
}
diff --git a/sound/soc/sof/ipc3-pcm.c b/sound/soc/sof/ipc3-pcm.c
index 58b75943cf6d..d7b6c67b2180 100644
--- a/sound/soc/sof/ipc3-pcm.c
+++ b/sound/soc/sof/ipc3-pcm.c
@@ -34,8 +34,7 @@ static int sof_ipc3_pcm_hw_free(struct snd_soc_component *component,
stream.comp_id = spcm->stream[substream->stream].comp_id;
/* send IPC to the DSP */
- return sof_ipc_tx_message(sdev->ipc, stream.hdr.cmd, &stream,
- sizeof(stream), &reply, sizeof(reply));
+ return sof_ipc_tx_message(sdev->ipc, &stream, sizeof(stream), &reply, sizeof(reply));
}
static int sof_ipc3_pcm_hw_params(struct snd_soc_component *component,
@@ -119,7 +118,7 @@ static int sof_ipc3_pcm_hw_params(struct snd_soc_component *component,
dev_dbg(component->dev, "stream_tag %d", pcm.params.stream_tag);
/* send hw_params IPC to the DSP */
- ret = sof_ipc_tx_message(sdev->ipc, pcm.hdr.cmd, &pcm, sizeof(pcm),
+ ret = sof_ipc_tx_message(sdev->ipc, &pcm, sizeof(pcm),
&ipc_params_reply, sizeof(ipc_params_reply));
if (ret < 0) {
dev_err(component->dev, "HW params ipc failed for stream %d\n",
@@ -175,8 +174,7 @@ static int sof_ipc3_pcm_trigger(struct snd_soc_component *component,
}
/* send IPC to the DSP */
- return sof_ipc_tx_message(sdev->ipc, stream.hdr.cmd, &stream,
- sizeof(stream), &reply, sizeof(reply));
+ return sof_ipc_tx_message(sdev->ipc, &stream, sizeof(stream), &reply, sizeof(reply));
}
static void ssp_dai_config_pcm_params_match(struct snd_sof_dev *sdev, const char *link_name,
diff --git a/sound/soc/sof/ipc3-topology.c b/sound/soc/sof/ipc3-topology.c
index 2e1c76ed087d..572bcbfdb356 100644
--- a/sound/soc/sof/ipc3-topology.c
+++ b/sound/soc/sof/ipc3-topology.c
@@ -1551,8 +1551,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.hdr.cmd, &connect, sizeof(connect),
- &reply, sizeof(reply));
+ ret = sof_ipc_tx_message(sdev->ipc, &connect, sizeof(connect), &reply, sizeof(reply));
if (ret < 0)
dev_err(sdev->dev, "%s: route %s -> %s failed\n", __func__,
sroute->src_widget->widget->name, sroute->sink_widget->widget->name);
@@ -1698,7 +1697,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.hdr.cmd, &fcomp, sizeof(fcomp), NULL, 0);
+ return sof_ipc_tx_message(sdev->ipc, &fcomp, sizeof(fcomp), NULL, 0);
}
/* send pcm params ipc */
@@ -1750,7 +1749,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.hdr.cmd, &pcm, sizeof(pcm),
+ ret = sof_ipc_tx_message(sdev->ipc, &pcm, sizeof(pcm),
&ipc_params_reply, sizeof(ipc_params_reply));
if (ret < 0)
dev_err(scomp->dev, "%s: PCM params failed for %s\n", __func__,
@@ -1774,8 +1773,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.hdr.cmd, &stream,
- sizeof(stream), &reply, sizeof(reply));
+ ret = sof_ipc_tx_message(sdev->ipc, &stream, sizeof(stream), &reply, sizeof(reply));
if (ret < 0)
dev_err(scomp->dev, "%s: Failed to trigger %s\n", __func__, swidget->widget->name);
@@ -1903,8 +1901,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.hdr.cmd, &ready, sizeof(ready), &reply,
- sizeof(reply));
+ ret = sof_ipc_tx_message(sdev->ipc, &ready, sizeof(ready), &reply, sizeof(reply));
if (ret < 0)
return ret;
@@ -1940,7 +1937,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.hdr.cmd, &ipc_free, sizeof(ipc_free),
+ ret = sof_ipc_tx_message(sdev->ipc, &ipc_free, sizeof(ipc_free),
&reply, sizeof(reply));
if (ret < 0)
dev_err(sdev->dev, "failed to free widget %s\n", swidget->widget->name);
@@ -2004,7 +2001,7 @@ static int sof_ipc3_dai_config(struct snd_sof_dev *sdev, struct snd_sof_widget *
/* 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->hdr.cmd, config, config->hdr.size,
+ ret = sof_ipc_tx_message(sdev->ipc, config, config->hdr.size,
&reply, sizeof(reply));
if (ret < 0)
dev_err(sdev->dev, "Failed to set dai config for %s\n", dai->name);
@@ -2029,7 +2026,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, comp->hdr.cmd, dai_data->comp_dai,
+ ret = sof_ipc_tx_message(sdev->ipc, dai_data->comp_dai,
comp->hdr.size, &reply, sizeof(reply));
break;
}
@@ -2038,8 +2035,8 @@ 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->hdr.cmd, pipeline,
- sizeof(*pipeline), &reply, sizeof(reply));
+ ret = sof_ipc_tx_message(sdev->ipc, pipeline, sizeof(*pipeline),
+ &reply, sizeof(reply));
break;
}
default:
@@ -2047,7 +2044,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, hdr->cmd, swidget->private, hdr->size,
+ ret = sof_ipc_tx_message(sdev->ipc, swidget->private, hdr->size,
&reply, sizeof(reply));
break;
}
diff --git a/sound/soc/sof/ipc3.c b/sound/soc/sof/ipc3.c
index 03e914b62728..a7289804efda 100644
--- a/sound/soc/sof/ipc3.c
+++ b/sound/soc/sof/ipc3.c
@@ -19,8 +19,8 @@ static int sof_ipc3_ctx_ipc(struct snd_sof_dev *sdev, int cmd)
struct sof_ipc_reply reply;
/* send ctx save ipc to dsp */
- return sof_ipc_tx_message(sdev->ipc, pm_ctx.hdr.cmd, &pm_ctx,
- sizeof(pm_ctx), &reply, sizeof(reply));
+ return sof_ipc_tx_message(sdev->ipc, &pm_ctx, sizeof(pm_ctx),
+ &reply, sizeof(reply));
}
static int sof_ipc3_ctx_save(struct snd_sof_dev *sdev)
diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c
index 658cd8966c9a..b5cbc8b5c0ee 100644
--- a/sound/soc/sof/pcm.c
+++ b/sound/soc/sof/pcm.c
@@ -347,12 +347,9 @@ static int sof_pcm_trigger(struct snd_soc_component *component,
snd_sof_pcm_platform_trigger(sdev, substream, cmd);
/* free PCM if reset_hw_params is set and the STOP IPC is successful */
- if (!ret && reset_hw_params) {
+ if (!ret && reset_hw_params)
ret = sof_pcm_stream_free(sdev, substream, spcm, substream->stream,
free_widget_list);
- if (ret < 0)
- return ret;
- }
return ret;
}
diff --git a/sound/soc/sof/pm.c b/sound/soc/sof/pm.c
index 1c319582ca6f..44008dd075c2 100644
--- a/sound/soc/sof/pm.c
+++ b/sound/soc/sof/pm.c
@@ -102,11 +102,18 @@ static int sof_resume(struct device *dev, bool runtime_resume)
/*
* Nothing further to be done for platforms that support the low power
- * D0 substate.
+ * D0 substate. Resume trace and return when resuming from
+ * low-power D0 substate
*/
if (!runtime_resume && sof_ops(sdev)->set_power_state &&
- old_state == SOF_DSP_PM_D0)
+ old_state == SOF_DSP_PM_D0) {
+ ret = snd_sof_trace_resume(sdev);
+ if (ret < 0)
+ /* non fatal */
+ dev_warn(sdev->dev,
+ "failed to enable trace after resume %d\n", ret);
return 0;
+ }
sof_set_fw_state(sdev, SOF_FW_BOOT_PREPARE);
@@ -135,8 +142,8 @@ static int sof_resume(struct device *dev, bool runtime_resume)
return ret;
}
- /* resume DMA trace, only need send ipc */
- ret = snd_sof_init_trace_ipc(sdev);
+ /* resume DMA trace */
+ ret = snd_sof_trace_resume(sdev);
if (ret < 0) {
/* non fatal */
dev_warn(sdev->dev,
@@ -201,6 +208,7 @@ static int sof_suspend(struct device *dev, bool runtime_suspend)
/* Skip to platform-specific suspend if DSP is entering D0 */
if (target_state == SOF_DSP_PM_D0) {
+ snd_sof_trace_suspend(sdev, pm_state);
/* Notify clients not managed by pm framework about core suspend */
sof_suspend_clients(sdev, pm_state);
goto suspend;
@@ -209,8 +217,8 @@ static int sof_suspend(struct device *dev, bool runtime_suspend)
if (tplg_ops->tear_down_all_pipelines)
tplg_ops->tear_down_all_pipelines(sdev, false);
- /* release trace */
- snd_sof_release_trace(sdev);
+ /* suspend DMA trace */
+ snd_sof_trace_suspend(sdev, pm_state);
/* Notify clients not managed by pm framework about core suspend */
sof_suspend_clients(sdev, pm_state);
diff --git a/sound/soc/sof/sof-audio.c b/sound/soc/sof/sof-audio.c
index b2f009a0c5b7..49fdfe06a9a3 100644
--- a/sound/soc/sof/sof-audio.c
+++ b/sound/soc/sof/sof-audio.c
@@ -16,9 +16,6 @@ static int sof_kcontrol_setup(struct snd_sof_dev *sdev, struct snd_sof_control *
{
int ret;
- /* reset readback offset for scontrol */
- scontrol->readback_offset = 0;
-
ret = snd_sof_ipc_set_get_comp_data(scontrol, true);
if (ret < 0)
dev_err(sdev->dev, "error: failed kcontrol value set for widget: %d\n",
diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h
index 7f15b3bc8196..4a8cd7f2a0eb 100644
--- a/sound/soc/sof/sof-audio.h
+++ b/sound/soc/sof/sof-audio.h
@@ -247,7 +247,6 @@ struct snd_sof_control {
int max_volume_step; /* max volume step for volume_table */
int num_channels;
unsigned int access;
- u32 readback_offset; /* offset to mmapped data if used */
int info_type;
int index; /* pipeline ID */
void *priv; /* private data copied from topology */
diff --git a/sound/soc/sof/sof-client.c b/sound/soc/sof/sof-client.c
index 686ad0c3bb61..5fb3eb21bf7d 100644
--- a/sound/soc/sof/sof-client.c
+++ b/sound/soc/sof/sof-client.c
@@ -247,7 +247,7 @@ int sof_client_ipc_tx_message(struct sof_client_dev *cdev, void *ipc_msg,
{
struct sof_ipc_cmd_hdr *hdr = ipc_msg;
- return sof_ipc_tx_message(cdev->sdev->ipc, hdr->cmd, ipc_msg, hdr->size,
+ return sof_ipc_tx_message(cdev->sdev->ipc, ipc_msg, hdr->size,
reply_data, reply_bytes);
}
EXPORT_SYMBOL_NS_GPL(sof_client_ipc_tx_message, SND_SOC_SOF_CLIENT);
diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h
index e537b1258aa8..df19d58d8894 100644
--- a/sound/soc/sof/sof-priv.h
+++ b/sound/soc/sof/sof-priv.h
@@ -349,7 +349,6 @@ struct snd_sof_mailbox {
/* IPC message descriptor for host <-> DSP IO */
struct snd_sof_ipc_msg {
/* message data */
- u32 header;
void *msg_data;
void *reply_data;
size_t msg_size;
@@ -394,12 +393,21 @@ struct snd_sof_ipc {
/* disables further sending of ipc's */
bool disable_ipc_tx;
+ /* Maximum allowed size of a single IPC message/reply */
+ size_t max_payload_size;
+
struct snd_sof_ipc_msg msg;
/* IPC ops based on version */
const struct sof_ipc_ops *ops;
};
+enum sof_dtrace_state {
+ SOF_DTRACE_DISABLED,
+ SOF_DTRACE_STOPPED,
+ SOF_DTRACE_ENABLED,
+};
+
/*
* SOF Device Level.
*/
@@ -457,8 +465,6 @@ struct snd_sof_dev {
bool ipc_dump_printed;
/* firmware loader */
- struct snd_dma_buffer dmab;
- struct snd_dma_buffer dmab_bdl;
struct sof_ipc_fw_ready fw_ready;
struct sof_ipc_fw_version fw_version;
struct sof_ipc_cc_version *cc_version;
@@ -489,9 +495,9 @@ struct snd_sof_dev {
wait_queue_head_t trace_sleep;
u32 host_offset;
bool dtrace_is_supported; /* set with Kconfig or module parameter */
- bool dtrace_is_enabled;
bool dtrace_error;
bool dtrace_draining;
+ enum sof_dtrace_state dtrace_state;
bool msi_enabled;
@@ -578,11 +584,9 @@ void snd_sof_ipc_get_reply(struct snd_sof_dev *sdev);
void snd_sof_ipc_reply(struct snd_sof_dev *sdev, u32 msg_id);
void snd_sof_ipc_msgs_rx(struct snd_sof_dev *sdev);
int snd_sof_ipc_valid(struct snd_sof_dev *sdev);
-int sof_ipc_tx_message(struct snd_sof_ipc *ipc, u32 header,
- void *msg_data, size_t msg_bytes, void *reply_data,
- size_t reply_bytes);
-int sof_ipc_tx_message_no_pm(struct snd_sof_ipc *ipc, u32 header,
- void *msg_data, size_t msg_bytes,
+int sof_ipc_tx_message(struct snd_sof_ipc *ipc, void *msg_data, size_t msg_bytes,
+ void *reply_data, size_t reply_bytes);
+int sof_ipc_tx_message_no_pm(struct snd_sof_ipc *ipc, void *msg_data, size_t msg_bytes,
void *reply_data, size_t reply_bytes);
int sof_ipc_init_msg_memory(struct snd_sof_dev *sdev);
static inline void snd_sof_ipc_process_reply(struct snd_sof_dev *sdev, u32 msg_id)
@@ -595,7 +599,6 @@ static inline void snd_sof_ipc_process_reply(struct snd_sof_dev *sdev, u32 msg_i
* Trace/debug
*/
int snd_sof_init_trace(struct snd_sof_dev *sdev);
-void snd_sof_release_trace(struct snd_sof_dev *sdev);
void snd_sof_free_trace(struct snd_sof_dev *sdev);
int snd_sof_dbg_init(struct snd_sof_dev *sdev);
void snd_sof_free_debug(struct snd_sof_dev *sdev);
@@ -609,7 +612,8 @@ void sof_print_oops_and_stack(struct snd_sof_dev *sdev, const char *level,
u32 panic_code, u32 tracep_code, void *oops,
struct sof_ipc_panic_info *panic_info,
void *stack, size_t stack_words);
-int snd_sof_init_trace_ipc(struct snd_sof_dev *sdev);
+void snd_sof_trace_suspend(struct snd_sof_dev *sdev, pm_message_t pm_state);
+int snd_sof_trace_resume(struct snd_sof_dev *sdev);
void snd_sof_handle_fw_exception(struct snd_sof_dev *sdev);
int snd_sof_dbg_memory_info_init(struct snd_sof_dev *sdev);
int snd_sof_debugfs_add_region_item_iomem(struct snd_sof_dev *sdev,
diff --git a/sound/soc/sof/trace.c b/sound/soc/sof/trace.c
index ea8e4506d02e..ba6361b5d64b 100644
--- a/sound/soc/sof/trace.c
+++ b/sound/soc/sof/trace.c
@@ -11,6 +11,7 @@
#include <linux/debugfs.h>
#include <linux/sched/signal.h>
#include "sof-priv.h"
+#include "sof-audio.h"
#include "ops.h"
#include "sof-utils.h"
@@ -151,8 +152,7 @@ static int sof_ipc_trace_update_filter(struct snd_sof_dev *sdev, int num_elems,
dev_err(sdev->dev, "error: enabling device failed: %d\n", ret);
goto error;
}
- ret = sof_ipc_tx_message(sdev->ipc, msg->hdr.cmd, msg, msg->hdr.size,
- &reply, sizeof(reply));
+ ret = sof_ipc_tx_message(sdev->ipc, msg, msg->hdr.size, &reply, sizeof(reply));
pm_runtime_mark_last_busy(sdev->dev);
pm_runtime_put_autosuspend(sdev->dev);
@@ -263,7 +263,7 @@ static size_t sof_wait_trace_avail(struct snd_sof_dev *sdev,
if (ret)
return ret;
- if (!sdev->dtrace_is_enabled && sdev->dtrace_draining) {
+ if (sdev->dtrace_state != SOF_DTRACE_ENABLED && sdev->dtrace_draining) {
/*
* tracing has ended and all traces have been
* read by client, return EOF
@@ -344,7 +344,7 @@ static int sof_dfsentry_trace_release(struct inode *inode, struct file *file)
struct snd_sof_dev *sdev = dfse->sdev;
/* avoid duplicate traces at next open */
- if (!sdev->dtrace_is_enabled)
+ if (sdev->dtrace_state != SOF_DTRACE_ENABLED)
sdev->host_offset = 0;
return 0;
@@ -384,7 +384,7 @@ static int trace_debugfs_create(struct snd_sof_dev *sdev)
return 0;
}
-int snd_sof_init_trace_ipc(struct snd_sof_dev *sdev)
+static int snd_sof_enable_trace(struct snd_sof_dev *sdev)
{
struct sof_ipc_fw_ready *ready = &sdev->fw_ready;
struct sof_ipc_fw_version *v = &ready->version;
@@ -395,9 +395,12 @@ int snd_sof_init_trace_ipc(struct snd_sof_dev *sdev)
if (!sdev->dtrace_is_supported)
return 0;
- if (sdev->dtrace_is_enabled || !sdev->dma_trace_pages)
+ if (sdev->dtrace_state == SOF_DTRACE_ENABLED || !sdev->dma_trace_pages)
return -EINVAL;
+ if (sdev->dtrace_state == SOF_DTRACE_STOPPED)
+ goto start;
+
/* set IPC parameters */
params.hdr.cmd = SOF_IPC_GLB_TRACE_MSG;
/* PARAMS_EXT is only supported from ABI 3.7.0 onwards */
@@ -426,15 +429,14 @@ int snd_sof_init_trace_ipc(struct snd_sof_dev *sdev)
dev_dbg(sdev->dev, "%s: stream_tag: %d\n", __func__, params.stream_tag);
/* send IPC to the DSP */
- ret = sof_ipc_tx_message(sdev->ipc,
- params.hdr.cmd, &params, sizeof(params),
- &ipc_reply, sizeof(ipc_reply));
+ ret = sof_ipc_tx_message(sdev->ipc, &params, sizeof(params), &ipc_reply, sizeof(ipc_reply));
if (ret < 0) {
dev_err(sdev->dev,
"error: can't set params for DMA for trace %d\n", ret);
goto trace_release;
}
+start:
ret = snd_sof_dma_trace_trigger(sdev, SNDRV_PCM_TRIGGER_START);
if (ret < 0) {
dev_err(sdev->dev,
@@ -442,7 +444,7 @@ int snd_sof_init_trace_ipc(struct snd_sof_dev *sdev)
goto trace_release;
}
- sdev->dtrace_is_enabled = true;
+ sdev->dtrace_state = SOF_DTRACE_ENABLED;
return 0;
@@ -459,7 +461,7 @@ int snd_sof_init_trace(struct snd_sof_dev *sdev)
return 0;
/* set false before start initialization */
- sdev->dtrace_is_enabled = false;
+ sdev->dtrace_state = SOF_DTRACE_DISABLED;
/* allocate trace page table buffer */
ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, sdev->dev,
@@ -498,7 +500,7 @@ int snd_sof_init_trace(struct snd_sof_dev *sdev)
init_waitqueue_head(&sdev->trace_sleep);
- ret = snd_sof_init_trace_ipc(sdev);
+ ret = snd_sof_enable_trace(sdev);
if (ret < 0)
goto table_err;
@@ -518,7 +520,8 @@ int snd_sof_trace_update_pos(struct snd_sof_dev *sdev,
if (!sdev->dtrace_is_supported)
return 0;
- if (sdev->dtrace_is_enabled && sdev->host_offset != posn->host_offset) {
+ if (sdev->dtrace_state == SOF_DTRACE_ENABLED &&
+ sdev->host_offset != posn->host_offset) {
sdev->host_offset = posn->host_offset;
wake_up(&sdev->trace_sleep);
}
@@ -537,14 +540,14 @@ void snd_sof_trace_notify_for_error(struct snd_sof_dev *sdev)
if (!sdev->dtrace_is_supported)
return;
- if (sdev->dtrace_is_enabled) {
+ if (sdev->dtrace_state == SOF_DTRACE_ENABLED) {
sdev->dtrace_error = true;
wake_up(&sdev->trace_sleep);
}
}
EXPORT_SYMBOL(snd_sof_trace_notify_for_error);
-void snd_sof_release_trace(struct snd_sof_dev *sdev)
+static void snd_sof_release_trace(struct snd_sof_dev *sdev, bool only_stop)
{
struct sof_ipc_fw_ready *ready = &sdev->fw_ready;
struct sof_ipc_fw_version *v = &ready->version;
@@ -552,13 +555,14 @@ void snd_sof_release_trace(struct snd_sof_dev *sdev)
struct sof_ipc_reply ipc_reply;
int ret;
- if (!sdev->dtrace_is_supported || !sdev->dtrace_is_enabled)
+ if (!sdev->dtrace_is_supported || sdev->dtrace_state == SOF_DTRACE_DISABLED)
return;
ret = snd_sof_dma_trace_trigger(sdev, SNDRV_PCM_TRIGGER_STOP);
if (ret < 0)
dev_err(sdev->dev,
"error: snd_sof_dma_trace_trigger: stop: %d\n", ret);
+ sdev->dtrace_state = SOF_DTRACE_STOPPED;
/*
* stop and free trace DMA in the DSP. TRACE_DMA_FREE is only supported from
@@ -568,29 +572,46 @@ void snd_sof_release_trace(struct snd_sof_dev *sdev)
hdr.size = sizeof(hdr);
hdr.cmd = SOF_IPC_GLB_TRACE_MSG | SOF_IPC_TRACE_DMA_FREE;
- ret = sof_ipc_tx_message(sdev->ipc, hdr.cmd, &hdr, hdr.size,
+ ret = sof_ipc_tx_message(sdev->ipc, &hdr, hdr.size,
&ipc_reply, sizeof(ipc_reply));
if (ret < 0)
dev_err(sdev->dev, "DMA_TRACE_FREE failed with error: %d\n", ret);
}
+ if (only_stop)
+ goto out;
+
ret = snd_sof_dma_trace_release(sdev);
if (ret < 0)
dev_err(sdev->dev,
"error: fail in snd_sof_dma_trace_release %d\n", ret);
- sdev->dtrace_is_enabled = false;
+ sdev->dtrace_state = SOF_DTRACE_DISABLED;
+
+out:
sdev->dtrace_draining = true;
wake_up(&sdev->trace_sleep);
}
-EXPORT_SYMBOL(snd_sof_release_trace);
+
+void snd_sof_trace_suspend(struct snd_sof_dev *sdev, pm_message_t pm_state)
+{
+ snd_sof_release_trace(sdev, pm_state.event == SOF_DSP_PM_D0);
+}
+EXPORT_SYMBOL(snd_sof_trace_suspend);
+
+int snd_sof_trace_resume(struct snd_sof_dev *sdev)
+{
+ return snd_sof_enable_trace(sdev);
+}
+EXPORT_SYMBOL(snd_sof_trace_resume);
void snd_sof_free_trace(struct snd_sof_dev *sdev)
{
if (!sdev->dtrace_is_supported)
return;
- snd_sof_release_trace(sdev);
+ /* release trace */
+ snd_sof_release_trace(sdev, false);
if (sdev->dma_trace_pages) {
snd_dma_free_pages(&sdev->dmatb);