Unverified Commit b1ad9437 authored by Mark Brown's avatar Mark Brown
Browse files

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).
parents e9c77480 5a8a9d70
Loading
Loading
Loading
Loading
+11 −4
Original line number Diff line number Diff line
@@ -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,
+40 −2
Original line number Diff line number Diff line
@@ -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__);
+1 −1
Original line number Diff line number Diff line
@@ -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;
+3 −0
Original line number Diff line number Diff line
@@ -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)
+5 −0
Original line number Diff line number Diff line
@@ -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),
};