mirror of
https://github.com/torvalds/linux.git
synced 2024-11-26 06:02:05 +00:00
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.
This commit is contained in:
commit
5f6c3f9084
@ -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));
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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",
|
||||
|
@ -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");
|
||||
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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",
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user