diff options
Diffstat (limited to 'sound/soc/intel')
-rw-r--r-- | sound/soc/intel/Kconfig | 2 | ||||
-rw-r--r-- | sound/soc/intel/avs/cldma.c | 12 | ||||
-rw-r--r-- | sound/soc/intel/avs/core.c | 13 | ||||
-rw-r--r-- | sound/soc/intel/avs/dsp.c | 11 | ||||
-rw-r--r-- | sound/soc/intel/avs/ipc.c | 1 | ||||
-rw-r--r-- | sound/soc/intel/avs/loader.c | 2 | ||||
-rw-r--r-- | sound/soc/intel/avs/messages.c | 18 | ||||
-rw-r--r-- | sound/soc/intel/avs/topology.c | 27 |
8 files changed, 64 insertions, 22 deletions
diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig index e5107a3ce16a..ded903f95b67 100644 --- a/sound/soc/intel/Kconfig +++ b/sound/soc/intel/Kconfig @@ -216,7 +216,7 @@ config SND_SOC_INTEL_AVS depends on COMMON_CLK select SND_SOC_ACPI if ACPI select SND_SOC_TOPOLOGY - select SND_HDA + select SND_SOC_HDA select SND_HDA_EXT_CORE select SND_HDA_DSP_LOADER select SND_INTEL_DSP_CONFIG diff --git a/sound/soc/intel/avs/cldma.c b/sound/soc/intel/avs/cldma.c index d100c6ba4d8a..d7a9390b5e48 100644 --- a/sound/soc/intel/avs/cldma.c +++ b/sound/soc/intel/avs/cldma.c @@ -176,17 +176,17 @@ int hda_cldma_reset(struct hda_cldma *cl) return ret; } - snd_hdac_stream_updateb(cl, SD_CTL, 1, 1); - ret = snd_hdac_stream_readb_poll(cl, SD_CTL, reg, (reg & 1), AVS_CL_OP_INTERVAL_US, - AVS_CL_OP_TIMEOUT_US); + snd_hdac_stream_updateb(cl, SD_CTL, SD_CTL_STREAM_RESET, SD_CTL_STREAM_RESET); + ret = snd_hdac_stream_readb_poll(cl, SD_CTL, reg, (reg & SD_CTL_STREAM_RESET), + AVS_CL_OP_INTERVAL_US, AVS_CL_OP_TIMEOUT_US); if (ret < 0) { dev_err(cl->dev, "cldma set SRST failed: %d\n", ret); return ret; } - snd_hdac_stream_updateb(cl, SD_CTL, 1, 0); - ret = snd_hdac_stream_readb_poll(cl, SD_CTL, reg, !(reg & 1), AVS_CL_OP_INTERVAL_US, - AVS_CL_OP_TIMEOUT_US); + snd_hdac_stream_updateb(cl, SD_CTL, SD_CTL_STREAM_RESET, 0); + ret = snd_hdac_stream_readb_poll(cl, SD_CTL, reg, !(reg & SD_CTL_STREAM_RESET), + AVS_CL_OP_INTERVAL_US, AVS_CL_OP_TIMEOUT_US); if (ret < 0) { dev_err(cl->dev, "cldma unset SRST failed: %d\n", ret); return ret; diff --git a/sound/soc/intel/avs/core.c b/sound/soc/intel/avs/core.c index 3a0997c3af2b..c50c20fd681a 100644 --- a/sound/soc/intel/avs/core.c +++ b/sound/soc/intel/avs/core.c @@ -23,6 +23,7 @@ #include <sound/hdaudio_ext.h> #include <sound/intel-dsp-config.h> #include <sound/intel-nhlt.h> +#include "../../codecs/hda.h" #include "avs.h" #include "cldma.h" @@ -356,7 +357,7 @@ static int avs_bus_init(struct avs_dev *adev, struct pci_dev *pci, const struct struct device *dev = &pci->dev; int ret; - ret = snd_hdac_ext_bus_init(&bus->core, dev, NULL, NULL); + ret = snd_hdac_ext_bus_init(&bus->core, dev, NULL, &soc_hda_ext_bus_ops); if (ret < 0) return ret; @@ -439,12 +440,9 @@ static int avs_pci_probe(struct pci_dev *pci, const struct pci_device_id *id) if (bus->mlcap) snd_hdac_ext_bus_get_ml_capabilities(bus); - if (!dma_set_mask(dev, DMA_BIT_MASK(64))) { - dma_set_coherent_mask(dev, DMA_BIT_MASK(64)); - } else { - dma_set_mask(dev, DMA_BIT_MASK(32)); - dma_set_coherent_mask(dev, DMA_BIT_MASK(32)); - } + if (!dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64))) + dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32)); + dma_set_max_seg_size(dev, UINT_MAX); ret = avs_hdac_bus_init_streams(bus); if (ret < 0) { @@ -555,6 +553,7 @@ static int __maybe_unused avs_suspend_common(struct avs_dev *adev) return AVS_IPC_RET(ret); } + avs_ipc_block(adev->ipc); avs_dsp_op(adev, int_control, false); snd_hdac_ext_bus_ppcap_int_enable(bus, false); diff --git a/sound/soc/intel/avs/dsp.c b/sound/soc/intel/avs/dsp.c index 06d2f7af520f..b881100d3e02 100644 --- a/sound/soc/intel/avs/dsp.c +++ b/sound/soc/intel/avs/dsp.c @@ -13,6 +13,7 @@ #define AVS_ADSPCS_INTERVAL_US 500 #define AVS_ADSPCS_TIMEOUT_US 50000 +#define AVS_ADSPCS_DELAY_US 1000 int avs_dsp_core_power(struct avs_dev *adev, u32 core_mask, bool power) { @@ -26,6 +27,8 @@ int avs_dsp_core_power(struct avs_dev *adev, u32 core_mask, bool power) value = power ? mask : 0; snd_hdac_adsp_updatel(adev, AVS_ADSP_REG_ADSPCS, mask, value); + /* Delay the polling to avoid false positives. */ + usleep_range(AVS_ADSPCS_DELAY_US, 2 * AVS_ADSPCS_DELAY_US); mask = AVS_ADSPCS_CPA_MASK(core_mask); value = power ? mask : 0; @@ -82,11 +85,15 @@ int avs_dsp_core_stall(struct avs_dev *adev, u32 core_mask, bool stall) reg, (reg & mask) == value, AVS_ADSPCS_INTERVAL_US, AVS_ADSPCS_TIMEOUT_US); - if (ret) + if (ret) { dev_err(adev->dev, "core_mask %d %sstall failed: %d\n", core_mask, stall ? "" : "un", ret); + return ret; + } - return ret; + /* Give HW time to propagate the change. */ + usleep_range(AVS_ADSPCS_DELAY_US, 2 * AVS_ADSPCS_DELAY_US); + return 0; } int avs_dsp_core_enable(struct avs_dev *adev, u32 core_mask) diff --git a/sound/soc/intel/avs/ipc.c b/sound/soc/intel/avs/ipc.c index d755ba8b8518..020d85c7520d 100644 --- a/sound/soc/intel/avs/ipc.c +++ b/sound/soc/intel/avs/ipc.c @@ -480,6 +480,7 @@ static int avs_dsp_do_send_msg(struct avs_dev *adev, struct avs_ipc_msg *request ret = ipc->rx.rsp.status; if (reply) { reply->header = ipc->rx.header; + reply->size = ipc->rx.size; if (reply->data && ipc->rx.size) memcpy(reply->data, ipc->rx.data, reply->size); } diff --git a/sound/soc/intel/avs/loader.c b/sound/soc/intel/avs/loader.c index 542fd44aa501..9e3f8ff33a87 100644 --- a/sound/soc/intel/avs/loader.c +++ b/sound/soc/intel/avs/loader.c @@ -27,8 +27,8 @@ #define APL_ROM_INIT_RETRIES 3 #define AVS_FW_INIT_POLLING_US 500 -#define AVS_FW_INIT_TIMEOUT_US 3000000 #define AVS_FW_INIT_TIMEOUT_MS 3000 +#define AVS_FW_INIT_TIMEOUT_US (AVS_FW_INIT_TIMEOUT_MS * 1000) #define AVS_CLDMA_START_DELAY_MS 100 diff --git a/sound/soc/intel/avs/messages.c b/sound/soc/intel/avs/messages.c index 6404fce8cde4..d4bcee1aabcf 100644 --- a/sound/soc/intel/avs/messages.c +++ b/sound/soc/intel/avs/messages.c @@ -59,7 +59,7 @@ int avs_ipc_unload_modules(struct avs_dev *adev, u16 *mod_ids, u32 num_mod_ids) request.data = mod_ids; request.size = sizeof(*mod_ids) * num_mod_ids; - ret = avs_dsp_send_msg_timeout(adev, &request, NULL, AVS_CL_TIMEOUT_MS); + ret = avs_dsp_send_msg(adev, &request, NULL); if (ret) avs_ipc_err(adev, &request, "unload multiple modules", ret); @@ -378,7 +378,6 @@ int avs_ipc_get_large_config(struct avs_dev *adev, u16 module_id, u8 instance_id union avs_module_msg msg = AVS_MODULE_REQUEST(LARGE_CONFIG_GET); struct avs_ipc_msg request; struct avs_ipc_msg reply = {{0}}; - size_t size; void *buf; int ret; @@ -406,15 +405,14 @@ int avs_ipc_get_large_config(struct avs_dev *adev, u16 module_id, u8 instance_id return ret; } - size = reply.rsp.ext.large_config.data_off_size; - buf = krealloc(reply.data, size, GFP_KERNEL); + buf = krealloc(reply.data, reply.size, GFP_KERNEL); if (!buf) { kfree(reply.data); return -ENOMEM; } *reply_data = buf; - *reply_size = size; + *reply_size = reply.size; return 0; } @@ -476,6 +474,9 @@ int avs_ipc_get_fw_config(struct avs_dev *adev, struct avs_fw_cfg *cfg) &payload, &payload_size); if (ret) return ret; + /* Non-zero payload expected for FIRMWARE_CONFIG. */ + if (!payload_size) + return -EREMOTEIO; while (offset < payload_size) { tlv = (struct avs_tlv *)(payload + offset); @@ -561,6 +562,7 @@ int avs_ipc_get_fw_config(struct avs_dev *adev, struct avs_fw_cfg *cfg) case AVS_FW_CFG_DMA_BUFFER_CONFIG: case AVS_FW_CFG_SCHEDULER_CONFIG: case AVS_FW_CFG_CLOCKS_CONFIG: + case AVS_FW_CFG_RESERVED: break; default: @@ -589,6 +591,9 @@ int avs_ipc_get_hw_config(struct avs_dev *adev, struct avs_hw_cfg *cfg) &payload, &payload_size); if (ret) return ret; + /* Non-zero payload expected for HARDWARE_CONFIG. */ + if (!payload_size) + return -EREMOTEIO; while (offset < payload_size) { tlv = (struct avs_tlv *)(payload + offset); @@ -672,6 +677,9 @@ int avs_ipc_get_modules_info(struct avs_dev *adev, struct avs_mods_info **info) &payload, &payload_size); if (ret) return ret; + /* Non-zero payload expected for MODULES_INFO. */ + if (!payload_size) + return -EREMOTEIO; *info = (struct avs_mods_info *)payload; return 0; diff --git a/sound/soc/intel/avs/topology.c b/sound/soc/intel/avs/topology.c index 6a06fe387d13..8a9f9fc48938 100644 --- a/sound/soc/intel/avs/topology.c +++ b/sound/soc/intel/avs/topology.c @@ -808,6 +808,30 @@ static const struct avs_tplg_token_parser pin_format_parsers[] = { }, }; +static void +assign_copier_gtw_instance(struct snd_soc_component *comp, struct avs_tplg_modcfg_ext *cfg) +{ + struct snd_soc_acpi_mach *mach; + + if (!guid_equal(&cfg->type, &AVS_COPIER_MOD_UUID)) + return; + + /* Only I2S boards assign port instance in ->i2s_link_mask. */ + switch (cfg->copier.dma_type) { + case AVS_DMA_I2S_LINK_OUTPUT: + case AVS_DMA_I2S_LINK_INPUT: + break; + default: + return; + } + + mach = dev_get_platdata(comp->card->dev); + + /* Automatic assignment only when board describes single SSP. */ + if (hweight_long(mach->mach_params.i2s_link_mask) == 1 && !cfg->copier.vindex.i2s.instance) + cfg->copier.vindex.i2s.instance = __ffs(mach->mach_params.i2s_link_mask); +} + static int avs_tplg_parse_modcfg_ext(struct snd_soc_component *comp, struct avs_tplg_modcfg_ext *cfg, struct snd_soc_tplg_vendor_array *tuples, @@ -827,6 +851,9 @@ static int avs_tplg_parse_modcfg_ext(struct snd_soc_component *comp, if (ret) return ret; + /* Update copier gateway based on board's i2s_link_mask. */ + assign_copier_gtw_instance(comp, cfg); + block_size -= esize; /* Parse trailing in/out pin formats if any. */ if (block_size) { |