diff --git a/include/sound/sof/info.h b/include/sound/sof/info.h index 0b7101aef596d3..65e86e4e9fd8e7 100644 --- a/include/sound/sof/info.h +++ b/include/sound/sof/info.h @@ -25,6 +25,7 @@ #define SOF_IPC_INFO_LOCKS BIT(1) #define SOF_IPC_INFO_LOCKSV BIT(2) #define SOF_IPC_INFO_GDB BIT(3) +#define SOF_IPC_INFO_D3_PERSISTENT BIT(4) /* extended data types that can be appended onto end of sof_ipc_fw_ready */ enum sof_ipc_ext_data { diff --git a/include/uapi/sound/sof/abi.h b/include/uapi/sound/sof/abi.h index fe2cfae94b45fd..f4232d289a22b5 100644 --- a/include/uapi/sound/sof/abi.h +++ b/include/uapi/sound/sof/abi.h @@ -26,7 +26,7 @@ /* SOF ABI version major, minor and patch numbers */ #define SOF_ABI_MAJOR 3 -#define SOF_ABI_MINOR 18 +#define SOF_ABI_MINOR 19 #define SOF_ABI_PATCH 0 /* SOF ABI version number. Format within 32bit word is MMmmmppp */ diff --git a/sound/soc/sof/intel/hda-loader.c b/sound/soc/sof/intel/hda-loader.c index b7007cbd415af5..6a1bdcc9c25df1 100644 --- a/sound/soc/sof/intel/hda-loader.c +++ b/sound/soc/sof/intel/hda-loader.c @@ -21,10 +21,49 @@ #include #include "ext_manifest.h" #include "../ops.h" +#include "../sof-priv.h" #include "hda.h" #define HDA_CL_STREAM_FORMAT 0x40 +static void hda_ssp_resume(struct snd_sof_dev *sdev) +{ + struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; + const struct sof_intel_dsp_desc *chip = hda->desc; + int i; + + /* DSP is powered up, set all SSPs to slave mode */ + for (i = 0; i < chip->ssp_count; i++) { + snd_sof_dsp_update_bits_unlocked(sdev, HDA_DSP_BAR, + chip->ssp_base_offset + + i * SSP_DEV_MEM_SIZE + + SSP_SSC1_OFFSET, + SSP_SET_SLAVE, + SSP_SET_SLAVE); + } +} + +static void hda_sdw_resume(struct snd_sof_dev *sdev) +{ + /* + * When a SoundWire link is in clock stop state, a secondary + * 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); +} + static struct hdac_ext_stream *cl_stream_prepare(struct snd_sof_dev *sdev, unsigned int format, unsigned int size, struct snd_dma_buffer *dmab, int direction) @@ -91,7 +130,6 @@ static int cl_dsp_init(struct snd_sof_dev *sdev, int stream_tag) char *dump_msg; u32 flags, j; int ret; - int i; /* step 1: power up corex */ ret = hda_dsp_enable_core(sdev, chip->host_managed_cores_mask); @@ -101,15 +139,7 @@ static int cl_dsp_init(struct snd_sof_dev *sdev, int stream_tag) goto err; } - /* DSP is powered up, set all SSPs to slave mode */ - for (i = 0; i < chip->ssp_count; i++) { - snd_sof_dsp_update_bits_unlocked(sdev, HDA_DSP_BAR, - chip->ssp_base_offset - + i * SSP_DEV_MEM_SIZE - + SSP_SSC1_OFFSET, - SSP_SET_SLAVE, - SSP_SET_SLAVE); - } + hda_ssp_resume(sdev); /* step 2: purge FW request */ snd_sof_dsp_write(sdev, HDA_DSP_BAR, chip->ipc_req, @@ -345,6 +375,37 @@ int hda_dsp_cl_boot_firmware_iccmax(struct snd_sof_dev *sdev) return ret; } +static int hda_dsp_boot_imr(struct snd_sof_dev *sdev) +{ + struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; + const struct sof_intel_dsp_desc *chip = hda->desc; + unsigned long mask; + u32 j; + int ret; + + /* power up & unstall/run the cores to run the firmware */ + ret = hda_dsp_enable_core(sdev, chip->init_core_mask); + if (ret < 0) { + dev_err(sdev->dev, "dsp core start failed %d\n", ret); + return -EIO; + } + + /* set enabled cores mask and increment ref count for cores in init_core_mask */ + sdev->enabled_cores_mask |= chip->init_core_mask; + mask = sdev->enabled_cores_mask; + for_each_set_bit(j, &mask, SOF_MAX_DSP_NUM_CORES) + sdev->dsp_core_ref_count[j]++; + + hda_ssp_resume(sdev); + + /* enable IPC interrupts */ + hda_dsp_ipc_int_enable(sdev); + + hda_sdw_resume(sdev); + + return ret; +} + int hda_dsp_cl_boot_firmware(struct snd_sof_dev *sdev) { struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; @@ -355,6 +416,13 @@ int hda_dsp_cl_boot_firmware(struct snd_sof_dev *sdev) struct firmware stripped_firmware; int ret, ret1, i; + if ((sdev->fw_ready.flags & SOF_IPC_INFO_D3_PERSISTENT) && + !(sof_debug_check_flag(SOF_DBG_IGNORE_D3_PERSISTENT)) && + !sdev->first_boot) { + dev_dbg(sdev->dev, "IMR restore supported, booting from IMR directly\n"); + return hda_dsp_boot_imr(sdev); + } + chip_info = desc->chip_info; if (plat_data->fw->size <= plat_data->fw_offset) { @@ -398,23 +466,7 @@ int hda_dsp_cl_boot_firmware(struct snd_sof_dev *sdev) 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); + hda_sdw_resume(sdev); /* * Set the boot_iteration to the last attempt, indicating that the diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index 96fc06965db1c8..32ae88a2bb6dc0 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -35,6 +35,9 @@ * on primary core */ #define SOF_DBG_PRINT_ALL_DUMPS BIT(6) /* Print all ipc and dsp dumps */ +#define SOF_DBG_IGNORE_D3_PERSISTENT BIT(7) /* ignore the DSP D3 persistent capability + * and always do FW downloading at resume + */ /* Flag definitions used for controlling the DSP dump behavior */ #define SOF_DBG_DUMP_REGS BIT(0)