From: Harendra Gautam <harendra.gautam@oss.qualcomm.com>
To: Srinivas Kandagatla <srini@kernel.org>
Cc: Mark Brown <broonie@kernel.org>,
Liam Girdwood <lgirdwood@gmail.com>,
Rob Herring <robh@kernel.org>,
Krzysztof Kozlowski <krzk+dt@kernel.org>,
Conor Dooley <conor+dt@kernel.org>,
Jaroslav Kysela <perex@perex.cz>, Takashi Iwai <tiwai@suse.com>,
linux-sound@vger.kernel.org, linux-arm-msm@vger.kernel.org,
devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
Prasad Kumpatla <prasad.kumpatla@oss.qualcomm.com>,
Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>,
Sarath Ganapathiraju <sarath.ganapathiraju@oss.qualcomm.com>,
Kumar Anurag Singh <kumar.singh@oss.qualcomm.com>,
Mohammad Rafi Shaik <mohammad.rafi.shaik@oss.qualcomm.com>
Subject: [PATCH v3 2/9] ASoC: qcom: Add QAIF shared data structures and variant interface
Date: Mon, 24 Aug 2026 12:06:20 +0530 [thread overview]
Message-ID: <20260824063627.3595610-3-harendra.gautam@oss.qualcomm.com> (raw)
In-Reply-To: <20260824063627.3595610-1-harendra.gautam@oss.qualcomm.com>
QAIF exposes AIF DMA paths for external audio interfaces and CIF DMA paths
for the internal codec interface. The two drivers need a common place to
describe DMA channel allocation, regmap fields, interrupt dispatch, SHRAM
buffer tracking and per-stream runtime data.
Introduce the QAIF driver data, AIF and CIF register-field descriptions,
IRQ mapping helpers and SoC variant descriptor. The variant descriptor
describes the register layout, DMA channel counts, clock names, DAI table
and platform callbacks used by the QAIF driver code.
Signed-off-by: Harendra Gautam <harendra.gautam@oss.qualcomm.com>
---
sound/soc/qcom/qaif.h | 302 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 302 insertions(+)
create mode 100644 sound/soc/qcom/qaif.h
diff --git a/sound/soc/qcom/qaif.h b/sound/soc/qcom/qaif.h
new file mode 100644
index 000000000000..c8d170684d05
--- /dev/null
+++ b/sound/soc/qcom/qaif.h
@@ -0,0 +1,302 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#ifndef SND_SOC_QCOM_QAIF_H
+#define SND_SOC_QCOM_QAIF_H
+
+#include <linux/bits.h>
+#include <linux/clk.h>
+#include <linux/interrupt.h>
+#include <linux/mutex.h>
+#include <linux/regmap.h>
+#include <linux/types.h>
+#include <sound/pcm.h>
+#include <dt-bindings/sound/qcom,qaif.h>
+
+struct snd_pcm_substream;
+struct snd_soc_dai_driver;
+struct snd_soc_dai_ops;
+struct platform_device;
+
+#define QAIF_CIF_DMA_INTF_ONE_CHANNEL 0x01
+#define QAIF_CIF_DMA_INTF_TWO_CHANNEL 0x03
+#define QAIF_CIF_DMA_INTF_FOUR_CHANNEL 0x0f
+#define QAIF_CIF_DMA_INTF_SIX_CHANNEL 0x3f
+#define QAIF_CIF_DMA_INTF_EIGHT_CHANNEL 0xff
+
+#define QAIF_AIF_SLOT_WIDTH(bits) ((bits) - 1)
+#define QAIF_AIF_SAMPLE_WIDTH(bits) ((bits) - 1)
+
+/* Watermark level 5 encoded as N-1: hardware field value = watermark - 1 */
+#define QAIF_DMACTL_WM_5 4
+
+#define QAIF_DMA_BYTES_TO_WORDS_SHIFT 3
+#define QAIF_DMA_CLOCK_FREQ 38400000
+
+#define QAIF_MAX_AIF_CFG_CNT 4
+#define QAIF_MAX_LANES 8
+
+#define QAIF_MAX_MI2S_PORTS 8
+#define QAIF_MI2S_SLOTS 2
+#define QAIF_MAX_AIF_DMA_IDX 8
+#define QAIF_MAX_CIF_DMA_IDX 8
+
+/* SID map register CSID field (WRDMA_SID/RDDMA_SID), bits [4:0] */
+#define QAIF_CSID_MASK GENMASK(4, 0)
+
+static inline bool qaif_is_cif_dma_port(int dai_id)
+{
+ if (dai_id >= QAIF_CDC_DMA_RX0 && dai_id <= QAIF_CDC_DMA_VA_TX9)
+ return true;
+ return false;
+}
+
+static inline bool qaif_is_mi2s_port(int dai_id)
+{
+ return dai_id >= QAIF_MI2S_AIF0 && dai_id <= QAIF_MI2S_AIF12;
+}
+
+static inline bool qaif_is_tdm_port(int dai_id)
+{
+ return dai_id >= QAIF_TDM_AIF0 && dai_id <= QAIF_TDM_AIF12;
+}
+
+static inline bool qaif_is_aif_port(int dai_id)
+{
+ return qaif_is_mi2s_port(dai_id) || qaif_is_tdm_port(dai_id);
+}
+
+enum qxm_sel {
+ QAIF_QXM0 = 0,
+ QAIF_QXM1 = 1,
+};
+
+enum qaif_irq_type {
+ QAIF_AIF_IRQ = 0,
+ QAIF_CIF_IRQ = 1,
+ QAIF_IRQ_TYPE_MAX,
+};
+
+enum qaif_dma_type {
+ QAIF_AIF_DMA = 0,
+ QAIF_CIF_DMA = 1,
+};
+
+struct qaif_aif_config {
+ u32 sync_mode;
+ u32 sync_src;
+ bool invert_sync;
+ u32 sync_delay;
+ u32 slot_width;
+ u32 slot_en_rx_mask;
+ u32 slot_en_tx_mask;
+ bool loopback_en;
+ bool ctrl_data_oe;
+ u32 lane_en_mask;
+ u32 lane_dir_mask;
+ bool full_cycle_en;
+ u32 slot_num;
+};
+
+struct qaif_pcm_data {
+ /* Flat slot in aif_substream[]/aif_dma_heap[] (or cif_*) used to track
+ * this stream. Direction-encoded: playback uses the raw DMA channel
+ * number (0..num_rddma-1), capture adds wrdma_start so playback and
+ * capture of the same DAI occupy distinct slots.
+ * Set by alloc_stream_dma_idx(); bounded by QAIF_MAX_AIF/CIF_DMA_IDX.
+ */
+ int stream_dma_idx;
+ /* Hardware channel number (0-based within its DMA bank) passed to
+ * register address helpers (e.g. QAIF_RDDMA_CFG_REG(v, chan)).
+ * Direction-agnostic: the register helpers select RDDMA or WRDMA bank
+ * based on stream direction, so both directions of the same DAI share
+ * the same value. Set by get_dma_idx().
+ */
+ int dma_reg_idx;
+};
+
+/* Named 0-based DMA channel indices used as the dma_idx of a
+ * qaif_dmaidx_dai_map entry, so board tables reference channels by name.
+ */
+enum qaif_dma_idx {
+ QAIF_DMA_IDX0 = 0,
+ QAIF_DMA_IDX1,
+ QAIF_DMA_IDX2,
+ QAIF_DMA_IDX3,
+ QAIF_DMA_IDX4,
+ QAIF_DMA_IDX5,
+ QAIF_DMA_IDX6,
+ QAIF_DMA_IDX7,
+};
+
+/* Associates a DAI ID with its physical DMA channel index on a given
+ * board/variant. @dai_id is the DAI to match; @dma_idx (a qaif_dma_idx value)
+ * is the 0-based hardware channel that get_dma_idx() returns for it.
+ */
+struct qaif_dmaidx_dai_map {
+ unsigned int dai_id;
+ int dma_idx;
+};
+
+struct qaif_dma_mem_info {
+ dma_addr_t dma_addr;
+ size_t alloc_size;
+ void *vaddr;
+};
+
+struct qaif_drv_data {
+ struct clk *mi2s_bit_clk[QAIF_MAX_MI2S_PORTS];
+ struct clk_bulk_data *clks;
+ int num_clks;
+ struct clk *aud_dma_clk;
+ struct clk *aud_dma_mem_clk;
+ void __iomem *audio_qaif;
+ struct regmap *audio_qaif_map;
+ int audio_qaif_irq;
+ struct mutex stream_lock; /* serializes stream open/close */
+ bool qaif_hw_configured;
+ const struct qaif_variant *variant;
+ struct qaif_aif_config aif_intf_cfg[QAIF_MAX_AIF_CFG_CNT];
+ unsigned long aif_dma_idx_bit_map;
+ unsigned long cif_dma_idx_bit_map;
+ struct snd_pcm_substream *aif_substream[QAIF_MAX_AIF_DMA_IDX];
+ struct snd_pcm_substream *cif_substream[QAIF_MAX_CIF_DMA_IDX];
+ u32 smmu_csid_bits; /* SMMU stream ID bits from DT iommus cell */
+ struct qaif_dma_mem_info *aif_dma_heap[QAIF_MAX_AIF_DMA_IDX];
+ struct qaif_dma_mem_info *cif_dma_heap[QAIF_MAX_CIF_DMA_IDX];
+};
+
+enum qaif_summary_irq_bitmask {
+ QAIF_SUMMARY_BITMASK_AIF_PERIOD_RDDMA = BIT(0),
+ QAIF_SUMMARY_BITMASK_AIF_UNDERFLOW_RDDMA = BIT(1),
+ QAIF_SUMMARY_BITMASK_AIF_ERR_RSP_RDDMA = BIT(2),
+ QAIF_SUMMARY_BITMASK_AIF_PERIOD_WRDMA = BIT(3),
+ QAIF_SUMMARY_BITMASK_AIF_OVERFLOW_WRDMA = BIT(4),
+ QAIF_SUMMARY_BITMASK_AIF_ERR_RSP_WRDMA = BIT(5),
+ QAIF_SUMMARY_BITMASK_CIF_PERIOD_RDDMA = BIT(18),
+ QAIF_SUMMARY_BITMASK_CIF_UNDERFLOW_RDDMA = BIT(19),
+ QAIF_SUMMARY_BITMASK_CIF_ERR_RSP_RDDMA = BIT(20),
+ QAIF_SUMMARY_BITMASK_CIF_PERIOD_WRDMA = BIT(24),
+ QAIF_SUMMARY_BITMASK_CIF_OVERFLOW_WRDMA = BIT(25),
+ QAIF_SUMMARY_BITMASK_CIF_ERR_RSP_WRDMA = BIT(26),
+};
+
+enum qaif_client_status_register_bitmask_info {
+ QAIF_BITMASK_AIF_RDDMA_WRDMA = GENMASK(5, 0),
+ QAIF_BITMASK_CIF_RDDMA_WRDMA = GENMASK(26, 18),
+};
+
+struct qaif_irq_map {
+ u32 client_id;
+ u32 mask;
+ /*
+ * Called from the hard IRQ handler (asoc_platform_qaif_irq()) with
+ * @status holding the summary interrupt status. Must not sleep.
+ */
+ irqreturn_t (*client_irq_handler)(struct qaif_drv_data *drvdata, u32 status);
+};
+
+enum qaif_dma_dir {
+ QAIF_DMA_RDDMA = 0,
+ QAIF_DMA_WRDMA = 1,
+};
+
+enum qaif_irq {
+ QAIF_IRQ_PERIOD = 0,
+ QAIF_IRQ_OVERFLOW,
+ QAIF_IRQ_UNDERFLOW,
+ QAIF_IRQ_ERROR,
+};
+
+enum qaif_irq_op {
+ QAIF_IRQ_CLEAR = 0,
+ QAIF_IRQ_ENABLE,
+ QAIF_IRQ_DISABLE,
+};
+
+enum qaif_client_info {
+ QAIF_CLIENT_ID_AIF_DMA = 0,
+ QAIF_CLIENT_ID_CIF_DMA,
+};
+
+struct qaif_variant {
+ u32 ee; /* Hardware EE index assigned to this driver instance */
+
+ u32 num_rddma;
+ u32 num_wrdma;
+ u32 wrdma_start;
+ u32 num_codec_rddma;
+ u32 num_codec_wrdma;
+ u32 codec_wrdma_start;
+ u32 num_intf;
+
+ u32 rddma_reg_base;
+ u32 rddma_stride;
+ u32 codec_rddma_reg_base;
+ u32 codec_rddma_stride;
+ u32 wrdma_reg_base;
+ u32 wrdma_stride;
+ u32 codec_wrdma_reg_base;
+ u32 codec_wrdma_stride;
+
+ u32 rddma_irq_reg_base;
+ u32 rddma_irq_stride;
+ u32 codec_rddma_irq_reg_base;
+ u32 codec_rddma_irq_stride;
+ u32 wrdma_irq_reg_base;
+ u32 wrdma_irq_stride;
+ u32 codec_wrdma_irq_reg_base;
+ u32 codec_wrdma_irq_stride;
+
+ /* QSB master port selector; only QAIF_QXM0 is supported today */
+ enum qxm_sel qxm_type;
+ /* All *_len values below are SHRAM sizes in 64-bit words */
+ u32 rd_len;
+ u32 rddma_shram_len;
+ /* SHRAM start offsets (in 64-bit words), indexed by enum qaif_dma_type */
+ u32 rddma_shram_start_addr[2];
+ u32 wr_len;
+ u32 wrdma_shram_len;
+ u32 wrdma_shram_start_addr[2];
+
+ const char * const *clk_name;
+ int num_clks;
+ struct snd_soc_dai_driver *dai_driver;
+ int num_dai;
+ const char * const *dai_bit_clk_names;
+ /*
+ * Optional per-AIF configuration tables, indexed by AIF interface
+ * index (0..num_intf-1). NULL if the variant does not use them.
+ */
+ const bool *aif_full_cycle_en;
+ const bool *aif_ctrl_data_oe;
+ const bool *aif_loopback_en;
+
+ /* Returns a direction-encoded flat slot index for use in
+ * aif_substream[]/cif_substream[] and the dma_idx_bit_map.
+ * Playback returns the raw channel number; capture adds wrdma_start (or
+ * codec_wrdma_start) so both directions of the same DAI get distinct
+ * slots. Sets the corresponding bit atomically; returns -EBUSY if
+ * already open, -EINVAL if @dai_id or the computed index is out of range.
+ */
+ int (*alloc_stream_dma_idx)(struct qaif_drv_data *data, int direction,
+ unsigned int dai_id);
+ /* Clears the bit set by alloc_stream_dma_idx. */
+ int (*free_stream_dma_idx)(struct qaif_drv_data *data, int chan,
+ unsigned int dai_id);
+ /* Returns the hardware channel number (0-based within its DMA bank)
+ * for @dai_id, direction-agnostic. Used as dma_reg_idx.
+ */
+ int (*get_dma_idx)(unsigned int dai_id);
+};
+
+extern const struct snd_soc_dai_ops asoc_qcom_qaif_cif_dai_ops;
+extern const struct snd_soc_dai_ops asoc_qcom_qaif_aif_cpu_dai_ops;
+
+int asoc_qcom_qaif_cpu_platform_probe(struct platform_device *pdev);
+int asoc_qcom_qaif_platform_register(struct platform_device *pdev);
+extern const struct dev_pm_ops asoc_qcom_qaif_pm_ops;
+
+#endif /* SND_SOC_QCOM_QAIF_H */
--
2.34.1
next prev parent reply other threads:[~2026-08-24 6:36 UTC|newest]
Thread overview: 32+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-24 6:36 [PATCH v3 0/9] ASoC: qcom: Add QAIF driver for Shikra audio platform Harendra Gautam
2026-08-24 6:36 ` [PATCH v3 1/9] ASoC: dt-bindings: qcom,qaif-cpu: Add binding Harendra Gautam
2026-08-24 8:39 ` Manuel Ebner
2026-08-24 9:14 ` Harendra Gautam
2026-08-25 5:59 ` Krzysztof Kozlowski
2026-08-26 8:31 ` Mohammad Rafi Shaik
2026-08-26 9:39 ` Harendra Gautam
2026-08-26 9:43 ` Srinivas Kandagatla
2026-08-26 9:55 ` Harendra Gautam
2026-08-26 10:01 ` Srinivas Kandagatla
2026-08-26 10:06 ` Harendra Gautam
2026-08-26 10:25 ` Harendra Gautam
2026-08-26 23:32 ` Mark Brown
2026-08-27 4:00 ` Harendra Gautam
2026-08-24 6:36 ` Harendra Gautam [this message]
2026-08-24 6:36 ` [PATCH v3 3/9] ASoC: qcom: Add QAIF hardware register map Harendra Gautam
2026-08-24 6:36 ` [PATCH v3 4/9] ASoC: qcom: Add QAIF CPU DAI ops, regmap, DT parsing and platform init Harendra Gautam
2026-08-24 6:36 ` [PATCH v3 5/9] ASoC: soc-core: Add snd_soc_of_xlate_dai_name() generic helper Harendra Gautam
2026-08-25 4:20 ` Kuninori Morimoto
2026-08-24 6:36 ` [PATCH v3 6/9] ASoC: qcom: Add QAIF PCM operations Harendra Gautam
2026-08-24 9:25 ` Markus Elfring
2026-08-24 10:10 ` Harendra Gautam
2026-08-25 6:07 ` Krzysztof Kozlowski
2026-08-24 6:36 ` [PATCH v3 7/9] ASoC: qcom: Add QAIF IRQ handling, suspend/resume and platform register Harendra Gautam
2026-08-24 6:36 ` [PATCH v3 8/9] ASoC: qcom: Add Shikra QAIF support Harendra Gautam
2026-08-26 8:35 ` Mohammad Rafi Shaik
2026-08-26 8:58 ` Harendra Gautam
2026-08-26 10:13 ` Srinivas Kandagatla
2026-08-26 10:37 ` Harendra Gautam
2026-08-24 6:36 ` [PATCH v3 9/9] MAINTAINERS: Add Qualcomm QAIF driver entry Harendra Gautam
2026-08-24 8:22 ` Abel Vesa
2026-08-24 8:31 ` Harendra Gautam
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260824063627.3595610-3-harendra.gautam@oss.qualcomm.com \
--to=harendra.gautam@oss.qualcomm.com \
--cc=broonie@kernel.org \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=krzk+dt@kernel.org \
--cc=krzysztof.kozlowski@oss.qualcomm.com \
--cc=kumar.singh@oss.qualcomm.com \
--cc=lgirdwood@gmail.com \
--cc=linux-arm-msm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-sound@vger.kernel.org \
--cc=mohammad.rafi.shaik@oss.qualcomm.com \
--cc=perex@perex.cz \
--cc=prasad.kumpatla@oss.qualcomm.com \
--cc=robh@kernel.org \
--cc=sarath.ganapathiraju@oss.qualcomm.com \
--cc=srini@kernel.org \
--cc=tiwai@suse.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox