mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-06 04:19:23 -04:00
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).
This commit is contained in:
@@ -106,12 +106,19 @@ enum sof_ipc4_global_msg {
|
||||
SOF_IPC4_GLB_SAVE_PIPELINE,
|
||||
SOF_IPC4_GLB_RESTORE_PIPELINE,
|
||||
|
||||
/* Loads library (using Code Load or HD/A Host Output DMA) */
|
||||
/*
|
||||
* library loading
|
||||
*
|
||||
* Loads library (using Code Load or HD/A Host Output DMA)
|
||||
*/
|
||||
SOF_IPC4_GLB_LOAD_LIBRARY,
|
||||
/*
|
||||
* Prepare the host DMA channel for library loading, must be followed by
|
||||
* a SOF_IPC4_GLB_LOAD_LIBRARY message as the library loading step
|
||||
*/
|
||||
SOF_IPC4_GLB_LOAD_LIBRARY_PREPARE,
|
||||
|
||||
/* 25: RESERVED - do not use */
|
||||
|
||||
SOF_IPC4_GLB_INTERNAL_MESSAGE = 26,
|
||||
SOF_IPC4_GLB_INTERNAL_MESSAGE,
|
||||
|
||||
/* Notification (FW to SW driver) */
|
||||
SOF_IPC4_GLB_NOTIFICATION,
|
||||
|
||||
@@ -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__);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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),
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user