diff options
author | Mark Brown <broonie@kernel.org> | 2022-04-05 11:24:59 +0200 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2022-04-05 11:24:59 +0200 |
commit | 5f6c3f90845343316d32a08bafea9faddbdfa6de (patch) | |
tree | e5f41351cc3d5c0b2ef4e7c408aa6f0cf3ed05d7 /sound | |
parent | ASoC: mediatek: Add support for MT8195 sound card with max98390 and rt5682 (diff) | |
parent | ASoC: SOF: Remove redundant return statements (diff) | |
download | linux-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.c | 8 | ||||
-rw-r--r-- | sound/soc/sof/debug.c | 2 | ||||
-rw-r--r-- | sound/soc/sof/intel/hda-dsp.c | 8 | ||||
-rw-r--r-- | sound/soc/sof/intel/hda-loader.c | 12 | ||||
-rw-r--r-- | sound/soc/sof/intel/tgl.c | 6 | ||||
-rw-r--r-- | sound/soc/sof/ipc.c | 76 | ||||
-rw-r--r-- | sound/soc/sof/ipc3-pcm.c | 8 | ||||
-rw-r--r-- | sound/soc/sof/ipc3-topology.c | 25 | ||||
-rw-r--r-- | sound/soc/sof/ipc3.c | 4 | ||||
-rw-r--r-- | sound/soc/sof/pcm.c | 5 | ||||
-rw-r--r-- | sound/soc/sof/pm.c | 20 | ||||
-rw-r--r-- | sound/soc/sof/sof-audio.c | 3 | ||||
-rw-r--r-- | sound/soc/sof/sof-audio.h | 1 | ||||
-rw-r--r-- | sound/soc/sof/sof-client.c | 2 | ||||
-rw-r--r-- | sound/soc/sof/sof-priv.h | 26 | ||||
-rw-r--r-- | sound/soc/sof/trace.c | 61 |
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, ¶ms, sizeof(params), - &ipc_reply, sizeof(ipc_reply)); + ret = sof_ipc_tx_message(sdev->ipc, ¶ms, 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); |