sound/soc/sof/intel/hda-loader.c

Source file repositories/reference/linux-study-clean/sound/soc/sof/intel/hda-loader.c

File Facts

System
Linux kernel
Corpus path
sound/soc/sof/intel/hda-loader.c
Extension
.c
Size
20185 bytes
Lines
641
Domain
Driver Families
Bucket
sound/soc
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (!ret) {
			hda->booted_from_imr = true;
			return 0;
		}

		dev_warn(sdev->dev, "IMR restore failed, trying to cold boot\n");
	}

	hda->booted_from_imr = false;

	chip_info = desc->chip_info;

	if (sdev->basefw.fw->size <= sdev->basefw.payload_offset) {
		dev_err(sdev->dev, "error: firmware size must be greater than firmware offset\n");
		return -EINVAL;
	}

	/* init for booting wait */
	init_waitqueue_head(&sdev->boot_wait);

	/* prepare DMA for code loader stream */
	stripped_firmware.size = sdev->basefw.fw->size - sdev->basefw.payload_offset;
	hext_stream = hda_cl_prepare(sdev->dev, HDA_CL_STREAM_FORMAT,
				     stripped_firmware.size,
				     &hda->cl_dmab, persistent_cl_buffer,
				     SNDRV_PCM_STREAM_PLAYBACK, false);
	if (IS_ERR(hext_stream)) {
		dev_err(sdev->dev, "error: dma prepare for fw loading failed\n");
		return PTR_ERR(hext_stream);
	}

	/*
	 * Copy the payload to the DMA buffer if it is temporary or if the
	 * buffer is  persistent but it does not have the basefw payload either
	 * because this is the first boot and the buffer needs to be initialized,
	 * or a library got loaded and it replaced the basefw.
	 */
	if (!persistent_cl_buffer || !hda->cl_dmab_contains_basefw) {
		stripped_firmware.data = sdev->basefw.fw->data + sdev->basefw.payload_offset;
		memcpy(hda->cl_dmab.area, stripped_firmware.data, stripped_firmware.size);
		hda->cl_dmab_contains_basefw = true;
	}

	/* try ROM init a few times before giving up */
	for (i = 0; i < HDA_FW_BOOT_ATTEMPTS; i++) {
		dev_dbg(sdev->dev,
			"Attempting iteration %d of Core En/ROM load...\n", i);

		hda->boot_iteration = i + 1;
		if (chip_info->cl_init)
			ret = chip_info->cl_init(sdev, hext_stream->hstream.stream_tag, false);
		else
			ret = -EINVAL;

		/* don't retry anymore if successful */
		if (!ret)
			break;
	}

	if (i == HDA_FW_BOOT_ATTEMPTS) {
		dev_err(sdev->dev, "error: dsp init failed after %d attempts with err: %d\n",
			i, ret);
		goto cleanup;
	}

	/*
	 * When a SoundWire link is in clock stop state, a Slave
	 * device may trigger in-band wakes for events such as jack
	 * insertion or acoustic event detection. This event will lead
	 * to a WAKEEN interrupt, handled by the PCI device and routed
	 * to PME if the PCI device is in D3. The resume function in
	 * audio PCI driver will be invoked by ACPI for PME event and
	 * initialize the device and process WAKEEN interrupt.
	 *
	 * The WAKEEN interrupt should be processed ASAP to prevent an
	 * interrupt flood, otherwise other interrupts, such IPC,
	 * cannot work normally.  The WAKEEN is handled after the ROM
	 * is initialized successfully, which ensures power rails are
	 * enabled before accessing the SoundWire SHIM registers
	 */
	if (!sdev->first_boot)
		hda_sdw_process_wakeen(sdev);

	/*
	 * Set the boot_iteration to the last attempt, indicating that the
	 * DSP ROM has been initialized and from this point there will be no
	 * retry done to boot.
	 *
	 * Continue with code loading and firmware boot
	 */

Annotation

Implementation Notes