diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2022-05-25 16:55:16 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2022-05-25 16:55:16 -0700 |
commit | d7227785e384d4422b3ca189aa5bf19f462337cc (patch) | |
tree | fbd117e5e3f31a8561f6b6d159413bc744f460e5 /sound/soc/intel/avs/loader.c | |
parent | 2518f226c60d8e04d18ba4295500a5b0b8ac7659 (diff) | |
parent | 60571929d06b028800f27b51a7c81de1144944cf (diff) | |
download | linux-d7227785e384d4422b3ca189aa5bf19f462337cc.tar.gz linux-d7227785e384d4422b3ca189aa5bf19f462337cc.tar.bz2 linux-d7227785e384d4422b3ca189aa5bf19f462337cc.zip |
Merge tag 'sound-5.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
Pull sound updates from Takashi Iwai:
"Not much dramatic changes at this time, but we've received quite a lot
of changes for ASoC, while there are still a few fixes and quirks for
usual HD- and USB-auido. Here are some highlights.
ASoC:
- Overhaul of endianness specification for data formats, avoiding
needless restrictions due to CODECs
- Initial stages of Intel AVS driver merge
- Introduction of v4 IPC mechanism for SOF
- TDM mode support for AK4613
- Support for Analog Devices ADAU1361, Cirrus Logic CS35L45, Maxim
MAX98396, MediaTek MT8186, NXP i.MX8 micfil and SAI interfaces,
nVidia Tegra186 ASRC, and Texas Instruments TAS2764 and TAS2780
Others:
- A few regression fixes after the USB-audio endpoint management
refactoring
- More enhancements for Cirrus HD-audio codec support (still ongoing)
- Addition of generic serial MIDI driver"
* tag 'sound-5.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (504 commits)
ALSA: hda/realtek - Add new type for ALC245
ALSA: usb-audio: Configure sync endpoints before data
ALSA: ctxfi: fix typo in comment
ALSA: cs5535audio: fix typo in comment
ALSA: ctxfi: Add SB046x PCI ID
ALSA: usb-audio: Add missing ep_idx in fixed EP quirks
ALSA: usb-audio: Workaround for clock setup on TEAC devices
ALSA: lola: Bounds check loop iterator against streams array size
ASoC: max98090: Move check for invalid values before casting in max98090_put_enab_tlv()
ASoC: rt1308-sdw: add the default value of register 0xc320
ASoC: rt9120: Use pm_runtime and regcache to optimize 'pwdnn' logic
ASoC: rt9120: Fix 3byte read, valule offset typo
ASoC: amd: acp: Set Speaker enable/disable pin through rt1019 codec driver.
ASoC: amd: acp: Set Speaker enable/disable pin through rt1019 codec driver
ASoC: wm2000: fix missing clk_disable_unprepare() on error in wm2000_anc_transition()
ASoC: codecs: lpass: Fix passing zero to 'PTR_ERR'
ASoC: SOF: sof-client-ipc-flood-test: use pm_runtime_resume_and_get()
ASoC: SOF: mediatek: remove duplicate include in mt8195.c
ASoC: SOF: mediatek: Add mt8195 debug dump
ASoC: SOF: mediatek: Add mediatek common debug dump
...
Diffstat (limited to 'sound/soc/intel/avs/loader.c')
-rw-r--r-- | sound/soc/intel/avs/loader.c | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/sound/soc/intel/avs/loader.c b/sound/soc/intel/avs/loader.c index c47f85161d95..542fd44aa501 100644 --- a/sound/soc/intel/avs/loader.c +++ b/sound/soc/intel/avs/loader.c @@ -15,6 +15,7 @@ #include "cldma.h" #include "messages.h" #include "registers.h" +#include "topology.h" #define AVS_ROM_STS_MASK 0xFF #define AVS_ROM_INIT_DONE 0x1 @@ -36,6 +37,8 @@ #define AVS_EXT_MANIFEST_MAGIC 0x31454124 #define SKL_MANIFEST_MAGIC 0x00000006 #define SKL_ADSPFW_OFFSET 0x284 +#define APL_MANIFEST_MAGIC 0x44504324 +#define APL_ADSPFW_OFFSET 0x2000 /* Occasionally, engineering (release candidate) firmware is provided for testing. */ static bool debug_ignore_fw_version; @@ -86,6 +89,8 @@ static int avs_fw_manifest_offset(struct firmware *fw) switch (magic) { case SKL_MANIFEST_MAGIC: return SKL_ADSPFW_OFFSET; + case APL_MANIFEST_MAGIC: + return APL_ADSPFW_OFFSET; default: return -EINVAL; } @@ -466,6 +471,71 @@ int avs_hda_transfer_modules(struct avs_dev *adev, bool load, return 0; } +int avs_dsp_load_libraries(struct avs_dev *adev, struct avs_tplg_library *libs, u32 num_libs) +{ + int start, id, i = 0; + int ret; + + /* Calculate the id to assign for the next lib. */ + for (id = 0; id < adev->fw_cfg.max_libs_count; id++) + if (adev->lib_names[id][0] == '\0') + break; + if (id + num_libs >= adev->fw_cfg.max_libs_count) + return -EINVAL; + + start = id; + while (i < num_libs) { + struct avs_fw_manifest *man; + const struct firmware *fw; + struct firmware stripped_fw; + char *filename; + int j; + + filename = kasprintf(GFP_KERNEL, "%s/%s/%s", AVS_ROOT_DIR, adev->spec->name, + libs[i].name); + if (!filename) + return -ENOMEM; + + /* + * If any call after this one fails, requested firmware is not released with + * avs_release_last_firmware() as failing to load code results in need for reload + * of entire driver module. And then avs_release_firmwares() is in place already. + */ + ret = avs_request_firmware(adev, &fw, filename); + kfree(filename); + if (ret < 0) + return ret; + + stripped_fw = *fw; + ret = avs_fw_manifest_strip_verify(adev, &stripped_fw, NULL); + if (ret) { + dev_err(adev->dev, "invalid library data: %d\n", ret); + return ret; + } + + ret = avs_fw_manifest_offset(&stripped_fw); + if (ret < 0) + return ret; + man = (struct avs_fw_manifest *)(stripped_fw.data + ret); + + /* Don't load anything that's already in DSP memory. */ + for (j = 0; j < id; j++) + if (!strncmp(adev->lib_names[j], man->name, AVS_LIB_NAME_SIZE)) + goto next_lib; + + ret = avs_dsp_op(adev, load_lib, &stripped_fw, id); + if (ret) + return ret; + + strncpy(adev->lib_names[id], man->name, AVS_LIB_NAME_SIZE); + id++; +next_lib: + i++; + } + + return start == id ? 1 : 0; +} + static int avs_dsp_load_basefw(struct avs_dev *adev) { const struct avs_fw_version *min_req; @@ -519,6 +589,7 @@ release_fw: int avs_dsp_boot_firmware(struct avs_dev *adev, bool purge) { + struct avs_soc_component *acomp; int ret, i; /* Forgo full boot if flash from IMR succeeds. */ @@ -538,7 +609,20 @@ int avs_dsp_boot_firmware(struct avs_dev *adev, bool purge) avs_hda_l1sen_enable(adev, false); ret = avs_dsp_load_basefw(adev); + if (ret) + goto reenable_gating; + + mutex_lock(&adev->comp_list_mutex); + list_for_each_entry(acomp, &adev->comp_list, node) { + struct avs_tplg *tplg = acomp->tplg; + + ret = avs_dsp_load_libraries(adev, tplg->libs, tplg->num_libs); + if (ret < 0) + break; + } + mutex_unlock(&adev->comp_list_mutex); +reenable_gating: avs_hda_l1sen_enable(adev, true); avs_hda_clock_gating_enable(adev, true); |