Re: [PATCH v3 8/9] ASoC: qcom: Add Shikra QAIF support
From: Harendra Gautam
Date: Wed Aug 26 2026 - 04:58:41 EST
On Wed, Aug 26, 2026 at 2:05 PM Mohammad Rafi Shaik
<mohammad.rafi.shaik@xxxxxxxxxxxxxxxx> wrote:
>
>
>
> On 8/24/2026 12:06 PM, Harendra Gautam wrote:
> > Provide the Shikra DMA-to-DAI mappings, DMA and SHRAM layout, clock
> > names, DAI driver data and power-management hooks required by the QAIF
> > driver. Add the Kconfig symbol and Makefile entries needed to build the
> > new variant.
> >
> > Signed-off-by: Harendra Gautam <harendra.gautam@xxxxxxxxxxxxxxxx>
> > ---
> > sound/soc/qcom/Kconfig | 10 +
> > sound/soc/qcom/Makefile | 3 +
> > sound/soc/qcom/qaif-shikra.c | 425 +++++++++++++++++++++++++++++++++++
> > 3 files changed, 438 insertions(+)
> > create mode 100644 sound/soc/qcom/qaif-shikra.c
> >
> > diff --git a/sound/soc/qcom/Kconfig b/sound/soc/qcom/Kconfig
> > index e6e24f3b9922..b7088b1e5cad 100644
> > --- a/sound/soc/qcom/Kconfig
> > +++ b/sound/soc/qcom/Kconfig
> > @@ -71,6 +71,16 @@ config SND_SOC_QCOM_COMMON
> > config SND_SOC_QCOM_SDW
> > tristate
> >
> > +config SND_SOC_QCOM_QAIF
> > + tristate "Qualcomm QAIF audio interface support"
> > + depends on COMMON_CLK
> > + select REGMAP_MMIO
> > + help
> > + Say Y or M to enable the Qualcomm Audio Interface (QAIF) driver
> > + for the Shikra audio platform. QAIF is a DMA-based audio
> > + subsystem that moves PCM data between memory and external serial
> > + audio interfaces (AIF) and internal codec interfaces (CIF).
> > +
> > config SND_SOC_QDSP6_COMMON
> > tristate
> >
> > diff --git a/sound/soc/qcom/Makefile b/sound/soc/qcom/Makefile
> > index 985ce2ae286b..cf50b7a24bcf 100644
> > --- a/sound/soc/qcom/Makefile
> > +++ b/sound/soc/qcom/Makefile
> > @@ -47,3 +47,6 @@ obj-$(CONFIG_SND_SOC_QCOM_OFFLOAD_UTILS) += snd-soc-qcom-offload-utils.o
> >
> > #DSP lib
> > obj-$(CONFIG_SND_SOC_QDSP6) += qdsp6/
> > +
> > +snd-soc-qcom-qaif-y := qaif-cpu.o qaif-platform.o qaif-shikra.o
> > +obj-$(CONFIG_SND_SOC_QCOM_QAIF) += snd-soc-qcom-qaif.o
> > diff --git a/sound/soc/qcom/qaif-shikra.c b/sound/soc/qcom/qaif-shikra.c
> > new file mode 100644
> > index 000000000000..484ffaa5b304
> > --- /dev/null
> > +++ b/sound/soc/qcom/qaif-shikra.c
> > @@ -0,0 +1,425 @@
> > +// SPDX-License-Identifier: GPL-2.0-only
> > +/*
> > + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
> > + *
> > + * qaif-shikra.c -- ALSA SoC CPU-Platform DAI driver for QTi QAIF
> > + */
> > +
> > +#include <linux/module.h>
> > +#include <linux/pm.h>
> > +#include <sound/pcm.h>
> > +#include <sound/soc.h>
> > +#include "qaif.h"
> > +
> > +static const struct qaif_dmaidx_dai_map shikra_mi2s_dma_dai_map[] = {
> > + { QAIF_MI2S_AIF0, QAIF_DMA_IDX0 },
> > + { QAIF_MI2S_AIF1, QAIF_DMA_IDX1 },
> > + { QAIF_MI2S_AIF2, QAIF_DMA_IDX2 },
> > + { QAIF_MI2S_AIF3, QAIF_DMA_IDX3 },
> > +};
> > +
> > +static const struct qaif_dmaidx_dai_map shikra_tdm_dma_dai_map[] = {
> > + { QAIF_TDM_AIF0, QAIF_DMA_IDX0 },
> > + { QAIF_TDM_AIF1, QAIF_DMA_IDX1 },
> > + { QAIF_TDM_AIF2, QAIF_DMA_IDX2 },
> > + { QAIF_TDM_AIF3, QAIF_DMA_IDX3 },
> > +};
> > +
> > +static const struct qaif_dmaidx_dai_map shikra_cif_rx_dma_dai_map[] = {
> > + { QAIF_CDC_DMA_RX0, QAIF_DMA_IDX0 },
> > + { QAIF_CDC_DMA_RX1, QAIF_DMA_IDX1 },
> > +};
> > +
> > +static const struct qaif_dmaidx_dai_map shikra_cif_va_dma_dai_map[] = {
> > + { QAIF_CDC_DMA_VA_TX0, QAIF_DMA_IDX0 },
> > + { QAIF_CDC_DMA_VA_TX1, QAIF_DMA_IDX1 },
> > +};
> > +
> > +static struct snd_soc_dai_driver shikra_qaif_cpu_dai_driver[] = {
> > + {
> > + .id = QAIF_MI2S_AIF0,
> > + .name = "MI2S AIF Zero",
> > + .playback = {
> > + .stream_name = "MI2S AIF Zero Playback",
> > + .formats = SNDRV_PCM_FMTBIT_S16 |
> > + SNDRV_PCM_FMTBIT_S32,
> > + .rates = SNDRV_PCM_RATE_8000_192000,
> > + .channels_min = 1,
> > + .channels_max = 2,
> > + },
> > + .capture = {
> > + .stream_name = "MI2S AIF Zero Capture",
> > + .formats = SNDRV_PCM_FMTBIT_S16 |
> > + SNDRV_PCM_FMTBIT_S32,
> > + .rates = SNDRV_PCM_RATE_8000_192000,
> > + .channels_min = 1,
> > + .channels_max = 2,
> > + },
> > + .ops = &asoc_qcom_qaif_aif_cpu_dai_ops,
> > + }, {
> > + .id = QAIF_MI2S_AIF1,
> > + .name = "MI2S AIF One",
> > + .playback = {
> > + .stream_name = "MI2S AIF One Playback",
> > + .formats = SNDRV_PCM_FMTBIT_S16 |
> > + SNDRV_PCM_FMTBIT_S32,
> > + .rates = SNDRV_PCM_RATE_8000_192000,
> > + .channels_min = 1,
> > + .channels_max = 2,
> > + },
> > + .capture = {
> > + .stream_name = "MI2S AIF One Capture",
> > + .formats = SNDRV_PCM_FMTBIT_S16 |
> > + SNDRV_PCM_FMTBIT_S32,
> > + .rates = SNDRV_PCM_RATE_8000_192000,
> > + .channels_min = 1,
> > + .channels_max = 2,
> > + },
> > + .ops = &asoc_qcom_qaif_aif_cpu_dai_ops,
> > + }, {
> > + .id = QAIF_MI2S_AIF2,
> > + .name = "MI2S AIF Two",
> > + .playback = {
> > + .stream_name = "MI2S AIF Two Playback",
> > + .formats = SNDRV_PCM_FMTBIT_S16 |
> > + SNDRV_PCM_FMTBIT_S32,
> > + .rates = SNDRV_PCM_RATE_8000_192000,
> > + .channels_min = 1,
> > + .channels_max = 2,
> > + },
> > + .capture = {
> > + .stream_name = "MI2S AIF Two Capture",
> > + .formats = SNDRV_PCM_FMTBIT_S16 |
> > + SNDRV_PCM_FMTBIT_S32,
> > + .rates = SNDRV_PCM_RATE_8000_192000,
> > + .channels_min = 1,
> > + .channels_max = 2,
> > + },
> > + .ops = &asoc_qcom_qaif_aif_cpu_dai_ops,
> > + }, {
> > + .id = QAIF_MI2S_AIF3,
> > + .name = "MI2S AIF Three",
> > + .playback = {
> > + .stream_name = "MI2S AIF Three Playback",
> > + .formats = SNDRV_PCM_FMTBIT_S16 |
> > + SNDRV_PCM_FMTBIT_S32,
> > + .rates = SNDRV_PCM_RATE_8000_192000,
> > + .channels_min = 1,
> > + .channels_max = 2,
> > + },
> > + .capture = {
> > + .stream_name = "MI2S AIF Three Capture",
> > + .formats = SNDRV_PCM_FMTBIT_S16 |
> > + SNDRV_PCM_FMTBIT_S32,
> > + .rates = SNDRV_PCM_RATE_8000_192000,
> > + .channels_min = 1,
> > + .channels_max = 2,
> > + },
> > + .ops = &asoc_qcom_qaif_aif_cpu_dai_ops,
> > + }, {
> > + .id = QAIF_TDM_AIF0,
> > + .name = "TDM AIF Zero",
> > + .playback = {
> > + .stream_name = "TDM AIF Zero Playback",
> > + .formats = SNDRV_PCM_FMTBIT_S16 |
> > + SNDRV_PCM_FMTBIT_S24 |
> > + SNDRV_PCM_FMTBIT_S32,
> > + .rates = SNDRV_PCM_RATE_8000_192000,
> > + .channels_min = 1,
> > + .channels_max = 8,
> > + },
> > + .capture = {
> > + .stream_name = "TDM AIF Zero Capture",
> > + .formats = SNDRV_PCM_FMTBIT_S16 |
> > + SNDRV_PCM_FMTBIT_S24 |
> > + SNDRV_PCM_FMTBIT_S32,
> > + .rates = SNDRV_PCM_RATE_8000_192000,
> > + .channels_min = 1,
> > + .channels_max = 8,
> > + },
> > + .ops = &asoc_qcom_qaif_aif_cpu_dai_ops,
> > + }, {
> > + .id = QAIF_TDM_AIF1,
> > + .name = "TDM AIF One",
> > + .playback = {
> > + .stream_name = "TDM AIF One Playback",
> > + .formats = SNDRV_PCM_FMTBIT_S16 |
> > + SNDRV_PCM_FMTBIT_S24 |
> > + SNDRV_PCM_FMTBIT_S32,
> > + .rates = SNDRV_PCM_RATE_8000_192000,
> > + .channels_min = 1,
> > + .channels_max = 8,
> > + },
> > + .capture = {
> > + .stream_name = "TDM AIF One Capture",
> > + .formats = SNDRV_PCM_FMTBIT_S16 |
> > + SNDRV_PCM_FMTBIT_S24 |
> > + SNDRV_PCM_FMTBIT_S32,
> > + .rates = SNDRV_PCM_RATE_8000_192000,
> > + .channels_min = 1,
> > + .channels_max = 8,
> > + },
> > + .ops = &asoc_qcom_qaif_aif_cpu_dai_ops,
> > + }, {
> > + .id = QAIF_TDM_AIF2,
> > + .name = "TDM AIF Two",
> > + .playback = {
> > + .stream_name = "TDM AIF Two Playback",
> > + .formats = SNDRV_PCM_FMTBIT_S16 |
> > + SNDRV_PCM_FMTBIT_S24 |
> > + SNDRV_PCM_FMTBIT_S32,
> > + .rates = SNDRV_PCM_RATE_8000_192000,
> > + .channels_min = 1,
> > + .channels_max = 8,
> > + },
> > + .capture = {
> > + .stream_name = "TDM AIF Two Capture",
> > + .formats = SNDRV_PCM_FMTBIT_S16 |
> > + SNDRV_PCM_FMTBIT_S24 |
> > + SNDRV_PCM_FMTBIT_S32,
> > + .rates = SNDRV_PCM_RATE_8000_192000,
> > + .channels_min = 1,
> > + .channels_max = 8,
> > + },
> > + .ops = &asoc_qcom_qaif_aif_cpu_dai_ops,
> > + }, {
> > + .id = QAIF_TDM_AIF3,
> > + .name = "TDM AIF Three",
> > + .playback = {
> > + .stream_name = "TDM AIF Three Playback",
> > + .formats = SNDRV_PCM_FMTBIT_S16 |
> > + SNDRV_PCM_FMTBIT_S24 |
> > + SNDRV_PCM_FMTBIT_S32,
> > + .rates = SNDRV_PCM_RATE_8000_192000,
> > + .channels_min = 1,
> > + .channels_max = 8,
> > + },
> > + .capture = {
> > + .stream_name = "TDM AIF Three Capture",
> > + .formats = SNDRV_PCM_FMTBIT_S16 |
> > + SNDRV_PCM_FMTBIT_S24 |
> > + SNDRV_PCM_FMTBIT_S32,
> > + .rates = SNDRV_PCM_RATE_8000_192000,
> > + .channels_min = 1,
> > + .channels_max = 8,
> > + },
> > + .ops = &asoc_qcom_qaif_aif_cpu_dai_ops,
> > + }, {
> > + .id = QAIF_CDC_DMA_RX0,
> > + .name = "CDC DMA RX0",
> > + .playback = {
> > + .stream_name = "WCD Playback0",
> > + .formats = SNDRV_PCM_FMTBIT_S16,
> > + .rates = SNDRV_PCM_RATE_48000,
> > + .rate_min = 48000,
> > + .rate_max = 48000,
> > + .channels_min = 1,
> > + .channels_max = 2,
> > + },
> > + .ops = &asoc_qcom_qaif_cif_dai_ops,
> > + }, {
> > + .id = QAIF_CDC_DMA_RX1,
> > + .name = "CDC DMA RX1",
> > + .playback = {
> > + .stream_name = "WCD Playback1",
>
> No dai for WCD capture (or) it's missing in this patch.
>
>
> Best Regards,
> Rafi.
>
On Shikra, capture is always through the VA Macro, irrespective of
whether the source is WCD AMIC or MSM DMIC and the stream_name is only
a descriptive identifier.
-Harendra
> > + .formats = SNDRV_PCM_FMTBIT_S16,
> > + .rates = SNDRV_PCM_RATE_48000,
> > + .rate_min = 48000,
> > + .rate_max = 48000,
> > + .channels_min = 1,
> > + .channels_max = 2,
> > + },
> > + .ops = &asoc_qcom_qaif_cif_dai_ops,
> > + }, {
> > + .id = QAIF_CDC_DMA_VA_TX0,
> > + .name = "CDC DMA VA_TX0",
> > + .capture = {
> > + .stream_name = "DMIC Capture0",
> > + .formats = SNDRV_PCM_FMTBIT_S16,
> > + .rates = SNDRV_PCM_RATE_48000,
> > + .rate_min = 48000,
> > + .rate_max = 48000,
> > + .channels_min = 1,
> > + .channels_max = 4,
> > + },
> > + .ops = &asoc_qcom_qaif_cif_dai_ops,
> > + }, {
> > + .id = QAIF_CDC_DMA_VA_TX1,
> > + .name = "CDC DMA VA_TX1",
> > + .capture = {
> > + .stream_name = "DMIC Capture1",
> > + .formats = SNDRV_PCM_FMTBIT_S16,
> > + .rates = SNDRV_PCM_RATE_48000,
> > + .rate_min = 48000,
> > + .rate_max = 48000,
> > + .channels_min = 1,
> > + .channels_max = 4,
> > + },
> > + .ops = &asoc_qcom_qaif_cif_dai_ops,
> > + },
> > +};
> > +
> > +static int shikra_qaif_get_dma_idx(unsigned int dai_id)
> > +{
> > + const struct qaif_dmaidx_dai_map *map;
> > + int i, size;
> > +
> > + switch (dai_id) {
> > + case QAIF_MI2S_AIF0 ... QAIF_MI2S_AIF12:
> > + map = shikra_mi2s_dma_dai_map;
> > + size = ARRAY_SIZE(shikra_mi2s_dma_dai_map);
> > + break;
> > + case QAIF_TDM_AIF0 ... QAIF_TDM_AIF12:
> > + map = shikra_tdm_dma_dai_map;
> > + size = ARRAY_SIZE(shikra_tdm_dma_dai_map);
> > + break;
> > + case QAIF_CDC_DMA_RX0 ... QAIF_CDC_DMA_RX9:
> > + map = shikra_cif_rx_dma_dai_map;
> > + size = ARRAY_SIZE(shikra_cif_rx_dma_dai_map);
> > + break;
> > + case QAIF_CDC_DMA_VA_TX0 ... QAIF_CDC_DMA_VA_TX9:
> > + map = shikra_cif_va_dma_dai_map;
> > + size = ARRAY_SIZE(shikra_cif_va_dma_dai_map);
> > + break;
> > + default:
> > + return -EINVAL;
> > + }
> > +
> > + for (i = 0; i < size; i++) {
> > + if (map[i].dai_id == dai_id)
> > + return map[i].dma_idx;
> > + }
> > + return -EINVAL;
> > +}
> > +
> > +static int shikra_qaif_alloc_stream_dma_idx(struct qaif_drv_data *drvdata,
> > + int direction,
> > + unsigned int dai_id)
> > +{
> > + const struct qaif_variant *v = drvdata->variant;
> > + int dma_idx, index;
> > +
> > + dma_idx = shikra_qaif_get_dma_idx(dai_id);
> > + if (dma_idx < 0)
> > + return dma_idx;
> > +
> > + switch (dai_id) {
> > + case QAIF_MI2S_AIF0 ... QAIF_MI2S_AIF12:
> > + case QAIF_TDM_AIF0 ... QAIF_TDM_AIF12:
> > + index = (direction == SNDRV_PCM_STREAM_PLAYBACK) ?
> > + dma_idx : v->wrdma_start + dma_idx;
> > + if (index >= QAIF_MAX_AIF_DMA_IDX)
> > + return -EINVAL;
> > + if (test_and_set_bit(index, &drvdata->aif_dma_idx_bit_map))
> > + return -EBUSY;
> > + break;
> > + case QAIF_CDC_DMA_RX0 ... QAIF_CDC_DMA_RX9:
> > + case QAIF_CDC_DMA_VA_TX0 ... QAIF_CDC_DMA_VA_TX9:
> > + index = (direction == SNDRV_PCM_STREAM_PLAYBACK) ?
> > + dma_idx : v->codec_wrdma_start + dma_idx;
> > + if (index >= QAIF_MAX_CIF_DMA_IDX)
> > + return -EINVAL;
> > + if (test_and_set_bit(index, &drvdata->cif_dma_idx_bit_map))
> > + return -EBUSY;
> > + break;
> > + default:
> > + return -EINVAL;
> > + }
> > +
> > + return index;
> > +}
> > +
> > +static int shikra_qaif_free_stream_dma_idx(struct qaif_drv_data *drvdata,
> > + int index,
> > + unsigned int dai_id)
> > +{
> > + if (qaif_is_aif_port(dai_id))
> > + clear_bit(index, &drvdata->aif_dma_idx_bit_map);
> > + else
> > + clear_bit(index, &drvdata->cif_dma_idx_bit_map);
> > + return 0;
> > +}
> > +
> > +static const struct qaif_variant shikra_qaif_data = {
> > + .ee = 0,
> > +
> > + .num_rddma = 4,
> > + .num_wrdma = 4,
> > + .wrdma_start = 4,
> > +
> > + .num_codec_rddma = 4,
> > + .num_codec_wrdma = 4,
> > + .codec_wrdma_start = 4,
> > + .num_intf = 4,
> > +
> > + .rddma_reg_base = 0x8000,
> > + .rddma_stride = 0x1000,
> > + .codec_rddma_reg_base = 0xc000,
> > + .codec_rddma_stride = 0x1000,
> > +
> > + .wrdma_reg_base = 0x11000,
> > + .wrdma_stride = 0x1000,
> > + .codec_wrdma_reg_base = 0x15000,
> > + .codec_wrdma_stride = 0x1000,
> > +
> > + .rddma_irq_reg_base = 0x19000,
> > + .rddma_irq_stride = 0x1000,
> > + .codec_rddma_irq_reg_base = 0x191A0,
> > + .codec_rddma_irq_stride = 0x1000,
> > +
> > + .wrdma_irq_reg_base = 0x19078,
> > + .wrdma_irq_stride = 0x1000,
> > + .codec_wrdma_irq_reg_base = 0x19290,
> > + .codec_wrdma_irq_stride = 0x1000,
> > +
> > + .qxm_type = QAIF_QXM0,
> > + .rd_len = 512,
> > + .rddma_shram_len = 64,
> > + .rddma_shram_start_addr = {0, 256},
> > + .wr_len = 512,
> > + .wrdma_shram_len = 64,
> > + .wrdma_shram_start_addr = {0, 256},
> > +
> > + .clk_name = (const char * const []) {
> > + "lpass_config",
> > + "lpass_core_axim",
> > + "bus",
> > + },
> > + .num_clks = 3,
> > +
> > + .dai_driver = shikra_qaif_cpu_dai_driver,
> > + .num_dai = ARRAY_SIZE(shikra_qaif_cpu_dai_driver),
> > +
> > + .dai_bit_clk_names = (const char * const []) {
> > + "aif_if0_ibit",
> > + "aif_if1_ibit",
> > + "aif_if2_ibit",
> > + "aif_if3_ibit",
> > + },
> > + .aif_full_cycle_en = (const bool []) { false, false, false, false },
> > + .aif_ctrl_data_oe = (const bool []) { false, false, false, false },
> > + .aif_loopback_en = (const bool []) { false, false, false, false },
> > + .alloc_stream_dma_idx = shikra_qaif_alloc_stream_dma_idx,
> > + .free_stream_dma_idx = shikra_qaif_free_stream_dma_idx,
> > + .get_dma_idx = shikra_qaif_get_dma_idx,
> > +};
> > +
> > +static const struct of_device_id shikra_qaif_cpu_device_id[] = {
> > + { .compatible = "qcom,shikra-qaif-cpu", .data = &shikra_qaif_data },
> > + {}
> > +};
> > +MODULE_DEVICE_TABLE(of, shikra_qaif_cpu_device_id);
> > +
> > +static struct platform_driver shikra_qaif_cpu_platform_driver = {
> > + .driver = {
> > + .name = "shikra-qaif-cpu",
> > + .of_match_table = shikra_qaif_cpu_device_id,
> > + .pm = pm_ptr(&asoc_qcom_qaif_pm_ops),
> > + },
> > + .probe = asoc_qcom_qaif_cpu_platform_probe,
> > +};
> > +module_platform_driver(shikra_qaif_cpu_platform_driver);
> > +
> > +MODULE_DESCRIPTION("Qualcomm Audio Interface (QAIF) Shikra variant driver");
> > +MODULE_AUTHOR("Harendra Gautam <harendra.gautam@xxxxxxxxxxxxxxxx>");
> > +MODULE_LICENSE("GPL");
>