diff options
author | Mark Brown <broonie@kernel.org> | 2023-09-15 19:03:35 +0100 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2023-09-15 19:03:35 +0100 |
commit | b1ad9437edd7f145fda807efb604ad84348170af (patch) | |
tree | 6744cbbff92d2478d6cea1e6fe33d0ab3b8ac052 /sound/soc/sof | |
parent | e9c7748084ac7236b657b9945789c574a3eb62e0 (diff) | |
parent | 5a8a9d70ecac3acbd49e70ad8f85153c0315643e (diff) |
ASoC: SOF: ipc4/Intel: Implement split fw library
Merge series from Peter Ujfalusi <peter.ujfalusi@linux.intel.com>:
This series implements support for split library loading to comply with the HDA
DMA programming sequence recommendation, which is:
1. DSP side DMA programming and GEN bit set to 1
2. host side DMA programming and RUN bit set to 1
The SOF support for library loading is based on this sequence, backwards
compatibility with older reference firmware is supported (where only the
LOAD_LIBRARY message is supported).
Diffstat (limited to 'sound/soc/sof')
-rw-r--r-- | sound/soc/sof/intel/hda-loader.c | 42 | ||||
-rw-r--r-- | sound/soc/sof/intel/hda-stream.c | 2 | ||||
-rw-r--r-- | sound/soc/sof/intel/hda.h | 3 | ||||
-rw-r--r-- | sound/soc/sof/ipc4.c | 5 |
4 files changed, 49 insertions, 3 deletions
diff --git a/sound/soc/sof/intel/hda-loader.c b/sound/soc/sof/intel/hda-loader.c index 50ce6b190002..1e2669a8088d 100644 --- a/sound/soc/sof/intel/hda-loader.c +++ b/sound/soc/sof/intel/hda-loader.c @@ -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__); diff --git a/sound/soc/sof/intel/hda-stream.c b/sound/soc/sof/intel/hda-stream.c index 0b0087abcc50..65e9242365be 100644 --- a/sound/soc/sof/intel/hda-stream.c +++ b/sound/soc/sof/intel/hda-stream.c @@ -668,7 +668,7 @@ int hda_dsp_stream_hw_params(struct snd_sof_dev *sdev, snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, sd_offset + SOF_HDA_ADSP_REG_SD_FIFOSIZE); - hstream->fifo_size &= 0xffff; + hstream->fifo_size &= SOF_HDA_SD_FIFOSIZE_FIFOS_MASK; hstream->fifo_size += 1; } else { hstream->fifo_size = 0; diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 5c517ec57d4a..2b228c63905b 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -135,6 +135,9 @@ #define SOF_HDA_ADSP_REG_SD_BDLPU 0x1C #define SOF_HDA_ADSP_SD_ENTRY_SIZE 0x20 +/* SDxFIFOS FIFOS */ +#define SOF_HDA_SD_FIFOSIZE_FIFOS_MASK GENMASK(15, 0) + /* CL: Software Position Based FIFO Capability Registers */ #define SOF_DSP_REG_CL_SPBFIFO \ (SOF_HDA_ADSP_LOADER_BASE + 0x20) diff --git a/sound/soc/sof/ipc4.c b/sound/soc/sof/ipc4.c index 9744627d6978..6c33ee5af32b 100644 --- a/sound/soc/sof/ipc4.c +++ b/sound/soc/sof/ipc4.c @@ -99,6 +99,10 @@ static int sof_ipc4_check_reply_status(struct snd_sof_dev *sdev, u32 status) to_errno: switch (status) { + case 2: + case 15: + ret = -EOPNOTSUPP; + break; case 8: case 11: case 105 ... 109: @@ -153,6 +157,7 @@ static const char * const ipc4_dbg_glb_msg_type[] = { DBG_IPC4_MSG_TYPE_ENTRY(GLB_SAVE_PIPELINE), DBG_IPC4_MSG_TYPE_ENTRY(GLB_RESTORE_PIPELINE), DBG_IPC4_MSG_TYPE_ENTRY(GLB_LOAD_LIBRARY), + DBG_IPC4_MSG_TYPE_ENTRY(GLB_LOAD_LIBRARY_PREPARE), DBG_IPC4_MSG_TYPE_ENTRY(GLB_INTERNAL_MESSAGE), DBG_IPC4_MSG_TYPE_ENTRY(GLB_NOTIFICATION), }; |