Commit 5a8a9d70 authored by Peter Ujfalusi's avatar Peter Ujfalusi Committed by Mark Brown

ASoC: SOF: Intel: hda-loader: Add support for split library loading

There is a certain sequence needs to be followed when configuring the HDA
DMA in host and DSP.
The firmware provides a way to handle this two stage sequencing by
splitting the library loading into two stage:
1st stage: LOAD_LIBRARY_PREPARE message
           the lib_id is 0, used to configure the DMA on DSP side
2nd stage: LOAD_LIBRARY message
           both dma_id and lib_id is valid, used for the actual transfer of
           the library

In case a firmware without support for this two stage loading is used then
the second stage message will trigger the loading and the first stage will
return with error, which is ignored by the kernel.
Signed-off-by: default avatarPeter Ujfalusi <peter.ujfalusi@linux.intel.com>
Reviewed-by: default avatarPierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: default avatarGuennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
Reviewed-by: default avatarRanjani Sridharan <ranjani.sridharan@linux.intel.com>
Reviewed-by: default avatarChao Song <chao.song@linux.intel.com>
Link: https://lore.kernel.org/r/20230915114018.1701-5-peter.ujfalusi@linux.intel.comSigned-off-by: default avatarMark Brown <broonie@kernel.org>
parent 4f0f3c77
......@@ -545,11 +545,40 @@ int hda_dsp_ipc4_load_library(struct snd_sof_dev *sdev,
memcpy(dmab.area, stripped_firmware.data, stripped_firmware.size);
/*
* 1st stage: SOF_IPC4_GLB_LOAD_LIBRARY_PREPARE
* Message includes the dma_id to be prepared for the library loading.
* If the firmware does not have support for the message, we will
* receive -EOPNOTSUPP. In this case we will use single step library
* loading and proceed to send the LOAD_LIBRARY message.
*/
msg.primary = hext_stream->hstream.stream_tag - 1;
msg.primary |= SOF_IPC4_MSG_TYPE_SET(SOF_IPC4_GLB_LOAD_LIBRARY);
msg.primary |= SOF_IPC4_MSG_TYPE_SET(SOF_IPC4_GLB_LOAD_LIBRARY_PREPARE);
msg.primary |= SOF_IPC4_MSG_DIR(SOF_IPC4_MSG_REQUEST);
msg.primary |= SOF_IPC4_MSG_TARGET(SOF_IPC4_FW_GEN_MSG);
msg.primary |= SOF_IPC4_GLB_LOAD_LIBRARY_LIB_ID(fw_lib->id);
ret = sof_ipc_tx_message_no_reply(sdev->ipc, &msg, 0);
if (!ret) {
int sd_offset = SOF_STREAM_SD_OFFSET(&hext_stream->hstream);
unsigned int status;
/*
* Make sure that the FIFOS value is not 0 in SDxFIFOS register
* which indicates that the firmware set the GEN bit and we can
* continue to start the DMA
*/
ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_HDA_BAR,
sd_offset + SOF_HDA_ADSP_REG_SD_FIFOSIZE,
status,
status & SOF_HDA_SD_FIFOSIZE_FIFOS_MASK,
HDA_DSP_REG_POLL_INTERVAL_US,
HDA_DSP_BASEFW_TIMEOUT_US);
if (ret < 0)
dev_warn(sdev->dev,
"%s: timeout waiting for FIFOS\n", __func__);
} else if (ret != -EOPNOTSUPP) {
goto cleanup;
}
ret = cl_trigger(sdev, hext_stream, SNDRV_PCM_TRIGGER_START);
if (ret < 0) {
......@@ -557,8 +586,17 @@ int hda_dsp_ipc4_load_library(struct snd_sof_dev *sdev,
goto cleanup;
}
/*
* 2nd stage: LOAD_LIBRARY
* Message includes the dma_id and the lib_id, the dma_id must be
* identical to the one sent via LOAD_LIBRARY_PREPARE
*/
msg.primary &= ~SOF_IPC4_MSG_TYPE_MASK;
msg.primary |= SOF_IPC4_MSG_TYPE_SET(SOF_IPC4_GLB_LOAD_LIBRARY);
msg.primary |= SOF_IPC4_GLB_LOAD_LIBRARY_LIB_ID(fw_lib->id);
ret = sof_ipc_tx_message_no_reply(sdev->ipc, &msg, 0);
/* Stop the DMA channel */
ret1 = cl_trigger(sdev, hext_stream, SNDRV_PCM_TRIGGER_STOP);
if (ret1 < 0) {
dev_err(sdev->dev, "%s: DMA trigger stop failed\n", __func__);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment