aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/intel
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2022-07-11 22:13:49 +0100
committerMark Brown <broonie@kernel.org>2022-07-11 22:13:49 +0100
commit388fe2b8a3a0f597b2680e8f1ef5324e1db76ed2 (patch)
tree9c8385506de4b218326592bd530dfb7ea3e4dd8f /sound/soc/intel
parentASoC: nau8821: Add headset button detection (diff)
parentASoC: Intel: avs: Update AVS_FW_INIT_TIMEOUT_US declaration (diff)
downloadlinux-dev-388fe2b8a3a0f597b2680e8f1ef5324e1db76ed2.tar.xz
linux-dev-388fe2b8a3a0f597b2680e8f1ef5324e1db76ed2.zip
ASoC: Intel: avs: Updates and cleanups
Merge series from Cezary Rojewski <cezary.rojewski@intel.com>: Series consists of loosely connected patches and does not concentrate on one specific subject. First, as generic HDAudio codec driver is now part of ASoC, avs-driver core is updated to register missing ext_bus operations. This completes driver's core implementation. The next change adds the last missing piece for port descriptions coming from topology in formatted string format e.g.: ssp%d have full effect. To do that, the port value needs to be provided to respective copier configuration. Third change relaxes core transition timings so that scenarios where modules are interfering with each other while being on separate cores are not occasionally causing trouble. All other changes are addressing warnings, cleaning things up a little and protecting driver from invalid firmware behavior - while not expected in release binaries, does not hurt to add them.
Diffstat (limited to 'sound/soc/intel')
-rw-r--r--sound/soc/intel/Kconfig2
-rw-r--r--sound/soc/intel/avs/cldma.c12
-rw-r--r--sound/soc/intel/avs/core.c13
-rw-r--r--sound/soc/intel/avs/dsp.c11
-rw-r--r--sound/soc/intel/avs/ipc.c1
-rw-r--r--sound/soc/intel/avs/loader.c2
-rw-r--r--sound/soc/intel/avs/messages.c18
-rw-r--r--sound/soc/intel/avs/topology.c27
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) {