[PATCH 10/13] ASoC: qcom: Add QAIF regmap, DT parsing and platform init
From: Harendra Gautam
Date: Fri Jun 05 2026 - 06:43:10 EST
Add the core CPU and platform bring-up needed for the Qualcomm Audio
Interface driver.
The existing QAIF DAI code needs device-level infrastructure before it can
configure interfaces or run PCM streams. Add the MMIO regmap setup,
including readable, writable and volatile register tables, so the driver
can safely access QAIF control, DMA, interrupt and SHRAM registers.
Parse the QAIF AIF child nodes from devicetree and store the per-interface
PCM, TDM or MI2S configuration for use when programming the AUD_INTF
registers. Add the platform probe, remove and shutdown entry points to map
the device registers, initialize variant-specific resources, allocate
regmap fields, acquire clocks and register the CPU DAI component.
Add the QAIF PCM platform support needed for DMA streams, including PCM
hardware constraints, coherent DMA buffer allocation using
dma_alloc_coherent(), EE resource mapping, QXM DMA routing and SHRAM
partitioning for AIF and CIF DMA channels.
Signed-off-by: Harendra Gautam <harendra.gautam@xxxxxxxxxxxxxxxx>
---
sound/soc/qcom/qaif-cpu.c | 808 +++++++++++++++++++++++++++++++++
sound/soc/qcom/qaif-platform.c | 276 +++++++++++
2 files changed, 1084 insertions(+)
create mode 100644 sound/soc/qcom/qaif-platform.c
diff --git a/sound/soc/qcom/qaif-cpu.c b/sound/soc/qcom/qaif-cpu.c
index a455c6ded243..62a78b30744c 100644
--- a/sound/soc/qcom/qaif-cpu.c
+++ b/sound/soc/qcom/qaif-cpu.c
@@ -779,3 +779,804 @@ const struct snd_soc_dai_ops asoc_qcom_qaif_aif_cpu_dai_ops = {
.trigger = qaif_aif_cpu_daiops_trigger,
};
EXPORT_SYMBOL_GPL(asoc_qcom_qaif_aif_cpu_dai_ops);
+
+static int qaif_cpu_of_xlate_dai_name(struct snd_soc_component *component,
+ const struct of_phandle_args *args,
+ const char **dai_name)
+{
+ struct qaif_drv_data *drvdata = snd_soc_component_get_drvdata(component);
+ const struct qaif_variant *v = drvdata->variant;
+
+ return asoc_qcom_of_xlate_dai_name(v->dai_driver,
+ v->num_dai, args, dai_name);
+}
+
+static const struct snd_soc_component_driver qaif_cpu_comp_driver = {
+ .name = "qaif-cpu",
+ .of_xlate_dai_name = qaif_cpu_of_xlate_dai_name,
+};
+
+static bool audio_qaif_regmap_writeable(struct device *dev, unsigned int reg)
+{
+ struct qaif_drv_data *drvdata = dev_get_drvdata(dev);
+ const struct qaif_variant *v = drvdata->variant;
+ int i;
+
+ /* EE maps */
+ if (reg == QAIF_EE_RDDMA_MAP_REG(v))
+ return true;
+ if (reg == QAIF_EE_WRDMA_MAP_REG(v))
+ return true;
+ if (reg == QAIF_EE_INTF_MAP_REG(v))
+ return true;
+ if (reg == QAIF_EE_CODEC_RDDMA_MAP_REG(v))
+ return true;
+ if (reg == QAIF_EE_CODEC_WRDMA_MAP_REG(v))
+ return true;
+
+ /* QXM DMA path mapping */
+ if (reg == QAIF_RDDMA_MAP_QXM)
+ return true;
+ if (reg == QAIF_WRDMA_MAP_QXM)
+ return true;
+ if (reg == QAIF_CODEC_RDDMA_MAP_QXM)
+ return true;
+ if (reg == QAIF_CODEC_WRDMA_MAP_QXM)
+ return true;
+
+ /* SID maps */
+ if (reg == QAIF_WRDMA_SID_MAP_REG)
+ return true;
+ if (reg == QAIF_CODEC_WRDMA_SID_MAP_REG)
+ return true;
+ if (reg == QAIF_RDDMA_SID_MAP_REG)
+ return true;
+ if (reg == QAIF_CODEC_RDDMA_SID_MAP_REG)
+ return true;
+
+ /* SHRAM QXM0 start address and length */
+ for (i = 0; i < v->num_rddma; i++) {
+ if (reg == QAIF_RDDMA_QXM0_SHRAM_ST_ADDR(i))
+ return true;
+ if (reg == QAIF_RDDMA_QXM0_SHRAM_LEN(i))
+ return true;
+ }
+ for (i = 0; i < v->num_codec_rddma; i++) {
+ if (reg == QAIF_CODEC_RDDMA_QXM0_SHRAM_ST_ADDR(i))
+ return true;
+ if (reg == QAIF_CODEC_RDDMA_QXM0_SHRAM_LEN(i))
+ return true;
+ }
+ for (i = 0; i < v->num_wrdma; i++) {
+ if (reg == QAIF_WRDMA_QXM0_SHRAM_ST_ADDR(i))
+ return true;
+ if (reg == QAIF_WRDMA_QXM0_SHRAM_LEN(i))
+ return true;
+ }
+ for (i = 0; i < v->num_codec_wrdma; i++) {
+ if (reg == QAIF_CODEC_WRDMA_QXM0_SHRAM_ST_ADDR(i))
+ return true;
+ if (reg == QAIF_CODEC_WRDMA_QXM0_SHRAM_LEN(i))
+ return true;
+ }
+
+ /* EE IRQ EN and CLR */
+ for (i = 0; i < DMA_TYPE_MAX; i++) {
+ if (reg == QAIF_EE_RDDMA_PERIOD_IRQ_EN_REG(v, i))
+ return true;
+ if (reg == QAIF_EE_RDDMA_PERIOD_IRQ_CLR_REG(v, i))
+ return true;
+ if (reg == QAIF_EE_RDDMA_UNDERFLOW_IRQ_EN_REG(v, i))
+ return true;
+ if (reg == QAIF_EE_RDDMA_UNDERFLOW_IRQ_CLR_REG(v, i))
+ return true;
+ if (reg == QAIF_EE_RDDMA_ERR_RSP_IRQ_EN_REG(v, i))
+ return true;
+ if (reg == QAIF_EE_RDDMA_ERR_RSP_IRQ_CLR_REG(v, i))
+ return true;
+ if (reg == QAIF_EE_WRDMA_PERIOD_IRQ_EN_REG(v, i))
+ return true;
+ if (reg == QAIF_EE_WRDMA_PERIOD_IRQ_CLR_REG(v, i))
+ return true;
+ if (reg == QAIF_EE_WRDMA_OVERFLOW_IRQ_EN_REG(v, i))
+ return true;
+ if (reg == QAIF_EE_WRDMA_OVERFLOW_IRQ_CLR_REG(v, i))
+ return true;
+ if (reg == QAIF_EE_WRDMA_ERR_RSP_IRQ_EN_REG(v, i))
+ return true;
+ if (reg == QAIF_EE_WRDMA_ERR_RSP_IRQ_CLR_REG(v, i))
+ return true;
+ }
+
+ /* AUD_INTF control and configuration */
+ for (i = 0; i < v->num_intf; i++) {
+ if (reg == QAIF_AUD_INTF_CTL_REG(i))
+ return true;
+ if (reg == QAIF_AUD_INTF_SYNC_CFG_REG(i))
+ return true;
+ if (reg == QAIF_AUD_INTF_BIT_WIDTH_CFG_REG(i))
+ return true;
+ if (reg == QAIF_AUD_INTF_FRAME_CFG_REG(i))
+ return true;
+ if (reg == QAIF_AUD_INTF_ACTV_SLOT_EN_TX_REG(i))
+ return true;
+ if (reg == QAIF_AUD_INTF_ACTV_SLOT_EN_RX_REG(i))
+ return true;
+ if (reg == QAIF_AUD_INTF_LANE_CFG_REG(i))
+ return true;
+ if (reg == QAIF_AUD_INTF_MI2S_CFG_REG(i))
+ return true;
+ if (reg == QAIF_AUD_INTF_CFG_REG(i))
+ return true;
+ }
+
+ /* RDDMA control and configuration */
+ for (i = 0; i < v->num_rddma; i++) {
+ if (reg == QAIF_RDDMA_CTL_REG(v, i))
+ return true;
+ if (reg == QAIF_RDDMA_CFG_REG(v, i))
+ return true;
+ if (reg == QAIF_RDDMA_BASE_ADDR_REG(v, i))
+ return true;
+ if (reg == QAIF_RDDMA_BUFF_LEN_REG(v, i))
+ return true;
+ if (reg == QAIF_RDDMA_PERIOD_LEN_REG(v, i))
+ return true;
+ }
+
+ /* CODEC RDDMA control and configuration */
+ for (i = 0; i < v->num_codec_rddma; i++) {
+ if (reg == QAIF_CODEC_RDDMA_CTL_REG(v, i))
+ return true;
+ if (reg == QAIF_CODEC_RDDMA_CFG_REG(v, i))
+ return true;
+ if (reg == QAIF_CODEC_RDDMA_BASE_ADDR_REG(v, i))
+ return true;
+ if (reg == QAIF_CODEC_RDDMA_BUFF_LEN_REG(v, i))
+ return true;
+ if (reg == QAIF_CODEC_RDDMA_PERIOD_LEN_REG(v, i))
+ return true;
+ if (reg == QAIF_CODEC_RDDMA_INTF_CFG_REG(v, i))
+ return true;
+ }
+
+ /* WRDMA control and configuration */
+ for (i = 0; i < v->num_wrdma; i++) {
+ if (reg == QAIF_WRDMA_CTL_REG(v, i))
+ return true;
+ if (reg == QAIF_WRDMA_CFG_REG(v, i))
+ return true;
+ if (reg == QAIF_WRDMA_BASE_ADDR_REG(v, i))
+ return true;
+ if (reg == QAIF_WRDMA_BUFF_LEN_REG(v, i))
+ return true;
+ if (reg == QAIF_WRDMA_PERIOD_LEN_REG(v, i))
+ return true;
+ }
+
+ /* CODEC WRDMA control and configuration */
+ for (i = 0; i < v->num_codec_wrdma; i++) {
+ if (reg == QAIF_CODEC_WRDMA_CTL_REG(v, i))
+ return true;
+ if (reg == QAIF_CODEC_WRDMA_CFG_REG(v, i))
+ return true;
+ if (reg == QAIF_CODEC_WRDMA_BASE_ADDR_REG(v, i))
+ return true;
+ if (reg == QAIF_CODEC_WRDMA_BUFF_LEN_REG(v, i))
+ return true;
+ if (reg == QAIF_CODEC_WRDMA_PERIOD_LEN_REG(v, i))
+ return true;
+ if (reg == QAIF_CODEC_WRDMA_INTF_CFG_REG(v, i))
+ return true;
+ }
+
+ return false;
+}
+
+static bool audio_qaif_regmap_readable(struct device *dev, unsigned int reg)
+{
+ struct qaif_drv_data *drvdata = dev_get_drvdata(dev);
+ const struct qaif_variant *v = drvdata->variant;
+ int i;
+
+ /* Summary IRQ status */
+ if (reg == QAIF_SUMMARY_IRQSTAT_REG(v))
+ return true;
+
+ /* EE maps */
+ if (reg == QAIF_EE_RDDMA_MAP_REG(v))
+ return true;
+ if (reg == QAIF_EE_WRDMA_MAP_REG(v))
+ return true;
+ if (reg == QAIF_EE_INTF_MAP_REG(v))
+ return true;
+ if (reg == QAIF_EE_CODEC_RDDMA_MAP_REG(v))
+ return true;
+ if (reg == QAIF_EE_CODEC_WRDMA_MAP_REG(v))
+ return true;
+
+ /* QXM DMA path mapping */
+ if (reg == QAIF_RDDMA_MAP_QXM)
+ return true;
+ if (reg == QAIF_WRDMA_MAP_QXM)
+ return true;
+ if (reg == QAIF_CODEC_RDDMA_MAP_QXM)
+ return true;
+ if (reg == QAIF_CODEC_WRDMA_MAP_QXM)
+ return true;
+
+ /* SID maps */
+ if (reg == QAIF_WRDMA_SID_MAP_REG)
+ return true;
+ if (reg == QAIF_CODEC_WRDMA_SID_MAP_REG)
+ return true;
+ if (reg == QAIF_RDDMA_SID_MAP_REG)
+ return true;
+ if (reg == QAIF_CODEC_RDDMA_SID_MAP_REG)
+ return true;
+
+ /* SHRAM QXM0 start address and length */
+ for (i = 0; i < v->num_rddma; i++) {
+ if (reg == QAIF_RDDMA_QXM0_SHRAM_ST_ADDR(i))
+ return true;
+ if (reg == QAIF_RDDMA_QXM0_SHRAM_LEN(i))
+ return true;
+ }
+ for (i = 0; i < v->num_codec_rddma; i++) {
+ if (reg == QAIF_CODEC_RDDMA_QXM0_SHRAM_ST_ADDR(i))
+ return true;
+ if (reg == QAIF_CODEC_RDDMA_QXM0_SHRAM_LEN(i))
+ return true;
+ }
+ for (i = 0; i < v->num_wrdma; i++) {
+ if (reg == QAIF_WRDMA_QXM0_SHRAM_ST_ADDR(i))
+ return true;
+ if (reg == QAIF_WRDMA_QXM0_SHRAM_LEN(i))
+ return true;
+ }
+ for (i = 0; i < v->num_codec_wrdma; i++) {
+ if (reg == QAIF_CODEC_WRDMA_QXM0_SHRAM_ST_ADDR(i))
+ return true;
+ if (reg == QAIF_CODEC_WRDMA_QXM0_SHRAM_LEN(i))
+ return true;
+ }
+
+ /* EE IRQ EN, CLR and STATUS */
+ for (i = 0; i < DMA_TYPE_MAX; i++) {
+ if (reg == QAIF_EE_RDDMA_PERIOD_IRQ_EN_REG(v, i))
+ return true;
+ if (reg == QAIF_EE_RDDMA_PERIOD_IRQ_CLR_REG(v, i))
+ return true;
+ if (reg == QAIF_EE_RDDMA_PERIOD_IRQ_STAT_REG(v, i))
+ return true;
+ if (reg == QAIF_EE_RDDMA_UNDERFLOW_IRQ_EN_REG(v, i))
+ return true;
+ if (reg == QAIF_EE_RDDMA_UNDERFLOW_IRQ_CLR_REG(v, i))
+ return true;
+ if (reg == QAIF_EE_RDDMA_UNDERFLOW_IRQ_STAT_REG(v, i))
+ return true;
+ if (reg == QAIF_EE_RDDMA_ERR_RSP_IRQ_EN_REG(v, i))
+ return true;
+ if (reg == QAIF_EE_RDDMA_ERR_RSP_IRQ_CLR_REG(v, i))
+ return true;
+ if (reg == QAIF_EE_RDDMA_ERR_RSP_IRQ_STAT_REG(v, i))
+ return true;
+ if (reg == QAIF_EE_WRDMA_PERIOD_IRQ_EN_REG(v, i))
+ return true;
+ if (reg == QAIF_EE_WRDMA_PERIOD_IRQ_CLR_REG(v, i))
+ return true;
+ if (reg == QAIF_EE_WRDMA_PERIOD_IRQ_STAT_REG(v, i))
+ return true;
+ if (reg == QAIF_EE_WRDMA_OVERFLOW_IRQ_EN_REG(v, i))
+ return true;
+ if (reg == QAIF_EE_WRDMA_OVERFLOW_IRQ_CLR_REG(v, i))
+ return true;
+ if (reg == QAIF_EE_WRDMA_OVERFLOW_IRQ_STAT_REG(v, i))
+ return true;
+ if (reg == QAIF_EE_WRDMA_ERR_RSP_IRQ_EN_REG(v, i))
+ return true;
+ if (reg == QAIF_EE_WRDMA_ERR_RSP_IRQ_CLR_REG(v, i))
+ return true;
+ if (reg == QAIF_EE_WRDMA_ERR_RSP_IRQ_STAT_REG(v, i))
+ return true;
+ }
+
+ /* AUD_INTF control and configuration */
+ for (i = 0; i < v->num_intf; i++) {
+ if (reg == QAIF_AUD_INTF_CTL_REG(i))
+ return true;
+ if (reg == QAIF_AUD_INTF_SYNC_CFG_REG(i))
+ return true;
+ if (reg == QAIF_AUD_INTF_BIT_WIDTH_CFG_REG(i))
+ return true;
+ if (reg == QAIF_AUD_INTF_FRAME_CFG_REG(i))
+ return true;
+ if (reg == QAIF_AUD_INTF_ACTV_SLOT_EN_TX_REG(i))
+ return true;
+ if (reg == QAIF_AUD_INTF_ACTV_SLOT_EN_RX_REG(i))
+ return true;
+ if (reg == QAIF_AUD_INTF_LANE_CFG_REG(i))
+ return true;
+ if (reg == QAIF_AUD_INTF_MI2S_CFG_REG(i))
+ return true;
+ if (reg == QAIF_AUD_INTF_CFG_REG(i))
+ return true;
+ }
+
+ /* RDDMA control, configuration and current address */
+ for (i = 0; i < v->num_rddma; i++) {
+ if (reg == QAIF_RDDMA_CTL_REG(v, i))
+ return true;
+ if (reg == QAIF_RDDMA_CFG_REG(v, i))
+ return true;
+ if (reg == QAIF_RDDMA_BASE_ADDR_REG(v, i))
+ return true;
+ if (reg == QAIF_RDDMA_BUFF_LEN_REG(v, i))
+ return true;
+ if (reg == QAIF_RDDMA_CURR_ADDR_REG(v, i))
+ return true;
+ if (reg == QAIF_RDDMA_PERIOD_LEN_REG(v, i))
+ return true;
+ }
+
+ /* CODEC RDDMA control, configuration and current address */
+ for (i = 0; i < v->num_codec_rddma; i++) {
+ if (reg == QAIF_CODEC_RDDMA_CTL_REG(v, i))
+ return true;
+ if (reg == QAIF_CODEC_RDDMA_CFG_REG(v, i))
+ return true;
+ if (reg == QAIF_CODEC_RDDMA_BASE_ADDR_REG(v, i))
+ return true;
+ if (reg == QAIF_CODEC_RDDMA_BUFF_LEN_REG(v, i))
+ return true;
+ if (reg == QAIF_CODEC_RDDMA_CURR_ADDR_REG(v, i))
+ return true;
+ if (reg == QAIF_CODEC_RDDMA_PERIOD_LEN_REG(v, i))
+ return true;
+ if (reg == QAIF_CODEC_RDDMA_INTF_CFG_REG(v, i))
+ return true;
+ }
+
+ /* WRDMA control, configuration and current address */
+ for (i = 0; i < v->num_wrdma; i++) {
+ if (reg == QAIF_WRDMA_CTL_REG(v, i))
+ return true;
+ if (reg == QAIF_WRDMA_CFG_REG(v, i))
+ return true;
+ if (reg == QAIF_WRDMA_BASE_ADDR_REG(v, i))
+ return true;
+ if (reg == QAIF_WRDMA_BUFF_LEN_REG(v, i))
+ return true;
+ if (reg == QAIF_WRDMA_CURR_ADDR_REG(v, i))
+ return true;
+ if (reg == QAIF_WRDMA_PERIOD_LEN_REG(v, i))
+ return true;
+ }
+
+ /* CODEC WRDMA control, configuration and current address */
+ for (i = 0; i < v->num_codec_wrdma; i++) {
+ if (reg == QAIF_CODEC_WRDMA_CTL_REG(v, i))
+ return true;
+ if (reg == QAIF_CODEC_WRDMA_CFG_REG(v, i))
+ return true;
+ if (reg == QAIF_CODEC_WRDMA_BASE_ADDR_REG(v, i))
+ return true;
+ if (reg == QAIF_CODEC_WRDMA_BUFF_LEN_REG(v, i))
+ return true;
+ if (reg == QAIF_CODEC_WRDMA_CURR_ADDR_REG(v, i))
+ return true;
+ if (reg == QAIF_CODEC_WRDMA_PERIOD_LEN_REG(v, i))
+ return true;
+ if (reg == QAIF_CODEC_WRDMA_INTF_CFG_REG(v, i))
+ return true;
+ }
+
+ return false;
+}
+
+static bool audio_qaif_regmap_volatile(struct device *dev, unsigned int reg)
+{
+ struct qaif_drv_data *drvdata = dev_get_drvdata(dev);
+ const struct qaif_variant *v = drvdata->variant;
+ int i;
+
+ /* Summary IRQ status - hardware updated on any interrupt */
+ if (reg == QAIF_SUMMARY_IRQSTAT_REG(v))
+ return true;
+
+ /* EE IRQ status - hardware updated on interrupt */
+ for (i = 0; i < DMA_TYPE_MAX; i++) {
+ if (reg == QAIF_EE_RDDMA_PERIOD_IRQ_STAT_REG(v, i))
+ return true;
+ if (reg == QAIF_EE_RDDMA_UNDERFLOW_IRQ_STAT_REG(v, i))
+ return true;
+ if (reg == QAIF_EE_RDDMA_ERR_RSP_IRQ_STAT_REG(v, i))
+ return true;
+ if (reg == QAIF_EE_WRDMA_PERIOD_IRQ_STAT_REG(v, i))
+ return true;
+ if (reg == QAIF_EE_WRDMA_OVERFLOW_IRQ_STAT_REG(v, i))
+ return true;
+ if (reg == QAIF_EE_WRDMA_ERR_RSP_IRQ_STAT_REG(v, i))
+ return true;
+ }
+
+ /* DMA current address - hardware updated during streaming */
+ for (i = 0; i < v->num_rddma; i++) {
+ if (reg == QAIF_RDDMA_CURR_ADDR_REG(v, i))
+ return true;
+ }
+ for (i = 0; i < v->num_wrdma; i++) {
+ if (reg == QAIF_WRDMA_CURR_ADDR_REG(v, i))
+ return true;
+ }
+ for (i = 0; i < v->num_codec_rddma; i++) {
+ if (reg == QAIF_CODEC_RDDMA_CURR_ADDR_REG(v, i))
+ return true;
+ }
+ for (i = 0; i < v->num_codec_wrdma; i++) {
+ if (reg == QAIF_CODEC_WRDMA_CURR_ADDR_REG(v, i))
+ return true;
+ }
+
+ return false;
+}
+
+static struct regmap_config audio_qaif_regmap_config = {
+ .name = "audio_qaif_cpu",
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .writeable_reg = audio_qaif_regmap_writeable,
+ .readable_reg = audio_qaif_regmap_readable,
+ .volatile_reg = audio_qaif_regmap_volatile,
+ .cache_type = REGCACHE_FLAT,
+};
+
+static int of_qaif_parse_aif_intf_cfg(struct device *dev,
+ struct qaif_drv_data *data)
+{
+ const struct qaif_variant *v = data->variant;
+ struct device_node *np = dev->of_node;
+ struct device_node *intf_np;
+ struct qaif_aif_config *cfg;
+ const __be32 *lane_cfg_prop;
+ int ret, j;
+ int lane_cfg_len;
+ u32 dai_id, intf_idx;
+ int num_interfaces = 0;
+
+ if (!v) {
+ dev_err(dev, "No variant data\n");
+ return -EINVAL;
+ }
+
+ /*
+ * Iterate over all child nodes of qaif_cpu and process only those
+ * with a recognised AIF interface compatible. The compatible string
+ * identifies the serial protocol the interface is wired for on the
+ * board: qcom,qaif-pcm-dai, qcom,qaif-tdm-dai or qcom,qaif-mi2s-dai.
+ * Other child nodes are silently skipped.
+ */
+ for_each_child_of_node(np, intf_np) {
+ enum qaif_aif_mode mode;
+
+ if (of_device_is_compatible(intf_np, "qcom,qaif-pcm-dai"))
+ mode = QAIF_AIF_MODE_PCM;
+ else if (of_device_is_compatible(intf_np, "qcom,qaif-tdm-dai"))
+ mode = QAIF_AIF_MODE_TDM;
+ else if (of_device_is_compatible(intf_np, "qcom,qaif-mi2s-dai"))
+ mode = QAIF_AIF_MODE_MI2S;
+ else
+ continue;
+
+ if (num_interfaces >= QAIF_MAX_AIF_CFG_CNT) {
+ dev_warn(dev, "Too many AIF interfaces, limiting to %d\n",
+ QAIF_MAX_AIF_CFG_CNT);
+ of_node_put(intf_np);
+ break;
+ }
+
+
+ ret = of_property_read_u32(intf_np, "reg", &dai_id);
+ if (ret) {
+ dev_err(dev, "Missing reg for interface %d: %s\n", num_interfaces, intf_np->name);
+ continue;
+ }
+
+ if (v->get_dma_idx) {
+ intf_idx = v->get_dma_idx(dai_id);
+ if (intf_idx < 0) {
+ dev_err(dev, "Invalid DAI ID %d for interface '%s' (node %d)\n",
+ dai_id, intf_np->name, num_interfaces);
+ continue;
+ }
+ if (intf_idx >= ARRAY_SIZE(data->aif_intf_cfg)) {
+ dev_err(dev, "DAI ID %d maps to out-of-range intf_idx %d\n",
+ dai_id, intf_idx);
+ continue;
+ }
+ } else {
+ dev_err(dev, "can not get intf idx for : %d: %s\n", num_interfaces, intf_np->name);
+ of_node_put(intf_np);
+ return -EINVAL;
+ }
+ cfg = &data->aif_intf_cfg[intf_idx];
+ cfg->mode = mode;
+
+ /* Parse sync configuration — mode-specific */
+ if (mode == QAIF_AIF_MODE_MI2S) {
+ /* MI2S: sync mode is fixed (long sync = 1, WS-based) */
+ cfg->sync_mode = 1;
+ } else {
+ /* PCM/TDM: sync mode comes from DT (0=short, 1=long) */
+ ret = of_property_read_u32(intf_np, "qcom,qaif-aif-sync-mode",
+ &cfg->sync_mode);
+ if (ret) {
+ dev_err(dev, "Missing sync-mode for interface %d\n",
+ num_interfaces);
+ of_node_put(intf_np);
+ return -EINVAL;
+ }
+ }
+
+ ret = of_property_read_u32(intf_np, "qcom,qaif-aif-sync-src", &cfg->sync_src);
+ if (ret) {
+ dev_warn(dev, "Missing sync-src for interface %d\n", num_interfaces);
+ cfg->sync_src = 0;
+ }
+
+ cfg->invert_sync = of_property_read_bool(intf_np, "qcom,qaif-aif-invert-sync");
+
+ ret = of_property_read_u32(intf_np, "qcom,qaif-aif-sync-delay", &cfg->sync_delay);
+ if (ret) {
+ dev_warn(dev, "Missing sync-delay for interface %d\n", num_interfaces);
+ cfg->sync_delay = 0;
+ }
+
+ /* Parse slot and sample width configuration */
+ ret = of_property_read_u32(intf_np, "qcom,qaif-aif-slot-width-rx", &cfg->slot_width_rx);
+ if (ret) {
+ dev_warn(dev, "Missing slot-width-rx for interface %d\n", num_interfaces);
+ cfg->slot_width_rx = 0;
+ }
+
+ ret = of_property_read_u32(intf_np, "qcom,qaif-aif-slot-width-tx", &cfg->slot_width_tx);
+ if (ret) {
+ dev_warn(dev, "Missing slot-width-tx for interface %d\n", num_interfaces);
+ cfg->slot_width_tx = 0;
+ }
+
+ /* Parse slot enable masks — mode-specific */
+ if (mode == QAIF_AIF_MODE_MI2S) {
+ /* MI2S: always 2 active slots (left + right) */
+ cfg->slot_en_rx_mask = 0x3;
+ cfg->slot_en_tx_mask = 0x3;
+ } else {
+ /* PCM/TDM: active slot mask comes from DT */
+ ret = of_property_read_u32(intf_np, "qcom,qaif-aif-slot-en-rx-mask",
+ &cfg->slot_en_rx_mask);
+ if (ret) {
+ dev_warn(dev, "Missing slot-en-rx-mask for interface %d\n",
+ num_interfaces);
+ cfg->slot_en_rx_mask = 0;
+ }
+ ret = of_property_read_u32(intf_np, "qcom,qaif-aif-slot-en-tx-mask",
+ &cfg->slot_en_tx_mask);
+ if (ret) {
+ dev_warn(dev, "Missing slot-en-tx-mask for interface %d\n",
+ num_interfaces);
+ cfg->slot_en_tx_mask = 0;
+ }
+ }
+
+ /* Parse control configuration */
+ cfg->loopback_en = of_property_read_bool(intf_np, "qcom,qaif-aif-loopback");
+
+ cfg->ctrl_data_oe = of_property_read_bool(intf_np, "qcom,qaif-aif-ctrl-data-oe");
+
+ /* Parse lane configuration */
+ lane_cfg_prop = of_get_property(intf_np, "qcom,qaif-aif-lane-config", &lane_cfg_len);
+ if (lane_cfg_prop) {
+ /* Each lane config has 2 u32 values: enable and direction */
+ cfg->num_lanes = lane_cfg_len / (2 * sizeof(u32));
+ if (cfg->num_lanes > QAIF_MAX_LANES) {
+ dev_warn(dev, "Too many lanes (%d), limiting to %d\n",
+ cfg->num_lanes, QAIF_MAX_LANES);
+ cfg->num_lanes = QAIF_MAX_LANES;
+ }
+
+ for (j = 0; j < cfg->num_lanes; j++) {
+ cfg->lane_cfg[j].enable = be32_to_cpup(lane_cfg_prop + (j * 2));
+ if (cfg->lane_cfg[j].enable)
+ cfg->lane_en_mask |= BIT(j);
+
+ cfg->lane_cfg[j].direction = be32_to_cpup(lane_cfg_prop + (j * 2 + 1));
+ if (cfg->lane_cfg[j].direction)
+ cfg->lane_dir_mask |= BIT(j);
+ }
+
+ } else {
+ dev_warn(dev, "Missing lane-config for interface %d\n", num_interfaces);
+ cfg->num_lanes = 0;
+ }
+
+ /* Mono/stereo mode is written directly from params_channels() in hw_params */
+
+ /* Parse frame configuration */
+ cfg->full_cycle_en = of_property_read_bool(intf_np, "qcom,qaif-aif-full-cycle-en");
+
+ ret = of_property_read_u32(intf_np, "qcom,qaif-aif-bits-per-lane", &cfg->bits_per_lane);
+ if (ret) {
+ dev_warn(dev, "Missing bits-per-lane for interface %d\n", num_interfaces);
+ cfg->bits_per_lane = 0;
+ }
+
+ num_interfaces++;
+ }
+
+ if (num_interfaces == 0) {
+ dev_err(dev, "No AIF child nodes with qcom,qaif-{pcm,tdm,mi2s}-dai compatible found\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int of_qaif_cdc_dma_clks_parse(struct device *dev,
+ struct qaif_drv_data *data)
+{
+ data->aud_dma_clk = devm_clk_get(dev, "aud_dma_clk");
+ if (IS_ERR(data->aud_dma_clk))
+ return PTR_ERR(data->aud_dma_clk);
+
+ data->aud_dma_mem_clk = devm_clk_get(dev, "aud_dma_mem_clk");
+ if (IS_ERR(data->aud_dma_mem_clk))
+ return PTR_ERR(data->aud_dma_mem_clk);
+
+ return 0;
+}
+
+int asoc_qcom_qaif_cpu_platform_probe(struct platform_device *pdev)
+{
+ struct qaif_drv_data *drvdata;
+ struct resource *res;
+ const struct qaif_variant *variant;
+ struct device *dev = &pdev->dev;
+ const struct of_device_id *match;
+ int ret, i, dai_id, idx;
+ bool variant_init_done = false;
+
+ dev_dbg(dev, "%s\n", __func__);
+ drvdata = devm_kzalloc(dev, sizeof(struct qaif_drv_data), GFP_KERNEL);
+ if (!drvdata)
+ return -ENOMEM;
+ platform_set_drvdata(pdev, drvdata);
+
+ match = of_match_device(dev->driver->of_match_table, dev);
+ if (!match || !match->data)
+ return -EINVAL;
+
+ drvdata->variant = (const struct qaif_variant *)match->data;
+ variant = drvdata->variant;
+ if (!variant) {
+ dev_err(dev, "No variant data\n");
+ return -EINVAL;
+ }
+
+ ret = of_qaif_parse_aif_intf_cfg(dev, drvdata);
+ if (ret) {
+ dev_err(dev, "Failed to parse aif interfaces: %d\n", ret);
+ return -EINVAL;
+ }
+
+ drvdata->audio_qaif =
+ devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(drvdata->audio_qaif))
+ return PTR_ERR(drvdata->audio_qaif);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -EINVAL;
+
+ audio_qaif_regmap_config.max_register = resource_size(res);
+
+ drvdata->audio_qaif_map = devm_regmap_init_mmio(dev, drvdata->audio_qaif,
+ &audio_qaif_regmap_config);
+ if (IS_ERR(drvdata->audio_qaif_map))
+ return PTR_ERR(drvdata->audio_qaif_map);
+
+ ret = of_qaif_cdc_dma_clks_parse(dev, drvdata);
+ if (ret) {
+ dev_err(dev, "failed to get cdc dma clocks %d\n", ret);
+ return ret;
+ }
+
+ if (variant->init) {
+ ret = variant->init(pdev);
+ if (ret) {
+ dev_err(dev, "error initializing variant: %d\n", ret);
+ return ret;
+ }
+ variant_init_done = true;
+ }
+
+ for (i = 0; i < variant->num_dai; i++) {
+ dai_id = variant->dai_driver[i].id;
+ if (is_cif_dma_port(dai_id))
+ continue;
+ idx = variant->get_dma_idx(dai_id);
+ if (idx < 0)
+ continue;
+
+ drvdata->mi2s_bit_clk[idx] = devm_clk_get(dev,
+ variant->dai_bit_clk_names[idx]);
+ if (IS_ERR(drvdata->mi2s_bit_clk[idx])) {
+ dev_err(dev,
+ "error getting %s: %ld\n",
+ variant->dai_bit_clk_names[idx],
+ PTR_ERR(drvdata->mi2s_bit_clk[idx]));
+ ret = PTR_ERR(drvdata->mi2s_bit_clk[idx]);
+ goto err;
+ }
+ }
+
+ ret = qaif_aif_cpu_init_bitfields(dev, drvdata->audio_qaif_map);
+ if (ret) {
+ dev_err(dev, "error init cif bitfield: %d\n", ret);
+ goto err;
+ }
+
+ ret = qaif_aif_cfg_cpu_init_bitfields(dev, drvdata->audio_qaif_map);
+ if (ret) {
+ dev_err(dev, "error init aif_intfctl field: %d\n", ret);
+ goto err;
+ }
+
+ ret = qaif_cif_cpu_init_bitfields(dev, drvdata->audio_qaif_map);
+ if (ret) {
+ dev_err(dev, "error init cif bitfield: %d\n", ret);
+ goto err;
+ }
+
+ ret = devm_snd_soc_register_component(dev, &qaif_cpu_comp_driver,
+ variant->dai_driver,
+ variant->num_dai);
+ if (ret) {
+ dev_err(dev, "error registering cpu driver: %d\n", ret);
+ goto err;
+ }
+
+ ret = asoc_qcom_qaif_platform_register(pdev);
+ if (ret) {
+ dev_err(dev, "error registering platform driver: %d\n", ret);
+ goto err;
+ }
+ dev_dbg(&pdev->dev, "%s: QAIF CPU-Platform Driver Registered Successfully\n", __func__);
+err:
+ if (ret && variant_init_done && variant->exit)
+ variant->exit(pdev);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(asoc_qcom_qaif_cpu_platform_probe);
+
+void asoc_qcom_qaif_cpu_platform_remove(struct platform_device *pdev)
+{
+ struct qaif_drv_data *drvdata = platform_get_drvdata(pdev);
+
+ if (drvdata->variant->exit)
+ drvdata->variant->exit(pdev);
+}
+EXPORT_SYMBOL_GPL(asoc_qcom_qaif_cpu_platform_remove);
+
+void asoc_qcom_qaif_cpu_platform_shutdown(struct platform_device *pdev)
+{
+ struct qaif_drv_data *drvdata = platform_get_drvdata(pdev);
+
+ if (drvdata->variant->exit)
+ drvdata->variant->exit(pdev);
+}
+EXPORT_SYMBOL_GPL(asoc_qcom_qaif_cpu_platform_shutdown);
+
+MODULE_DESCRIPTION("Qualcomm Audio Interface (QAIF) CPU DAI driver");
+MODULE_AUTHOR("Harendra Gautam <harendra.gautam@xxxxxxxxxxxxxxxx>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/qcom/qaif-platform.c b/sound/soc/qcom/qaif-platform.c
new file mode 100644
index 000000000000..14e3379ca560
--- /dev/null
+++ b/sound/soc/qcom/qaif-platform.c
@@ -0,0 +1,282 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ *
+ * qaif-platform.c -- ALSA SoC PCM platform driver for the Qualcomm Audio Interface (QAIF)
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/export.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <sound/pcm_params.h>
+#include <linux/regmap.h>
+#include <sound/soc.h>
+#include "qaif-reg.h"
+#include "qaif.h"
+
+#define DRV_NAME "qaif-platform"
+
+/* 20 ms period at 48 kHz S16 stereo = 3840 bytes */
+#define QAIF_PLATFORM_BUFFER_MIN_SIZE (960 * 2 * 2)
+#define QAIF_PLATFORM_PERIOD_BYTES_MIN (960 * 2 * 2)
+#define QAIF_PLATFORM_BUFFER_SIZE (4 * QAIF_PLATFORM_BUFFER_MIN_SIZE)
+#define QAIF_PLATFORM_PERIODS_MIN 2
+#define QAIF_PLATFORM_PERIODS_MAX 4
+
+
+static const struct snd_pcm_hardware qaif_platform_aif_hardware = {
+ .info = SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_PAUSE |
+ SNDRV_PCM_INFO_RESUME,
+ .formats = SNDRV_PCM_FMTBIT_S16 |
+ SNDRV_PCM_FMTBIT_S24 |
+ SNDRV_PCM_FMTBIT_S32,
+ .rates = SNDRV_PCM_RATE_8000_192000,
+ .rate_min = 8000,
+ .rate_max = 192000,
+ .channels_min = 1,
+ .channels_max = 8,
+ .buffer_bytes_max = QAIF_PLATFORM_BUFFER_SIZE,
+ .period_bytes_min = QAIF_PLATFORM_PERIOD_BYTES_MIN,
+ .period_bytes_max = QAIF_PLATFORM_BUFFER_SIZE / QAIF_PLATFORM_PERIODS_MIN,
+ .periods_min = QAIF_PLATFORM_PERIODS_MIN,
+ .periods_max = QAIF_PLATFORM_PERIODS_MAX,
+ .fifo_size = 0,
+};
+
+static const struct snd_pcm_hardware qaif_platform_cif_hardware = {
+ .info = SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_PAUSE |
+ SNDRV_PCM_INFO_RESUME,
+ .formats = SNDRV_PCM_FMTBIT_S16 |
+ SNDRV_PCM_FMTBIT_S24 |
+ SNDRV_PCM_FMTBIT_S32,
+ .rates = SNDRV_PCM_RATE_8000_192000,
+ .rate_min = 8000,
+ .rate_max = 192000,
+ .channels_min = 1,
+ .channels_max = 8,
+ .buffer_bytes_max = QAIF_PLATFORM_BUFFER_SIZE,
+ .period_bytes_min = QAIF_PLATFORM_PERIOD_BYTES_MIN,
+ .period_bytes_max = QAIF_PLATFORM_BUFFER_SIZE / QAIF_PLATFORM_PERIODS_MIN,
+ .periods_min = QAIF_PLATFORM_PERIODS_MIN,
+ .periods_max = QAIF_PLATFORM_PERIODS_MAX,
+ .fifo_size = 0,
+};
+
+static struct qaif_dma_mem_info *qaif_mem_alloc_attach(
+ struct snd_soc_component *component, size_t alloc_size)
+{
+ struct device *dev = component->dev;
+ struct qaif_dma_mem_info *dma_mem_info;
+
+ dma_mem_info = kzalloc(sizeof(*dma_mem_info), GFP_KERNEL);
+ if (!dma_mem_info)
+ return NULL;
+
+ dma_mem_info->alloc_size = alloc_size;
+
+ dma_mem_info->vaddr = dma_alloc_coherent(dev, alloc_size,
+ &dma_mem_info->dma_addr,
+ GFP_KERNEL);
+ if (!dma_mem_info->vaddr) {
+ dev_err(dev, "dma_alloc_coherent failed for %zu bytes\n", alloc_size);
+ kfree(dma_mem_info);
+ return NULL;
+ }
+
+ dev_dbg(dev, "%s: dma_addr=%pad vaddr=%p\n", __func__,
+ &dma_mem_info->dma_addr, dma_mem_info->vaddr);
+ return dma_mem_info;
+}
+
+static void qaif_mem_dealloc_detach(struct device *dev,
+ struct qaif_dma_mem_info *dma_info)
+{
+ if (!dma_info)
+ return;
+
+ if (dma_info->vaddr)
+ dma_free_coherent(dev, dma_info->alloc_size,
+ dma_info->vaddr, dma_info->dma_addr);
+
+ kfree(dma_info);
+}
+
+static struct qaif_dmactl *qaif_get_dmactl_handle(const struct snd_pcm_substream *substream,
+ struct snd_soc_component *component)
+{
+ struct snd_soc_pcm_runtime *soc_runtime = snd_soc_substream_to_rtd(substream);
+ struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(soc_runtime, 0);
+ struct qaif_drv_data *drvdata = snd_soc_component_get_drvdata(component);
+ struct qaif_dmactl *dmactl = NULL;
+
+ switch (cpu_dai->driver->id) {
+ case QAIF_MI2S_TDM_AIF0 ... QAIF_MI2S_TDM_AIF12:
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ dmactl = drvdata->aif_rd_dmactl;
+ else
+ dmactl = drvdata->aif_wr_dmactl;
+ break;
+ case QAIF_CDC_DMA_RX0 ... QAIF_CDC_DMA_RX9:
+ dmactl = drvdata->cif_rd_dmactl;
+ break;
+ case QAIF_CDC_DMA_TX0 ... QAIF_CDC_DMA_TX9:
+ case QAIF_CDC_DMA_VA_TX0 ... QAIF_CDC_DMA_VA_TX9:
+ dmactl = drvdata->cif_wr_dmactl;
+ break;
+ }
+
+ return dmactl;
+}
+
+
+static int qaif_map_ee_resource(struct qaif_drv_data *drvdata)
+{
+ const struct qaif_variant *v = drvdata->variant;
+ struct regmap *map = drvdata->audio_qaif_map;
+ int ret = 0;
+ u32 mask;
+
+ mask = GENMASK(v->num_rddma - 1, 0);
+ ret |= regmap_write(map, QAIF_EE_RDDMA_MAP_REG(v), mask);
+
+ mask = GENMASK(v->num_wrdma - 1, 0);
+ ret |= regmap_write(map, QAIF_EE_WRDMA_MAP_REG(v), mask);
+
+ if (v->num_intf > 0) {
+ mask = GENMASK(v->num_intf - 1, 0);
+ ret |= regmap_write(map, QAIF_EE_INTF_MAP_REG(v), mask);
+ }
+
+ mask = GENMASK(v->num_codec_rddma - 1, 0);
+ ret |= regmap_write(map, QAIF_EE_CODEC_RDDMA_MAP_REG(v), mask);
+
+ mask = GENMASK(v->num_codec_wrdma - 1, 0);
+ ret |= regmap_write(map, QAIF_EE_CODEC_WRDMA_MAP_REG(v), mask);
+
+ if (ret)
+ return ret;
+ return 0;
+}
+
+static int qaif_map_dma_path(struct qaif_drv_data *drvdata)
+{
+ struct regmap *map = drvdata->audio_qaif_map;
+ const struct qaif_variant *v = drvdata->variant;
+ int ret = 0;
+ int qxm_sel = v->qxm_type;
+
+ if (qxm_sel != QXM0) {
+ dev_err(regmap_get_device(map),
+ "%s: only QXM0 is supported, qxm_type=%d\n",
+ __func__, qxm_sel);
+ return -EINVAL;
+ }
+
+ ret |= regmap_write(map, QAIF_RDDMA_MAP_QXM, qxm_sel);
+ ret |= regmap_write(map, QAIF_WRDMA_MAP_QXM, qxm_sel);
+ ret |= regmap_write(map, QAIF_CODEC_RDDMA_MAP_QXM, qxm_sel);
+ ret |= regmap_write(map, QAIF_CODEC_WRDMA_MAP_QXM, qxm_sel);
+
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int qaif_config_shram(struct qaif_drv_data *drvdata)
+{
+ const struct qaif_variant *v = drvdata->variant;
+ u32 start_addr, shram_len;
+ int ret = 0, i = 0;
+ struct regmap *map = drvdata->audio_qaif_map;
+
+ if (v->qxm_type != QXM0) {
+ dev_err(regmap_get_device(map),
+ "%s: only QXM0 is supported, qxm_type=%d\n",
+ __func__, v->qxm_type);
+ return -EINVAL;
+ }
+ start_addr = v->rddma_shram_start_addr[QAIF_AIF_DMA];
+ shram_len = v->rddma_shram_len;
+ for (i = 0; i < v->num_rddma; i++) {
+ ret = regmap_write(map, QAIF_RDDMA_QXM0_SHRAM_ST_ADDR(i), start_addr + (shram_len * i));
+ if (ret)
+ return ret;
+ ret = regmap_write(map, QAIF_RDDMA_QXM0_SHRAM_LEN(i), shram_len);
+ if (ret)
+ return ret;
+ }
+ start_addr = v->wrdma_shram_start_addr[QAIF_AIF_DMA];
+ shram_len = v->wrdma_shram_len;
+ for (i = 0; i < v->num_wrdma; i++) {
+ ret = regmap_write(map, QAIF_WRDMA_QXM0_SHRAM_ST_ADDR(i), start_addr + (shram_len * i));
+ if (ret)
+ return ret;
+ ret = regmap_write(map, QAIF_WRDMA_QXM0_SHRAM_LEN(i), shram_len);
+ if (ret)
+ return ret;
+ }
+ start_addr = v->rddma_shram_start_addr[QAIF_CIF_DMA];
+ shram_len = v->rddma_shram_len;
+ for (i = 0; i < v->num_codec_rddma; i++) {
+ ret = regmap_write(map, QAIF_CODEC_RDDMA_QXM0_SHRAM_ST_ADDR(i), start_addr + (shram_len * i));
+ if (ret)
+ return ret;
+ ret = regmap_write(map, QAIF_CODEC_RDDMA_QXM0_SHRAM_LEN(i), shram_len);
+ if (ret)
+ return ret;
+ }
+ start_addr = v->wrdma_shram_start_addr[QAIF_CIF_DMA];
+ shram_len = v->wrdma_shram_len;
+ for (i = 0; i < v->num_codec_wrdma; i++) {
+ ret = regmap_write(map, QAIF_CODEC_WRDMA_QXM0_SHRAM_ST_ADDR(i), start_addr + (shram_len * i));
+ if (ret)
+ return ret;
+ ret = regmap_write(map, QAIF_CODEC_WRDMA_QXM0_SHRAM_LEN(i), shram_len);
+
+ if (ret)
+ return ret;
+ }
+ return 0;
+}
+
+static int qaif_init(struct snd_soc_component *component)
+{
+ struct qaif_drv_data *drvdata = snd_soc_component_get_drvdata(component);
+ int ret = 0;
+
+ if (drvdata->qaif_init_ref_cnt) {
+ dev_dbg(component->dev, "%s: QAIF init is done already: ref cnt: %d\n",
+ __func__, drvdata->qaif_init_ref_cnt);
+ return 0;
+ }
+
+ ret = qaif_config_shram(drvdata);
+ if (ret) {
+ dev_err(component->dev, "QAIF: Failed to config shram: %d\n", ret);
+ return ret;
+ }
+
+ ret = qaif_map_ee_resource(drvdata);
+ if (ret) {
+ dev_err(component->dev, "QAIF: Failed to map EE resources: %d\n", ret);
+ return ret;
+ }
+
+ ret = qaif_map_dma_path(drvdata);
+ if (ret) {
+ dev_err(component->dev, "QAIF: Failed to map DMA path: %d\n", ret);
+ return ret;
+ }
+ dev_dbg(component->dev, "%s: QAIF init is done ref cnt: %d\n",
+ __func__, drvdata->qaif_init_ref_cnt);
+ return 0;
+}
--
2.34.1