* [PATCH v3 0/9] ASoC: qcom: Add QAIF driver for Shikra audio platform
@ 2026-08-24 6:36 Harendra Gautam
2026-08-24 6:36 ` [PATCH v3 1/9] ASoC: dt-bindings: qcom,qaif-cpu: Add binding Harendra Gautam
` (8 more replies)
0 siblings, 9 replies; 32+ messages in thread
From: Harendra Gautam @ 2026-08-24 6:36 UTC (permalink / raw)
To: Srinivas Kandagatla
Cc: Mark Brown, Liam Girdwood, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Jaroslav Kysela, Takashi Iwai, linux-sound,
linux-arm-msm, devicetree, linux-kernel, Prasad Kumpatla,
Krzysztof Kozlowski, Sarath Ganapathiraju, Kumar Anurag Singh,
Mohammad Rafi Shaik
Hardware IP Overview
====================
QAIF (Qualcomm Audio Interface) is a fully configurable DMA-based audio
subsystem used to transmit and receive audio data over serial audio
interfaces (PCM, TDM, MI2S) and to provide a DMA interface for internal
codec connections. It manages two independent data paths:
Unified Audio Interface (AIF): Serialises and deserialises PCM audio
between system memory and external serial audio peripherals. Each
interface supports up to 8 independent data lanes, each configurable
as TX (speaker) or RX (mic). All lanes of an interface share a single
bit clock and frame sync. The AUD_INTFa hardware block controls the
serial protocol -- sync source (master/slave), sync mode (short/long
PCM, TDM, MI2S), sync delay and inversion, slot and sample widths,
active slot masks, lane enable/direction, mono/stereo mode and
full-cycle path support for long chip-to-chip connections.
Codec DMA Interface (CIF): Provides a parallel DMA interface to the
internal Bolero digital codec. The RDDMA path carries playback data
to Bolero and the WRDMA path carries capture data from Bolero. Each
channel has an INTF_CFG register controlling the active channel enable
mask, frame-sync selection, frame-sync delay, frame-sync output gating,
dynamic clock gating and 16-bit packing/unpacking.
DMA Engine: Read DMAs (RDDMA) fetch audio from DDR/TCM/LPM into a
shared on-chip SRAM latency buffer (SHRAM) and drain it to the
interface. Write DMAs (WRDMA) collect data from the interface into
SHRAM and write it to memory. Each DMA channel owns a private SHRAM
region. Two QSB master ports (QXM0 and QXM1) provide the memory
fabric. Burst sizes of 1/2/4/8/16 beats and up to 4 outstanding
transactions per DMA are supported.
Execution Environments (EE): Resources (DMAs, audio interfaces,
interface groups) are partitioned among up to 5 EEs via map registers.
Each EE receives an independent interrupt output. The interrupt
hierarchy has two levels: a summary register identifies the event class
(DMA period, underflow/overflow, error response, AUD_INTF
underflow/overflow, group done, rate detector, VFR), and per-resource
status registers identify the specific channel and event type.
Interface Grouping (Bonding): Multiple AIF and CIF interfaces can be
bonded into a group to start synchronously and align their DMA period
interrupts within half a frame duration using the RDDMA padding feature.
Rate Detector: Two rate detector blocks measure the frequency of
incoming frame sync or word select signals and generate interrupts on
rate change, undetected rate or sync timeout.
Block Diagram
=============
System Memory (DDR / LPM / TCM)
+---------------------------------+
| Circular Buffers (ping-pong) |
+----------+----------+-----------+
| ^
64-bit AXI 64-bit AXI
| |
+----------v----------+-----------+
| QSB Master Ports |
| +----------+ +----------+ |
| | QXM0 | | QXM1 | |
| +----+-----+ +-----+----+ |
+-------|--------------|----------+
| |
+-------v--------------v----------+
| Shared RAM (SHRAM) |
| +------------+ +------------+ |
| | QXM0 Read | | QXM0 Write | |
| | SHRAM | | SHRAM | |
| +------------+ +------------+ |
| +------------+ +------------+ |
| | QXM1 Read | | QXM1 Write | |
| | SHRAM | | SHRAM | |
| +------------+ +------------+ |
+---+--------+--------+-------+---+
| | | |
+---v--+ +--v---+ +--v---+ +-v----+
|RDDMA | |RDDMA | |WRDMA | |WRDMA |
| AIF | | CIF | | AIF | | CIF |
|[0..n]| |[0..n]| |[0..n]| |[0..n]|
+--+---+ +--+---+ +--+---+ +-+----+
| | ^ ^
| TX | TX | RX | RX
v v | |
+--+--------------------+ +----+----------+
| Unified Audio Intf | | Codec DMA |
| (AIF 0..12) | | Interface |
| | | (CIF) |
| AUD_INTFa block: | | |
| - Serializer (TX) | | RDDMA: DDR -> |
| - De-serializer (RX) | | internal |
| - Sync gen/detect | | codec |
| - Up to 8 data lanes | | WRDMA: codec |
| - PCM / TDM / MI2S | | -> DDR |
| - Near Pad Logic | | Up to 16 ch |
+--+--------------------+ +----+----------+
| Lane 0..7 (TX/RX) | Parallel bus
| Bit clk + Frame sync | + Frame sync
v v
+--+--------+ +------+------+
| External | | Internal |
| Serial | | Digital |
| Peripherals| | Codec |
| (PCM/TDM/ | | (Bolero/ |
| MI2S) | | WCD) |
+-----------+ +-------------+
Software Design
===============
The driver follows the standard ALSA SoC split:
qaif-cpu.c: CPU DAI component. Manages clocks, implements DAI ops
(startup/shutdown/hw_free/hw_params/trigger) for both AIF and CIF
paths using direct regmap_update_bits() calls with address macros from
qaif-reg.h, registers an of_xlate_dai_name callback so that sound-dai
references using non-sequential DAI IDs resolve correctly, and parses
per-interface AIF configuration from DT child nodes. AIF child nodes
use standard properties (dai-format, dai-tdm-slot-*, qcom,qaif-aif-
lane-map) without a compatible string; the protocol is identified by
dai-format and set_fmt() is called by the machine driver.
qaif-platform.c: PCM platform component. Handles DMA buffer allocation
(dma_alloc_pages()), PCM ops (open/close/hw_params/prepare/trigger/
pointer/mmap/copy), table-driven two-level IRQ dispatch with
period-elapsed notification, and component suspend/resume across power
collapse.
qaif-shikra.c: Shikra SoC-specific variant descriptor. Provides
register base addresses, DMA channel counts, SHRAM geometry, clock
names and the DAI driver array. This abstraction keeps the core driver
portable across future QAIF integrations.
qaif.h / qaif-reg.h: Shared data structures, constants and the complete
MMIO register address map consumed by both the CPU and platform drivers.
soc-core.c: This series adds snd_soc_of_xlate_dai_name() as a generic
ASoC helper that resolves a sound-dai phandle argument to a DAI name by
searching the component DAI list by ID. Both lpass-cpu.c and qaif-cpu.c
assign it directly as .of_xlate_dai_name, removing their private
implementations.
The series is split by functionality to aid review -- register map and
data structures first, then CPU DAI ops with regmap and DT parsing, the
of_xlate helper, PCM ops, IRQ handling and finally the Shikra variant
glue.
Link to v2:
https://lore.kernel.org/lkml/20260701105757.2779738-1-harendra.gautam@oss.qualcomm.com/
Link to v1:
https://lore.kernel.org/lkml/20260605103739.3557573-1-harendra.gautam@oss.qualcomm.com/
Changes in v3:
- series restructured: replace regmap_field abstraction with direct
regmap_update_bits(); merge CIF/AIF DAI ops and regmap/DT/init into
single CPU DAI patch; move of_xlate_dai_name to soc-core.c (was
qcom/common.c); split Shikra variant into qaif-shikra.c; add
Kconfig/Makefile and MAINTAINERS entries
- binding: rename aif-interface@N to aif@N; remove compatible from
child nodes; replace custom qcom,qaif-aif-sync-*/qcom,qaif-aif-lane-*
properties with standard dai-format and dai-tdm-slot-*; fix example
to aif@d7/reg=<215>; allow hex unit addresses; fix CIF channel count
to 10; clarify QAIF_CDC_DMA_* IDs are sound-dai references only
- qcom,qaif.h: replace QAIF_MI2S_TDM_AIF0..12 with separate
QAIF_MI2S_AIF* (200-212) and QAIF_TDM_AIF* (213-225); renumber CIF
IDs to RX (226-235), TX (236-245), VA_TX (246-255)
- qaif.h: add qaif_ prefix to is_cif_dma_port() and new is_mi2s_port(),
is_tdm_port(), is_aif_port() helpers; add QAIF_MI2S_SLOTS; add
comments on smmu_csid_bits and ee fields
- qaif-reg.h: rename CODEC_ prefix to CDC_; rename UF/OF IRQ macros;
add _REG suffix to CDC debug/status macros
- qaif-cpu.c: fix MI2S sync config per HPG; replace custom sync/lane
DT properties with set_fmt()/set_tdm_slot() DAI ops; replace
clk_prepare/clk_enable pairs with clk_prepare_enable; remove codec
DAI set_tdm_slot/set_sysclk from hw_params(); use devm unwind
- qaif-shikra.c: new file; separate MI2S and TDM DMA maps; restrict
MI2S formats to S16|S32; widen TDM AIF constraints; rename VA DAI
names to "CDC DMA VA_TX*"
- soc-core.c: move of_xlate_dai_name helper from qcom/common.c to
soc-core.c as snd_soc_of_xlate_dai_name() generic ASoC helper
- lpass-cpu.c: remove local xlate wrapper; use snd_soc_of_xlate_dai_name()
- qaif-platform.c: move dma_set_mask_and_coherent() to probe; fix IRQ
dispatch READ_ONCE() race; add synchronize_irq() via .sync_stop;
always proceed to IRQ_DISABLE in trigger(STOP) if dynclk fails
Changes in v2:
- Rename YAML file to qcom,qaif-cpu.yaml, add qcom,qaif-cpu compatible
- Merge DAI ID header into binding patch, drop _clk suffix from
clock-names, add enum constraints, remove status: true (Krzysztof)
- Fix dt_binding_check failure in binding example (Rob)
- Fix IRQ storm: client status register bitmask missing BIT(16)
- Fix race: use test_and_set_bit for DMA bitmap allocation
- Fix regmap_config: use non-const with dynamic max_register
- Use dev_err_probe() in probe path, sizeof(*var) in kzalloc (Krzysztof)
- Add kerneldoc for all EXPORT_SYMBOL_GPL functions (Krzysztof)
- Use goto-based error cleanup in pcmops_open()
- Move MAINTAINERS entry to last patch (Krzysztof)
- Add shared asoc_qcom_of_xlate_dai_name() helper used by lpass-cpu
and qaif-cpu
- Fix checkpatch --strict warnings and alignment issues
Harendra Gautam (9):
ASoC: dt-bindings: qcom,qaif-cpu: Add binding
ASoC: qcom: Add QAIF shared data structures and variant interface
ASoC: qcom: Add QAIF hardware register map
ASoC: qcom: Add QAIF CPU DAI ops, regmap, DT parsing and platform init
ASoC: soc-core: Add snd_soc_of_xlate_dai_name() generic helper
ASoC: qcom: Add QAIF PCM operations
ASoC: qcom: Add QAIF IRQ handling, suspend/resume and platform
register
ASoC: qcom: Add Shikra QAIF support
MAINTAINERS: Add Qualcomm QAIF driver entry
.../bindings/sound/qcom,qaif-cpu.yaml | 307 ++++++
MAINTAINERS | 10 +
include/dt-bindings/sound/qcom,qaif.h | 97 ++
include/sound/soc.h | 3 +
sound/soc/qcom/Kconfig | 10 +
sound/soc/qcom/Makefile | 3 +
sound/soc/qcom/lpass-cpu.c | 23 +-
sound/soc/qcom/qaif-cpu.c | 877 ++++++++++++++++
sound/soc/qcom/qaif-platform.c | 935 ++++++++++++++++++
sound/soc/qcom/qaif-reg.h | 458 +++++++++
sound/soc/qcom/qaif-shikra.c | 425 ++++++++
sound/soc/qcom/qaif.h | 302 ++++++
sound/soc/soc-core.c | 33 +
13 files changed, 3461 insertions(+), 22 deletions(-)
create mode 100644 Documentation/devicetree/bindings/sound/qcom,qaif-cpu.yaml
create mode 100644 include/dt-bindings/sound/qcom,qaif.h
create mode 100644 sound/soc/qcom/qaif-cpu.c
create mode 100644 sound/soc/qcom/qaif-platform.c
create mode 100644 sound/soc/qcom/qaif-reg.h
create mode 100644 sound/soc/qcom/qaif-shikra.c
create mode 100644 sound/soc/qcom/qaif.h
--
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH v3 1/9] ASoC: dt-bindings: qcom,qaif-cpu: Add binding
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 ` Harendra Gautam
2026-08-24 8:39 ` Manuel Ebner
2026-08-26 8:31 ` Mohammad Rafi Shaik
2026-08-24 6:36 ` [PATCH v3 2/9] ASoC: qcom: Add QAIF shared data structures and variant interface Harendra Gautam
` (7 subsequent siblings)
8 siblings, 2 replies; 32+ messages in thread
From: Harendra Gautam @ 2026-08-24 6:36 UTC (permalink / raw)
To: Srinivas Kandagatla
Cc: Mark Brown, Liam Girdwood, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Jaroslav Kysela, Takashi Iwai, linux-sound,
linux-arm-msm, devicetree, linux-kernel, Prasad Kumpatla,
Krzysztof Kozlowski, Sarath Ganapathiraju, Kumar Anurag Singh,
Mohammad Rafi Shaik
QAIF routes audio between system memory, external PCM/TDM/MI2S serial
interfaces and the internal Bolero/WCD codec. Platform Devicetree files
need a binding to describe the controller resources, DAI cells and per-
interface AIF configuration, and named constants to avoid raw numeric IDs
in sound-dai references and child-node reg values.
Describe the MMIO region, interrupt, clocks, DMA IOMMU mapping and
aif-interface child nodes required by the controller.
Signed-off-by: Harendra Gautam <harendra.gautam@oss.qualcomm.com>
---
.../bindings/sound/qcom,qaif-cpu.yaml | 307 ++++++++++++++++++
include/dt-bindings/sound/qcom,qaif.h | 97 ++++++
2 files changed, 404 insertions(+)
create mode 100644 Documentation/devicetree/bindings/sound/qcom,qaif-cpu.yaml
create mode 100644 include/dt-bindings/sound/qcom,qaif.h
diff --git a/Documentation/devicetree/bindings/sound/qcom,qaif-cpu.yaml b/Documentation/devicetree/bindings/sound/qcom,qaif-cpu.yaml
new file mode 100644
index 000000000000..134356114733
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/qcom,qaif-cpu.yaml
@@ -0,0 +1,307 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/qcom,qaif-cpu.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Audio Interface (QAIF) CPU DAI Controller
+
+maintainers:
+ - Harendra Gautam <harendra.gautam@oss.qualcomm.com>
+
+description: |
+ The Qualcomm Audio Interface (QAIF) is a fully configurable DMA-based
+ audio subsystem controller. It serialises and deserialises PCM audio
+ between system memory and external serial audio peripherals (PCM, TDM,
+ I2S, MI2S) through the AIF path, and transfers parallel audio between
+ memory and an internal WCD codec through the CIF path.
+
+ AIF (Audio Interface): up to 13 multi-lane Unified Audio Interfaces,
+ each supporting up to 8 independent data lanes. Each lane is individually
+ configurable as TX (output/speaker) or RX (input/mic). All lanes of an
+ interface share a single bit clock and frame sync. Supported modes are
+ PCM (short/long sync), TDM, and MI2S (stereo/mono). Per-interface
+ configuration includes sync source (master/slave), sync mode, sync delay,
+ sync inversion, slot width (8/16/24/32-bit), sample width, active slot
+ masks (up to 32 slots), bits-per-lane frame size, lane enable/direction
+ masks, loopback, output-enable control, and full-cycle path support for
+ long chip-to-chip connections.
+
+ CIF (Codec Interface): up to 10 RDDMA (playback) and 10 WRDMA (capture)
+ channels connecting to an internal codec over a parallel bus. Each channel
+ supports active-channel enable mask (up to 16 channels), frame-sync
+ selection, frame-sync delay, frame-sync output gating, dynamic clock
+ gating, and 16-bit packing/unpacking.
+
+ Note on RX/TX naming convention: in QAIF, TX refers to the output
+ (speaker/playback) direction and RX refers to the input (mic/capture)
+ direction. This applies to both AIF lane directions and CIF slot/mask
+ properties.
+
+ DMA engine: RDDMA fetches audio from DDR/TCM/LPM into a shared SRAM
+ latency buffer (SHRAM) and drains it to the interface. WRDMA collects
+ data from the interface into SHRAM and writes it to memory. Each DMA
+ owns a private SHRAM region defined by start address and length registers.
+ Burst sizes of 1/2/4/8/16 beats (64-bit) are supported with up to 4
+ outstanding transactions per DMA. Two QSB master ports (QXM0 for TCM,
+ QXM1 for DDR/LPM) provide the memory interface.
+
+ Resources are partitioned among up to 5 Execution Engines (EEs) via
+ EE map registers. Each EE owns a set of DMAs, audio interfaces, and
+ interface groups, and receives its own independent interrupt output.
+ The interrupt hierarchy has a two-level structure: a summary register
+ identifies the event class (DMA period, underflow/overflow, error
+ response, audio interface underflow/overflow, group done, rate detector,
+ VFR), and per-resource status registers identify the specific channel.
+
+ Interface grouping (bonding) allows up to 6 groups of audio and codec
+ interfaces to start synchronously and align their DMA period interrupts
+ within half a frame duration using the RDDMA padding feature.
+
+ Two rate detector blocks measure the frequency of incoming frame sync or
+ word select signals and generate interrupts on rate change, undetected
+ rate, or sync timeout.
+
+ Block diagram::
+
+ System Memory (DDR / LPM / TCM)
+ +---------------------------------+
+ | Circular Buffers (ping-pong) |
+ +----------+----------+-----------+
+ | ^
+ 64-bit AXI 64-bit AXI
+ | |
+ +----------v----------+-----------+
+ | QSB Master Ports |
+ | +----------+ +----------+ |
+ | | QXM0 | | QXM1 | |
+ | +----+-----+ +-----+----+ |
+ +-------|--------------|----------+
+ | |
+ +-------v--------------v----------+
+ | Shared RAM (SHRAM) |
+ | +------------+ +------------+ |
+ | | QXM0 Read | | QXM0 Write | |
+ | | SHRAM | | SHRAM | |
+ | +------------+ +------------+ |
+ | +------------+ +------------+ |
+ | | QXM1 Read | | QXM1 Write | |
+ | | SHRAM | | SHRAM | |
+ | +------------+ +------------+ |
+ +---+--------+--------+-------+---+
+ | | | |
+ +---v--+ +--v---+ +--v---+ +-v----+
+ |RDDMA | |RDDMA | |WRDMA | |WRDMA |
+ | AIF | | CIF | | AIF | | CIF |
+ |[0..n]| |[0..n]| |[0..n]| |[0..n]|
+ +--+---+ +--+---+ +--+---+ +-+----+
+ | | ^ ^
+ | TX | TX | RX | RX
+ v v | |
+ +--+--------------------+ +----+----------+
+ | Unified Audio Intf | | Codec DMA |
+ | (AIF 0..12) | | Interface |
+ | | | (CIF) |
+ | AUD_INTFa block: | | |
+ | - Serializer (TX) | | RDDMA: DDR -> |
+ | - De-serializer (RX) | | internal |
+ | - Sync gen/detect | | codec |
+ | - Up to 8 data lanes | | WRDMA: codec |
+ | - PCM / TDM / MI2S | | -> DDR |
+ | - Near Pad Logic | | Up to 16 ch |
+ +--+--------------------+ +----+----------+
+ | Lane 0..7 (TX/RX) | Parallel bus
+ | Bit clk + Frame sync | + Frame sync
+ v v
+ +--+--------+ +------+------+
+ | External | | Internal |
+ | Serial | | Digital |
+ | Peripherals| | Codec |
+ | (PCM/TDM/ | | (Bolero/ |
+ | MI2S) | | WCD) |
+ +-----------+ +-------------+
+
+allOf:
+ - $ref: dai-common.yaml#
+
+properties:
+ compatible:
+ const: qcom,shikra-qaif-cpu
+
+ reg:
+ maxItems: 1
+ description: QAIF core registers
+
+ interrupts:
+ maxItems: 1
+ description:
+ QAIF summary interrupt for this Execution Engine. Signals DMA period
+ completion, buffer underflow/overflow, error response, audio interface
+ underflow/overflow, interface-group done, rate detector and VFR events.
+
+ iommus:
+ maxItems: 1
+ description: Phandle to apps_smmu node with sid mask
+
+ dma-coherent: true
+
+ clocks:
+ minItems: 5
+ maxItems: 9
+
+ clock-names:
+ description:
+ The first five clocks are always required. Any further entries are the
+ per-AIF bit clocks (aif_if<N>_ibit), supplied in order starting from
+ AIF interface 0 for as many serial AIF interfaces as the board uses.
+ minItems: 5
+ items:
+ - const: lpass_config
+ - const: lpass_core_axim
+ - const: aud_dma
+ - const: aud_dma_mem
+ - const: bus
+ - const: aif_if0_ibit
+ - const: aif_if1_ibit
+ - const: aif_if2_ibit
+ - const: aif_if3_ibit
+
+ '#sound-dai-cells':
+ const: 1
+
+ '#address-cells':
+ const: 1
+
+ '#size-cells':
+ const: 0
+
+patternProperties:
+ '^aif@[0-9a-f]+$':
+ type: object
+ description:
+ QAIF AIF interface child node for PCM, TDM or MI2S configuration.
+
+ properties:
+ reg:
+ maxItems: 1
+ description:
+ DAI ID of the AIF interface (QAIF_MI2S_AIF* or QAIF_TDM_AIF*).
+
+ dai-format:
+ description: Serial audio interface format (MI2S, TDM or PCM).
+ enum: [i2s, dsp_a, dsp_b]
+
+ dai-tdm-slot-width:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum: [8, 16, 24, 32]
+ description:
+ Slot width in bits.
+
+ dai-tdm-slot-num:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description:
+ Number of slots per lane.
+ minimum: 1
+ maximum: 32
+
+ dai-tdm-slot-rx-mask:
+ $ref: /schemas/types.yaml#/definitions/uint32-array
+ description:
+ Active RX slots, one entry per slot. A nonzero value marks the
+ slot as active.
+ minItems: 1
+ maxItems: 32
+
+ dai-tdm-slot-tx-mask:
+ $ref: /schemas/types.yaml#/definitions/uint32-array
+ description:
+ Active TX slots, one entry per slot. A nonzero value marks the
+ slot as active.
+ minItems: 1
+ maxItems: 32
+
+ qcom,qaif-aif-lane-map:
+ $ref: /schemas/types.yaml#/definitions/uint32-array
+ description:
+ Per-lane direction map, one entry per lane starting from lane 0.
+ Use 0 for TX (output/speaker) and 1 for RX (input/mic).
+ minItems: 1
+ maxItems: 8
+ items:
+ enum: [0, 1]
+
+ required:
+ - reg
+ - dai-format
+ - qcom,qaif-aif-lane-map
+
+ if:
+ properties:
+ dai-format:
+ enum: [dsp_a, dsp_b]
+ then:
+ required:
+ - dai-tdm-slot-width
+ - dai-tdm-slot-num
+ - dai-tdm-slot-rx-mask
+ - dai-tdm-slot-tx-mask
+
+ additionalProperties: false
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - iommus
+ - clocks
+ - clock-names
+ - '#sound-dai-cells'
+ - '#address-cells'
+ - '#size-cells'
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ soc {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ qaif_cpu: audio-controller@a000000 {
+ compatible = "qcom,shikra-qaif-cpu";
+ reg = <0x0 0x0a000000 0x0 0x20000>;
+ interrupts = <0 331 4>;
+ iommus = <&apps_smmu 0x1c0 0x0>;
+ clocks = <&gcc 213>,
+ <&gcc 214>,
+ <&audiocorecc 15>,
+ <&audiocorecc 17>,
+ <&audiocorecc 18>,
+ <&audiocorecc 5>,
+ <&audiocorecc 8>,
+ <&audiocorecc 11>,
+ <&audiocorecc 14>;
+ clock-names = "lpass_config",
+ "lpass_core_axim",
+ "aud_dma",
+ "aud_dma_mem",
+ "bus",
+ "aif_if0_ibit",
+ "aif_if1_ibit",
+ "aif_if2_ibit",
+ "aif_if3_ibit";
+ #sound-dai-cells = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ aif@d7 {
+ reg = <215>;
+ dai-format = "dsp_a";
+ dai-tdm-slot-width = <32>;
+ dai-tdm-slot-num = <2>;
+ dai-tdm-slot-rx-mask = <1 1>;
+ dai-tdm-slot-tx-mask = <1 1>;
+ qcom,qaif-aif-lane-map = <1 0>;
+ };
+ };
+ };
diff --git a/include/dt-bindings/sound/qcom,qaif.h b/include/dt-bindings/sound/qcom,qaif.h
new file mode 100644
index 000000000000..24706efd07d1
--- /dev/null
+++ b/include/dt-bindings/sound/qcom,qaif.h
@@ -0,0 +1,97 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ *
+ * DAI IDs for the Qualcomm Audio Interface (QAIF) controller.
+ * QAIF_MI2S_AIF* and QAIF_TDM_AIF* values are used in sound-dai
+ * references and as the reg value of aif@N child nodes.
+ * QAIF_CDC_DMA_* values are for sound-dai references only and must
+ * not be used as aif@N child node reg values.
+ */
+#ifndef __DT_QCOM_QAIF_H
+#define __DT_QCOM_QAIF_H
+
+/*
+ * MI2S DAI IDs -- one per physical AIF port in MI2S mode.
+ * Each port supports up to 2 channels (stereo I2S) over a single
+ * data lane sharing a bit clock and frame sync.
+ */
+#define QAIF_MI2S_AIF0 200
+#define QAIF_MI2S_AIF1 201
+#define QAIF_MI2S_AIF2 202
+#define QAIF_MI2S_AIF3 203
+#define QAIF_MI2S_AIF4 204
+#define QAIF_MI2S_AIF5 205
+#define QAIF_MI2S_AIF6 206
+#define QAIF_MI2S_AIF7 207
+#define QAIF_MI2S_AIF8 208
+#define QAIF_MI2S_AIF9 209
+#define QAIF_MI2S_AIF10 210
+#define QAIF_MI2S_AIF11 211
+#define QAIF_MI2S_AIF12 212
+
+/*
+ * TDM DAI IDs -- one per physical AIF port in TDM mode.
+ * Each port supports up to 8 channels over up to 8 independent data
+ * lanes sharing a single bit clock and frame sync.
+ */
+#define QAIF_TDM_AIF0 213
+#define QAIF_TDM_AIF1 214
+#define QAIF_TDM_AIF2 215
+#define QAIF_TDM_AIF3 216
+#define QAIF_TDM_AIF4 217
+#define QAIF_TDM_AIF5 218
+#define QAIF_TDM_AIF6 219
+#define QAIF_TDM_AIF7 220
+#define QAIF_TDM_AIF8 221
+#define QAIF_TDM_AIF9 222
+#define QAIF_TDM_AIF10 223
+#define QAIF_TDM_AIF11 224
+#define QAIF_TDM_AIF12 225
+
+/*
+ * CIF (Codec Interface) RX DAI IDs -- playback to internal codec.
+ * RDDMA channels fetch audio from memory and drain it to the codec.
+ */
+#define QAIF_CDC_DMA_RX0 226
+#define QAIF_CDC_DMA_RX1 227
+#define QAIF_CDC_DMA_RX2 228
+#define QAIF_CDC_DMA_RX3 229
+#define QAIF_CDC_DMA_RX4 230
+#define QAIF_CDC_DMA_RX5 231
+#define QAIF_CDC_DMA_RX6 232
+#define QAIF_CDC_DMA_RX7 233
+#define QAIF_CDC_DMA_RX8 234
+#define QAIF_CDC_DMA_RX9 235
+
+/*
+ * CIF (Codec Interface) TX DAI IDs -- capture from internal codec.
+ * WRDMA channels collect audio from the codec and write it to memory.
+ */
+#define QAIF_CDC_DMA_TX0 236
+#define QAIF_CDC_DMA_TX1 237
+#define QAIF_CDC_DMA_TX2 238
+#define QAIF_CDC_DMA_TX3 239
+#define QAIF_CDC_DMA_TX4 240
+#define QAIF_CDC_DMA_TX5 241
+#define QAIF_CDC_DMA_TX6 242
+#define QAIF_CDC_DMA_TX7 243
+#define QAIF_CDC_DMA_TX8 244
+#define QAIF_CDC_DMA_TX9 245
+
+/*
+ * CIF (Codec Interface) VA TX DAI IDs -- capture from voice activity codec.
+ * WRDMA channels collect audio from the VA codec and write it to memory.
+ */
+#define QAIF_CDC_DMA_VA_TX0 246
+#define QAIF_CDC_DMA_VA_TX1 247
+#define QAIF_CDC_DMA_VA_TX2 248
+#define QAIF_CDC_DMA_VA_TX3 249
+#define QAIF_CDC_DMA_VA_TX4 250
+#define QAIF_CDC_DMA_VA_TX5 251
+#define QAIF_CDC_DMA_VA_TX6 252
+#define QAIF_CDC_DMA_VA_TX7 253
+#define QAIF_CDC_DMA_VA_TX8 254
+#define QAIF_CDC_DMA_VA_TX9 255
+
+#endif /* __DT_QCOM_QAIF_H */
--
2.34.1
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PATCH v3 2/9] ASoC: qcom: Add QAIF shared data structures and variant interface
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 6:36 ` Harendra Gautam
2026-08-24 6:36 ` [PATCH v3 3/9] ASoC: qcom: Add QAIF hardware register map Harendra Gautam
` (6 subsequent siblings)
8 siblings, 0 replies; 32+ messages in thread
From: Harendra Gautam @ 2026-08-24 6:36 UTC (permalink / raw)
To: Srinivas Kandagatla
Cc: Mark Brown, Liam Girdwood, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Jaroslav Kysela, Takashi Iwai, linux-sound,
linux-arm-msm, devicetree, linux-kernel, Prasad Kumpatla,
Krzysztof Kozlowski, Sarath Ganapathiraju, Kumar Anurag Singh,
Mohammad Rafi Shaik
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
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PATCH v3 3/9] ASoC: qcom: Add QAIF hardware register map
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 6:36 ` [PATCH v3 2/9] ASoC: qcom: Add QAIF shared data structures and variant interface Harendra Gautam
@ 2026-08-24 6:36 ` 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
` (5 subsequent siblings)
8 siblings, 0 replies; 32+ messages in thread
From: Harendra Gautam @ 2026-08-24 6:36 UTC (permalink / raw)
To: Srinivas Kandagatla
Cc: Mark Brown, Liam Girdwood, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Jaroslav Kysela, Takashi Iwai, linux-sound,
linux-arm-msm, devicetree, linux-kernel, Prasad Kumpatla,
Krzysztof Kozlowski, Sarath Ganapathiraju, Kumar Anurag Singh,
Mohammad Rafi Shaik
The QAIF driver needs a common register map to program the core registers,
audio interfaces, AIF/CIF DMA channels, interrupt registers, SHRAM/QXM
routing, and SID maps. Add accessor helpers so the driver can select the
proper AIF or CIF DMA register set based on the DAI ID.
Signed-off-by: Harendra Gautam <harendra.gautam@oss.qualcomm.com>
---
sound/soc/qcom/qaif-reg.h | 458 ++++++++++++++++++++++++++++++++++++++
1 file changed, 458 insertions(+)
create mode 100644 sound/soc/qcom/qaif-reg.h
diff --git a/sound/soc/qcom/qaif-reg.h b/sound/soc/qcom/qaif-reg.h
new file mode 100644
index 000000000000..fc968d584487
--- /dev/null
+++ b/sound/soc/qcom/qaif-reg.h
@@ -0,0 +1,458 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ *
+ * qaif-reg.h -- QAIF ALSA SoC CPU-Platform DAI driver register header
+ */
+#ifndef SND_SOC_QCOM_QAIF_REG_H
+#define SND_SOC_QCOM_QAIF_REG_H
+
+#include "qaif.h"
+
+#define QAIF_SUMMARY_IRQSTAT_REG(v) (0x19188 + (0x1000 * ((v)->ee)))
+
+/* Core HW info */
+#define QAIF_HW_VERSION_REG (0x0000)
+#define QAIF_HW_INFO_REG (0x0004)
+#define QAIF_HW_INFO2_REG (0x0008)
+
+/* Interface lane and channel info */
+#define QAIF_AUD_INTF_LANE_INFO_REG (0x0020)
+#define QAIF_AUD_INTF_LANE_INFO2_REG (0x0024)
+#define QAIF_CDC_TX_INTF_CH_INFO_REG(n) (0x0028 + (0x4 * (n)))
+#define QAIF_CDC_RX_INTF_CH_INFO_REG(n) (0x0068 + (0x4 * (n)))
+#define QAIF_QXM1_SHRAM_LENGTH_INFO_REG (0x0088)
+#define QAIF_QXM0_SHRAM_LENGTH_INFO_REG (0x008C)
+#define QAIF_NUM_AUD_INTF_TO_RAIL_INFO_REG (0x0090)
+
+/* Debug/control and status */
+#define QAIF_DEBUG_CTL_REG (0x0200)
+#define QAIF_WRDMA_LOOPBACK_EN_REG (0x0204)
+#define QAIF_WRDMA_LOOPBACK_SEL_REG (0x0208)
+#define QAIF_SHRAM_DYNAMIC_CLK_GATING_EN_REG (0x0300)
+#define QAIF_AXI_STATUS_REG (0x0304)
+#define QAIF_QSB_DYNAMIC_CLK_GATING_EN_REG (0x0308)
+#define QAIF_START_STOP_CTRL_BYPASS_EN_REG (0x030C)
+#define QAIF_QXM0_AXI_ATTR_CFG_REG (0x040C)
+
+/* QXM request/grant debug */
+#define QAIF_QXM0_AUD_WR_REQ_GNT_DBG_STAT_REG (0x0500)
+#define QAIF_QXM1_AUD_WR_REQ_GNT_DBG_STAT_REG (0x0504)
+#define QAIF_QXM0_CODEC_RX_WR_REQ_DBG_STAT_REG (0x0508)
+#define QAIF_QXM0_CODEC_RX_WR_GNT_DBG_STAT_REG (0x050C)
+#define QAIF_QXM1_CODEC_RX_WR_REQ_DBG_STAT_REG (0x0510)
+#define QAIF_QXM1_CODEC_RX_WR_GNT_DBG_STAT_REG (0x0514)
+#define QAIF_QXM0_AUD_RD_REQ_GNT_DBG_STAT_REG (0x0518)
+#define QAIF_QXM1_AUD_RD_REQ_GNT_DBG_STAT_REG (0x051C)
+#define QAIF_QXM0_CODEC_TX_RD_REQ_DBG_STAT_REG (0x0520)
+#define QAIF_QXM0_CODEC_TX_RD_GNT_DBG_STAT_REG (0x0524)
+#define QAIF_QXM1_CODEC_TX_RD_REQ_DBG_STAT_REG (0x0528)
+#define QAIF_QXM1_CODEC_TX_RD_GNT_DBG_STAT_REG (0x052C)
+#define QAIF_QXM0_EXT_RDDMA_RD_REQ_GNT_DBG_STAT_REG (0x0530)
+#define QAIF_QXM1_EXT_RDDMA_RD_REQ_GNT_DBG_STAT_REG (0x0534)
+
+/* QSB transaction debug */
+#define QAIF_QSB_AUD_WR_TXN_DBG_STAT_REG (0x0538)
+#define QAIF_QSB_CODEC_RX_WR_TXN_ERR_DBG_STAT_REG (0x053C)
+#define QAIF_QSB_CODEC_RX_WR_TXN_OKAY_DBG_STAT_REG (0x0540)
+#define QAIF_QSB_AUD_ADDR_SENT_DBG_STAT_REG (0x0544)
+#define QAIF_QSB_CODEC_TX_RD_ADDR_SENT_DBG_STAT_REG (0x0548)
+#define QAIF_QSB_EXT_RDDMA_RD_ADDR_SENT_DBG_STAT_REG (0x054C)
+#define QAIF_QSB_CODEC_RX_WR_ADDR_SENT_DBG_STAT_REG (0x0550)
+#define QAIF_QSB_AUD_RD_TXN_DBG_STAT_REG (0x0554)
+#define QAIF_QSB_CODEC_TX_RD_TXN_ERR_DBG_STAT_REG (0x0558)
+#define QAIF_QSB_CODEC_TX_RD_TXN_RCVD_DBG_STAT_REG (0x055C)
+#define QAIF_QSB_EXT_RDDMA_RD_TXN_DBG_STAT_REG (0x0560)
+#define QAIF_QSB_MISC_DBG_STATUS_REG (0x0564)
+
+/* Global spare and HWE */
+#define QAIF_GLOBAL_SPARE_IN_REG (0x0B00)
+#define QAIF_GLOBAL_SPARE_OUT_REG (0x0B04)
+#define QAIF_HWE_CFG_REG (0x0B08)
+
+/* SID maps */
+#define QAIF_WRDMA_SID_MAP_REG (0x1B00)
+#define QAIF_CDC_WRDMA_SID_MAP_REG (0x1B40)
+#define QAIF_RDDMA_SID_MAP_REG (0x1C00)
+#define QAIF_CDC_RDDMA_SID_MAP_REG (0x1C40)
+
+/* EE overlap interrupts */
+#define QAIF_EE_OVERLAP_IRQ_EN_REG (0x1D00)
+#define QAIF_EE_OVERLAP_IRQ_RAW_STATUS_REG (0x1D04)
+#define QAIF_EE_OVERLAP_IRQ_CLEAR_REG (0x1D08)
+#define QAIF_EE_OVERLAP_IRQ_FORCE_REG (0x1D0C)
+
+/*
+ * EE (Execution Engine) assignment and map registers.
+ *
+ * The EE offset (v->ee) is an address/index offset relative to the
+ * platform-defined QAIF/EE base and lets the hardware route the AIF
+ * operation to the correct EE context. It is hardware/platform-specific and
+ * must match the mapping defined for the selected QAIF AIF/lane in the
+ * hardware programming guide. It is not a runtime data offset and must not
+ * be changed based on the stream configuration.
+ */
+#define QAIF_EE_RDDMA_ASSIGNMENT_REG(v) (0x19148 + (0x1000 * ((v)->ee)))
+#define QAIF_EE_WRDMA_ASSIGNMENT_REG(v) (0x19150 + (0x1000 * ((v)->ee)))
+#define QAIF_EE_INTF_ASSIGNMENT_REG(v) (0x19158 + (0x1000 * ((v)->ee)))
+#define QAIF_EE_CODEC_RDDMA_ASSIGN_REG(v) (0x19308 + (0x1000 * ((v)->ee)))
+#define QAIF_EE_CODEC_WRDMA_ASSIGN_REG(v) (0x19318 + (0x1000 * ((v)->ee)))
+#define QAIF_EE_RDDMA_MAP_REG(v) (0x1920 + (0x1000 * ((v)->ee)))
+#define QAIF_EE_WRDMA_MAP_REG(v) (0x1940 + (0x1000 * ((v)->ee)))
+#define QAIF_EE_INTF_MAP_REG(v) (0x1960 + (0x1000 * ((v)->ee)))
+#define QAIF_EE_CODEC_RDDMA_MAP_REG(v) (0x1980 + (0x1000 * ((v)->ee)))
+#define QAIF_EE_CODEC_WRDMA_MAP_REG(v) (0x1A00 + (0x1000 * ((v)->ee)))
+
+/* EE rate-detection and VFR interrupts */
+#define QAIF_EE_RATE_DET_IRQ_EN_REG(v) (0x190F0 + (0x1000 * ((v)->ee)))
+#define QAIF_EE_RATE_DET_IRQ_STAT_REG(v) (0x190F4 + (0x1000 * ((v)->ee)))
+#define QAIF_EE_RATE_DET_IRQ_RAW_STAT_REG(v) (0x190F8 + (0x1000 * ((v)->ee)))
+#define QAIF_EE_RATE_DET_IRQ_CLEAR_REG(v) (0x190FC + (0x1000 * ((v)->ee)))
+#define QAIF_EE_RATE_DET_IRQ_FORCE_REG(v) (0x19100 + (0x1000 * ((v)->ee)))
+
+#define QAIF_EE_VFR_IRQ_EN_REG(v) (0x19104 + (0x1000 * ((v)->ee)))
+#define QAIF_EE_VFR_IRQ_STATUS_REG(v) (0x19108 + (0x1000 * ((v)->ee)))
+#define QAIF_EE_VFR_IRQ_RAW_STATUS_REG(v) (0x1910C + (0x1000 * ((v)->ee)))
+#define QAIF_EE_VFR_IRQ_CLEAR_REG(v) (0x19110 + (0x1000 * ((v)->ee)))
+#define QAIF_EE_VFR_IRQ_FORCE_REG(v) (0x19114 + (0x1000 * ((v)->ee)))
+
+/* EE AUD_INTF underflow/overflow interrupts */
+#define QAIF_EE_AUD_INTF_UF_IRQ_EN_REG(v) (0x19160 + (0x1000 * ((v)->ee)))
+#define QAIF_EE_AUD_INTF_UF_IRQ_STAT_REG(v) (0x19164 + (0x1000 * ((v)->ee)))
+#define QAIF_EE_AUD_INTF_UF_IRQ_RAW_STAT_REG(v) (0x19168 + (0x1000 * ((v)->ee)))
+#define QAIF_EE_AUD_INTF_UF_IRQ_CLEAR_REG(v) (0x1916C + (0x1000 * ((v)->ee)))
+#define QAIF_EE_AUD_INTF_UF_IRQ_FORCE_REG(v) (0x19170 + (0x1000 * ((v)->ee)))
+
+#define QAIF_EE_AUD_INTF_OF_IRQ_EN_REG(v) (0x19174 + (0x1000 * ((v)->ee)))
+#define QAIF_EE_AUD_INTF_OF_IRQ_STAT_REG(v) (0x19178 + (0x1000 * ((v)->ee)))
+#define QAIF_EE_AUD_INTF_OF_IRQ_RAW_STAT_REG(v) (0x1917C + (0x1000 * ((v)->ee)))
+#define QAIF_EE_AUD_INTF_OF_IRQ_CLEAR_REG(v) (0x19180 + (0x1000 * ((v)->ee)))
+#define QAIF_EE_AUD_INTF_OF_IRQ_FORCE_REG(v) (0x19184 + (0x1000 * ((v)->ee)))
+
+/* EE L2 Period IRQ mux selection */
+#define QAIF_EE_L2_PERIOD_IRQ_0_3_MUX_SEL_REG(v) (0x19F00 + (0x1000 * ((v)->ee)))
+#define QAIF_EE_L2_PERIOD_IRQ_4_7_MUX_SEL_REG(v) (0x19F04 + (0x1000 * ((v)->ee)))
+
+/* AUD_INTF block (per interface, stride 0x1000 starting at 0x4000) */
+#define QAIF_AUD_INTF_REG_ADDR(offset, i) (0x4000 + (offset) + (0x1000 * (i)))
+
+#define QAIF_AUD_INTF_CTL_REG(i) QAIF_AUD_INTF_REG_ADDR(0x0000, (i))
+#define QAIF_AUD_INTF_SYNC_CFG_REG(i) QAIF_AUD_INTF_REG_ADDR(0x0004, (i))
+#define QAIF_AUD_INTF_BIT_WIDTH_CFG_REG(i) QAIF_AUD_INTF_REG_ADDR(0x0008, (i))
+#define QAIF_AUD_INTF_FRAME_CFG_REG(i) QAIF_AUD_INTF_REG_ADDR(0x000C, (i))
+#define QAIF_AUD_INTF_ACTV_SLOT_EN_TX_REG(i) QAIF_AUD_INTF_REG_ADDR(0x0010, (i))
+#define QAIF_AUD_INTF_ACTV_SLOT_EN_RX_REG(i) QAIF_AUD_INTF_REG_ADDR(0x0030, (i))
+#define QAIF_AUD_INTF_LANE_CFG_REG(i) QAIF_AUD_INTF_REG_ADDR(0x0050, (i))
+#define QAIF_AUD_INTF_MI2S_CFG_REG(i) QAIF_AUD_INTF_REG_ADDR(0x0054, (i))
+#define QAIF_AUD_INTF_CFG_REG(i) QAIF_AUD_INTF_REG_ADDR(0x0058, (i))
+#define QAIF_AUD_INTF_CHAR_CTL_REG(i) QAIF_AUD_INTF_REG_ADDR(0x005C, (i))
+#define QAIF_AUD_INTF_CHAR_CFG_REG(i) QAIF_AUD_INTF_REG_ADDR(0x0060, (i))
+#define QAIF_AUD_INTF_CHAR_DATA_REG(i) QAIF_AUD_INTF_REG_ADDR(0x0064, (i))
+#define QAIF_AUD_INTF_CHAR_DATA_EXT_REG(i) QAIF_AUD_INTF_REG_ADDR(0x0068, (i))
+#define QAIF_AUD_INTF_CHAR_SYNC_REG(i) QAIF_AUD_INTF_REG_ADDR(0x006C, (i))
+#define QAIF_AUD_INTF_INIT_DBG_STATUS_REG(i) QAIF_AUD_INTF_REG_ADDR(0x0FF0, (i))
+#define QAIF_AUD_INTF_TX_DBG_STATUS_REG(i) QAIF_AUD_INTF_REG_ADDR(0x0FF4, (i))
+#define QAIF_AUD_INTF_RX_DBG_STATUS_REG(i) QAIF_AUD_INTF_REG_ADDR(0x0FF8, (i))
+
+/* RATE_DET block (per detector, stride 0x1000 starting at 0x1E000) */
+#define QAIF_RATE_DET_REG_ADDR(offset, det) (0x1E000 + (offset) + (0x1000 * (det)))
+
+#define QAIF_RATE_DET_CONFIG_REG(det) QAIF_RATE_DET_REG_ADDR(0x0000, (det))
+#define QAIF_RATE_DET_TARGET1_CONF_REG(det) QAIF_RATE_DET_REG_ADDR(0x0004, (det))
+#define QAIF_RATE_DET_TARGET2_CONF_REG(det) QAIF_RATE_DET_REG_ADDR(0x0008, (det))
+#define QAIF_RATE_DET_BIN_REG(det) QAIF_RATE_DET_REG_ADDR(0x000C, (det))
+#define QAIF_RATE_DET_STC_DIFF_REG(det) QAIF_RATE_DET_REG_ADDR(0x0010, (det))
+#define QAIF_RATE_DET_SEL_REG(det) QAIF_RATE_DET_REG_ADDR(0x0014, (det))
+#define QAIF_RATE_DET_TIMEOUT_CFG_REG(det) QAIF_RATE_DET_REG_ADDR(0x0018, (det))
+
+#define QAIF_WRDMA_MAP_QXM (0x1000)
+#define QAIF_CDC_WRDMA_MAP_QXM (0x1004)
+#define QAIF_RDDMA_MAP_QXM (0x1010)
+#define QAIF_CDC_RDDMA_MAP_QXM (0x1014)
+#define QAIF_RDDMA_QXM1_SHRAM_ST_ADDR(i) (0x1100 + (0x4 * (i)))
+#define QAIF_CDC_RDDMA_QXM1_SHRAM_ST_ADDR(i) (0x1140 + (0x4 * (i)))
+#define QAIF_RDDMA_QXM0_SHRAM_ST_ADDR(i) (0x1200 + (0x4 * (i)))
+#define QAIF_CDC_RDDMA_QXM0_SHRAM_ST_ADDR(i) (0x1240 + (0x4 * (i)))
+#define QAIF_RDDMA_QXM1_SHRAM_LEN(i) (0x1300 + (0x4 * (i)))
+#define QAIF_CDC_RDDMA_QXM1_SHRAM_LEN(i) (0x1340 + (0x4 * (i)))
+#define QAIF_RDDMA_QXM0_SHRAM_LEN(i) (0x1400 + (0x4 * (i)))
+#define QAIF_CDC_RDDMA_QXM0_SHRAM_LEN(i) (0x1440 + (0x4 * (i)))
+#define QAIF_WRDMA_QXM1_SHRAM_ST_ADDR(i) (0x1500 + (0x4 * (i)))
+#define QAIF_CDC_WRDMA_QXM1_SHRAM_ST_ADDR(i) (0x1540 + (0x4 * (i)))
+#define QAIF_WRDMA_QXM0_SHRAM_ST_ADDR(i) (0x1600 + (0x4 * (i)))
+#define QAIF_CDC_WRDMA_QXM0_SHRAM_ST_ADDR(i) (0x1640 + (0x4 * (i)))
+#define QAIF_WRDMA_QXM1_SHRAM_LEN(i) (0x1700 + (0x4 * (i)))
+#define QAIF_CDC_WRDMA_QXM1_SHRAM_LEN(i) (0x1740 + (0x4 * (i)))
+#define QAIF_WRDMA_QXM0_SHRAM_LEN(i) (0x1800 + (0x4 * (i)))
+#define QAIF_CDC_WRDMA_QXM0_SHRAM_LEN(i) (0x1840 + (0x4 * (i)))
+
+/* RDDMA */
+static inline u32 qaif_rddma_reg_addr(const struct qaif_variant *v,
+ u32 offset, u32 i)
+{
+ return v->rddma_reg_base + offset + v->rddma_stride * i;
+}
+
+#define QAIF_RDDMA_CTL_REG(v, i) qaif_rddma_reg_addr(v, 0x00, (i))
+#define QAIF_RDDMA_CFG_REG(v, i) qaif_rddma_reg_addr(v, 0x04, (i))
+#define QAIF_RDDMA_BASE_ADDR_REG(v, i) qaif_rddma_reg_addr(v, 0x08, (i))
+#define QAIF_RDDMA_BUFF_LEN_REG(v, i) qaif_rddma_reg_addr(v, 0x10, (i))
+#define QAIF_RDDMA_CURR_ADDR_REG(v, i) qaif_rddma_reg_addr(v, 0x14, (i))
+#define QAIF_RDDMA_PERIOD_LEN_REG(v, i) qaif_rddma_reg_addr(v, 0x1C, (i))
+#define QAIF_RDDMA_PERIOD_CNT_REG(v, i) qaif_rddma_reg_addr(v, 0x20, (i))
+#define QAIF_RDDMA_SHRAM_WORDCNT_REG(v, i) qaif_rddma_reg_addr(v, 0x24, (i))
+#define QAIF_RDDMA_FRAME_STATUS_REG(v, i) qaif_rddma_reg_addr(v, 0x28, (i))
+#define QAIF_RDDMA_FRAME_STATUS_EXTN_REG(v, i) qaif_rddma_reg_addr(v, 0x2C, (i))
+#define QAIF_RDDMA_FRAME_STATUS_CLR_REG(v, i) qaif_rddma_reg_addr(v, 0x30, (i))
+#define QAIF_RDDMA_SET_BUFF_CNT_REG(v, i) qaif_rddma_reg_addr(v, 0x34, (i))
+#define QAIF_RDDMA_SET_PERIOD_CNT_REG(v, i) qaif_rddma_reg_addr(v, 0x38, (i))
+#define QAIF_RDDMA_STC_LSB_REG(v, i) qaif_rddma_reg_addr(v, 0x3C, (i))
+#define QAIF_RDDMA_STC_MSB_REG(v, i) qaif_rddma_reg_addr(v, 0x40, (i))
+#define QAIF_RDDMA_PERIOD_DET_STAT_REG(v, i) qaif_rddma_reg_addr(v, 0x44, (i))
+#define QAIF_RDDMA_PERIOD_DET_CLR_REG(v, i) qaif_rddma_reg_addr(v, 0x48, (i))
+#define QAIF_RDDMA_FORMAT_ERR_REG(v, i) qaif_rddma_reg_addr(v, 0x4C, (i))
+#define QAIF_RDDMA_AHB_BYPASS_REG(v, i) qaif_rddma_reg_addr(v, 0x50, (i))
+#define QAIF_RDDMA_SHUTDOWN_STAT_REG(v, i) qaif_rddma_reg_addr(v, 0x54, (i))
+#define QAIF_RDDMA_PADDING_CFG_REG(v, i) qaif_rddma_reg_addr(v, 0x58, (i))
+#define QAIF_RDDMA_STATUS_REG(v, i) qaif_rddma_reg_addr(v, 0x60, (i))
+#define QAIF_RDDMA_DBG_STATUS_REG(v, i) qaif_rddma_reg_addr(v, 0xFF0, (i))
+
+static inline u32 qaif_codec_rddma_reg_addr(const struct qaif_variant *v,
+ u32 offset, u32 i)
+{
+ return v->codec_rddma_reg_base + offset + v->codec_rddma_stride * i;
+}
+
+#define QAIF_CDC_RDDMA_CTL_REG(v, i) qaif_codec_rddma_reg_addr(v, 0x00, (i))
+#define QAIF_CDC_RDDMA_CFG_REG(v, i) qaif_codec_rddma_reg_addr(v, 0x04, (i))
+#define QAIF_CDC_RDDMA_BASE_ADDR_REG(v, i) qaif_codec_rddma_reg_addr(v, 0x08, (i))
+#define QAIF_CDC_RDDMA_BUFF_LEN_REG(v, i) qaif_codec_rddma_reg_addr(v, 0x10, (i))
+#define QAIF_CDC_RDDMA_CURR_ADDR_REG(v, i) qaif_codec_rddma_reg_addr(v, 0x14, (i))
+#define QAIF_CDC_RDDMA_PERIOD_LEN_REG(v, i) qaif_codec_rddma_reg_addr(v, 0x1C, (i))
+#define QAIF_CDC_RDDMA_PERIOD_CNT_REG(v, i) qaif_codec_rddma_reg_addr(v, 0x20, (i))
+#define QAIF_CDC_RDDMA_SHRAM_WORDCNT_REG(v, i) qaif_codec_rddma_reg_addr(v, 0x24, (i))
+#define QAIF_CDC_RDDMA_FRAME_STAT_REG(v, i) qaif_codec_rddma_reg_addr(v, 0x28, (i))
+#define QAIF_CDC_RDDMA_FRAME_STAT_EXTN_REG(v, i) qaif_codec_rddma_reg_addr(v, 0x2C, (i))
+#define QAIF_CDC_RDDMA_FRAME_STAT_CLR_REG(v, i) qaif_codec_rddma_reg_addr(v, 0x30, (i))
+#define QAIF_CDC_RDDMA_SET_BUFF_CNT_REG(v, i) qaif_codec_rddma_reg_addr(v, 0x34, (i))
+#define QAIF_CDC_RDDMA_SET_PERIOD_CNT_REG(v, i) qaif_codec_rddma_reg_addr(v, 0x38, (i))
+#define QAIF_CDC_RDDMA_STC_LSB_REG(v, i) qaif_codec_rddma_reg_addr(v, 0x3C, (i))
+#define QAIF_CDC_RDDMA_STC_MSB_REG(v, i) qaif_codec_rddma_reg_addr(v, 0x40, (i))
+#define QAIF_CDC_RDDMA_PERIOD_DET_STAT_REG(v, i) qaif_codec_rddma_reg_addr(v, 0x44, (i))
+#define QAIF_CDC_RDDMA_PERIOD_DET_CLR_REG(v, i) qaif_codec_rddma_reg_addr(v, 0x48, (i))
+#define QAIF_CDC_RDDMA_FORMAT_ERR_REG(v, i) qaif_codec_rddma_reg_addr(v, 0x4C, (i))
+#define QAIF_CDC_RDDMA_AHB_BYPASS_REG(v, i) qaif_codec_rddma_reg_addr(v, 0x50, (i))
+#define QAIF_CDC_RDDMA_SHUTDOWN_STAT_REG(v, i) qaif_codec_rddma_reg_addr(v, 0x54, (i))
+#define QAIF_CDC_RDDMA_PADDING_CFG_REG(v, i) qaif_codec_rddma_reg_addr(v, 0x58, (i))
+#define QAIF_CDC_RDDMA_INTF_CFG_REG(v, i) qaif_codec_rddma_reg_addr(v, 0x5C, (i))
+#define QAIF_CDC_RDDMA_STATUS_REG(v, i) qaif_codec_rddma_reg_addr(v, 0x60, (i))
+#define QAIF_CDC_RDDMA_DBG_STATUS_REG(v, i) qaif_codec_rddma_reg_addr(v, 0xFF0, (i))
+#define QAIF_CDC_RDDMA_INTF_DBG_STATUS_REG(v, i) qaif_codec_rddma_reg_addr(v, 0xFF4, (i))
+
+/* WRDMA */
+static inline u32 qaif_wrdma_reg_addr(const struct qaif_variant *v,
+ u32 offset, u32 i)
+{
+ return v->wrdma_reg_base + offset + v->wrdma_stride * i;
+}
+
+#define QAIF_WRDMA_CTL_REG(v, i) qaif_wrdma_reg_addr(v, 0x00, (i))
+#define QAIF_WRDMA_CFG_REG(v, i) qaif_wrdma_reg_addr(v, 0x04, (i))
+#define QAIF_WRDMA_BASE_ADDR_REG(v, i) qaif_wrdma_reg_addr(v, 0x08, (i))
+#define QAIF_WRDMA_BUFF_LEN_REG(v, i) qaif_wrdma_reg_addr(v, 0x10, (i))
+#define QAIF_WRDMA_CURR_ADDR_REG(v, i) qaif_wrdma_reg_addr(v, 0x14, (i))
+#define QAIF_WRDMA_PERIOD_LEN_REG(v, i) qaif_wrdma_reg_addr(v, 0x1C, (i))
+#define QAIF_WRDMA_PERIOD_CNT_REG(v, i) qaif_wrdma_reg_addr(v, 0x20, (i))
+#define QAIF_WRDMA_SHRAM_WORDCNT_REG(v, i) qaif_wrdma_reg_addr(v, 0x24, (i))
+#define QAIF_WRDMA_FRAME_STATUS_REG(v, i) qaif_wrdma_reg_addr(v, 0x28, (i))
+#define QAIF_WRDMA_FRAME_STATUS_EXTN_REG(v, i) qaif_wrdma_reg_addr(v, 0x2C, (i))
+#define QAIF_WRDMA_FRAME_STATUS_CLR_REG(v, i) qaif_wrdma_reg_addr(v, 0x30, (i))
+#define QAIF_WRDMA_SET_BUFF_CNT_REG(v, i) qaif_wrdma_reg_addr(v, 0x34, (i))
+#define QAIF_WRDMA_SET_PERIOD_CNT_REG(v, i) qaif_wrdma_reg_addr(v, 0x38, (i))
+#define QAIF_WRDMA_STC_LSB_REG(v, i) qaif_wrdma_reg_addr(v, 0x3C, (i))
+#define QAIF_WRDMA_STC_MSB_REG(v, i) qaif_wrdma_reg_addr(v, 0x40, (i))
+#define QAIF_WRDMA_PERIOD_DET_STAT_REG(v, i) qaif_wrdma_reg_addr(v, 0x44, (i))
+#define QAIF_WRDMA_PERIOD_DET_CLR_REG(v, i) qaif_wrdma_reg_addr(v, 0x48, (i))
+#define QAIF_WRDMA_FORMAT_ERR_REG(v, i) qaif_wrdma_reg_addr(v, 0x4C, (i))
+#define QAIF_WRDMA_AHB_BYPASS_REG(v, i) qaif_wrdma_reg_addr(v, 0x50, (i))
+#define QAIF_WRDMA_SHUTDOWN_STAT_REG(v, i) qaif_wrdma_reg_addr(v, 0x54, (i))
+#define QAIF_WRDMA_DBG_STATUS_REG(v, i) qaif_wrdma_reg_addr(v, 0xFF0, (i))
+
+static inline u32 qaif_codec_wrdma_reg_addr(const struct qaif_variant *v,
+ u32 offset, u32 i)
+{
+ return v->codec_wrdma_reg_base + offset + v->codec_wrdma_stride * i;
+}
+
+#define QAIF_CDC_WRDMA_CTL_REG(v, i) qaif_codec_wrdma_reg_addr(v, 0x00, (i))
+#define QAIF_CDC_WRDMA_CFG_REG(v, i) qaif_codec_wrdma_reg_addr(v, 0x04, (i))
+#define QAIF_CDC_WRDMA_BASE_ADDR_REG(v, i) qaif_codec_wrdma_reg_addr(v, 0x08, (i))
+#define QAIF_CDC_WRDMA_BUFF_LEN_REG(v, i) qaif_codec_wrdma_reg_addr(v, 0x10, (i))
+#define QAIF_CDC_WRDMA_CURR_ADDR_REG(v, i) qaif_codec_wrdma_reg_addr(v, 0x14, (i))
+#define QAIF_CDC_WRDMA_PERIOD_LEN_REG(v, i) qaif_codec_wrdma_reg_addr(v, 0x1C, (i))
+#define QAIF_CDC_WRDMA_PERIOD_CNT_REG(v, i) qaif_codec_wrdma_reg_addr(v, 0x20, (i))
+#define QAIF_CDC_WRDMA_SHRAM_WORDCNT_REG(v, i) qaif_codec_wrdma_reg_addr(v, 0x24, (i))
+#define QAIF_CDC_WRDMA_FRAME_STAT_REG(v, i) qaif_codec_wrdma_reg_addr(v, 0x28, (i))
+#define QAIF_CDC_WRDMA_FRAME_STAT_EXTN_REG(v, i) qaif_codec_wrdma_reg_addr(v, 0x2C, (i))
+#define QAIF_CDC_WRDMA_FRAME_STAT_CLR_REG(v, i) qaif_codec_wrdma_reg_addr(v, 0x30, (i))
+#define QAIF_CDC_WRDMA_SET_BUFF_CNT_REG(v, i) qaif_codec_wrdma_reg_addr(v, 0x34, (i))
+#define QAIF_CDC_WRDMA_SET_PERIOD_CNT_REG(v, i) qaif_codec_wrdma_reg_addr(v, 0x38, (i))
+#define QAIF_CDC_WRDMA_STC_LSB_REG(v, i) qaif_codec_wrdma_reg_addr(v, 0x3C, (i))
+#define QAIF_CDC_WRDMA_STC_MSB_REG(v, i) qaif_codec_wrdma_reg_addr(v, 0x40, (i))
+#define QAIF_CDC_WRDMA_PERIOD_DET_STAT_REG(v, i) qaif_codec_wrdma_reg_addr(v, 0x44, (i))
+#define QAIF_CDC_WRDMA_PERIOD_DET_CLR_REG(v, i) qaif_codec_wrdma_reg_addr(v, 0x48, (i))
+#define QAIF_CDC_WRDMA_FORMAT_ERR_REG(v, i) qaif_codec_wrdma_reg_addr(v, 0x4C, (i))
+#define QAIF_CDC_WRDMA_AHB_BYPASS_REG(v, i) qaif_codec_wrdma_reg_addr(v, 0x50, (i))
+#define QAIF_CDC_WRDMA_SHUTDOWN_STAT_REG(v, i) qaif_codec_wrdma_reg_addr(v, 0x54, (i))
+#define QAIF_CDC_WRDMA_INTF_CFG_REG(v, i) qaif_codec_wrdma_reg_addr(v, 0x58, (i))
+#define QAIF_CDC_WRDMA_DBG_STATUS_REG(v, i) qaif_codec_wrdma_reg_addr(v, 0xFF0, (i))
+#define QAIF_CDC_WRDMA_INTF_DBG_STATUS_REG(v, i) qaif_codec_wrdma_reg_addr(v, 0xFF4, (i))
+
+static inline u32 qaif_rddma_irq_reg_addr(const struct qaif_variant *v,
+ enum qaif_irq_type dma_type,
+ u32 offset)
+{
+ if (dma_type == QAIF_AIF_IRQ)
+ return v->rddma_irq_reg_base + offset +
+ v->rddma_irq_stride * v->ee;
+ return v->codec_rddma_irq_reg_base + offset +
+ v->codec_rddma_irq_stride * v->ee;
+}
+
+/* RDDMA Period Interrupts */
+#define QAIF_EE_RDDMA_PERIOD_IRQ_EN_REG(v, i) qaif_rddma_irq_reg_addr(v, i, 0x00)
+#define QAIF_EE_RDDMA_PERIOD_IRQ_STAT_REG(v, i) qaif_rddma_irq_reg_addr(v, i, 0x08)
+#define QAIF_EE_RDDMA_PERIOD_IRQ_RAW_STAT_REG(v, i) qaif_rddma_irq_reg_addr(v, i, 0x10)
+#define QAIF_EE_RDDMA_PERIOD_IRQ_CLR_REG(v, i) qaif_rddma_irq_reg_addr(v, i, 0x18)
+#define QAIF_EE_RDDMA_PERIOD_IRQ_FORCE_REG(v, i) qaif_rddma_irq_reg_addr(v, i, 0x20)
+/* RDDMA Underflow Interrupts */
+#define QAIF_EE_RDDMA_UF_IRQ_EN_REG(v, i) qaif_rddma_irq_reg_addr(v, i, 0x28)
+#define QAIF_EE_RDDMA_UF_IRQ_STAT_REG(v, i) qaif_rddma_irq_reg_addr(v, i, 0x30)
+#define QAIF_EE_RDDMA_UF_IRQ_RAW_STAT_REG(v, i) qaif_rddma_irq_reg_addr(v, i, 0x38)
+#define QAIF_EE_RDDMA_UF_IRQ_CLR_REG(v, i) qaif_rddma_irq_reg_addr(v, i, 0x40)
+#define QAIF_EE_RDDMA_UF_IRQ_FORCE_REG(v, i) qaif_rddma_irq_reg_addr(v, i, 0x48)
+/* RDDMA Error Response Interrupts */
+#define QAIF_EE_RDDMA_ERR_RSP_IRQ_EN_REG(v, i) qaif_rddma_irq_reg_addr(v, i, 0x50)
+#define QAIF_EE_RDDMA_ERR_RSP_IRQ_STAT_REG(v, i) qaif_rddma_irq_reg_addr(v, i, 0x58)
+#define QAIF_EE_RDDMA_ERR_RSP_IRQ_RAW_STAT(v, i) qaif_rddma_irq_reg_addr(v, i, 0x60)
+#define QAIF_EE_RDDMA_ERR_RSP_IRQ_CLR_REG(v, i) qaif_rddma_irq_reg_addr(v, i, 0x68)
+#define QAIF_EE_RDDMA_ERR_RSP_IRQ_FORCE_REG(v, i) qaif_rddma_irq_reg_addr(v, i, 0x70)
+
+static inline u32 qaif_wrdma_irq_reg_addr(const struct qaif_variant *v,
+ enum qaif_irq_type dma_type,
+ u32 offset)
+{
+ if (dma_type == QAIF_AIF_IRQ)
+ return v->wrdma_irq_reg_base + offset +
+ v->wrdma_irq_stride * v->ee;
+ return v->codec_wrdma_irq_reg_base + offset +
+ v->codec_wrdma_irq_stride * v->ee;
+}
+
+/* WRDMA Period Interrupts */
+#define QAIF_EE_WRDMA_PERIOD_IRQ_EN_REG(v, i) qaif_wrdma_irq_reg_addr(v, i, 0x00)
+#define QAIF_EE_WRDMA_PERIOD_IRQ_STAT_REG(v, i) qaif_wrdma_irq_reg_addr(v, i, 0x08)
+#define QAIF_EE_WRDMA_PERIOD_IRQ_RAW_STAT_REG(v, i) qaif_wrdma_irq_reg_addr(v, i, 0x10)
+#define QAIF_EE_WRDMA_PERIOD_IRQ_CLR_REG(v, i) qaif_wrdma_irq_reg_addr(v, i, 0x18)
+#define QAIF_EE_WRDMA_PERIOD_IRQ_FORCE_REG(v, i) qaif_wrdma_irq_reg_addr(v, i, 0x20)
+/* WRDMA Overflow Interrupts */
+#define QAIF_EE_WRDMA_OF_IRQ_EN_REG(v, i) qaif_wrdma_irq_reg_addr(v, i, 0x28)
+#define QAIF_EE_WRDMA_OF_IRQ_STAT_REG(v, i) qaif_wrdma_irq_reg_addr(v, i, 0x30)
+#define QAIF_EE_WRDMA_OF_IRQ_RAW_STAT_REG(v, i) qaif_wrdma_irq_reg_addr(v, i, 0x38)
+#define QAIF_EE_WRDMA_OF_IRQ_CLR_REG(v, i) qaif_wrdma_irq_reg_addr(v, i, 0x40)
+#define QAIF_EE_WRDMA_OF_IRQ_FORCE_REG(v, i) qaif_wrdma_irq_reg_addr(v, i, 0x48)
+/* WRDMA Error Response Interrupts */
+#define QAIF_EE_WRDMA_ERR_RSP_IRQ_EN_REG(v, i) qaif_wrdma_irq_reg_addr(v, i, 0x50)
+#define QAIF_EE_WRDMA_ERR_RSP_IRQ_STAT_REG(v, i) qaif_wrdma_irq_reg_addr(v, i, 0x58)
+#define QAIF_EE_WRDMA_ERR_RSP_IRQ_RAW_STAT(v, i) qaif_wrdma_irq_reg_addr(v, i, 0x60)
+#define QAIF_EE_WRDMA_ERR_RSP_IRQ_CLR_REG(v, i) qaif_wrdma_irq_reg_addr(v, i, 0x68)
+#define QAIF_EE_WRDMA_ERR_RSP_IRQ_FORCE_REG(v, i) qaif_wrdma_irq_reg_addr(v, i, 0x70)
+
+static inline u32 qaif_dmacfg_reg(const struct qaif_variant *v,
+ u32 i, int dir, unsigned int dai_id)
+{
+ if (qaif_is_cif_dma_port(dai_id))
+ return dir == SNDRV_PCM_STREAM_PLAYBACK ?
+ QAIF_CDC_RDDMA_CFG_REG(v, i) :
+ QAIF_CDC_WRDMA_CFG_REG(v, i);
+ return dir == SNDRV_PCM_STREAM_PLAYBACK ?
+ QAIF_RDDMA_CFG_REG(v, i) : QAIF_WRDMA_CFG_REG(v, i);
+}
+
+static inline u32 qaif_dmactl_reg(const struct qaif_variant *v,
+ u32 i, int dir, unsigned int dai_id)
+{
+ if (qaif_is_cif_dma_port(dai_id))
+ return dir == SNDRV_PCM_STREAM_PLAYBACK ?
+ QAIF_CDC_RDDMA_CTL_REG(v, i) :
+ QAIF_CDC_WRDMA_CTL_REG(v, i);
+ return dir == SNDRV_PCM_STREAM_PLAYBACK ?
+ QAIF_RDDMA_CTL_REG(v, i) : QAIF_WRDMA_CTL_REG(v, i);
+}
+
+static inline u32 qaif_dmabuff_reg(const struct qaif_variant *v,
+ u32 i, int dir, unsigned int dai_id)
+{
+ if (qaif_is_cif_dma_port(dai_id))
+ return dir == SNDRV_PCM_STREAM_PLAYBACK ?
+ QAIF_CDC_RDDMA_BUFF_LEN_REG(v, i) :
+ QAIF_CDC_WRDMA_BUFF_LEN_REG(v, i);
+ return dir == SNDRV_PCM_STREAM_PLAYBACK ?
+ QAIF_RDDMA_BUFF_LEN_REG(v, i) : QAIF_WRDMA_BUFF_LEN_REG(v, i);
+}
+
+static inline u32 qaif_dmacurr_reg(const struct qaif_variant *v,
+ u32 i, int dir, unsigned int dai_id)
+{
+ if (qaif_is_cif_dma_port(dai_id))
+ return dir == SNDRV_PCM_STREAM_PLAYBACK ?
+ QAIF_CDC_RDDMA_CURR_ADDR_REG(v, i) :
+ QAIF_CDC_WRDMA_CURR_ADDR_REG(v, i);
+ return dir == SNDRV_PCM_STREAM_PLAYBACK ?
+ QAIF_RDDMA_CURR_ADDR_REG(v, i) : QAIF_WRDMA_CURR_ADDR_REG(v, i);
+}
+
+static inline u32 qaif_dmaper_cnt_reg(const struct qaif_variant *v,
+ u32 i, int dir, unsigned int dai_id)
+{
+ if (qaif_is_cif_dma_port(dai_id))
+ return dir == SNDRV_PCM_STREAM_PLAYBACK ?
+ QAIF_CDC_RDDMA_PERIOD_CNT_REG(v, i) :
+ QAIF_CDC_WRDMA_PERIOD_CNT_REG(v, i);
+ return dir == SNDRV_PCM_STREAM_PLAYBACK ?
+ QAIF_RDDMA_PERIOD_CNT_REG(v, i) : QAIF_WRDMA_PERIOD_CNT_REG(v, i);
+}
+
+static inline u32 qaif_dmaper_len_reg(const struct qaif_variant *v,
+ u32 i, int dir, unsigned int dai_id)
+{
+ if (qaif_is_cif_dma_port(dai_id))
+ return dir == SNDRV_PCM_STREAM_PLAYBACK ?
+ QAIF_CDC_RDDMA_PERIOD_LEN_REG(v, i) :
+ QAIF_CDC_WRDMA_PERIOD_LEN_REG(v, i);
+ return dir == SNDRV_PCM_STREAM_PLAYBACK ?
+ QAIF_RDDMA_PERIOD_LEN_REG(v, i) : QAIF_WRDMA_PERIOD_LEN_REG(v, i);
+}
+
+static inline u32 qaif_dmabase_reg(const struct qaif_variant *v,
+ u32 i, int dir, unsigned int dai_id)
+{
+ if (qaif_is_cif_dma_port(dai_id))
+ return dir == SNDRV_PCM_STREAM_PLAYBACK ?
+ QAIF_CDC_RDDMA_BASE_ADDR_REG(v, i) :
+ QAIF_CDC_WRDMA_BASE_ADDR_REG(v, i);
+ return dir == SNDRV_PCM_STREAM_PLAYBACK ?
+ QAIF_RDDMA_BASE_ADDR_REG(v, i) : QAIF_WRDMA_BASE_ADDR_REG(v, i);
+}
+
+static inline u32 qaif_sid_map_reg(int dir, unsigned int dai_id)
+{
+ if (qaif_is_cif_dma_port(dai_id))
+ return dir == SNDRV_PCM_STREAM_PLAYBACK ?
+ QAIF_CDC_RDDMA_SID_MAP_REG :
+ QAIF_CDC_WRDMA_SID_MAP_REG;
+ return dir == SNDRV_PCM_STREAM_PLAYBACK ?
+ QAIF_RDDMA_SID_MAP_REG : QAIF_WRDMA_SID_MAP_REG;
+}
+
+#endif /* SND_SOC_QCOM_QAIF_REG_H */
--
2.34.1
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PATCH v3 4/9] ASoC: qcom: Add QAIF CPU DAI ops, regmap, DT parsing and platform init
2026-08-24 6:36 [PATCH v3 0/9] ASoC: qcom: Add QAIF driver for Shikra audio platform Harendra Gautam
` (2 preceding siblings ...)
2026-08-24 6:36 ` [PATCH v3 3/9] ASoC: qcom: Add QAIF hardware register map Harendra Gautam
@ 2026-08-24 6:36 ` 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
` (4 subsequent siblings)
8 siblings, 0 replies; 32+ messages in thread
From: Harendra Gautam @ 2026-08-24 6:36 UTC (permalink / raw)
To: Srinivas Kandagatla
Cc: Mark Brown, Liam Girdwood, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Jaroslav Kysela, Takashi Iwai, linux-sound,
linux-arm-msm, devicetree, linux-kernel, Prasad Kumpatla,
Krzysztof Kozlowski, Sarath Ganapathiraju, Kumar Anurag Singh,
Mohammad Rafi Shaik
Implement CIF DAI operations for CDC DMA paths, including channel mask
programming and dynamic clock control. Implement AIF DAI operations for
MI2S, TDM and PCM paths, including format setup, slot and lane
configuration, bit clock management and stream enable handling.
Also add the QAIF MMIO regmap setup, parse per-interface configuration
from devicetree, manage required clocks and register the CPU DAI
component.
Signed-off-by: Harendra Gautam <harendra.gautam@oss.qualcomm.com>
---
sound/soc/qcom/qaif-cpu.c | 876 ++++++++++++++++++++++++++++++++++++++
1 file changed, 876 insertions(+)
create mode 100644 sound/soc/qcom/qaif-cpu.c
diff --git a/sound/soc/qcom/qaif-cpu.c b/sound/soc/qcom/qaif-cpu.c
new file mode 100644
index 000000000000..8792d01254a6
--- /dev/null
+++ b/sound/soc/qcom/qaif-cpu.c
@@ -0,0 +1,876 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ *
+ * qaif-cpu.c -- ALSA SoC CPU-Platform DAI driver for QTi QAIF
+ */
+
+#include <linux/clk.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dai.h>
+#include "qaif-reg.h"
+#include "qaif.h"
+
+/* CIF INTF CFG register bit positions */
+#define QAIF_CIF_INTF_16BIT_UNPACK_BIT BIT(0)
+#define QAIF_CIF_INTF_DYNCLK_BIT BIT(2)
+#define QAIF_CIF_INTF_FS_SEL_MASK GENMASK(7, 4)
+#define QAIF_CIF_INTF_ACTIVE_CH_MASK GENMASK(27, 12)
+#define QAIF_CIF_INTF_ACTIVE_CH_SHIFT 12
+
+/* AIF CTL register (QAIF_AUD_INTF_CTL_REG) bit positions */
+#define QAIF_AIF_CTL_ENABLE_BIT BIT(0)
+#define QAIF_AIF_CTL_ENABLE_TX_BIT BIT(4)
+#define QAIF_AIF_CTL_ENABLE_RX_BIT BIT(8)
+
+/* AIF SYNC CFG register (QAIF_AUD_INTF_SYNC_CFG_REG) bit positions */
+#define QAIF_AIF_SYNC_SRC_BIT BIT(0)
+#define QAIF_AIF_SYNC_MODE_MASK GENMASK(5, 4)
+#define QAIF_AIF_SYNC_MODE_SHIFT 4
+#define QAIF_AIF_SYNC_DELAY_MASK GENMASK(9, 8)
+#define QAIF_AIF_SYNC_DELAY_SHIFT 8
+#define QAIF_AIF_SYNC_INV_BIT BIT(12)
+
+/* SYNC_MODE field values */
+#define QAIF_AIF_SYNC_MODE_SHORT 0
+#define QAIF_AIF_SYNC_MODE_ONE_SLOT 1
+#define QAIF_AIF_SYNC_MODE_LONG 2
+
+/* SYNC_DELAY field values */
+#define QAIF_AIF_SYNC_DELAY_SAME 0
+#define QAIF_AIF_SYNC_DELAY_ONE 1
+
+/* AIF BIT WIDTH CFG register (QAIF_AUD_INTF_BIT_WIDTH_CFG_REG) bit positions */
+#define QAIF_AIF_SLOT_WIDTH_TX_MASK GENMASK(4, 0)
+#define QAIF_AIF_SLOT_WIDTH_RX_MASK GENMASK(12, 8)
+#define QAIF_AIF_SLOT_WIDTH_RX_SHIFT 8
+#define QAIF_AIF_SAMPLE_WIDTH_TX_MASK GENMASK(20, 16)
+#define QAIF_AIF_SAMPLE_WIDTH_TX_SHIFT 16
+#define QAIF_AIF_SAMPLE_WIDTH_RX_MASK GENMASK(28, 24)
+#define QAIF_AIF_SAMPLE_WIDTH_RX_SHIFT 24
+
+/*
+ * slot_width is programmed 0-based into the 5-bit SLOT_WIDTH field and the
+ * frame length (slots * slot_width) 0-based into the 10-bit BITS_PER_LANE
+ * field, so these are the largest values the registers can represent.
+ */
+#define QAIF_AIF_SLOT_WIDTH_MAX 32
+#define QAIF_AIF_FRAME_BITS_MAX 1024
+
+/* AIF FRAME CFG register (QAIF_AUD_INTF_FRAME_CFG_REG) bit positions */
+#define QAIF_AIF_BITS_PER_LANE_MASK GENMASK(9, 0)
+
+/* AIF LANE CFG register (QAIF_AUD_INTF_LANE_CFG_REG) bit positions */
+#define QAIF_AIF_LANE_DIR_MASK GENMASK(7, 0)
+#define QAIF_AIF_LANE_EN_MASK GENMASK(15, 8)
+#define QAIF_AIF_LANE_EN_SHIFT 8
+#define QAIF_AIF_CTRL_DATA_OE_BIT BIT(16)
+#define QAIF_AIF_LOOPBACK_EN_BIT BIT(31)
+
+/* AIF MI2S CFG register (QAIF_AUD_INTF_MI2S_CFG_REG) bit positions */
+#define QAIF_AIF_MONO_MODE_TX_BIT BIT(0)
+#define QAIF_AIF_MONO_MODE_RX_BIT BIT(1)
+
+/* AIF CFG register (QAIF_AUD_INTF_CFG_REG) bit positions */
+#define QAIF_AIF_FULL_CYCLE_EN_BIT BIT(0)
+
+static inline u32 qaif_cif_intf_reg(const struct qaif_variant *v,
+ int idx, unsigned int dai_id)
+{
+ if (dai_id >= QAIF_CDC_DMA_RX0 && dai_id <= QAIF_CDC_DMA_RX9)
+ return QAIF_CDC_RDDMA_INTF_CFG_REG(v, idx);
+ return QAIF_CDC_WRDMA_INTF_CFG_REG(v, idx);
+}
+
+static int qaif_cif_daiops_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
+ struct qaif_drv_data *drvdata = snd_soc_dai_get_drvdata(dai);
+ const struct qaif_variant *v = drvdata->variant;
+ unsigned int dai_id = dai->driver->id;
+ unsigned int regval;
+ int idx;
+
+ switch (params_channels(params)) {
+ case 1:
+ regval = QAIF_CIF_DMA_INTF_ONE_CHANNEL;
+ break;
+ case 2:
+ regval = QAIF_CIF_DMA_INTF_TWO_CHANNEL;
+ break;
+ case 4:
+ regval = QAIF_CIF_DMA_INTF_FOUR_CHANNEL;
+ break;
+ case 6:
+ regval = QAIF_CIF_DMA_INTF_SIX_CHANNEL;
+ break;
+ case 8:
+ regval = QAIF_CIF_DMA_INTF_EIGHT_CHANNEL;
+ break;
+ default:
+ dev_dbg(rtd->dev, "unsupported channel count %u\n",
+ params_channels(params));
+ return -EINVAL;
+ }
+
+ idx = v->get_dma_idx(dai_id);
+ if (idx < 0) {
+ dev_err(rtd->dev, "Invalid DMA index: %d\n", idx);
+ return -EINVAL;
+ }
+
+ return regmap_update_bits(drvdata->audio_qaif_map,
+ qaif_cif_intf_reg(v, idx, dai_id),
+ QAIF_CIF_INTF_ACTIVE_CH_MASK,
+ regval << QAIF_CIF_INTF_ACTIVE_CH_SHIFT);
+}
+
+static int qaif_cif_daiops_trigger(struct snd_pcm_substream *substream,
+ int cmd, struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
+ struct qaif_drv_data *drvdata = snd_soc_dai_get_drvdata(dai);
+ const struct qaif_variant *v = drvdata->variant;
+ unsigned int dai_id = dai->driver->id;
+ struct regmap *map = drvdata->audio_qaif_map;
+ u32 reg;
+ int idx, ret;
+
+ idx = v->get_dma_idx(dai_id);
+ if (idx < 0) {
+ dev_err(rtd->dev, "Invalid DMA index: %d\n", idx);
+ return -EINVAL;
+ }
+
+ reg = qaif_cif_intf_reg(v, idx, dai_id);
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ ret = regmap_update_bits(map, reg,
+ QAIF_CIF_INTF_DYNCLK_BIT,
+ QAIF_CIF_INTF_DYNCLK_BIT);
+ if (ret)
+ return ret;
+ ret = regmap_update_bits(map, reg, QAIF_CIF_INTF_FS_SEL_MASK, 0);
+ if (ret)
+ return ret;
+ return regmap_update_bits(map, reg,
+ QAIF_CIF_INTF_16BIT_UNPACK_BIT,
+ QAIF_CIF_INTF_16BIT_UNPACK_BIT);
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ ret = regmap_update_bits(map, reg, QAIF_CIF_INTF_DYNCLK_BIT, 0);
+ if (ret)
+ return ret;
+ return regmap_update_bits(map, reg,
+ QAIF_CIF_INTF_16BIT_UNPACK_BIT, 0);
+ default:
+ dev_err(rtd->dev, "invalid trigger cmd %d\n", cmd);
+ return -EINVAL;
+ }
+}
+
+static int qaif_cif_daiops_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct qaif_drv_data *drvdata = snd_soc_dai_get_drvdata(dai);
+ int ret;
+
+ ret = clk_prepare_enable(drvdata->aud_dma_clk);
+ if (ret) {
+ dev_err(dai->dev, "error enabling aud_dma clk: %d\n", ret);
+ return ret;
+ }
+
+ ret = clk_prepare_enable(drvdata->aud_dma_mem_clk);
+ if (ret) {
+ dev_err(dai->dev, "error enabling aud_dma_mem clk: %d\n", ret);
+ clk_disable_unprepare(drvdata->aud_dma_clk);
+ return ret;
+ }
+ return 0;
+}
+
+static void qaif_cif_daiops_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct qaif_drv_data *drvdata = snd_soc_dai_get_drvdata(dai);
+
+ clk_disable_unprepare(drvdata->aud_dma_mem_clk);
+ clk_disable_unprepare(drvdata->aud_dma_clk);
+}
+
+/*
+ * asoc_qcom_qaif_cif_dai_ops - DAI ops for QAIF CIF (CDC DMA) paths
+ *
+ * Provides startup, shutdown, hw_params and trigger callbacks for the
+ * Codec Interface DMA (CIF) DAI. startup/shutdown enable and disable the
+ * audio DMA clocks. Used by Shikra machine drivers for Bolero CDC DMA
+ * RX, TX and VA TX paths.
+ */
+const struct snd_soc_dai_ops asoc_qcom_qaif_cif_dai_ops = {
+ .startup = qaif_cif_daiops_startup,
+ .shutdown = qaif_cif_daiops_shutdown,
+ .hw_params = qaif_cif_daiops_hw_params,
+ .trigger = qaif_cif_daiops_trigger,
+};
+EXPORT_SYMBOL_GPL(asoc_qcom_qaif_cif_dai_ops);
+
+static int qaif_aif_cpu_daiops_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct qaif_drv_data *drvdata = snd_soc_dai_get_drvdata(dai);
+ const struct qaif_variant *v = drvdata->variant;
+ int idx, ret;
+
+ idx = v->get_dma_idx(dai->driver->id);
+ if (idx < 0) {
+ dev_err(dai->dev, "Invalid DMA index: %d\n", idx);
+ return -EINVAL;
+ }
+
+ ret = clk_prepare_enable(drvdata->aud_dma_clk);
+ if (ret) {
+ dev_err(dai->dev, "error enabling aud_dma clk: %d\n", ret);
+ return ret;
+ }
+
+ ret = clk_prepare_enable(drvdata->aud_dma_mem_clk);
+ if (ret) {
+ dev_err(dai->dev, "error enabling aud_dma_mem clk: %d\n", ret);
+ clk_disable_unprepare(drvdata->aud_dma_clk);
+ return ret;
+ }
+
+ ret = clk_prepare_enable(drvdata->mi2s_bit_clk[idx]);
+ if (ret) {
+ dev_err(dai->dev, "error enabling mi2s bit clk: %d\n", ret);
+ clk_disable_unprepare(drvdata->aud_dma_mem_clk);
+ clk_disable_unprepare(drvdata->aud_dma_clk);
+ }
+ return ret;
+}
+
+static void qaif_aif_cpu_daiops_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct qaif_drv_data *drvdata = snd_soc_dai_get_drvdata(dai);
+ const struct qaif_variant *v = drvdata->variant;
+ const struct qaif_aif_config *cfg;
+ unsigned int enable_bit;
+ int idx = v->get_dma_idx(dai->driver->id);
+ int ret;
+
+ if (idx < 0) {
+ dev_err(dai->dev, "Invalid DMA index: %d\n", idx);
+ return;
+ }
+
+ cfg = &drvdata->aif_intf_cfg[idx];
+ if (cfg->loopback_en)
+ enable_bit = QAIF_AIF_CTL_ENABLE_BIT;
+ else if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ enable_bit = QAIF_AIF_CTL_ENABLE_TX_BIT;
+ else
+ enable_bit = QAIF_AIF_CTL_ENABLE_RX_BIT;
+
+ ret = regmap_update_bits(drvdata->audio_qaif_map,
+ QAIF_AUD_INTF_CTL_REG(idx), enable_bit, 0);
+ if (ret)
+ dev_err(dai->dev, "error clearing AIF enable bit: %d\n", ret);
+
+ clk_disable_unprepare(drvdata->mi2s_bit_clk[idx]);
+ clk_disable_unprepare(drvdata->aud_dma_mem_clk);
+ clk_disable_unprepare(drvdata->aud_dma_clk);
+}
+
+static int qaif_aif_cpu_daiops_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct qaif_drv_data *drvdata = snd_soc_dai_get_drvdata(dai);
+ const struct qaif_variant *v = drvdata->variant;
+ const struct qaif_aif_config *cfg;
+ struct regmap *map = drvdata->audio_qaif_map;
+ snd_pcm_format_t format = params_format(params);
+ unsigned int channels = params_channels(params);
+ unsigned int slot_width;
+ int bitwidth, idx, ret;
+
+ idx = v->get_dma_idx(dai->driver->id);
+ if (idx < 0) {
+ dev_err(dai->dev, "Invalid DMA index: %d\n", idx);
+ return -EINVAL;
+ }
+
+ cfg = &drvdata->aif_intf_cfg[idx];
+
+ bitwidth = snd_pcm_format_width(format);
+ if (bitwidth < 0) {
+ dev_err(dai->dev, "invalid bit width given: %d\n", bitwidth);
+ return bitwidth;
+ }
+
+ /*
+ * The sync, lane and frame configuration and the MI2S bit clock are
+ * shared by both directions of an AIF. Concurrent playback and
+ * capture on the same interface are therefore expected to use a
+ * compatible format, rate and slot configuration.
+ */
+ ret = regmap_update_bits(map, QAIF_AUD_INTF_SYNC_CFG_REG(idx),
+ QAIF_AIF_SYNC_SRC_BIT |
+ QAIF_AIF_SYNC_MODE_MASK |
+ QAIF_AIF_SYNC_DELAY_MASK |
+ QAIF_AIF_SYNC_INV_BIT,
+ (cfg->sync_src ? QAIF_AIF_SYNC_SRC_BIT : 0) |
+ (cfg->sync_mode << QAIF_AIF_SYNC_MODE_SHIFT) |
+ (cfg->sync_delay << QAIF_AIF_SYNC_DELAY_SHIFT) |
+ (cfg->invert_sync ? QAIF_AIF_SYNC_INV_BIT : 0));
+ if (ret)
+ return ret;
+
+ ret = regmap_update_bits(map, QAIF_AUD_INTF_LANE_CFG_REG(idx),
+ QAIF_AIF_LANE_DIR_MASK |
+ QAIF_AIF_LANE_EN_MASK |
+ QAIF_AIF_CTRL_DATA_OE_BIT |
+ QAIF_AIF_LOOPBACK_EN_BIT,
+ cfg->lane_dir_mask |
+ (cfg->lane_en_mask << QAIF_AIF_LANE_EN_SHIFT) |
+ (cfg->ctrl_data_oe ? QAIF_AIF_CTRL_DATA_OE_BIT : 0) |
+ (cfg->loopback_en ? QAIF_AIF_LOOPBACK_EN_BIT : 0));
+ if (ret)
+ return ret;
+
+ ret = regmap_update_bits(map, QAIF_AUD_INTF_CFG_REG(idx),
+ QAIF_AIF_FULL_CYCLE_EN_BIT,
+ cfg->full_cycle_en ? QAIF_AIF_FULL_CYCLE_EN_BIT : 0);
+ if (ret)
+ return ret;
+
+ if (qaif_is_mi2s_port(dai->driver->id) && !cfg->slot_width) {
+ slot_width = bitwidth;
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ drvdata->aif_intf_cfg[idx].slot_en_tx_mask =
+ GENMASK(channels - 1, 0);
+ else
+ drvdata->aif_intf_cfg[idx].slot_en_rx_mask =
+ GENMASK(channels - 1, 0);
+ drvdata->aif_intf_cfg[idx].slot_num = QAIF_MI2S_SLOTS;
+ } else {
+ slot_width = cfg->slot_width;
+ if (!slot_width || !cfg->slot_num) {
+ dev_err(dai->dev, "invalid TDM slot config: width=%u num=%u\n",
+ slot_width, cfg->slot_num);
+ return -EINVAL;
+ }
+ }
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ ret = regmap_update_bits(map, QAIF_AUD_INTF_BIT_WIDTH_CFG_REG(idx),
+ QAIF_AIF_SLOT_WIDTH_TX_MASK |
+ QAIF_AIF_SAMPLE_WIDTH_TX_MASK,
+ QAIF_AIF_SLOT_WIDTH(slot_width) |
+ (QAIF_AIF_SAMPLE_WIDTH(bitwidth) <<
+ QAIF_AIF_SAMPLE_WIDTH_TX_SHIFT));
+ if (ret)
+ return ret;
+ ret = regmap_write(map, QAIF_AUD_INTF_ACTV_SLOT_EN_TX_REG(idx),
+ cfg->slot_en_tx_mask);
+ if (ret)
+ return ret;
+ ret = regmap_update_bits(map, QAIF_AUD_INTF_MI2S_CFG_REG(idx),
+ QAIF_AIF_MONO_MODE_TX_BIT,
+ (channels < 2) ? QAIF_AIF_MONO_MODE_TX_BIT : 0);
+ } else {
+ ret = regmap_update_bits(map, QAIF_AUD_INTF_BIT_WIDTH_CFG_REG(idx),
+ QAIF_AIF_SLOT_WIDTH_RX_MASK |
+ QAIF_AIF_SAMPLE_WIDTH_RX_MASK,
+ (QAIF_AIF_SLOT_WIDTH(slot_width) <<
+ QAIF_AIF_SLOT_WIDTH_RX_SHIFT) |
+ (QAIF_AIF_SAMPLE_WIDTH(bitwidth) <<
+ QAIF_AIF_SAMPLE_WIDTH_RX_SHIFT));
+ if (ret)
+ return ret;
+ ret = regmap_write(map, QAIF_AUD_INTF_ACTV_SLOT_EN_RX_REG(idx),
+ cfg->slot_en_rx_mask);
+ if (ret)
+ return ret;
+ ret = regmap_update_bits(map, QAIF_AUD_INTF_MI2S_CFG_REG(idx),
+ QAIF_AIF_MONO_MODE_RX_BIT,
+ (channels < 2) ? QAIF_AIF_MONO_MODE_RX_BIT : 0);
+ }
+ if (ret)
+ return ret;
+
+ ret = regmap_update_bits(map, QAIF_AUD_INTF_FRAME_CFG_REG(idx),
+ QAIF_AIF_BITS_PER_LANE_MASK,
+ (slot_width * cfg->slot_num) - 1);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int qaif_aif_cpu_daiops_trigger(struct snd_pcm_substream *substream,
+ int cmd, struct snd_soc_dai *dai)
+{
+ struct qaif_drv_data *drvdata = snd_soc_dai_get_drvdata(dai);
+ const struct qaif_variant *v = drvdata->variant;
+ const struct qaif_aif_config *cfg;
+ unsigned int enable_bit;
+ int idx, ret;
+
+ idx = v->get_dma_idx(dai->driver->id);
+ if (idx < 0) {
+ dev_err(dai->dev, "Invalid DMA index: %d\n", idx);
+ return -EINVAL;
+ }
+
+ cfg = &drvdata->aif_intf_cfg[idx];
+ if (cfg->loopback_en)
+ enable_bit = QAIF_AIF_CTL_ENABLE_BIT;
+ else if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ enable_bit = QAIF_AIF_CTL_ENABLE_TX_BIT;
+ else
+ enable_bit = QAIF_AIF_CTL_ENABLE_RX_BIT;
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ ret = regmap_update_bits(drvdata->audio_qaif_map,
+ QAIF_AUD_INTF_CTL_REG(idx), enable_bit, enable_bit);
+ if (ret)
+ dev_err(dai->dev, "error setting AIF enable bit: %d\n", ret);
+ return ret;
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ ret = regmap_update_bits(drvdata->audio_qaif_map,
+ QAIF_AUD_INTF_CTL_REG(idx), enable_bit, 0);
+ if (ret)
+ dev_err(dai->dev, "error clearing AIF enable bit: %d\n", ret);
+ return ret;
+ default:
+ dev_err(dai->dev, "invalid trigger cmd %d\n", cmd);
+ return -EINVAL;
+ }
+}
+
+static int qaif_aif_cpu_daiops_set_tdm_slot(struct snd_soc_dai *dai,
+ unsigned int tx_mask,
+ unsigned int rx_mask, int slots,
+ int slot_width)
+{
+ struct qaif_drv_data *drvdata = snd_soc_dai_get_drvdata(dai);
+ const struct qaif_variant *v = drvdata->variant;
+ int idx = v->get_dma_idx(dai->driver->id);
+ struct qaif_aif_config *cfg;
+
+ if (idx < 0)
+ return -EINVAL;
+
+ if (slots <= 0 || slot_width <= 0)
+ return -EINVAL;
+
+ if (slot_width > QAIF_AIF_SLOT_WIDTH_MAX ||
+ slots * slot_width > QAIF_AIF_FRAME_BITS_MAX)
+ return -EINVAL;
+
+ cfg = &drvdata->aif_intf_cfg[idx];
+ cfg->slot_num = slots;
+ cfg->slot_width = slot_width;
+ cfg->slot_en_tx_mask = tx_mask;
+ cfg->slot_en_rx_mask = rx_mask;
+
+ return 0;
+}
+
+static int qaif_aif_cpu_daiops_set_sysclk(struct snd_soc_dai *dai,
+ int clk_id, unsigned int freq,
+ int dir)
+{
+ struct qaif_drv_data *drvdata = snd_soc_dai_get_drvdata(dai);
+ const struct qaif_variant *v = drvdata->variant;
+ int idx = v->get_dma_idx(dai->driver->id);
+
+ if (idx < 0)
+ return -EINVAL;
+
+ /*
+ * The bit clock is prepared and enabled for the lifetime of the
+ * stream by startup()/shutdown(); only the rate is set here.
+ */
+ return clk_set_rate(drvdata->mi2s_bit_clk[idx], freq);
+}
+
+static int qaif_aif_cpu_daiops_set_fmt(struct snd_soc_dai *dai,
+ unsigned int fmt)
+{
+ struct qaif_drv_data *drvdata = snd_soc_dai_get_drvdata(dai);
+ const struct qaif_variant *v = drvdata->variant;
+ int idx = v->get_dma_idx(dai->driver->id);
+ struct qaif_aif_config *cfg;
+
+ if (idx < 0)
+ return -EINVAL;
+
+ cfg = &drvdata->aif_intf_cfg[idx];
+
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ cfg->sync_mode = QAIF_AIF_SYNC_MODE_LONG;
+ cfg->sync_delay = QAIF_AIF_SYNC_DELAY_ONE;
+ break;
+ case SND_SOC_DAIFMT_DSP_A:
+ cfg->sync_mode = QAIF_AIF_SYNC_MODE_ONE_SLOT;
+ cfg->sync_delay = QAIF_AIF_SYNC_DELAY_ONE;
+ break;
+ case SND_SOC_DAIFMT_DSP_B:
+ cfg->sync_mode = QAIF_AIF_SYNC_MODE_SHORT;
+ cfg->sync_delay = QAIF_AIF_SYNC_DELAY_SAME;
+ break;
+ default:
+ dev_err(dai->dev, "unsupported format 0x%x\n",
+ fmt & SND_SOC_DAIFMT_FORMAT_MASK);
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
+ case SND_SOC_DAIFMT_CBP_CFP:
+ cfg->sync_src = 1;
+ break;
+ case SND_SOC_DAIFMT_CBC_CFC:
+ cfg->sync_src = 0;
+ break;
+ default:
+ dev_err(dai->dev, "unsupported clock provider mode\n");
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ case SND_SOC_DAIFMT_NB_IF:
+ cfg->invert_sync = (fmt & SND_SOC_DAIFMT_INV_MASK) ==
+ SND_SOC_DAIFMT_NB_IF;
+ break;
+ default:
+ dev_err(dai->dev, "bit clock inversion is not supported\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/*
+ * asoc_qcom_qaif_aif_cpu_dai_ops - DAI ops for QAIF AIF (MI2S/TDM/PCM) paths
+ *
+ * Provides startup, shutdown, hw_params and trigger callbacks
+ * for the Unified Audio Interface (AIF) DAI. Used by Shikra machine
+ * drivers for MI2S, TDM and PCM serial audio paths.
+ */
+const struct snd_soc_dai_ops asoc_qcom_qaif_aif_cpu_dai_ops = {
+ .set_fmt = qaif_aif_cpu_daiops_set_fmt,
+ .set_tdm_slot = qaif_aif_cpu_daiops_set_tdm_slot,
+ .set_sysclk = qaif_aif_cpu_daiops_set_sysclk,
+ .startup = qaif_aif_cpu_daiops_startup,
+ .shutdown = qaif_aif_cpu_daiops_shutdown,
+ .hw_params = qaif_aif_cpu_daiops_hw_params,
+ .trigger = qaif_aif_cpu_daiops_trigger,
+};
+EXPORT_SYMBOL_GPL(asoc_qcom_qaif_aif_cpu_dai_ops);
+
+static const struct snd_soc_component_driver qaif_cpu_comp_driver = {
+ .name = "qaif-cpu",
+};
+
+static const struct regmap_config audio_qaif_regmap_config = {
+ .name = "audio_qaif_cpu",
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .cache_type = REGCACHE_NONE,
+};
+
+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;
+ int ret;
+ u32 dai_id;
+ int intf_idx;
+ int num_interfaces = 0;
+ u32 val_buf[QAIF_MAX_LANES];
+ int j, n;
+ unsigned long configured_intf_mask = 0;
+
+ for_each_child_of_node(np, intf_np) {
+ if (!of_property_present(intf_np, "reg"))
+ 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 %pOFn\n", intf_np);
+ of_node_put(intf_np);
+ return ret;
+ }
+
+ intf_idx = v->get_dma_idx(dai_id);
+ if (intf_idx < 0) {
+ dev_err(dev, "Invalid DAI ID %d for interface %pOFn\n",
+ dai_id, intf_np);
+ of_node_put(intf_np);
+ return -EINVAL;
+ }
+ 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);
+ of_node_put(intf_np);
+ return -EINVAL;
+ }
+
+ if (configured_intf_mask & BIT(intf_idx)) {
+ dev_err(dev, "Duplicate reg %d for interface %pOFn\n",
+ dai_id, intf_np);
+ of_node_put(intf_np);
+ return -EINVAL;
+ }
+ configured_intf_mask |= BIT(intf_idx);
+
+ cfg = &data->aif_intf_cfg[intf_idx];
+ if (v->aif_full_cycle_en)
+ cfg->full_cycle_en = v->aif_full_cycle_en[intf_idx];
+ if (v->aif_ctrl_data_oe)
+ cfg->ctrl_data_oe = v->aif_ctrl_data_oe[intf_idx];
+ if (v->aif_loopback_en)
+ cfg->loopback_en = v->aif_loopback_en[intf_idx];
+
+ switch (snd_soc_daifmt_parse_format(intf_np, NULL) &
+ SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ cfg->sync_mode = QAIF_AIF_SYNC_MODE_LONG;
+ cfg->sync_delay = QAIF_AIF_SYNC_DELAY_ONE;
+ cfg->invert_sync = true;
+ break;
+ case SND_SOC_DAIFMT_DSP_A:
+ cfg->sync_mode = QAIF_AIF_SYNC_MODE_ONE_SLOT;
+ cfg->sync_delay = QAIF_AIF_SYNC_DELAY_ONE;
+ break;
+ case SND_SOC_DAIFMT_DSP_B:
+ cfg->sync_mode = QAIF_AIF_SYNC_MODE_SHORT;
+ cfg->sync_delay = QAIF_AIF_SYNC_DELAY_SAME;
+ break;
+ default:
+ break;
+ }
+
+ if (!qaif_is_mi2s_port(dai_id)) {
+ ret = of_property_read_u32(intf_np, "dai-tdm-slot-width",
+ &cfg->slot_width);
+ if (ret || !cfg->slot_width) {
+ dev_err(dev, "Missing/invalid dai-tdm-slot-width for %pOFn\n",
+ intf_np);
+ of_node_put(intf_np);
+ return ret ? ret : -EINVAL;
+ }
+ ret = of_property_read_u32(intf_np, "dai-tdm-slot-num",
+ &cfg->slot_num);
+ if (ret || !cfg->slot_num) {
+ dev_err(dev, "Missing/invalid dai-tdm-slot-num for %pOFn\n",
+ intf_np);
+ of_node_put(intf_np);
+ return ret ? ret : -EINVAL;
+ }
+ snd_soc_of_get_slot_mask(intf_np, "dai-tdm-slot-rx-mask",
+ &cfg->slot_en_rx_mask);
+ snd_soc_of_get_slot_mask(intf_np, "dai-tdm-slot-tx-mask",
+ &cfg->slot_en_tx_mask);
+ if (!cfg->slot_en_rx_mask && !cfg->slot_en_tx_mask) {
+ dev_err(dev, "No active TDM slots for %pOFn\n",
+ intf_np);
+ of_node_put(intf_np);
+ return -EINVAL;
+ }
+ }
+
+ n = of_property_read_variable_u32_array(intf_np,
+ "qcom,qaif-aif-lane-map",
+ val_buf, 1, QAIF_MAX_LANES);
+ if (n < 0) {
+ dev_err(dev, "Missing qcom,qaif-aif-lane-map for %pOFn\n",
+ intf_np);
+ of_node_put(intf_np);
+ return n;
+ }
+ for (j = 0; j < n; j++) {
+ if (val_buf[j] > 1) {
+ dev_err(dev, "Invalid lane-map value %u for %pOFn\n",
+ val_buf[j], intf_np);
+ of_node_put(intf_np);
+ return -EINVAL;
+ }
+ cfg->lane_en_mask |= BIT(j);
+ if (val_buf[j])
+ cfg->lane_dir_mask |= BIT(j);
+ }
+
+ num_interfaces++;
+ }
+
+ return 0;
+}
+
+/**
+ * asoc_qcom_qaif_cpu_platform_probe - Probe the QAIF CPU and platform driver
+ * @pdev: Platform device
+ *
+ * Initialises the QAIF regmap, parses DT, sets up clocks and registers
+ * the CPU DAI component and PCM platform.
+ *
+ * Return: 0 on success, negative error code on failure.
+ */
+int asoc_qcom_qaif_cpu_platform_probe(struct platform_device *pdev)
+{
+ struct regmap_config regmap_cfg = audio_qaif_regmap_config;
+ 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;
+
+ drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
+ if (!drvdata)
+ return dev_err_probe(dev, -ENOMEM, "Failed to allocate driver data\n");
+ platform_set_drvdata(pdev, drvdata);
+
+ match = of_match_device(dev->driver->of_match_table, dev);
+ if (!match || !match->data)
+ return dev_err_probe(dev, -EINVAL, "No matching device data\n");
+
+ drvdata->variant = match->data;
+ variant = drvdata->variant;
+
+ if (!variant->get_dma_idx)
+ return dev_err_probe(dev, -EINVAL,
+ "variant is missing get_dma_idx callback\n");
+
+ ret = of_qaif_parse_aif_intf_cfg(dev, drvdata);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to parse aif interfaces\n");
+
+ drvdata->audio_qaif = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(drvdata->audio_qaif))
+ return dev_err_probe(dev, PTR_ERR(drvdata->audio_qaif),
+ "Failed to ioremap QAIF registers\n");
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return dev_err_probe(dev, -EINVAL, "Failed to get MMIO resource\n");
+
+ regmap_cfg.max_register = resource_size(res) - regmap_cfg.reg_stride;
+ drvdata->audio_qaif_map = devm_regmap_init_mmio(dev, drvdata->audio_qaif,
+ ®map_cfg);
+ if (IS_ERR(drvdata->audio_qaif_map))
+ return dev_err_probe(dev, PTR_ERR(drvdata->audio_qaif_map),
+ "Failed to init regmap\n");
+
+ drvdata->aud_dma_clk = devm_clk_get(dev, "aud_dma");
+ if (IS_ERR(drvdata->aud_dma_clk))
+ return dev_err_probe(dev, PTR_ERR(drvdata->aud_dma_clk),
+ "Failed to get aud_dma clock\n");
+
+ drvdata->aud_dma_mem_clk = devm_clk_get(dev, "aud_dma_mem");
+ if (IS_ERR(drvdata->aud_dma_mem_clk))
+ return dev_err_probe(dev, PTR_ERR(drvdata->aud_dma_mem_clk),
+ "Failed to get aud_dma_mem clock\n");
+
+ for (i = 0; i < variant->num_dai; i++) {
+ dai_id = variant->dai_driver[i].id;
+ if (qaif_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]))
+ return dev_err_probe(dev, PTR_ERR(drvdata->mi2s_bit_clk[idx]),
+ "Failed to get bit clock %d\n", idx);
+ }
+
+ drvdata->num_clks = variant->num_clks;
+ drvdata->clks = devm_kcalloc(dev, drvdata->num_clks,
+ sizeof(*drvdata->clks), GFP_KERNEL);
+ if (!drvdata->clks)
+ return dev_err_probe(dev, -ENOMEM, "Failed to allocate clocks\n");
+
+ for (i = 0; i < drvdata->num_clks; i++)
+ drvdata->clks[i].id = variant->clk_name[i];
+
+ ret = devm_clk_bulk_get(dev, drvdata->num_clks, drvdata->clks);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to get clocks\n");
+
+ ret = devm_pm_runtime_enable(dev);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to enable runtime PM\n");
+
+ ret = devm_snd_soc_register_component(dev, &qaif_cpu_comp_driver,
+ variant->dai_driver, variant->num_dai);
+ if (ret)
+ return dev_err_probe(dev, ret, "error registering cpu driver\n");
+
+ return asoc_qcom_qaif_platform_register(pdev);
+}
+EXPORT_SYMBOL_GPL(asoc_qcom_qaif_cpu_platform_probe);
+
+static int asoc_qcom_qaif_runtime_suspend(struct device *dev)
+{
+ struct qaif_drv_data *drvdata = dev_get_drvdata(dev);
+
+ clk_bulk_disable_unprepare(drvdata->num_clks, drvdata->clks);
+ return 0;
+}
+
+static int asoc_qcom_qaif_runtime_resume(struct device *dev)
+{
+ struct qaif_drv_data *drvdata = dev_get_drvdata(dev);
+
+ return clk_bulk_prepare_enable(drvdata->num_clks, drvdata->clks);
+}
+
+EXPORT_GPL_DEV_PM_OPS(asoc_qcom_qaif_pm_ops) = {
+ RUNTIME_PM_OPS(asoc_qcom_qaif_runtime_suspend,
+ asoc_qcom_qaif_runtime_resume, NULL)
+ SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume)
+};
+
+MODULE_DESCRIPTION("Qualcomm Audio Interface (QAIF) CPU DAI driver");
+MODULE_AUTHOR("Harendra Gautam <harendra.gautam@oss.qualcomm.com>");
+MODULE_LICENSE("GPL");
--
2.34.1
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PATCH v3 5/9] ASoC: soc-core: Add snd_soc_of_xlate_dai_name() generic helper
2026-08-24 6:36 [PATCH v3 0/9] ASoC: qcom: Add QAIF driver for Shikra audio platform Harendra Gautam
` (3 preceding siblings ...)
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 ` 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
` (3 subsequent siblings)
8 siblings, 1 reply; 32+ messages in thread
From: Harendra Gautam @ 2026-08-24 6:36 UTC (permalink / raw)
To: Srinivas Kandagatla
Cc: Mark Brown, Liam Girdwood, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Jaroslav Kysela, Takashi Iwai, linux-sound,
linux-arm-msm, devicetree, linux-kernel, Prasad Kumpatla,
Krzysztof Kozlowski, Sarath Ganapathiraju, Kumar Anurag Singh,
Mohammad Rafi Shaik
Add snd_soc_of_xlate_dai_name() to soc-core.c as a generic helper
that can be assigned directly to the .of_xlate_dai_name component
driver callback. It iterates the component's DAI list using
for_each_component_dais() and matches by DAI ID.
Use the helper in lpass-cpu.c and qaif-cpu.c, and remove the local
lpass implementation.
Signed-off-by: Harendra Gautam <harendra.gautam@oss.qualcomm.com>
---
include/sound/soc.h | 3 +++
sound/soc/qcom/lpass-cpu.c | 23 +----------------------
sound/soc/qcom/qaif-cpu.c | 1 +
sound/soc/soc-core.c | 33 +++++++++++++++++++++++++++++++++
4 files changed, 38 insertions(+), 22 deletions(-)
diff --git a/include/sound/soc.h b/include/sound/soc.h
index 10ad80f930c2..9d2b16a7ac2d 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -1329,6 +1329,9 @@ int snd_soc_of_parse_tdm_slot(struct device_node *np,
unsigned int *rx_mask,
unsigned int *slots,
unsigned int *slot_width);
+int snd_soc_of_xlate_dai_name(struct snd_soc_component *component,
+ const struct of_phandle_args *args,
+ const char **dai_name);
void snd_soc_of_parse_node_prefix(struct device_node *np,
struct snd_soc_codec_conf *codec_conf,
struct device_node *of_node,
diff --git a/sound/soc/qcom/lpass-cpu.c b/sound/soc/qcom/lpass-cpu.c
index 242bc16da36d..61efa45376cd 100644
--- a/sound/soc/qcom/lpass-cpu.c
+++ b/sound/soc/qcom/lpass-cpu.c
@@ -458,30 +458,9 @@ const struct snd_soc_dai_ops asoc_qcom_lpass_cpu_dai_ops2 = {
};
EXPORT_SYMBOL_GPL(asoc_qcom_lpass_cpu_dai_ops2);
-static int asoc_qcom_of_xlate_dai_name(struct snd_soc_component *component,
- const struct of_phandle_args *args,
- const char **dai_name)
-{
- struct lpass_data *drvdata = snd_soc_component_get_drvdata(component);
- const struct lpass_variant *variant = drvdata->variant;
- int id = args->args[0];
- int ret = -EINVAL;
- int i;
-
- for (i = 0; i < variant->num_dai; i++) {
- if (variant->dai_driver[i].id == id) {
- *dai_name = variant->dai_driver[i].name;
- ret = 0;
- break;
- }
- }
-
- return ret;
-}
-
static const struct snd_soc_component_driver lpass_cpu_comp_driver = {
.name = "lpass-cpu",
- .of_xlate_dai_name = asoc_qcom_of_xlate_dai_name,
+ .of_xlate_dai_name = snd_soc_of_xlate_dai_name,
.legacy_dai_naming = 1,
};
diff --git a/sound/soc/qcom/qaif-cpu.c b/sound/soc/qcom/qaif-cpu.c
index 8792d01254a6..384562dbd56a 100644
--- a/sound/soc/qcom/qaif-cpu.c
+++ b/sound/soc/qcom/qaif-cpu.c
@@ -596,6 +596,7 @@ EXPORT_SYMBOL_GPL(asoc_qcom_qaif_aif_cpu_dai_ops);
static const struct snd_soc_component_driver qaif_cpu_comp_driver = {
.name = "qaif-cpu",
+ .of_xlate_dai_name = snd_soc_of_xlate_dai_name,
};
static const struct regmap_config audio_qaif_regmap_config = {
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 7817beea5b3b..4b3efcd56b37 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -3040,6 +3040,39 @@ int snd_soc_of_parse_tdm_slot(struct device_node *np,
}
EXPORT_SYMBOL_GPL(snd_soc_of_parse_tdm_slot);
+/**
+ * snd_soc_of_xlate_dai_name - Resolve a sound-dai phandle argument to a
+ * DAI name by searching the component DAI list.
+ * @component: ASoC component to search.
+ * @args: Phandle arguments from the sound-dai property; args[0] is the
+ * DAI ID.
+ * @dai_name: Output pointer set to the matched DAI name on success.
+ *
+ * Return: 0 on success, -EINVAL if args_count != 1 or no match is found.
+ */
+int snd_soc_of_xlate_dai_name(struct snd_soc_component *component,
+ const struct of_phandle_args *args,
+ const char **dai_name)
+{
+ struct snd_soc_dai *dai;
+ int id;
+
+ if (args->args_count != 1)
+ return -EINVAL;
+
+ id = args->args[0];
+
+ for_each_component_dais(component, dai) {
+ if (dai->driver->id == id) {
+ *dai_name = snd_soc_dai_name_get(dai);
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(snd_soc_of_xlate_dai_name);
+
void snd_soc_dlc_use_cpu_as_platform(struct snd_soc_dai_link_component *platforms,
struct snd_soc_dai_link_component *cpus)
{
--
2.34.1
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PATCH v3 6/9] ASoC: qcom: Add QAIF PCM operations
2026-08-24 6:36 [PATCH v3 0/9] ASoC: qcom: Add QAIF driver for Shikra audio platform Harendra Gautam
` (4 preceding siblings ...)
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-24 6:36 ` Harendra Gautam
2026-08-24 9:25 ` Markus Elfring
2026-08-24 6:36 ` [PATCH v3 7/9] ASoC: qcom: Add QAIF IRQ handling, suspend/resume and platform register Harendra Gautam
` (2 subsequent siblings)
8 siblings, 1 reply; 32+ messages in thread
From: Harendra Gautam @ 2026-08-24 6:36 UTC (permalink / raw)
To: Srinivas Kandagatla
Cc: Mark Brown, Liam Girdwood, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Jaroslav Kysela, Takashi Iwai, linux-sound,
linux-arm-msm, devicetree, linux-kernel, Prasad Kumpatla,
Krzysztof Kozlowski, Sarath Ganapathiraju, Kumar Anurag Singh,
Mohammad Rafi Shaik
Allocate and map the DMA buffer in open(), reserve a stream DMA index
and perform the one-time QAIF hardware initialization. Program the DMA
configuration in hw_params(), set the DMA clock rate and program the
DMA base, buffer and period registers in prepare(), and report the
current DMA position from pointer(). Release all resources in close().
The DMA clocks themselves are prepared and enabled by the CPU DAI
driver's startup and shutdown callbacks.
Support mmap() for CIF and AIF paths, and add copy() to transfer PCM
data between userspace and the DMA buffer.
Signed-off-by: Harendra Gautam <harendra.gautam@oss.qualcomm.com>
---
sound/soc/qcom/qaif-platform.c | 544 +++++++++++++++++++++++++++++++++
1 file changed, 544 insertions(+)
create mode 100644 sound/soc/qcom/qaif-platform.c
diff --git a/sound/soc/qcom/qaif-platform.c b/sound/soc/qcom/qaif-platform.c
new file mode 100644
index 000000000000..4b4647641d11
--- /dev/null
+++ b/sound/soc/qcom/qaif-platform.c
@@ -0,0 +1,544 @@
+// 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/of.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include "qaif-reg.h"
+#include "qaif.h"
+
+#define DRV_NAME "qaif-platform"
+
+/* period: 5ms @ 48kHz/1ch/S16 min, 20ms @ 48kHz/8ch/S32 max */
+#define QAIF_PLATFORM_PERIOD_BYTES_MIN (48 * 5 * 1 * 2) /* 480 B */
+#define QAIF_PLATFORM_PERIOD_BYTES_MAX (48 * 20 * 8 * 4) /* 30720 B */
+#define QAIF_PLATFORM_PERIODS_MIN 2
+#define QAIF_PLATFORM_PERIODS_MAX 4
+/* QAIF_PLATFORM_PERIODS_MAX * QAIF_PLATFORM_PERIOD_BYTES_MAX = 122880 B */
+#define QAIF_PLATFORM_BUFFER_BYTES_MAX \
+ (QAIF_PLATFORM_PERIODS_MAX * QAIF_PLATFORM_PERIOD_BYTES_MAX)
+
+/* DMA CFG register bit positions */
+#define QAIF_DMACFG_SHRAM_WM_MASK GENMASK(11, 0)
+#define QAIF_DMACFG_BURST4_BIT BIT(18)
+#define QAIF_DMACFG_DYNCLK_BIT BIT(24)
+
+/* DMA CTL register bit positions */
+#define QAIF_DMACTL_ENABLE_BIT BIT(0)
+#define QAIF_ALL_CLIENTS_MASK (QAIF_BITMASK_AIF_RDDMA_WRDMA | \
+ QAIF_BITMASK_CIF_RDDMA_WRDMA)
+
+static const struct snd_pcm_hardware qaif_platform_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_BYTES_MAX,
+ .period_bytes_min = QAIF_PLATFORM_PERIOD_BYTES_MIN,
+ .period_bytes_max = QAIF_PLATFORM_PERIOD_BYTES_MAX,
+ .periods_min = QAIF_PLATFORM_PERIODS_MIN,
+ .periods_max = QAIF_PLATFORM_PERIODS_MAX,
+ .fifo_size = 0,
+};
+
+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;
+
+ ret = regmap_write(map, QAIF_EE_RDDMA_MAP_REG(v), GENMASK(v->num_rddma - 1, 0));
+ if (ret)
+ return ret;
+ ret = regmap_write(map, QAIF_EE_WRDMA_MAP_REG(v), GENMASK(v->num_wrdma - 1, 0));
+ if (ret)
+ return ret;
+ if (v->num_intf > 0) {
+ ret = regmap_write(map, QAIF_EE_INTF_MAP_REG(v), GENMASK(v->num_intf - 1, 0));
+ if (ret)
+ return ret;
+ }
+ ret = regmap_write(map, QAIF_EE_CODEC_RDDMA_MAP_REG(v),
+ GENMASK(v->num_codec_rddma - 1, 0));
+ if (ret)
+ return ret;
+ return regmap_write(map, QAIF_EE_CODEC_WRDMA_MAP_REG(v),
+ GENMASK(v->num_codec_wrdma - 1, 0));
+}
+
+static int qaif_map_dma_path(struct qaif_drv_data *drvdata)
+{
+ struct regmap *map = drvdata->audio_qaif_map;
+ int ret;
+
+ if (drvdata->variant->qxm_type != QAIF_QXM0) {
+ dev_err(regmap_get_device(map),
+ "only QXM0 is supported, qxm_type=%d\n",
+ drvdata->variant->qxm_type);
+ return -EINVAL;
+ }
+
+ ret = regmap_write(map, QAIF_RDDMA_MAP_QXM, QAIF_QXM0);
+ if (ret)
+ return ret;
+ ret = regmap_write(map, QAIF_WRDMA_MAP_QXM, QAIF_QXM0);
+ if (ret)
+ return ret;
+ ret = regmap_write(map, QAIF_CDC_RDDMA_MAP_QXM, QAIF_QXM0);
+ if (ret)
+ return ret;
+ return regmap_write(map, QAIF_CDC_WRDMA_MAP_QXM, QAIF_QXM0);
+}
+
+static int qaif_config_shram(struct qaif_drv_data *drvdata)
+{
+ const struct qaif_variant *v = drvdata->variant;
+ struct regmap *map = drvdata->audio_qaif_map;
+ u32 start_addr, shram_len;
+ int ret, i;
+
+ if (v->qxm_type != QAIF_QXM0) {
+ dev_err(regmap_get_device(map),
+ "only QXM0 is supported, qxm_type=%d\n",
+ 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_CDC_RDDMA_QXM0_SHRAM_ST_ADDR(i),
+ start_addr + (shram_len * i));
+ if (ret)
+ return ret;
+ ret = regmap_write(map, QAIF_CDC_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_CDC_WRDMA_QXM0_SHRAM_ST_ADDR(i),
+ start_addr + (shram_len * i));
+ if (ret)
+ return ret;
+ ret = regmap_write(map, QAIF_CDC_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;
+
+ if (drvdata->qaif_hw_configured)
+ return 0;
+
+ ret = qaif_config_shram(drvdata);
+ if (ret) {
+ dev_err(component->dev, "failed to config shram: %d\n", ret);
+ return ret;
+ }
+
+ ret = qaif_map_ee_resource(drvdata);
+ if (ret) {
+ dev_err(component->dev, "failed to map EE resources: %d\n", ret);
+ return ret;
+ }
+
+ ret = qaif_map_dma_path(drvdata);
+ if (ret)
+ return ret;
+
+ drvdata->qaif_hw_configured = true;
+ return 0;
+}
+
+static int qaif_platform_pcmops_open(struct snd_soc_component *component,
+ struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ 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);
+ const struct qaif_variant *v = drvdata->variant;
+ unsigned int dai_id = cpu_dai->driver->id;
+ struct snd_dma_buffer *buf = &substream->dma_buffer;
+ struct qaif_dma_mem_info *dma_mem_info;
+ struct qaif_pcm_data *data;
+ int ret, stream_dma_idx, dma_reg_idx, dir = substream->stream;
+
+ dma_reg_idx = v->get_dma_idx(dai_id);
+ if (dma_reg_idx < 0) {
+ dev_err(component->dev, "invalid DMA register index for DAI %u: %d\n",
+ dai_id, dma_reg_idx);
+ return dma_reg_idx;
+ }
+
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+ runtime->private_data = data;
+
+ buf->dev.dev = component->dev;
+ buf->private_data = NULL;
+ buf->dev.type = SNDRV_DMA_TYPE_DEV;
+
+ dma_mem_info = kzalloc(sizeof(*dma_mem_info), GFP_KERNEL);
+ if (!dma_mem_info) {
+ ret = -ENOMEM;
+ goto err_free_data;
+ }
+ dma_mem_info->alloc_size = qaif_platform_hardware.buffer_bytes_max;
+ dma_mem_info->vaddr = dma_alloc_coherent(component->dev,
+ dma_mem_info->alloc_size,
+ &dma_mem_info->dma_addr,
+ GFP_KERNEL);
+ if (!dma_mem_info->vaddr) {
+ ret = -ENOMEM;
+ goto err_free_mem_info;
+ }
+
+ mutex_lock(&drvdata->stream_lock);
+ if (!v->alloc_stream_dma_idx) {
+ ret = -EINVAL;
+ goto err_unlock;
+ }
+ stream_dma_idx = v->alloc_stream_dma_idx(drvdata, dir, dai_id);
+ if (stream_dma_idx < 0) {
+ ret = stream_dma_idx;
+ goto err_unlock;
+ }
+ mutex_unlock(&drvdata->stream_lock);
+
+ data->stream_dma_idx = stream_dma_idx;
+ data->dma_reg_idx = dma_reg_idx;
+
+ buf->bytes = qaif_platform_hardware.buffer_bytes_max;
+ buf->addr = dma_mem_info->dma_addr;
+ buf->area = (unsigned char *)dma_mem_info->vaddr;
+
+ if (qaif_is_cif_dma_port(dai_id)) {
+ WRITE_ONCE(drvdata->cif_substream[stream_dma_idx], substream);
+ drvdata->cif_dma_heap[stream_dma_idx] = dma_mem_info;
+ } else {
+ WRITE_ONCE(drvdata->aif_substream[stream_dma_idx], substream);
+ drvdata->aif_dma_heap[stream_dma_idx] = dma_mem_info;
+ }
+
+ snd_soc_set_runtime_hwparams(substream, &qaif_platform_hardware);
+ runtime->dma_bytes = qaif_platform_hardware.buffer_bytes_max;
+ snd_pcm_set_runtime_buffer(substream, buf);
+
+ /*
+ * The DMA buffer/period length registers are programmed in 64-bit
+ * (8-byte) words, so constrain buffer and period sizes to that step
+ * to keep the ALSA and hardware sizes identical.
+ */
+ ret = snd_pcm_hw_constraint_step(runtime, 0,
+ SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
+ BIT(QAIF_DMA_BYTES_TO_WORDS_SHIFT));
+ if (ret >= 0)
+ ret = snd_pcm_hw_constraint_step(runtime, 0,
+ SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
+ BIT(QAIF_DMA_BYTES_TO_WORDS_SHIFT));
+ if (ret >= 0)
+ ret = snd_pcm_hw_constraint_integer(runtime,
+ SNDRV_PCM_HW_PARAM_PERIODS);
+ if (ret < 0) {
+ dev_err(soc_runtime->dev, "setting constraints failed: %d\n", ret);
+ if (qaif_is_cif_dma_port(dai_id)) {
+ WRITE_ONCE(drvdata->cif_substream[stream_dma_idx], NULL);
+ drvdata->cif_dma_heap[stream_dma_idx] = NULL;
+ } else {
+ WRITE_ONCE(drvdata->aif_substream[stream_dma_idx], NULL);
+ drvdata->aif_dma_heap[stream_dma_idx] = NULL;
+ }
+ mutex_lock(&drvdata->stream_lock);
+ if (v->free_stream_dma_idx)
+ v->free_stream_dma_idx(drvdata, stream_dma_idx, dai_id);
+ mutex_unlock(&drvdata->stream_lock);
+ goto err_free_dma;
+ }
+ return 0;
+
+err_unlock:
+ mutex_unlock(&drvdata->stream_lock);
+err_free_dma:
+ dma_free_coherent(component->dev, dma_mem_info->alloc_size,
+ dma_mem_info->vaddr, dma_mem_info->dma_addr);
+err_free_mem_info:
+ kfree(dma_mem_info);
+err_free_data:
+ kfree(data);
+ return ret;
+}
+
+static int qaif_platform_pcmops_close(struct snd_soc_component *component,
+ struct snd_pcm_substream *substream)
+{
+ 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);
+ const struct qaif_variant *v = drvdata->variant;
+ struct qaif_pcm_data *data = substream->runtime->private_data;
+ struct qaif_dma_mem_info *dma_mem_info;
+ unsigned int dai_id = cpu_dai->driver->id;
+
+ if (qaif_is_cif_dma_port(dai_id)) {
+ WRITE_ONCE(drvdata->cif_substream[data->stream_dma_idx], NULL);
+ dma_mem_info = drvdata->cif_dma_heap[data->stream_dma_idx];
+ drvdata->cif_dma_heap[data->stream_dma_idx] = NULL;
+ } else {
+ WRITE_ONCE(drvdata->aif_substream[data->stream_dma_idx], NULL);
+ dma_mem_info = drvdata->aif_dma_heap[data->stream_dma_idx];
+ drvdata->aif_dma_heap[data->stream_dma_idx] = NULL;
+ }
+
+ mutex_lock(&drvdata->stream_lock);
+ if (v->free_stream_dma_idx)
+ v->free_stream_dma_idx(drvdata, data->stream_dma_idx, dai_id);
+ mutex_unlock(&drvdata->stream_lock);
+
+ if (dma_mem_info) {
+ dma_free_coherent(component->dev, dma_mem_info->alloc_size,
+ dma_mem_info->vaddr, dma_mem_info->dma_addr);
+ kfree(dma_mem_info);
+ }
+
+ snd_pcm_set_runtime_buffer(substream, NULL);
+ substream->runtime->private_data = NULL;
+
+ kfree(data);
+ return 0;
+}
+
+static int qaif_platform_pcmops_hw_params(struct snd_soc_component *component,
+ struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ 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);
+ const struct qaif_variant *v = drvdata->variant;
+ struct qaif_pcm_data *data = substream->runtime->private_data;
+ unsigned int dai_id = cpu_dai->driver->id;
+ int idx = data->dma_reg_idx;
+ int ret;
+
+ mutex_lock(&drvdata->stream_lock);
+ ret = qaif_init(component);
+ mutex_unlock(&drvdata->stream_lock);
+ if (ret) {
+ dev_err(soc_runtime->dev, "qaif_init failed: %d\n", ret);
+ return ret;
+ }
+
+ ret = regmap_update_bits(drvdata->audio_qaif_map,
+ qaif_dmacfg_reg(v, idx, substream->stream, dai_id),
+ QAIF_DMACFG_BURST4_BIT | QAIF_DMACFG_SHRAM_WM_MASK,
+ QAIF_DMACFG_BURST4_BIT | QAIF_DMACTL_WM_5);
+ if (ret)
+ dev_err(soc_runtime->dev, "error updating DMA CFG: %d\n", ret);
+ return ret;
+}
+
+static int qaif_platform_pcmops_hw_free(struct snd_soc_component *component,
+ struct snd_pcm_substream *substream)
+{
+ 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);
+ const struct qaif_variant *v = drvdata->variant;
+ struct qaif_pcm_data *data = substream->runtime->private_data;
+ unsigned int dai_id = cpu_dai->driver->id;
+ int idx = data->dma_reg_idx;
+ int ret;
+
+ ret = regmap_update_bits(drvdata->audio_qaif_map,
+ qaif_dmactl_reg(v, idx, substream->stream, dai_id),
+ QAIF_DMACTL_ENABLE_BIT, 0);
+ if (ret) {
+ dev_err(soc_runtime->dev, "error disabling DMA: %d\n", ret);
+ return ret;
+ }
+
+ ret = regmap_write(drvdata->audio_qaif_map,
+ qaif_dmacfg_reg(v, idx, substream->stream, dai_id), 0);
+ if (ret)
+ dev_err(soc_runtime->dev, "error clearing DMA CFG: %d\n", ret);
+ return ret;
+}
+
+static int qaif_platform_pcmops_prepare(struct snd_soc_component *component,
+ struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ 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);
+ const struct qaif_variant *v = drvdata->variant;
+ struct regmap *map = drvdata->audio_qaif_map;
+ struct qaif_pcm_data *data = runtime->private_data;
+ unsigned int dai_id = cpu_dai->driver->id;
+ int idx = data->dma_reg_idx;
+ int ret, dir = substream->stream;
+
+ ret = clk_set_rate(drvdata->aud_dma_clk, QAIF_DMA_CLOCK_FREQ);
+ if (ret) {
+ dev_err(soc_runtime->dev, "error setting aud_dma_clk rate: %d\n", ret);
+ return ret;
+ }
+ ret = clk_set_rate(drvdata->aud_dma_mem_clk, QAIF_DMA_CLOCK_FREQ);
+ if (ret) {
+ dev_err(soc_runtime->dev, "error setting aud_dma_mem_clk rate: %d\n", ret);
+ return ret;
+ }
+
+ ret = regmap_write(map, qaif_sid_map_reg(dir, dai_id), drvdata->smmu_csid_bits);
+ if (ret) {
+ dev_err(soc_runtime->dev, "error writing to SID MAP reg: %d\n", ret);
+ return ret;
+ }
+
+ ret = regmap_write(map, qaif_dmabase_reg(v, idx, dir, dai_id),
+ lower_32_bits(runtime->dma_addr));
+ if (ret) {
+ dev_err(soc_runtime->dev, "error writing to dma base reg: %d\n", ret);
+ return ret;
+ }
+
+ ret = regmap_write(map, qaif_dmabuff_reg(v, idx, dir, dai_id),
+ (snd_pcm_lib_buffer_bytes(substream) >>
+ QAIF_DMA_BYTES_TO_WORDS_SHIFT) - 1);
+ if (ret) {
+ dev_err(soc_runtime->dev, "error writing to dma buf reg: %d\n", ret);
+ return ret;
+ }
+
+ ret = regmap_write(map, qaif_dmaper_len_reg(v, idx, dir, dai_id),
+ (snd_pcm_lib_period_bytes(substream) >>
+ QAIF_DMA_BYTES_TO_WORDS_SHIFT) - 1);
+ if (ret)
+ dev_err(soc_runtime->dev, "error writing to dma period reg: %d\n", ret);
+ return ret;
+}
+
+static snd_pcm_uframes_t qaif_platform_pcmops_pointer(struct snd_soc_component *component,
+ struct snd_pcm_substream *substream)
+{
+ 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);
+ const struct qaif_variant *v = drvdata->variant;
+ struct regmap *map = drvdata->audio_qaif_map;
+ struct qaif_pcm_data *data = substream->runtime->private_data;
+ unsigned int dai_id = cpu_dai->driver->id;
+ unsigned int base_addr, curr_addr;
+ int idx = data->dma_reg_idx;
+ int ret, dir = substream->stream;
+
+ ret = regmap_read(map, qaif_dmabase_reg(v, idx, dir, dai_id), &base_addr);
+ if (ret) {
+ dev_err(soc_runtime->dev, "error reading from rdmabase reg: %d\n", ret);
+ return SNDRV_PCM_POS_XRUN;
+ }
+
+ ret = regmap_read(map, qaif_dmacurr_reg(v, idx, dir, dai_id), &curr_addr);
+ if (ret) {
+ dev_err(soc_runtime->dev, "error reading from rdmacurr reg: %d\n", ret);
+ return SNDRV_PCM_POS_XRUN;
+ }
+
+ return bytes_to_frames(substream->runtime,
+ (curr_addr - base_addr) %
+ snd_pcm_lib_buffer_bytes(substream));
+}
+
+static int qaif_platform_pcmops_mmap(struct snd_soc_component *component,
+ struct snd_pcm_substream *substream,
+ struct vm_area_struct *vma)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+
+ return dma_mmap_coherent(component->dev, vma,
+ runtime->dma_area, runtime->dma_addr,
+ runtime->dma_bytes);
+}
+
+static int qaif_platform_copy(struct snd_soc_component *component,
+ struct snd_pcm_substream *substream,
+ int channel, unsigned long pos,
+ struct iov_iter *buf, unsigned long bytes)
+{
+ struct snd_pcm_runtime *rt = substream->runtime;
+ size_t buffer_bytes = snd_pcm_lib_buffer_bytes(substream);
+ size_t channel_bytes = buffer_bytes / rt->channels;
+ unsigned long offset;
+ void *dma_buf;
+ size_t copied;
+
+ if (channel < 0 || channel >= rt->channels)
+ return -EINVAL;
+
+ /* Absolute byte offset into the configured (not the max) buffer. */
+ offset = pos + channel * channel_bytes;
+ if (offset > buffer_bytes || bytes > buffer_bytes - offset)
+ return -EINVAL;
+
+ dma_buf = rt->dma_area + offset;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ copied = copy_from_iter(dma_buf, bytes, buf);
+ else
+ copied = copy_to_iter(dma_buf, bytes, buf);
+
+ return (copied != bytes) ? -EFAULT : 0;
+}
--
2.34.1
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PATCH v3 7/9] ASoC: qcom: Add QAIF IRQ handling, suspend/resume and platform register
2026-08-24 6:36 [PATCH v3 0/9] ASoC: qcom: Add QAIF driver for Shikra audio platform Harendra Gautam
` (5 preceding siblings ...)
2026-08-24 6:36 ` [PATCH v3 6/9] ASoC: qcom: Add QAIF PCM operations Harendra Gautam
@ 2026-08-24 6:36 ` Harendra Gautam
2026-08-24 6:36 ` [PATCH v3 8/9] ASoC: qcom: Add Shikra QAIF support Harendra Gautam
2026-08-24 6:36 ` [PATCH v3 9/9] MAINTAINERS: Add Qualcomm QAIF driver entry Harendra Gautam
8 siblings, 0 replies; 32+ messages in thread
From: Harendra Gautam @ 2026-08-24 6:36 UTC (permalink / raw)
To: Srinivas Kandagatla
Cc: Mark Brown, Liam Girdwood, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Jaroslav Kysela, Takashi Iwai, linux-sound,
linux-arm-msm, devicetree, linux-kernel, Prasad Kumpatla,
Krzysztof Kozlowski, Sarath Ganapathiraju, Kumar Anurag Singh,
Mohammad Rafi Shaik
Register the ASoC component, request the QAIF interrupt and add trigger
handling to enable or disable DMA and its interrupt sources. Dispatch the
top-level IRQ status to the AIF and CIF DMA handlers, report period elapsed
events to ALSA, warn on xrun conditions and stop the stream on bus errors.
Signed-off-by: Harendra Gautam <harendra.gautam@oss.qualcomm.com>
---
sound/soc/qcom/qaif-platform.c | 391 +++++++++++++++++++++++++++++++++
1 file changed, 391 insertions(+)
diff --git a/sound/soc/qcom/qaif-platform.c b/sound/soc/qcom/qaif-platform.c
index 4b4647641d11..2e5dc5b081cd 100644
--- a/sound/soc/qcom/qaif-platform.c
+++ b/sound/soc/qcom/qaif-platform.c
@@ -542,3 +542,394 @@ static int qaif_platform_copy(struct snd_soc_component *component,
return (copied != bytes) ? -EFAULT : 0;
}
+
+static int qaif_platform_irq_op(struct qaif_drv_data *drvdata, int dir,
+ enum qaif_irq_type irq_type, int idx,
+ enum qaif_irq_op op)
+{
+ const struct qaif_variant *v = drvdata->variant;
+ struct regmap *map = drvdata->audio_qaif_map;
+ unsigned int bit = BIT(idx);
+ unsigned int val = op == QAIF_IRQ_ENABLE ? bit : 0;
+ u32 per_reg, err_reg, xrun_reg;
+ int ret;
+
+ if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
+ per_reg = op == QAIF_IRQ_CLEAR ? QAIF_EE_RDDMA_PERIOD_IRQ_CLR_REG(v, irq_type)
+ : QAIF_EE_RDDMA_PERIOD_IRQ_EN_REG(v, irq_type);
+ xrun_reg = op == QAIF_IRQ_CLEAR ? QAIF_EE_RDDMA_UF_IRQ_CLR_REG(v, irq_type)
+ : QAIF_EE_RDDMA_UF_IRQ_EN_REG(v, irq_type);
+ err_reg = op == QAIF_IRQ_CLEAR ? QAIF_EE_RDDMA_ERR_RSP_IRQ_CLR_REG(v, irq_type)
+ : QAIF_EE_RDDMA_ERR_RSP_IRQ_EN_REG(v, irq_type);
+ } else {
+ per_reg = op == QAIF_IRQ_CLEAR ? QAIF_EE_WRDMA_PERIOD_IRQ_CLR_REG(v, irq_type)
+ : QAIF_EE_WRDMA_PERIOD_IRQ_EN_REG(v, irq_type);
+ xrun_reg = op == QAIF_IRQ_CLEAR ? QAIF_EE_WRDMA_OF_IRQ_CLR_REG(v, irq_type)
+ : QAIF_EE_WRDMA_OF_IRQ_EN_REG(v, irq_type);
+ err_reg = op == QAIF_IRQ_CLEAR ? QAIF_EE_WRDMA_ERR_RSP_IRQ_CLR_REG(v, irq_type)
+ : QAIF_EE_WRDMA_ERR_RSP_IRQ_EN_REG(v, irq_type);
+ }
+
+ if (op == QAIF_IRQ_CLEAR) {
+ ret = regmap_write(map, per_reg, bit);
+ if (ret)
+ return ret;
+ ret = regmap_write(map, xrun_reg, bit);
+ if (ret)
+ return ret;
+ return regmap_write(map, err_reg, bit);
+ }
+
+ ret = regmap_write_bits(map, per_reg, bit, val);
+ if (ret)
+ return ret;
+ ret = regmap_write_bits(map, xrun_reg, bit, val);
+ if (ret)
+ return ret;
+ return regmap_write_bits(map, err_reg, bit, val);
+}
+
+static int qaif_platform_pcmops_trigger(struct snd_soc_component *component,
+ struct snd_pcm_substream *substream,
+ int cmd)
+{
+ 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);
+ const struct qaif_variant *v = drvdata->variant;
+ struct qaif_pcm_data *data = substream->runtime->private_data;
+ unsigned int dai_id = cpu_dai->driver->id;
+ enum qaif_irq_type irq_type = qaif_is_cif_dma_port(dai_id) ? QAIF_CIF_IRQ : QAIF_AIF_IRQ;
+ struct regmap *map = drvdata->audio_qaif_map;
+ int idx = data->dma_reg_idx;
+ int ret;
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ ret = qaif_platform_irq_op(drvdata, substream->stream, irq_type,
+ idx, QAIF_IRQ_CLEAR);
+ if (ret) {
+ dev_err(soc_runtime->dev, "error clearing irq regs: %d\n", ret);
+ return ret;
+ }
+ ret = regmap_update_bits(map,
+ qaif_dmacfg_reg(v, idx, substream->stream, dai_id),
+ QAIF_DMACFG_DYNCLK_BIT, QAIF_DMACFG_DYNCLK_BIT);
+ if (ret) {
+ dev_err(soc_runtime->dev, "error enabling dma_dynclk: %d\n", ret);
+ return ret;
+ }
+ ret = regmap_update_bits(map,
+ qaif_dmactl_reg(v, idx, substream->stream, dai_id),
+ QAIF_DMACTL_ENABLE_BIT, QAIF_DMACTL_ENABLE_BIT);
+ if (ret) {
+ dev_err(soc_runtime->dev, "error enabling DMA: %d\n", ret);
+ return ret;
+ }
+ ret = qaif_platform_irq_op(drvdata, substream->stream, irq_type,
+ idx, QAIF_IRQ_ENABLE);
+ if (ret)
+ dev_err(soc_runtime->dev, "error enabling irq regs: %d\n", ret);
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ ret = regmap_update_bits(map,
+ qaif_dmactl_reg(v, idx, substream->stream, dai_id),
+ QAIF_DMACTL_ENABLE_BIT, 0);
+ if (ret) {
+ dev_err(soc_runtime->dev, "error disabling DMA: %d\n", ret);
+ return ret;
+ }
+ ret = regmap_update_bits(map,
+ qaif_dmacfg_reg(v, idx, substream->stream, dai_id),
+ QAIF_DMACFG_DYNCLK_BIT, 0);
+ if (ret)
+ dev_err(soc_runtime->dev, "error disabling dma_dynclk: %d\n", ret);
+ ret = qaif_platform_irq_op(drvdata, substream->stream, irq_type,
+ idx, QAIF_IRQ_DISABLE);
+ if (ret)
+ dev_err(soc_runtime->dev, "error disabling irq regs: %d\n", ret);
+ break;
+ default:
+ return -EINVAL;
+ }
+ return ret;
+}
+
+static int qaif_platform_pcmops_sync_stop(struct snd_soc_component *component,
+ struct snd_pcm_substream *substream)
+{
+ 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_pcm_data *data = substream->runtime->private_data;
+ unsigned int dai_id = cpu_dai->driver->id;
+ enum qaif_irq_type irq_type = qaif_is_cif_dma_port(dai_id) ? QAIF_CIF_IRQ : QAIF_AIF_IRQ;
+ int idx = data->dma_reg_idx;
+ int ret;
+
+ synchronize_irq(drvdata->audio_qaif_irq);
+ ret = qaif_platform_irq_op(drvdata, substream->stream, irq_type,
+ idx, QAIF_IRQ_CLEAR);
+ if (ret)
+ dev_err(soc_runtime->dev, "error clearing irq regs: %d\n", ret);
+ return ret;
+}
+
+static irqreturn_t qaif_process_dma_irq(struct qaif_drv_data *drvdata,
+ u32 stat_reg_addr,
+ u32 clr_reg_addr,
+ enum qaif_irq_type irq_type,
+ enum qaif_dma_dir dma_type,
+ enum qaif_irq irq,
+ struct snd_pcm_substream **substream)
+{
+ const struct qaif_variant *v = drvdata->variant;
+ unsigned int reg = 0;
+ int dma_idx, stream_dma_idx, rv, num_dma, stream_offset, array_size;
+ u32 mask;
+ struct snd_pcm_substream *ss;
+
+ stream_offset = (dma_type == QAIF_DMA_WRDMA) ?
+ ((irq_type == QAIF_AIF_IRQ) ? v->wrdma_start : v->codec_wrdma_start) : 0;
+ num_dma = (dma_type == QAIF_DMA_WRDMA) ?
+ ((irq_type == QAIF_AIF_IRQ) ? v->num_wrdma : v->num_codec_wrdma) :
+ ((irq_type == QAIF_AIF_IRQ) ? v->num_rddma : v->num_codec_rddma);
+ if (!num_dma)
+ return IRQ_NONE;
+
+ array_size = (irq_type == QAIF_AIF_IRQ) ?
+ QAIF_MAX_AIF_DMA_IDX : QAIF_MAX_CIF_DMA_IDX;
+ if (stream_offset + num_dma > array_size) {
+ dev_err(regmap_get_device(drvdata->audio_qaif_map),
+ "DMA index range %d+%d exceeds substream table %d\n",
+ stream_offset, num_dma, array_size);
+ return IRQ_NONE;
+ }
+ mask = GENMASK(num_dma - 1, 0);
+
+ rv = regmap_read(drvdata->audio_qaif_map, stat_reg_addr, ®);
+ if (rv) {
+ dev_err_ratelimited(regmap_get_device(drvdata->audio_qaif_map),
+ "error reading stat reg 0x%x: %d\n", stat_reg_addr, rv);
+ return IRQ_NONE;
+ }
+
+ if (!(reg & mask)) {
+ dev_warn_ratelimited(regmap_get_device(drvdata->audio_qaif_map),
+ "spurious IRQ: stat reg 0x%x status 0x%x mask 0x%x\n",
+ stat_reg_addr, reg, mask);
+ return IRQ_NONE;
+ }
+
+ if (regmap_write(drvdata->audio_qaif_map, clr_reg_addr, reg & mask))
+ return IRQ_NONE;
+
+ for (dma_idx = 0; dma_idx < num_dma; dma_idx++) {
+ stream_dma_idx = dma_idx + stream_offset;
+ ss = READ_ONCE(substream[stream_dma_idx]);
+ if (!(reg & BIT(dma_idx)) || !ss)
+ continue;
+ switch (irq) {
+ case QAIF_IRQ_PERIOD:
+ snd_pcm_period_elapsed(ss);
+ break;
+ case QAIF_IRQ_OVERFLOW:
+ case QAIF_IRQ_UNDERFLOW:
+ dev_warn_ratelimited(regmap_get_device(drvdata->audio_qaif_map),
+ "QAIF DMA xRun\n");
+ snd_pcm_stop_xrun(ss);
+ break;
+ case QAIF_IRQ_ERROR:
+ snd_pcm_stop_xrun(ss);
+ dev_err_ratelimited(regmap_get_device(drvdata->audio_qaif_map),
+ "QAIF bus error\n");
+ break;
+ }
+ }
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t qaif_aif_irq_handler(struct qaif_drv_data *drvdata, u32 status)
+{
+ const struct qaif_variant *v = drvdata->variant;
+ struct snd_pcm_substream **ss = drvdata->aif_substream;
+ irqreturn_t ret = IRQ_NONE;
+
+ if (status & QAIF_SUMMARY_BITMASK_AIF_PERIOD_RDDMA)
+ ret |= qaif_process_dma_irq(drvdata,
+ QAIF_EE_RDDMA_PERIOD_IRQ_STAT_REG(v, QAIF_AIF_IRQ),
+ QAIF_EE_RDDMA_PERIOD_IRQ_CLR_REG(v, QAIF_AIF_IRQ),
+ QAIF_AIF_IRQ, QAIF_DMA_RDDMA, QAIF_IRQ_PERIOD, ss);
+ if (status & QAIF_SUMMARY_BITMASK_AIF_PERIOD_WRDMA)
+ ret |= qaif_process_dma_irq(drvdata,
+ QAIF_EE_WRDMA_PERIOD_IRQ_STAT_REG(v, QAIF_AIF_IRQ),
+ QAIF_EE_WRDMA_PERIOD_IRQ_CLR_REG(v, QAIF_AIF_IRQ),
+ QAIF_AIF_IRQ, QAIF_DMA_WRDMA, QAIF_IRQ_PERIOD, ss);
+ if (status & QAIF_SUMMARY_BITMASK_AIF_OVERFLOW_WRDMA)
+ ret |= qaif_process_dma_irq(drvdata,
+ QAIF_EE_WRDMA_OF_IRQ_STAT_REG(v, QAIF_AIF_IRQ),
+ QAIF_EE_WRDMA_OF_IRQ_CLR_REG(v, QAIF_AIF_IRQ),
+ QAIF_AIF_IRQ, QAIF_DMA_WRDMA, QAIF_IRQ_OVERFLOW, ss);
+ if (status & QAIF_SUMMARY_BITMASK_AIF_UNDERFLOW_RDDMA)
+ ret |= qaif_process_dma_irq(drvdata,
+ QAIF_EE_RDDMA_UF_IRQ_STAT_REG(v, QAIF_AIF_IRQ),
+ QAIF_EE_RDDMA_UF_IRQ_CLR_REG(v, QAIF_AIF_IRQ),
+ QAIF_AIF_IRQ, QAIF_DMA_RDDMA, QAIF_IRQ_UNDERFLOW, ss);
+ if (status & QAIF_SUMMARY_BITMASK_AIF_ERR_RSP_RDDMA)
+ ret |= qaif_process_dma_irq(drvdata,
+ QAIF_EE_RDDMA_ERR_RSP_IRQ_STAT_REG(v, QAIF_AIF_IRQ),
+ QAIF_EE_RDDMA_ERR_RSP_IRQ_CLR_REG(v, QAIF_AIF_IRQ),
+ QAIF_AIF_IRQ, QAIF_DMA_RDDMA, QAIF_IRQ_ERROR, ss);
+ if (status & QAIF_SUMMARY_BITMASK_AIF_ERR_RSP_WRDMA)
+ ret |= qaif_process_dma_irq(drvdata,
+ QAIF_EE_WRDMA_ERR_RSP_IRQ_STAT_REG(v, QAIF_AIF_IRQ),
+ QAIF_EE_WRDMA_ERR_RSP_IRQ_CLR_REG(v, QAIF_AIF_IRQ),
+ QAIF_AIF_IRQ, QAIF_DMA_WRDMA, QAIF_IRQ_ERROR, ss);
+ return ret;
+}
+
+static irqreturn_t qaif_cif_irq_handler(struct qaif_drv_data *drvdata, u32 status)
+{
+ const struct qaif_variant *v = drvdata->variant;
+ struct snd_pcm_substream **ss = drvdata->cif_substream;
+ irqreturn_t ret = IRQ_NONE;
+
+ if (status & QAIF_SUMMARY_BITMASK_CIF_PERIOD_RDDMA)
+ ret |= qaif_process_dma_irq(drvdata,
+ QAIF_EE_RDDMA_PERIOD_IRQ_STAT_REG(v, QAIF_CIF_IRQ),
+ QAIF_EE_RDDMA_PERIOD_IRQ_CLR_REG(v, QAIF_CIF_IRQ),
+ QAIF_CIF_IRQ, QAIF_DMA_RDDMA, QAIF_IRQ_PERIOD, ss);
+ if (status & QAIF_SUMMARY_BITMASK_CIF_PERIOD_WRDMA)
+ ret |= qaif_process_dma_irq(drvdata,
+ QAIF_EE_WRDMA_PERIOD_IRQ_STAT_REG(v, QAIF_CIF_IRQ),
+ QAIF_EE_WRDMA_PERIOD_IRQ_CLR_REG(v, QAIF_CIF_IRQ),
+ QAIF_CIF_IRQ, QAIF_DMA_WRDMA, QAIF_IRQ_PERIOD, ss);
+ if (status & QAIF_SUMMARY_BITMASK_CIF_OVERFLOW_WRDMA)
+ ret |= qaif_process_dma_irq(drvdata,
+ QAIF_EE_WRDMA_OF_IRQ_STAT_REG(v, QAIF_CIF_IRQ),
+ QAIF_EE_WRDMA_OF_IRQ_CLR_REG(v, QAIF_CIF_IRQ),
+ QAIF_CIF_IRQ, QAIF_DMA_WRDMA, QAIF_IRQ_OVERFLOW, ss);
+ if (status & QAIF_SUMMARY_BITMASK_CIF_UNDERFLOW_RDDMA)
+ ret |= qaif_process_dma_irq(drvdata,
+ QAIF_EE_RDDMA_UF_IRQ_STAT_REG(v, QAIF_CIF_IRQ),
+ QAIF_EE_RDDMA_UF_IRQ_CLR_REG(v, QAIF_CIF_IRQ),
+ QAIF_CIF_IRQ, QAIF_DMA_RDDMA, QAIF_IRQ_UNDERFLOW, ss);
+ if (status & QAIF_SUMMARY_BITMASK_CIF_ERR_RSP_RDDMA)
+ ret |= qaif_process_dma_irq(drvdata,
+ QAIF_EE_RDDMA_ERR_RSP_IRQ_STAT_REG(v, QAIF_CIF_IRQ),
+ QAIF_EE_RDDMA_ERR_RSP_IRQ_CLR_REG(v, QAIF_CIF_IRQ),
+ QAIF_CIF_IRQ, QAIF_DMA_RDDMA, QAIF_IRQ_ERROR, ss);
+ if (status & QAIF_SUMMARY_BITMASK_CIF_ERR_RSP_WRDMA)
+ ret |= qaif_process_dma_irq(drvdata,
+ QAIF_EE_WRDMA_ERR_RSP_IRQ_STAT_REG(v, QAIF_CIF_IRQ),
+ QAIF_EE_WRDMA_ERR_RSP_IRQ_CLR_REG(v, QAIF_CIF_IRQ),
+ QAIF_CIF_IRQ, QAIF_DMA_WRDMA, QAIF_IRQ_ERROR, ss);
+ return ret;
+}
+
+static const struct qaif_irq_map qaif_irq_clients[] = {
+ { QAIF_CLIENT_ID_AIF_DMA, QAIF_BITMASK_AIF_RDDMA_WRDMA, qaif_aif_irq_handler },
+ { QAIF_CLIENT_ID_CIF_DMA, QAIF_BITMASK_CIF_RDDMA_WRDMA, qaif_cif_irq_handler },
+};
+
+static irqreturn_t asoc_platform_qaif_irq(int irq, void *data)
+{
+ struct qaif_drv_data *drvdata = data;
+ const struct qaif_variant *v = drvdata->variant;
+ u32 summary_irq_status;
+ int rv, client;
+ irqreturn_t ret = IRQ_NONE;
+
+ rv = regmap_read(drvdata->audio_qaif_map, QAIF_SUMMARY_IRQSTAT_REG(v),
+ &summary_irq_status);
+ if (rv) {
+ dev_err(regmap_get_device(drvdata->audio_qaif_map),
+ "error reading from irqstat reg: %d\n", rv);
+ return IRQ_NONE;
+ }
+
+ if (!(summary_irq_status & QAIF_ALL_CLIENTS_MASK))
+ return IRQ_NONE;
+
+ for (client = 0; client < ARRAY_SIZE(qaif_irq_clients); client++) {
+ if (summary_irq_status & qaif_irq_clients[client].mask)
+ ret |= qaif_irq_clients[client].client_irq_handler(drvdata,
+ summary_irq_status);
+ }
+ return ret;
+}
+
+static const struct snd_soc_component_driver qaif_component_driver = {
+ .name = DRV_NAME,
+ .open = qaif_platform_pcmops_open,
+ .close = qaif_platform_pcmops_close,
+ .hw_params = qaif_platform_pcmops_hw_params,
+ .hw_free = qaif_platform_pcmops_hw_free,
+ .prepare = qaif_platform_pcmops_prepare,
+ .trigger = qaif_platform_pcmops_trigger,
+ .sync_stop = qaif_platform_pcmops_sync_stop,
+ .pointer = qaif_platform_pcmops_pointer,
+ .mmap = qaif_platform_pcmops_mmap,
+ .copy = qaif_platform_copy,
+};
+
+int asoc_qcom_qaif_platform_register(struct platform_device *pdev)
+{
+ struct qaif_drv_data *drvdata = platform_get_drvdata(pdev);
+ struct of_phandle_args iommu_spec;
+ u32 sid;
+ int ret;
+
+ if (!drvdata || !drvdata->variant)
+ return dev_err_probe(&pdev->dev, -EINVAL,
+ "Invalid drvdata or variant\n");
+
+ ret = of_parse_phandle_with_fixed_args(pdev->dev.of_node,
+ "iommus", 2, 0,
+ &iommu_spec);
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret,
+ "failed to parse iommus property\n");
+ sid = iommu_spec.args[0];
+ of_node_put(iommu_spec.np);
+ drvdata->smmu_csid_bits = sid & QAIF_CSID_MASK;
+
+ /*
+ * The DMA base register only holds the low 32 bits of the buffer
+ * address, so the coherent buffer must come from the low 32-bit
+ * address space.
+ */
+ ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret,
+ "Failed to set 32-bit DMA mask\n");
+
+ drvdata->audio_qaif_irq = platform_get_irq(pdev, 0);
+ if (drvdata->audio_qaif_irq < 0)
+ return dev_err_probe(&pdev->dev, drvdata->audio_qaif_irq,
+ "Failed to get IRQ\n");
+
+ drvdata->qaif_hw_configured = false;
+ mutex_init(&drvdata->stream_lock);
+
+ ret = devm_request_irq(&pdev->dev, drvdata->audio_qaif_irq,
+ asoc_platform_qaif_irq, 0,
+ "qaif-irq-audio-core", drvdata);
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret, "irq request failed\n");
+
+ ret = devm_snd_soc_register_component(&pdev->dev, &qaif_component_driver, NULL, 0);
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret,
+ "Failed to register platform component\n");
+ return 0;
+}
+EXPORT_SYMBOL_GPL(asoc_qcom_qaif_platform_register);
+
+MODULE_DESCRIPTION("Qualcomm Audio Interface (QAIF) PCM platform driver");
+MODULE_AUTHOR("Harendra Gautam <harendra.gautam@oss.qualcomm.com>");
+MODULE_LICENSE("GPL");
--
2.34.1
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PATCH v3 8/9] ASoC: qcom: Add Shikra QAIF support
2026-08-24 6:36 [PATCH v3 0/9] ASoC: qcom: Add QAIF driver for Shikra audio platform Harendra Gautam
` (6 preceding siblings ...)
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 ` Harendra Gautam
2026-08-26 8:35 ` Mohammad Rafi Shaik
2026-08-24 6:36 ` [PATCH v3 9/9] MAINTAINERS: Add Qualcomm QAIF driver entry Harendra Gautam
8 siblings, 1 reply; 32+ messages in thread
From: Harendra Gautam @ 2026-08-24 6:36 UTC (permalink / raw)
To: Srinivas Kandagatla
Cc: Mark Brown, Liam Girdwood, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Jaroslav Kysela, Takashi Iwai, linux-sound,
linux-arm-msm, devicetree, linux-kernel, Prasad Kumpatla,
Krzysztof Kozlowski, Sarath Ganapathiraju, Kumar Anurag Singh,
Mohammad Rafi Shaik
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@oss.qualcomm.com>
---
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",
+ .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@oss.qualcomm.com>");
+MODULE_LICENSE("GPL");
--
2.34.1
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PATCH v3 9/9] MAINTAINERS: Add Qualcomm QAIF driver entry
2026-08-24 6:36 [PATCH v3 0/9] ASoC: qcom: Add QAIF driver for Shikra audio platform Harendra Gautam
` (7 preceding siblings ...)
2026-08-24 6:36 ` [PATCH v3 8/9] ASoC: qcom: Add Shikra QAIF support Harendra Gautam
@ 2026-08-24 6:36 ` Harendra Gautam
2026-08-24 8:22 ` Abel Vesa
8 siblings, 1 reply; 32+ messages in thread
From: Harendra Gautam @ 2026-08-24 6:36 UTC (permalink / raw)
To: Srinivas Kandagatla
Cc: Mark Brown, Liam Girdwood, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Jaroslav Kysela, Takashi Iwai, linux-sound,
linux-arm-msm, devicetree, linux-kernel, Prasad Kumpatla,
Krzysztof Kozlowski, Sarath Ganapathiraju, Kumar Anurag Singh,
Mohammad Rafi Shaik
Signed-off-by: Harendra Gautam <harendra.gautam@oss.qualcomm.com>
---
MAINTAINERS | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index 68cfa7f7faa0..5413153bf7b5 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -21900,6 +21900,16 @@ F: sound/soc/codecs/wcd93*.*
F: sound/soc/codecs/wsa88*.*
F: sound/soc/qcom/
+QCOM AUDIO INTERFACE (QAIF) DRIVER
+M: Harendra Gautam <harendra.gautam@oss.qualcomm.com>
+M: Srinivas Kandagatla <srini@kernel.org>
+L: linux-sound@vger.kernel.org
+L: linux-arm-msm@vger.kernel.org
+S: Supported
+F: Documentation/devicetree/bindings/sound/qcom,qaif-cpu.yaml
+F: include/dt-bindings/sound/qcom,qaif.h
+F: sound/soc/qcom/qaif*
+
QCOM EMBEDDED USB DEBUGGER (EUD)
M: Souradeep Chowdhury <quic_schowdhu@quicinc.com>
L: linux-arm-msm@vger.kernel.org
--
2.34.1
^ permalink raw reply related [flat|nested] 32+ messages in thread
* Re: [PATCH v3 9/9] MAINTAINERS: Add Qualcomm QAIF driver entry
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
0 siblings, 1 reply; 32+ messages in thread
From: Abel Vesa @ 2026-08-24 8:22 UTC (permalink / raw)
To: Harendra Gautam
Cc: Srinivas Kandagatla, Mark Brown, Liam Girdwood, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Jaroslav Kysela, Takashi Iwai,
linux-sound, linux-arm-msm, devicetree, linux-kernel,
Prasad Kumpatla, Krzysztof Kozlowski, Sarath Ganapathiraju,
Kumar Anurag Singh, Mohammad Rafi Shaik
On 26-08-24 12:06:27, Harendra Gautam wrote:
> Signed-off-by: Harendra Gautam <harendra.gautam@oss.qualcomm.com>
Commit message missing.
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH v3 9/9] MAINTAINERS: Add Qualcomm QAIF driver entry
2026-08-24 8:22 ` Abel Vesa
@ 2026-08-24 8:31 ` Harendra Gautam
0 siblings, 0 replies; 32+ messages in thread
From: Harendra Gautam @ 2026-08-24 8:31 UTC (permalink / raw)
To: Abel Vesa
Cc: Srinivas Kandagatla, Mark Brown, Liam Girdwood, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Jaroslav Kysela, Takashi Iwai,
linux-sound, linux-arm-msm, devicetree, linux-kernel,
Prasad Kumpatla, Krzysztof Kozlowski, Sarath Ganapathiraju,
Kumar Anurag Singh, Mohammad Rafi Shaik
On Mon, Aug 24, 2026 at 1:52 PM Abel Vesa <abel.vesa@oss.qualcomm.com> wrote:
>
> On 26-08-24 12:06:27, Harendra Gautam wrote:
> > Signed-off-by: Harendra Gautam <harendra.gautam@oss.qualcomm.com>
>
> Commit message missing.
Looks like due to spacing, commit text was ignored. Will add in next
patch. below is the content of commit text
"Add a dedicated MAINTAINERS entry for the Qualcomm Audio Interface (QAIF)
driver so changes to its devicetree binding, dt-bindings header, and ASoC
driver files are routed to the Qualcomm ASoC maintainers and mailing lists."
-Harendra
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH v3 1/9] ASoC: dt-bindings: qcom,qaif-cpu: Add binding
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
1 sibling, 2 replies; 32+ messages in thread
From: Manuel Ebner @ 2026-08-24 8:39 UTC (permalink / raw)
To: Harendra Gautam, Srinivas Kandagatla
Cc: Mark Brown, Liam Girdwood, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Jaroslav Kysela, Takashi Iwai, linux-sound,
linux-arm-msm, devicetree, linux-kernel, Prasad Kumpatla,
Krzysztof Kozlowski, Sarath Ganapathiraju, Kumar Anurag Singh,
Mohammad Rafi Shaik
Hi
On Mon, 2026-08-24 at 12:06 +0530, Harendra Gautam wrote:
> QAIF routes audio between system memory, external PCM/TDM/MI2S serial
> interfaces and the internal Bolero/WCD codec. Platform Devicetree files
> need a binding to describe the controller resources, DAI cells and per-
> interface AIF configuration, and named constants to avoid raw numeric IDs
> in sound-dai references and child-node reg values.
>
> Describe the MMIO region, interrupt, clocks, DMA IOMMU mapping and
> aif-interface child nodes required by the controller.
>
> Signed-off-by: Harendra Gautam <harendra.gautam@oss.qualcomm.com>
> ---
> .../bindings/sound/qcom,qaif-cpu.yaml | 307 ++++++++++++++++++
> include/dt-bindings/sound/qcom,qaif.h | 97 ++++++
> 2 files changed, 404 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/sound/qcom,qaif-cpu.yaml
> create mode 100644 include/dt-bindings/sound/qcom,qaif.h
>
> diff --git a/Documentation/devicetree/bindings/sound/qcom,qaif-cpu.yaml b/Documentation/devicetree/bindings/sound/qcom,qaif-cpu.yaml
> new file mode 100644
> index 000000000000..134356114733
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/sound/qcom,qaif-cpu.yaml
> @@ -0,0 +1,307 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/sound/qcom,qaif-cpu.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
Both of the links redirect to https://www.devicetree.org/
>
> ...
>
> diff --git a/include/dt-bindings/sound/qcom,qaif.h b/include/dt-bindings/sound/qcom,qaif.h
> new file mode 100644
> index 000000000000..24706efd07d1
> --- /dev/null
> +++ b/include/dt-bindings/sound/qcom,qaif.h
> @@ -0,0 +1,97 @@
> +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
> +/*
> + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
> + *
> + * DAI IDs for the Qualcomm Audio Interface (QAIF) controller.
> + * QAIF_MI2S_AIF* and QAIF_TDM_AIF* values are used in sound-dai
> + * references and as the reg value of aif@N child nodes.
> + * QAIF_CDC_DMA_* values are for sound-dai references only and must
> + * not be used as aif@N child node reg values.
> + */
> +#ifndef __DT_QCOM_QAIF_H
> +#define __DT_QCOM_QAIF_H
> +
> +/*
> + * MI2S DAI IDs -- one per physical AIF port in MI2S mode.
> + * Each port supports up to 2 channels (stereo I2S) over a single
> + * data lane sharing a bit clock and frame sync.
> + */
> +#define QAIF_MI2S_AIF0 200
> +#define QAIF_MI2S_AIF1 201
> +#define QAIF_MI2S_AIF2 202
> +#define QAIF_MI2S_AIF3 203
> +#define QAIF_MI2S_AIF4 204
> +#define QAIF_MI2S_AIF5 205
> +#define QAIF_MI2S_AIF6 206
> +#define QAIF_MI2S_AIF7 207
> +#define QAIF_MI2S_AIF8 208
> +#define QAIF_MI2S_AIF9 209
> +#define QAIF_MI2S_AIF10 210
> +#define QAIF_MI2S_AIF11 211
> +#define QAIF_MI2S_AIF12 212
> +
> +/*
> + * TDM DAI IDs -- one per physical AIF port in TDM mode.
Is this sentence complete?
> + * Each port supports up to 8 channels over up to 8 independent data
> + * lanes sharing a single bit clock and frame sync.
> + */
>
> ...
Thanks
Manuel
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH v3 1/9] ASoC: dt-bindings: qcom,qaif-cpu: Add binding
2026-08-24 8:39 ` Manuel Ebner
@ 2026-08-24 9:14 ` Harendra Gautam
2026-08-25 5:59 ` Krzysztof Kozlowski
1 sibling, 0 replies; 32+ messages in thread
From: Harendra Gautam @ 2026-08-24 9:14 UTC (permalink / raw)
To: Manuel Ebner
Cc: Srinivas Kandagatla, Mark Brown, Liam Girdwood, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Jaroslav Kysela, Takashi Iwai,
linux-sound, linux-arm-msm, devicetree, linux-kernel,
Prasad Kumpatla, Krzysztof Kozlowski, Sarath Ganapathiraju,
Kumar Anurag Singh, Mohammad Rafi Shaik
On Mon, Aug 24, 2026 at 2:09 PM Manuel Ebner <manuelebnerli@mailbox.org> wrote:
>
> Hi
>
> On Mon, 2026-08-24 at 12:06 +0530, Harendra Gautam wrote:
> > QAIF routes audio between system memory, external PCM/TDM/MI2S serial
> > interfaces and the internal Bolero/WCD codec. Platform Devicetree files
> > need a binding to describe the controller resources, DAI cells and per-
> > interface AIF configuration, and named constants to avoid raw numeric IDs
> > in sound-dai references and child-node reg values.
> >
> > Describe the MMIO region, interrupt, clocks, DMA IOMMU mapping and
> > aif-interface child nodes required by the controller.
> >
> > Signed-off-by: Harendra Gautam <harendra.gautam@oss.qualcomm.com>
> > ---
> > .../bindings/sound/qcom,qaif-cpu.yaml | 307 ++++++++++++++++++
> > include/dt-bindings/sound/qcom,qaif.h | 97 ++++++
> > 2 files changed, 404 insertions(+)
> > create mode 100644 Documentation/devicetree/bindings/sound/qcom,qaif-cpu.yaml
> > create mode 100644 include/dt-bindings/sound/qcom,qaif.h
> >
> > diff --git a/Documentation/devicetree/bindings/sound/qcom,qaif-cpu.yaml b/Documentation/devicetree/bindings/sound/qcom,qaif-cpu.yaml
> > new file mode 100644
> > index 000000000000..134356114733
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/sound/qcom,qaif-cpu.yaml
> > @@ -0,0 +1,307 @@
> > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> > +%YAML 1.2
> > +---
> > +$id: http://devicetree.org/schemas/sound/qcom,qaif-cpu.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
>
> Both of the links redirect to https://www.devicetree.org/
Thanks for the note. This follows the same convention used across all
other DT bindings in the kernel tree.
-Harendra
>
> >
> > ...
> >
> > diff --git a/include/dt-bindings/sound/qcom,qaif.h b/include/dt-bindings/sound/qcom,qaif.h
> > new file mode 100644
> > index 000000000000..24706efd07d1
> > --- /dev/null
> > +++ b/include/dt-bindings/sound/qcom,qaif.h
> > @@ -0,0 +1,97 @@
> > +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
> > +/*
> > + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
> > + *
> > + * DAI IDs for the Qualcomm Audio Interface (QAIF) controller.
> > + * QAIF_MI2S_AIF* and QAIF_TDM_AIF* values are used in sound-dai
> > + * references and as the reg value of aif@N child nodes.
> > + * QAIF_CDC_DMA_* values are for sound-dai references only and must
> > + * not be used as aif@N child node reg values.
> > + */
> > +#ifndef __DT_QCOM_QAIF_H
> > +#define __DT_QCOM_QAIF_H
> > +
> > +/*
> > + * MI2S DAI IDs -- one per physical AIF port in MI2S mode.
> > + * Each port supports up to 2 channels (stereo I2S) over a single
> > + * data lane sharing a bit clock and frame sync.
> > + */
> > +#define QAIF_MI2S_AIF0 200
> > +#define QAIF_MI2S_AIF1 201
> > +#define QAIF_MI2S_AIF2 202
> > +#define QAIF_MI2S_AIF3 203
> > +#define QAIF_MI2S_AIF4 204
> > +#define QAIF_MI2S_AIF5 205
> > +#define QAIF_MI2S_AIF6 206
> > +#define QAIF_MI2S_AIF7 207
> > +#define QAIF_MI2S_AIF8 208
> > +#define QAIF_MI2S_AIF9 209
> > +#define QAIF_MI2S_AIF10 210
> > +#define QAIF_MI2S_AIF11 211
> > +#define QAIF_MI2S_AIF12 212
> > +
> > +/*
> > + * TDM DAI IDs -- one per physical AIF port in TDM mode.
>
> Is this sentence complete?
Comment is written in fragments. Please let me know if it is not
conveying the intent and needs to be rewritten.
-Harendra
>
> > + * Each port supports up to 8 channels over up to 8 independent data
> > + * lanes sharing a single bit clock and frame sync.
> > + */
> >
> > ...
>
> Thanks
> Manuel
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH v3 6/9] ASoC: qcom: Add QAIF PCM operations
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
0 siblings, 1 reply; 32+ messages in thread
From: Markus Elfring @ 2026-08-24 9:25 UTC (permalink / raw)
To: Harendra Gautam, linux-sound, devicetree, linux-arm-msm,
Srinivas Kandagatla
Cc: LKML, Conor Dooley, Jaroslav Kysela, Krzysztof Kozlowski,
Krzysztof Kozlowski, Kumar Anurag Singh, Liam Girdwood,
Mark Brown, Mohammad Rafi Shaik, Prasad Kumpatla, Rob Herring,
Sarath Ganapathiraju, Takashi Iwai
…
> +++ b/sound/soc/qcom/qaif-platform.c
> @@ -0,0 +1,544 @@
…
> +static int qaif_platform_pcmops_close(struct snd_soc_component *component,
> + struct snd_pcm_substream *substream)
> +{
…
> + mutex_lock(&drvdata->stream_lock);
> + if (v->free_stream_dma_idx)
> + v->free_stream_dma_idx(drvdata, data->stream_dma_idx, dai_id);
> + mutex_unlock(&drvdata->stream_lock);
…
Under which circumstances would you become interested to apply a statement
like “guard(mutex)(&drvdata->stream_lock);”?
https://elixir.bootlin.com/linux/v7.2/source/include/linux/mutex.h#L253
Regards,
Markus
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH v3 6/9] ASoC: qcom: Add QAIF PCM operations
2026-08-24 9:25 ` Markus Elfring
@ 2026-08-24 10:10 ` Harendra Gautam
2026-08-25 6:07 ` Krzysztof Kozlowski
0 siblings, 1 reply; 32+ messages in thread
From: Harendra Gautam @ 2026-08-24 10:10 UTC (permalink / raw)
To: Markus Elfring
Cc: linux-sound, devicetree, linux-arm-msm, Srinivas Kandagatla, LKML,
Conor Dooley, Jaroslav Kysela, Krzysztof Kozlowski,
Krzysztof Kozlowski, Kumar Anurag Singh, Liam Girdwood,
Mark Brown, Mohammad Rafi Shaik, Prasad Kumpatla, Rob Herring,
Sarath Ganapathiraju, Takashi Iwai
On Mon, Aug 24, 2026 at 2:55 PM Markus Elfring <Markus.Elfring@web.de> wrote:
>
> …
> > +++ b/sound/soc/qcom/qaif-platform.c
> > @@ -0,0 +1,544 @@
> …
> > +static int qaif_platform_pcmops_close(struct snd_soc_component *component,
> > + struct snd_pcm_substream *substream)
> > +{
> …
> > + mutex_lock(&drvdata->stream_lock);
> > + if (v->free_stream_dma_idx)
> > + v->free_stream_dma_idx(drvdata, data->stream_dma_idx, dai_id);
> > + mutex_unlock(&drvdata->stream_lock);
> …
>
> Under which circumstances would you become interested to apply a statement
> like “guard(mutex)(&drvdata->stream_lock);”?
> https://elixir.bootlin.com/linux/v7.2/source/include/linux/mutex.h#L253
>
> Regards,
> Markus
Thanks for the pointer. I believe guard() can be used across all
stream_lock. I Will address it in the next version.
-Harendra
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH v3 5/9] ASoC: soc-core: Add snd_soc_of_xlate_dai_name() generic helper
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
0 siblings, 0 replies; 32+ messages in thread
From: Kuninori Morimoto @ 2026-08-25 4:20 UTC (permalink / raw)
To: Harendra Gautam
Cc: Srinivas Kandagatla, Mark Brown, Liam Girdwood, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Jaroslav Kysela, Takashi Iwai,
linux-sound, linux-arm-msm, devicetree, linux-kernel,
Prasad Kumpatla, Krzysztof Kozlowski, Sarath Ganapathiraju,
Kumar Anurag Singh, Mohammad Rafi Shaik
Hi Harendra
Thank you for the patch
> Add snd_soc_of_xlate_dai_name() to soc-core.c as a generic helper
> that can be assigned directly to the .of_xlate_dai_name component
> driver callback. It iterates the component's DAI list using
> for_each_component_dais() and matches by DAI ID.
>
> Use the helper in lpass-cpu.c and qaif-cpu.c, and remove the local
> lpass implementation.
>
> Signed-off-by: Harendra Gautam <harendra.gautam@oss.qualcomm.com>
> ---
I think this patch want to be separated into 2 patches.
- add snd_soc_of_xlate_dai_name()
- switch to use it
It makes backport easy.
Thank you for your help !!
Best regards
---
Kuninori Morimoto
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH v3 1/9] ASoC: dt-bindings: qcom,qaif-cpu: Add binding
2026-08-24 8:39 ` Manuel Ebner
2026-08-24 9:14 ` Harendra Gautam
@ 2026-08-25 5:59 ` Krzysztof Kozlowski
1 sibling, 0 replies; 32+ messages in thread
From: Krzysztof Kozlowski @ 2026-08-25 5:59 UTC (permalink / raw)
To: Manuel Ebner, Harendra Gautam, Srinivas Kandagatla
Cc: Mark Brown, Liam Girdwood, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Jaroslav Kysela, Takashi Iwai, linux-sound,
linux-arm-msm, devicetree, linux-kernel, Prasad Kumpatla,
Sarath Ganapathiraju, Kumar Anurag Singh, Mohammad Rafi Shaik
On 24/08/2026 10:39, Manuel Ebner wrote:
> Hi
>
> On Mon, 2026-08-24 at 12:06 +0530, Harendra Gautam wrote:
>> QAIF routes audio between system memory, external PCM/TDM/MI2S serial
>> interfaces and the internal Bolero/WCD codec. Platform Devicetree files
>> need a binding to describe the controller resources, DAI cells and per-
>> interface AIF configuration, and named constants to avoid raw numeric IDs
>> in sound-dai references and child-node reg values.
>>
>> Describe the MMIO region, interrupt, clocks, DMA IOMMU mapping and
>> aif-interface child nodes required by the controller.
>>
>> Signed-off-by: Harendra Gautam <harendra.gautam@oss.qualcomm.com>
>> ---
>> .../bindings/sound/qcom,qaif-cpu.yaml | 307 ++++++++++++++++++
>> include/dt-bindings/sound/qcom,qaif.h | 97 ++++++
>> 2 files changed, 404 insertions(+)
>> create mode 100644 Documentation/devicetree/bindings/sound/qcom,qaif-cpu.yaml
>> create mode 100644 include/dt-bindings/sound/qcom,qaif.h
>>
>> diff --git a/Documentation/devicetree/bindings/sound/qcom,qaif-cpu.yaml b/Documentation/devicetree/bindings/sound/qcom,qaif-cpu.yaml
>> new file mode 100644
>> index 000000000000..134356114733
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/sound/qcom,qaif-cpu.yaml
>> @@ -0,0 +1,307 @@
>> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
>> +%YAML 1.2
>> +---
>> +$id: http://devicetree.org/schemas/sound/qcom,qaif-cpu.yaml#
>> +$schema: http://devicetree.org/meta-schemas/core.yaml#
>
> Both of the links redirect to https://www.devicetree.org/
I don't think you are providing anyhow useful review. Please avoid
focusing on unimportant details.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH v3 6/9] ASoC: qcom: Add QAIF PCM operations
2026-08-24 10:10 ` Harendra Gautam
@ 2026-08-25 6:07 ` Krzysztof Kozlowski
0 siblings, 0 replies; 32+ messages in thread
From: Krzysztof Kozlowski @ 2026-08-25 6:07 UTC (permalink / raw)
To: Harendra Gautam
Cc: linux-sound, devicetree, linux-arm-msm, Srinivas Kandagatla, LKML,
Conor Dooley, Jaroslav Kysela, Krzysztof Kozlowski,
Kumar Anurag Singh, Liam Girdwood, Mark Brown,
Mohammad Rafi Shaik, Prasad Kumpatla, Rob Herring,
Sarath Ganapathiraju, Takashi Iwai
On 24/08/2026 12:10, Harendra Gautam wrote:
> On Mon, Aug 24, 2026 at 2:55 PM Markus Elfring <Markus.Elfring@web.de> wrote:
>>
>> …
>>> +++ b/sound/soc/qcom/qaif-platform.c
>>> @@ -0,0 +1,544 @@
>> …
>>> +static int qaif_platform_pcmops_close(struct snd_soc_component *component,
>>> + struct snd_pcm_substream *substream)
>>> +{
>> …
>>> + mutex_lock(&drvdata->stream_lock);
>>> + if (v->free_stream_dma_idx)
>>> + v->free_stream_dma_idx(drvdata, data->stream_dma_idx, dai_id);
>>> + mutex_unlock(&drvdata->stream_lock);
>> …
>>
>> Under which circumstances would you become interested to apply a statement
>> like “guard(mutex)(&drvdata->stream_lock);”?
>> https://elixir.bootlin.com/linux/v7.2/source/include/linux/mutex.h#L253
>>
>> Regards,
>> Markus
> Thanks for the pointer. I believe guard() can be used across all
> stream_lock. I Will address it in the next version.
No, not really. Obvious code is replaced with more complicated one.
<form letter>
Feel free to ignore all comments from Markus, regardless whether the
suggestion is reasonable or not. Several maintainers ignore Markus'
feedback, because it is just a waste of time.
</form letter>
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH v3 1/9] ASoC: dt-bindings: qcom,qaif-cpu: Add binding
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-26 8:31 ` Mohammad Rafi Shaik
2026-08-26 9:39 ` Harendra Gautam
2026-08-26 23:32 ` Mark Brown
1 sibling, 2 replies; 32+ messages in thread
From: Mohammad Rafi Shaik @ 2026-08-26 8:31 UTC (permalink / raw)
To: Harendra Gautam, Srinivas Kandagatla
Cc: Mark Brown, Liam Girdwood, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Jaroslav Kysela, Takashi Iwai, linux-sound,
linux-arm-msm, devicetree, linux-kernel, Prasad Kumpatla,
Krzysztof Kozlowski, Sarath Ganapathiraju, Kumar Anurag Singh
On 8/24/2026 12:06 PM, Harendra Gautam wrote:
> QAIF routes audio between system memory, external PCM/TDM/MI2S serial
> interfaces and the internal Bolero/WCD codec. Platform Devicetree files
> need a binding to describe the controller resources, DAI cells and per-
> interface AIF configuration, and named constants to avoid raw numeric IDs
> in sound-dai references and child-node reg values.
>
> Describe the MMIO region, interrupt, clocks, DMA IOMMU mapping and
> aif-interface child nodes required by the controller.
>
> Signed-off-by: Harendra Gautam <harendra.gautam@oss.qualcomm.com>
> ---
> .../bindings/sound/qcom,qaif-cpu.yaml | 307 ++++++++++++++++++
> include/dt-bindings/sound/qcom,qaif.h | 97 ++++++
> 2 files changed, 404 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/sound/qcom,qaif-cpu.yaml
> create mode 100644 include/dt-bindings/sound/qcom,qaif.h
>
> diff --git a/Documentation/devicetree/bindings/sound/qcom,qaif-cpu.yaml b/Documentation/devicetree/bindings/sound/qcom,qaif-cpu.yaml
> new file mode 100644
> index 000000000000..134356114733
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/sound/qcom,qaif-cpu.yaml
> @@ -0,0 +1,307 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/sound/qcom,qaif-cpu.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Qualcomm Audio Interface (QAIF) CPU DAI Controller
> +
> +maintainers:
> + - Harendra Gautam <harendra.gautam@oss.qualcomm.com>
> +
> +description: |
> + The Qualcomm Audio Interface (QAIF) is a fully configurable DMA-based
> + audio subsystem controller. It serialises and deserialises PCM audio
> + between system memory and external serial audio peripherals (PCM, TDM,
> + I2S, MI2S) through the AIF path, and transfers parallel audio between
> + memory and an internal WCD codec through the CIF path.
> +
> + AIF (Audio Interface): up to 13 multi-lane Unified Audio Interfaces,
> + each supporting up to 8 independent data lanes. Each lane is individually
> + configurable as TX (output/speaker) or RX (input/mic). All lanes of an
> + interface share a single bit clock and frame sync. Supported modes are
> + PCM (short/long sync), TDM, and MI2S (stereo/mono). Per-interface
> + configuration includes sync source (master/slave), sync mode, sync delay,
> + sync inversion, slot width (8/16/24/32-bit), sample width, active slot
> + masks (up to 32 slots), bits-per-lane frame size, lane enable/direction
> + masks, loopback, output-enable control, and full-cycle path support for
> + long chip-to-chip connections.
> +
> + CIF (Codec Interface): up to 10 RDDMA (playback) and 10 WRDMA (capture)
> + channels connecting to an internal codec over a parallel bus. Each channel
> + supports active-channel enable mask (up to 16 channels), frame-sync
> + selection, frame-sync delay, frame-sync output gating, dynamic clock
> + gating, and 16-bit packing/unpacking.
> +
> + Note on RX/TX naming convention: in QAIF, TX refers to the output
> + (speaker/playback) direction and RX refers to the input (mic/capture)
> + direction. This applies to both AIF lane directions and CIF slot/mask
> + properties.
> +
> + DMA engine: RDDMA fetches audio from DDR/TCM/LPM into a shared SRAM
> + latency buffer (SHRAM) and drains it to the interface. WRDMA collects
> + data from the interface into SHRAM and writes it to memory. Each DMA
> + owns a private SHRAM region defined by start address and length registers.
> + Burst sizes of 1/2/4/8/16 beats (64-bit) are supported with up to 4
> + outstanding transactions per DMA. Two QSB master ports (QXM0 for TCM,
> + QXM1 for DDR/LPM) provide the memory interface.
> +
> + Resources are partitioned among up to 5 Execution Engines (EEs) via
> + EE map registers. Each EE owns a set of DMAs, audio interfaces, and
> + interface groups, and receives its own independent interrupt output.
> + The interrupt hierarchy has a two-level structure: a summary register
> + identifies the event class (DMA period, underflow/overflow, error
> + response, audio interface underflow/overflow, group done, rate detector,
> + VFR), and per-resource status registers identify the specific channel.
> +
> + Interface grouping (bonding) allows up to 6 groups of audio and codec
> + interfaces to start synchronously and align their DMA period interrupts
> + within half a frame duration using the RDDMA padding feature.
> +
> + Two rate detector blocks measure the frequency of incoming frame sync or
> + word select signals and generate interrupts on rate change, undetected
> + rate, or sync timeout.
> +
> + Block diagram::
> +
> + System Memory (DDR / LPM / TCM)
> + +---------------------------------+
> + | Circular Buffers (ping-pong) |
> + +----------+----------+-----------+
> + | ^
> + 64-bit AXI 64-bit AXI
> + | |
> + +----------v----------+-----------+
> + | QSB Master Ports |
> + | +----------+ +----------+ |
> + | | QXM0 | | QXM1 | |
> + | +----+-----+ +-----+----+ |
> + +-------|--------------|----------+
> + | |
> + +-------v--------------v----------+
> + | Shared RAM (SHRAM) |
> + | +------------+ +------------+ |
> + | | QXM0 Read | | QXM0 Write | |
> + | | SHRAM | | SHRAM | |
> + | +------------+ +------------+ |
> + | +------------+ +------------+ |
> + | | QXM1 Read | | QXM1 Write | |
> + | | SHRAM | | SHRAM | |
> + | +------------+ +------------+ |
> + +---+--------+--------+-------+---+
> + | | | |
> + +---v--+ +--v---+ +--v---+ +-v----+
> + |RDDMA | |RDDMA | |WRDMA | |WRDMA |
> + | AIF | | CIF | | AIF | | CIF |
> + |[0..n]| |[0..n]| |[0..n]| |[0..n]|
> + +--+---+ +--+---+ +--+---+ +-+----+
> + | | ^ ^
> + | TX | TX | RX | RX
> + v v | |
> + +--+--------------------+ +----+----------+
> + | Unified Audio Intf | | Codec DMA |
> + | (AIF 0..12) | | Interface |
> + | | | (CIF) |
> + | AUD_INTFa block: | | |
> + | - Serializer (TX) | | RDDMA: DDR -> |
> + | - De-serializer (RX) | | internal |
> + | - Sync gen/detect | | codec |
> + | - Up to 8 data lanes | | WRDMA: codec |
> + | - PCM / TDM / MI2S | | -> DDR |
> + | - Near Pad Logic | | Up to 16 ch |
> + +--+--------------------+ +----+----------+
> + | Lane 0..7 (TX/RX) | Parallel bus
> + | Bit clk + Frame sync | + Frame sync
> + v v
> + +--+--------+ +------+------+
> + | External | | Internal |
> + | Serial | | Digital |
> + | Peripherals| | Codec |
> + | (PCM/TDM/ | | (Bolero/ |
> + | MI2S) | | WCD) |
> + +-----------+ +-------------+
> +
> +allOf:
> + - $ref: dai-common.yaml#
> +
> +properties:
> + compatible:
> + const: qcom,shikra-qaif-cpu
> +
> + reg:
> + maxItems: 1
> + description: QAIF core registers
> +
> + interrupts:
> + maxItems: 1
> + description:
> + QAIF summary interrupt for this Execution Engine. Signals DMA period
> + completion, buffer underflow/overflow, error response, audio interface
> + underflow/overflow, interface-group done, rate detector and VFR events.
> +
> + iommus:
> + maxItems: 1
> + description: Phandle to apps_smmu node with sid mask
> +
> + dma-coherent: true
> +
> + clocks:
> + minItems: 5
> + maxItems: 9
> +
> + clock-names:
> + description:
> + The first five clocks are always required. Any further entries are the
> + per-AIF bit clocks (aif_if<N>_ibit), supplied in order starting from
> + AIF interface 0 for as many serial AIF interfaces as the board uses.
> + minItems: 5
> + items:
> + - const: lpass_config
> + - const: lpass_core_axim
> + - const: aud_dma
> + - const: aud_dma_mem
> + - const: bus
> + - const: aif_if0_ibit
> + - const: aif_if1_ibit
> + - const: aif_if2_ibit
> + - const: aif_if3_ibit
> +
> + '#sound-dai-cells':
> + const: 1
> +
> + '#address-cells':
> + const: 1
> +
> + '#size-cells':
> + const: 0
> +
> +patternProperties:
> + '^aif@[0-9a-f]+$':
> + type: object
> + description:
> + QAIF AIF interface child node for PCM, TDM or MI2S configuration.
> +
> + properties:
> + reg:
> + maxItems: 1
> + description:
> + DAI ID of the AIF interface (QAIF_MI2S_AIF* or QAIF_TDM_AIF*).
> +
> + dai-format:
> + description: Serial audio interface format (MI2S, TDM or PCM).
> + enum: [i2s, dsp_a, dsp_b]
> +
> + dai-tdm-slot-width:
> + $ref: /schemas/types.yaml#/definitions/uint32
> + enum: [8, 16, 24, 32]
> + description:
> + Slot width in bits.
> +
> + dai-tdm-slot-num:
> + $ref: /schemas/types.yaml#/definitions/uint32
> + description:
> + Number of slots per lane.
> + minimum: 1
> + maximum: 32
> +
> + dai-tdm-slot-rx-mask:
> + $ref: /schemas/types.yaml#/definitions/uint32-array
> + description:
> + Active RX slots, one entry per slot. A nonzero value marks the
> + slot as active.
> + minItems: 1
> + maxItems: 32
> +
> + dai-tdm-slot-tx-mask:
> + $ref: /schemas/types.yaml#/definitions/uint32-array
> + description:
> + Active TX slots, one entry per slot. A nonzero value marks the
> + slot as active.
> + minItems: 1
> + maxItems: 32
> +
> + qcom,qaif-aif-lane-map:
> + $ref: /schemas/types.yaml#/definitions/uint32-array
> + description:
> + Per-lane direction map, one entry per lane starting from lane 0.
> + Use 0 for TX (output/speaker) and 1 for RX (input/mic).
> + minItems: 1
> + maxItems: 8
> + items:
> + enum: [0, 1]
> +
> + required:
> + - reg
> + - dai-format
> + - qcom,qaif-aif-lane-map
> +
> + if:
> + properties:
> + dai-format:
> + enum: [dsp_a, dsp_b]
> + then:
> + required:
> + - dai-tdm-slot-width
> + - dai-tdm-slot-num
> + - dai-tdm-slot-rx-mask
> + - dai-tdm-slot-tx-mask
> +
> + additionalProperties: false
> +
> +required:
> + - compatible
> + - reg
> + - interrupts
> + - iommus
> + - clocks
> + - clock-names
> + - '#sound-dai-cells'
> + - '#address-cells'
> + - '#size-cells'
> +
> +unevaluatedProperties: false
> +
> +examples:
> + - |
> + soc {
> + #address-cells = <2>;
> + #size-cells = <2>;
> +
> + qaif_cpu: audio-controller@a000000 {
> + compatible = "qcom,shikra-qaif-cpu";
> + reg = <0x0 0x0a000000 0x0 0x20000>;
> + interrupts = <0 331 4>;
> + iommus = <&apps_smmu 0x1c0 0x0>;
> + clocks = <&gcc 213>,
> + <&gcc 214>,
> + <&audiocorecc 15>,
> + <&audiocorecc 17>,
> + <&audiocorecc 18>,
> + <&audiocorecc 5>,
> + <&audiocorecc 8>,
> + <&audiocorecc 11>,
> + <&audiocorecc 14>;
> + clock-names = "lpass_config",
> + "lpass_core_axim",
> + "aud_dma",
> + "aud_dma_mem",
> + "bus",
> + "aif_if0_ibit",
> + "aif_if1_ibit",
> + "aif_if2_ibit",
> + "aif_if3_ibit";
> + #sound-dai-cells = <1>;
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + aif@d7 {
> + reg = <215>;
> + dai-format = "dsp_a";
> + dai-tdm-slot-width = <32>;
> + dai-tdm-slot-num = <2>;
> + dai-tdm-slot-rx-mask = <1 1>;
> + dai-tdm-slot-tx-mask = <1 1>;
> + qcom,qaif-aif-lane-map = <1 0>;
> + };
> + };
> + };
> diff --git a/include/dt-bindings/sound/qcom,qaif.h b/include/dt-bindings/sound/qcom,qaif.h
> new file mode 100644
> index 000000000000..24706efd07d1
> --- /dev/null
> +++ b/include/dt-bindings/sound/qcom,qaif.h
> @@ -0,0 +1,97 @@
> +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
> +/*
> + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
> + *
> + * DAI IDs for the Qualcomm Audio Interface (QAIF) controller.
> + * QAIF_MI2S_AIF* and QAIF_TDM_AIF* values are used in sound-dai
> + * references and as the reg value of aif@N child nodes.
> + * QAIF_CDC_DMA_* values are for sound-dai references only and must
> + * not be used as aif@N child node reg values.
> + */
> +#ifndef __DT_QCOM_QAIF_H
> +#define __DT_QCOM_QAIF_H
> +
> +/*
> + * MI2S DAI IDs -- one per physical AIF port in MI2S mode.
> + * Each port supports up to 2 channels (stereo I2S) over a single
> + * data lane sharing a bit clock and frame sync.
> + */
> +#define QAIF_MI2S_AIF0 200
> +#define QAIF_MI2S_AIF1 201
> +#define QAIF_MI2S_AIF2 202
> +#define QAIF_MI2S_AIF3 203
> +#define QAIF_MI2S_AIF4 204
> +#define QAIF_MI2S_AIF5 205
> +#define QAIF_MI2S_AIF6 206
> +#define QAIF_MI2S_AIF7 207
> +#define QAIF_MI2S_AIF8 208
> +#define QAIF_MI2S_AIF9 209
> +#define QAIF_MI2S_AIF10 210
> +#define QAIF_MI2S_AIF11 211
> +#define QAIF_MI2S_AIF12 212
> +
> +/*
> + * TDM DAI IDs -- one per physical AIF port in TDM mode.
> + * Each port supports up to 8 channels over up to 8 independent data
> + * lanes sharing a single bit clock and frame sync.
> + */
> +#define QAIF_TDM_AIF0 213
> +#define QAIF_TDM_AIF1 214
> +#define QAIF_TDM_AIF2 215
> +#define QAIF_TDM_AIF3 216
> +#define QAIF_TDM_AIF4 217
> +#define QAIF_TDM_AIF5 218
> +#define QAIF_TDM_AIF6 219
> +#define QAIF_TDM_AIF7 220
> +#define QAIF_TDM_AIF8 221
> +#define QAIF_TDM_AIF9 222
> +#define QAIF_TDM_AIF10 223
> +#define QAIF_TDM_AIF11 224
> +#define QAIF_TDM_AIF12 225
> +
> +/*
> + * CIF (Codec Interface) RX DAI IDs -- playback to internal codec.
> + * RDDMA channels fetch audio from memory and drain it to the codec.
> + */
> +#define QAIF_CDC_DMA_RX0 226
> +#define QAIF_CDC_DMA_RX1 227
> +#define QAIF_CDC_DMA_RX2 228
> +#define QAIF_CDC_DMA_RX3 229
> +#define QAIF_CDC_DMA_RX4 230
> +#define QAIF_CDC_DMA_RX5 231
> +#define QAIF_CDC_DMA_RX6 232
> +#define QAIF_CDC_DMA_RX7 233
> +#define QAIF_CDC_DMA_RX8 234
> +#define QAIF_CDC_DMA_RX9 235
> +
> +/*
> + * CIF (Codec Interface) TX DAI IDs -- capture from internal codec.
> + * WRDMA channels collect audio from the codec and write it to memory.
> + */
> +#define QAIF_CDC_DMA_TX0 236
> +#define QAIF_CDC_DMA_TX1 237
> +#define QAIF_CDC_DMA_TX2 238
> +#define QAIF_CDC_DMA_TX3 239
> +#define QAIF_CDC_DMA_TX4 240
> +#define QAIF_CDC_DMA_TX5 241
> +#define QAIF_CDC_DMA_TX6 242
> +#define QAIF_CDC_DMA_TX7 243
> +#define QAIF_CDC_DMA_TX8 244
> +#define QAIF_CDC_DMA_TX9 245
> +
> +/*
> + * CIF (Codec Interface) VA TX DAI IDs -- capture from voice activity codec.
> + * WRDMA channels collect audio from the VA codec and write it to memory.
> + */
> +#define QAIF_CDC_DMA_VA_TX0 246
> +#define QAIF_CDC_DMA_VA_TX1 247
> +#define QAIF_CDC_DMA_VA_TX2 248
> +#define QAIF_CDC_DMA_VA_TX3 249
> +#define QAIF_CDC_DMA_VA_TX4 250
> +#define QAIF_CDC_DMA_VA_TX5 251
> +#define QAIF_CDC_DMA_VA_TX6 252
> +#define QAIF_CDC_DMA_VA_TX7 253
> +#define QAIF_CDC_DMA_VA_TX8 254
> +#define QAIF_CDC_DMA_VA_TX9 255
> +
These DAI IDs exceed the LPASS_MAX_PORT limit, which will cause sound
card registration to fail.
Check sound/soc/qcom/common.c, as the current indices (246-255) are
beyond the supported LPASS port range.
Best Regards,
Rafi.
> +#endif /* __DT_QCOM_QAIF_H */
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH v3 8/9] ASoC: qcom: Add Shikra QAIF support
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
0 siblings, 1 reply; 32+ messages in thread
From: Mohammad Rafi Shaik @ 2026-08-26 8:35 UTC (permalink / raw)
To: Harendra Gautam, Srinivas Kandagatla
Cc: Mark Brown, Liam Girdwood, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Jaroslav Kysela, Takashi Iwai, linux-sound,
linux-arm-msm, devicetree, linux-kernel, Prasad Kumpatla,
Krzysztof Kozlowski, Sarath Ganapathiraju, Kumar Anurag Singh
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@oss.qualcomm.com>
> ---
> 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.
> + .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@oss.qualcomm.com>");
> +MODULE_LICENSE("GPL");
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH v3 8/9] ASoC: qcom: Add Shikra QAIF support
2026-08-26 8:35 ` Mohammad Rafi Shaik
@ 2026-08-26 8:58 ` Harendra Gautam
2026-08-26 10:13 ` Srinivas Kandagatla
0 siblings, 1 reply; 32+ messages in thread
From: Harendra Gautam @ 2026-08-26 8:58 UTC (permalink / raw)
To: Mohammad Rafi Shaik
Cc: Srinivas Kandagatla, Mark Brown, Liam Girdwood, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Jaroslav Kysela, Takashi Iwai,
linux-sound, linux-arm-msm, devicetree, linux-kernel,
Prasad Kumpatla, Krzysztof Kozlowski, Sarath Ganapathiraju,
Kumar Anurag Singh
On Wed, Aug 26, 2026 at 2:05 PM Mohammad Rafi Shaik
<mohammad.rafi.shaik@oss.qualcomm.com> 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@oss.qualcomm.com>
> > ---
> > 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@oss.qualcomm.com>");
> > +MODULE_LICENSE("GPL");
>
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH v3 1/9] ASoC: dt-bindings: qcom,qaif-cpu: Add binding
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 23:32 ` Mark Brown
1 sibling, 1 reply; 32+ messages in thread
From: Harendra Gautam @ 2026-08-26 9:39 UTC (permalink / raw)
To: Mohammad Rafi Shaik
Cc: Srinivas Kandagatla, Mark Brown, Liam Girdwood, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Jaroslav Kysela, Takashi Iwai,
linux-sound, linux-arm-msm, devicetree, linux-kernel,
Prasad Kumpatla, Krzysztof Kozlowski, Sarath Ganapathiraju,
Kumar Anurag Singh
On Wed, Aug 26, 2026 at 2:02 PM Mohammad Rafi Shaik
<mohammad.rafi.shaik@oss.qualcomm.com> wrote:
>
>
>
> On 8/24/2026 12:06 PM, Harendra Gautam wrote:
> > QAIF routes audio between system memory, external PCM/TDM/MI2S serial
> > interfaces and the internal Bolero/WCD codec. Platform Devicetree files
> > need a binding to describe the controller resources, DAI cells and per-
> > interface AIF configuration, and named constants to avoid raw numeric IDs
> > in sound-dai references and child-node reg values.
> >
> > Describe the MMIO region, interrupt, clocks, DMA IOMMU mapping and
> > aif-interface child nodes required by the controller.
> >
> > Signed-off-by: Harendra Gautam <harendra.gautam@oss.qualcomm.com>
> > ---
> > .../bindings/sound/qcom,qaif-cpu.yaml | 307 ++++++++++++++++++
> > include/dt-bindings/sound/qcom,qaif.h | 97 ++++++
> > 2 files changed, 404 insertions(+)
> > create mode 100644 Documentation/devicetree/bindings/sound/qcom,qaif-cpu.yaml
> > create mode 100644 include/dt-bindings/sound/qcom,qaif.h
> >
> > diff --git a/Documentation/devicetree/bindings/sound/qcom,qaif-cpu.yaml b/Documentation/devicetree/bindings/sound/qcom,qaif-cpu.yaml
> > new file mode 100644
> > index 000000000000..134356114733
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/sound/qcom,qaif-cpu.yaml
> > @@ -0,0 +1,307 @@
> > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> > +%YAML 1.2
> > +---
> > +$id: http://devicetree.org/schemas/sound/qcom,qaif-cpu.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: Qualcomm Audio Interface (QAIF) CPU DAI Controller
> > +
> > +maintainers:
> > + - Harendra Gautam <harendra.gautam@oss.qualcomm.com>
> > +
> > +description: |
> > + The Qualcomm Audio Interface (QAIF) is a fully configurable DMA-based
> > + audio subsystem controller. It serialises and deserialises PCM audio
> > + between system memory and external serial audio peripherals (PCM, TDM,
> > + I2S, MI2S) through the AIF path, and transfers parallel audio between
> > + memory and an internal WCD codec through the CIF path.
> > +
> > + AIF (Audio Interface): up to 13 multi-lane Unified Audio Interfaces,
> > + each supporting up to 8 independent data lanes. Each lane is individually
> > + configurable as TX (output/speaker) or RX (input/mic). All lanes of an
> > + interface share a single bit clock and frame sync. Supported modes are
> > + PCM (short/long sync), TDM, and MI2S (stereo/mono). Per-interface
> > + configuration includes sync source (master/slave), sync mode, sync delay,
> > + sync inversion, slot width (8/16/24/32-bit), sample width, active slot
> > + masks (up to 32 slots), bits-per-lane frame size, lane enable/direction
> > + masks, loopback, output-enable control, and full-cycle path support for
> > + long chip-to-chip connections.
> > +
> > + CIF (Codec Interface): up to 10 RDDMA (playback) and 10 WRDMA (capture)
> > + channels connecting to an internal codec over a parallel bus. Each channel
> > + supports active-channel enable mask (up to 16 channels), frame-sync
> > + selection, frame-sync delay, frame-sync output gating, dynamic clock
> > + gating, and 16-bit packing/unpacking.
> > +
> > + Note on RX/TX naming convention: in QAIF, TX refers to the output
> > + (speaker/playback) direction and RX refers to the input (mic/capture)
> > + direction. This applies to both AIF lane directions and CIF slot/mask
> > + properties.
> > +
> > + DMA engine: RDDMA fetches audio from DDR/TCM/LPM into a shared SRAM
> > + latency buffer (SHRAM) and drains it to the interface. WRDMA collects
> > + data from the interface into SHRAM and writes it to memory. Each DMA
> > + owns a private SHRAM region defined by start address and length registers.
> > + Burst sizes of 1/2/4/8/16 beats (64-bit) are supported with up to 4
> > + outstanding transactions per DMA. Two QSB master ports (QXM0 for TCM,
> > + QXM1 for DDR/LPM) provide the memory interface.
> > +
> > + Resources are partitioned among up to 5 Execution Engines (EEs) via
> > + EE map registers. Each EE owns a set of DMAs, audio interfaces, and
> > + interface groups, and receives its own independent interrupt output.
> > + The interrupt hierarchy has a two-level structure: a summary register
> > + identifies the event class (DMA period, underflow/overflow, error
> > + response, audio interface underflow/overflow, group done, rate detector,
> > + VFR), and per-resource status registers identify the specific channel.
> > +
> > + Interface grouping (bonding) allows up to 6 groups of audio and codec
> > + interfaces to start synchronously and align their DMA period interrupts
> > + within half a frame duration using the RDDMA padding feature.
> > +
> > + Two rate detector blocks measure the frequency of incoming frame sync or
> > + word select signals and generate interrupts on rate change, undetected
> > + rate, or sync timeout.
> > +
> > + Block diagram::
> > +
> > + System Memory (DDR / LPM / TCM)
> > + +---------------------------------+
> > + | Circular Buffers (ping-pong) |
> > + +----------+----------+-----------+
> > + | ^
> > + 64-bit AXI 64-bit AXI
> > + | |
> > + +----------v----------+-----------+
> > + | QSB Master Ports |
> > + | +----------+ +----------+ |
> > + | | QXM0 | | QXM1 | |
> > + | +----+-----+ +-----+----+ |
> > + +-------|--------------|----------+
> > + | |
> > + +-------v--------------v----------+
> > + | Shared RAM (SHRAM) |
> > + | +------------+ +------------+ |
> > + | | QXM0 Read | | QXM0 Write | |
> > + | | SHRAM | | SHRAM | |
> > + | +------------+ +------------+ |
> > + | +------------+ +------------+ |
> > + | | QXM1 Read | | QXM1 Write | |
> > + | | SHRAM | | SHRAM | |
> > + | +------------+ +------------+ |
> > + +---+--------+--------+-------+---+
> > + | | | |
> > + +---v--+ +--v---+ +--v---+ +-v----+
> > + |RDDMA | |RDDMA | |WRDMA | |WRDMA |
> > + | AIF | | CIF | | AIF | | CIF |
> > + |[0..n]| |[0..n]| |[0..n]| |[0..n]|
> > + +--+---+ +--+---+ +--+---+ +-+----+
> > + | | ^ ^
> > + | TX | TX | RX | RX
> > + v v | |
> > + +--+--------------------+ +----+----------+
> > + | Unified Audio Intf | | Codec DMA |
> > + | (AIF 0..12) | | Interface |
> > + | | | (CIF) |
> > + | AUD_INTFa block: | | |
> > + | - Serializer (TX) | | RDDMA: DDR -> |
> > + | - De-serializer (RX) | | internal |
> > + | - Sync gen/detect | | codec |
> > + | - Up to 8 data lanes | | WRDMA: codec |
> > + | - PCM / TDM / MI2S | | -> DDR |
> > + | - Near Pad Logic | | Up to 16 ch |
> > + +--+--------------------+ +----+----------+
> > + | Lane 0..7 (TX/RX) | Parallel bus
> > + | Bit clk + Frame sync | + Frame sync
> > + v v
> > + +--+--------+ +------+------+
> > + | External | | Internal |
> > + | Serial | | Digital |
> > + | Peripherals| | Codec |
> > + | (PCM/TDM/ | | (Bolero/ |
> > + | MI2S) | | WCD) |
> > + +-----------+ +-------------+
> > +
> > +allOf:
> > + - $ref: dai-common.yaml#
> > +
> > +properties:
> > + compatible:
> > + const: qcom,shikra-qaif-cpu
> > +
> > + reg:
> > + maxItems: 1
> > + description: QAIF core registers
> > +
> > + interrupts:
> > + maxItems: 1
> > + description:
> > + QAIF summary interrupt for this Execution Engine. Signals DMA period
> > + completion, buffer underflow/overflow, error response, audio interface
> > + underflow/overflow, interface-group done, rate detector and VFR events.
> > +
> > + iommus:
> > + maxItems: 1
> > + description: Phandle to apps_smmu node with sid mask
> > +
> > + dma-coherent: true
> > +
> > + clocks:
> > + minItems: 5
> > + maxItems: 9
> > +
> > + clock-names:
> > + description:
> > + The first five clocks are always required. Any further entries are the
> > + per-AIF bit clocks (aif_if<N>_ibit), supplied in order starting from
> > + AIF interface 0 for as many serial AIF interfaces as the board uses.
> > + minItems: 5
> > + items:
> > + - const: lpass_config
> > + - const: lpass_core_axim
> > + - const: aud_dma
> > + - const: aud_dma_mem
> > + - const: bus
> > + - const: aif_if0_ibit
> > + - const: aif_if1_ibit
> > + - const: aif_if2_ibit
> > + - const: aif_if3_ibit
> > +
> > + '#sound-dai-cells':
> > + const: 1
> > +
> > + '#address-cells':
> > + const: 1
> > +
> > + '#size-cells':
> > + const: 0
> > +
> > +patternProperties:
> > + '^aif@[0-9a-f]+$':
> > + type: object
> > + description:
> > + QAIF AIF interface child node for PCM, TDM or MI2S configuration.
> > +
> > + properties:
> > + reg:
> > + maxItems: 1
> > + description:
> > + DAI ID of the AIF interface (QAIF_MI2S_AIF* or QAIF_TDM_AIF*).
> > +
> > + dai-format:
> > + description: Serial audio interface format (MI2S, TDM or PCM).
> > + enum: [i2s, dsp_a, dsp_b]
> > +
> > + dai-tdm-slot-width:
> > + $ref: /schemas/types.yaml#/definitions/uint32
> > + enum: [8, 16, 24, 32]
> > + description:
> > + Slot width in bits.
> > +
> > + dai-tdm-slot-num:
> > + $ref: /schemas/types.yaml#/definitions/uint32
> > + description:
> > + Number of slots per lane.
> > + minimum: 1
> > + maximum: 32
> > +
> > + dai-tdm-slot-rx-mask:
> > + $ref: /schemas/types.yaml#/definitions/uint32-array
> > + description:
> > + Active RX slots, one entry per slot. A nonzero value marks the
> > + slot as active.
> > + minItems: 1
> > + maxItems: 32
> > +
> > + dai-tdm-slot-tx-mask:
> > + $ref: /schemas/types.yaml#/definitions/uint32-array
> > + description:
> > + Active TX slots, one entry per slot. A nonzero value marks the
> > + slot as active.
> > + minItems: 1
> > + maxItems: 32
> > +
> > + qcom,qaif-aif-lane-map:
> > + $ref: /schemas/types.yaml#/definitions/uint32-array
> > + description:
> > + Per-lane direction map, one entry per lane starting from lane 0.
> > + Use 0 for TX (output/speaker) and 1 for RX (input/mic).
> > + minItems: 1
> > + maxItems: 8
> > + items:
> > + enum: [0, 1]
> > +
> > + required:
> > + - reg
> > + - dai-format
> > + - qcom,qaif-aif-lane-map
> > +
> > + if:
> > + properties:
> > + dai-format:
> > + enum: [dsp_a, dsp_b]
> > + then:
> > + required:
> > + - dai-tdm-slot-width
> > + - dai-tdm-slot-num
> > + - dai-tdm-slot-rx-mask
> > + - dai-tdm-slot-tx-mask
> > +
> > + additionalProperties: false
> > +
> > +required:
> > + - compatible
> > + - reg
> > + - interrupts
> > + - iommus
> > + - clocks
> > + - clock-names
> > + - '#sound-dai-cells'
> > + - '#address-cells'
> > + - '#size-cells'
> > +
> > +unevaluatedProperties: false
> > +
> > +examples:
> > + - |
> > + soc {
> > + #address-cells = <2>;
> > + #size-cells = <2>;
> > +
> > + qaif_cpu: audio-controller@a000000 {
> > + compatible = "qcom,shikra-qaif-cpu";
> > + reg = <0x0 0x0a000000 0x0 0x20000>;
> > + interrupts = <0 331 4>;
> > + iommus = <&apps_smmu 0x1c0 0x0>;
> > + clocks = <&gcc 213>,
> > + <&gcc 214>,
> > + <&audiocorecc 15>,
> > + <&audiocorecc 17>,
> > + <&audiocorecc 18>,
> > + <&audiocorecc 5>,
> > + <&audiocorecc 8>,
> > + <&audiocorecc 11>,
> > + <&audiocorecc 14>;
> > + clock-names = "lpass_config",
> > + "lpass_core_axim",
> > + "aud_dma",
> > + "aud_dma_mem",
> > + "bus",
> > + "aif_if0_ibit",
> > + "aif_if1_ibit",
> > + "aif_if2_ibit",
> > + "aif_if3_ibit";
> > + #sound-dai-cells = <1>;
> > + #address-cells = <1>;
> > + #size-cells = <0>;
> > +
> > + aif@d7 {
> > + reg = <215>;
> > + dai-format = "dsp_a";
> > + dai-tdm-slot-width = <32>;
> > + dai-tdm-slot-num = <2>;
> > + dai-tdm-slot-rx-mask = <1 1>;
> > + dai-tdm-slot-tx-mask = <1 1>;
> > + qcom,qaif-aif-lane-map = <1 0>;
> > + };
> > + };
> > + };
> > diff --git a/include/dt-bindings/sound/qcom,qaif.h b/include/dt-bindings/sound/qcom,qaif.h
> > new file mode 100644
> > index 000000000000..24706efd07d1
> > --- /dev/null
> > +++ b/include/dt-bindings/sound/qcom,qaif.h
> > @@ -0,0 +1,97 @@
> > +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
> > +/*
> > + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
> > + *
> > + * DAI IDs for the Qualcomm Audio Interface (QAIF) controller.
> > + * QAIF_MI2S_AIF* and QAIF_TDM_AIF* values are used in sound-dai
> > + * references and as the reg value of aif@N child nodes.
> > + * QAIF_CDC_DMA_* values are for sound-dai references only and must
> > + * not be used as aif@N child node reg values.
> > + */
> > +#ifndef __DT_QCOM_QAIF_H
> > +#define __DT_QCOM_QAIF_H
> > +
> > +/*
> > + * MI2S DAI IDs -- one per physical AIF port in MI2S mode.
> > + * Each port supports up to 2 channels (stereo I2S) over a single
> > + * data lane sharing a bit clock and frame sync.
> > + */
> > +#define QAIF_MI2S_AIF0 200
> > +#define QAIF_MI2S_AIF1 201
> > +#define QAIF_MI2S_AIF2 202
> > +#define QAIF_MI2S_AIF3 203
> > +#define QAIF_MI2S_AIF4 204
> > +#define QAIF_MI2S_AIF5 205
> > +#define QAIF_MI2S_AIF6 206
> > +#define QAIF_MI2S_AIF7 207
> > +#define QAIF_MI2S_AIF8 208
> > +#define QAIF_MI2S_AIF9 209
> > +#define QAIF_MI2S_AIF10 210
> > +#define QAIF_MI2S_AIF11 211
> > +#define QAIF_MI2S_AIF12 212
> > +
> > +/*
> > + * TDM DAI IDs -- one per physical AIF port in TDM mode.
> > + * Each port supports up to 8 channels over up to 8 independent data
> > + * lanes sharing a single bit clock and frame sync.
> > + */
> > +#define QAIF_TDM_AIF0 213
> > +#define QAIF_TDM_AIF1 214
> > +#define QAIF_TDM_AIF2 215
> > +#define QAIF_TDM_AIF3 216
> > +#define QAIF_TDM_AIF4 217
> > +#define QAIF_TDM_AIF5 218
> > +#define QAIF_TDM_AIF6 219
> > +#define QAIF_TDM_AIF7 220
> > +#define QAIF_TDM_AIF8 221
> > +#define QAIF_TDM_AIF9 222
> > +#define QAIF_TDM_AIF10 223
> > +#define QAIF_TDM_AIF11 224
> > +#define QAIF_TDM_AIF12 225
> > +
> > +/*
> > + * CIF (Codec Interface) RX DAI IDs -- playback to internal codec.
> > + * RDDMA channels fetch audio from memory and drain it to the codec.
> > + */
> > +#define QAIF_CDC_DMA_RX0 226
> > +#define QAIF_CDC_DMA_RX1 227
> > +#define QAIF_CDC_DMA_RX2 228
> > +#define QAIF_CDC_DMA_RX3 229
> > +#define QAIF_CDC_DMA_RX4 230
> > +#define QAIF_CDC_DMA_RX5 231
> > +#define QAIF_CDC_DMA_RX6 232
> > +#define QAIF_CDC_DMA_RX7 233
> > +#define QAIF_CDC_DMA_RX8 234
> > +#define QAIF_CDC_DMA_RX9 235
> > +
> > +/*
> > + * CIF (Codec Interface) TX DAI IDs -- capture from internal codec.
> > + * WRDMA channels collect audio from the codec and write it to memory.
> > + */
> > +#define QAIF_CDC_DMA_TX0 236
> > +#define QAIF_CDC_DMA_TX1 237
> > +#define QAIF_CDC_DMA_TX2 238
> > +#define QAIF_CDC_DMA_TX3 239
> > +#define QAIF_CDC_DMA_TX4 240
> > +#define QAIF_CDC_DMA_TX5 241
> > +#define QAIF_CDC_DMA_TX6 242
> > +#define QAIF_CDC_DMA_TX7 243
> > +#define QAIF_CDC_DMA_TX8 244
> > +#define QAIF_CDC_DMA_TX9 245
> > +
> > +/*
> > + * CIF (Codec Interface) VA TX DAI IDs -- capture from voice activity codec.
> > + * WRDMA channels collect audio from the VA codec and write it to memory.
> > + */
> > +#define QAIF_CDC_DMA_VA_TX0 246
> > +#define QAIF_CDC_DMA_VA_TX1 247
> > +#define QAIF_CDC_DMA_VA_TX2 248
> > +#define QAIF_CDC_DMA_VA_TX3 249
> > +#define QAIF_CDC_DMA_VA_TX4 250
> > +#define QAIF_CDC_DMA_VA_TX5 251
> > +#define QAIF_CDC_DMA_VA_TX6 252
> > +#define QAIF_CDC_DMA_VA_TX7 253
> > +#define QAIF_CDC_DMA_VA_TX8 254
> > +#define QAIF_CDC_DMA_VA_TX9 255
> > +
>
> These DAI IDs exceed the LPASS_MAX_PORT limit, which will cause sound
> card registration to fail.
>
> Check sound/soc/qcom/common.c, as the current indices (246-255) are
> beyond the supported LPASS port range.
>
> Best Regards,
> Rafi.
Thanks for pointing this out. We can either add the range check for
min/max QAIF DAI IDs in qcom/common.c or introduce a common helper in
qcom/common.h to validate the supported DAI IDs across Qualcomm
platforms.
-Harendra
>
> > +#endif /* __DT_QCOM_QAIF_H */
>
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH v3 1/9] ASoC: dt-bindings: qcom,qaif-cpu: Add binding
2026-08-26 9:39 ` Harendra Gautam
@ 2026-08-26 9:43 ` Srinivas Kandagatla
2026-08-26 9:55 ` Harendra Gautam
0 siblings, 1 reply; 32+ messages in thread
From: Srinivas Kandagatla @ 2026-08-26 9:43 UTC (permalink / raw)
To: Harendra Gautam, Mohammad Rafi Shaik
Cc: Srinivas Kandagatla, Mark Brown, Liam Girdwood, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Jaroslav Kysela, Takashi Iwai,
linux-sound, linux-arm-msm, devicetree, linux-kernel,
Prasad Kumpatla, Krzysztof Kozlowski, Sarath Ganapathiraju,
Kumar Anurag Singh
On 8/26/26 10:39 AM, Harendra Gautam wrote:
>>> + * CIF (Codec Interface) VA TX DAI IDs -- capture from voice activity codec.
>>> + * WRDMA channels collect audio from the VA codec and write it to memory.
>>> + */
>>> +#define QAIF_CDC_DMA_VA_TX0 246
>>> +#define QAIF_CDC_DMA_VA_TX1 247
>>> +#define QAIF_CDC_DMA_VA_TX2 248
>>> +#define QAIF_CDC_DMA_VA_TX3 249
>>> +#define QAIF_CDC_DMA_VA_TX4 250
>>> +#define QAIF_CDC_DMA_VA_TX5 251
>>> +#define QAIF_CDC_DMA_VA_TX6 252
>>> +#define QAIF_CDC_DMA_VA_TX7 253
>>> +#define QAIF_CDC_DMA_VA_TX8 254
>>> +#define QAIF_CDC_DMA_VA_TX9 255
>>> +
>> These DAI IDs exceed the LPASS_MAX_PORT limit, which will cause sound
>> card registration to fail.
>>
>> Check sound/soc/qcom/common.c, as the current indices (246-255) are
>> beyond the supported LPASS port range.
>>
>> Best Regards,
>> Rafi.
> Thanks for pointing this out. We can either add the range check for
> min/max QAIF DAI IDs in qcom/common.c or introduce a common helper in
> qcom/common.h to validate the supported DAI IDs across Qualcomm
> platforms.
You should add these ids to
include/dt-bindings/sound/qcom,q6dsp-lpass-ports.h instead to avoid
conflicts with common code.
--srini
> -Harendra
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH v3 1/9] ASoC: dt-bindings: qcom,qaif-cpu: Add binding
2026-08-26 9:43 ` Srinivas Kandagatla
@ 2026-08-26 9:55 ` Harendra Gautam
2026-08-26 10:01 ` Srinivas Kandagatla
0 siblings, 1 reply; 32+ messages in thread
From: Harendra Gautam @ 2026-08-26 9:55 UTC (permalink / raw)
To: Srinivas Kandagatla
Cc: Mohammad Rafi Shaik, Srinivas Kandagatla, Mark Brown,
Liam Girdwood, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Jaroslav Kysela, Takashi Iwai, linux-sound, linux-arm-msm,
devicetree, linux-kernel, Prasad Kumpatla, Krzysztof Kozlowski,
Sarath Ganapathiraju, Kumar Anurag Singh
On Wed, Aug 26, 2026 at 3:13 PM Srinivas Kandagatla
<srinivas.kandagatla@oss.qualcomm.com> wrote:
>
>
>
> On 8/26/26 10:39 AM, Harendra Gautam wrote:
> >>> + * CIF (Codec Interface) VA TX DAI IDs -- capture from voice activity codec.
> >>> + * WRDMA channels collect audio from the VA codec and write it to memory.
> >>> + */
> >>> +#define QAIF_CDC_DMA_VA_TX0 246
> >>> +#define QAIF_CDC_DMA_VA_TX1 247
> >>> +#define QAIF_CDC_DMA_VA_TX2 248
> >>> +#define QAIF_CDC_DMA_VA_TX3 249
> >>> +#define QAIF_CDC_DMA_VA_TX4 250
> >>> +#define QAIF_CDC_DMA_VA_TX5 251
> >>> +#define QAIF_CDC_DMA_VA_TX6 252
> >>> +#define QAIF_CDC_DMA_VA_TX7 253
> >>> +#define QAIF_CDC_DMA_VA_TX8 254
> >>> +#define QAIF_CDC_DMA_VA_TX9 255
> >>> +
> >> These DAI IDs exceed the LPASS_MAX_PORT limit, which will cause sound
> >> card registration to fail.
> >>
> >> Check sound/soc/qcom/common.c, as the current indices (246-255) are
> >> beyond the supported LPASS port range.
> >>
> >> Best Regards,
> >> Rafi.
> > Thanks for pointing this out. We can either add the range check for
> > min/max QAIF DAI IDs in qcom/common.c or introduce a common helper in
> > qcom/common.h to validate the supported DAI IDs across Qualcomm
> > platforms.
>
> You should add these ids to
> include/dt-bindings/sound/qcom,q6dsp-lpass-ports.h instead to avoid
> conflicts with common code.
>
> --srini
Thanks for the suggestion. qcom,q6dsp-lpass-ports.h is specific to Q6
DSP/AFE virtual port IDs. Since QAIF is a direct MMIO driver with no
Q6 DSP involvement, would adding QAIF IDs there not be misleading?
would it be better to update the range check in common.c/common.h to
accommodate both LPASS and QAIF DAI ID ranges instead?
-Harendra
> > -Harendra
>
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH v3 1/9] ASoC: dt-bindings: qcom,qaif-cpu: Add binding
2026-08-26 9:55 ` Harendra Gautam
@ 2026-08-26 10:01 ` Srinivas Kandagatla
2026-08-26 10:06 ` Harendra Gautam
0 siblings, 1 reply; 32+ messages in thread
From: Srinivas Kandagatla @ 2026-08-26 10:01 UTC (permalink / raw)
To: Harendra Gautam, Srinivas Kandagatla
Cc: Mohammad Rafi Shaik, Srinivas Kandagatla, Mark Brown,
Liam Girdwood, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Jaroslav Kysela, Takashi Iwai, linux-sound, linux-arm-msm,
devicetree, linux-kernel, Prasad Kumpatla, Krzysztof Kozlowski,
Sarath Ganapathiraju, Kumar Anurag Singh
On 8/26/26 10:55 AM, Harendra Gautam wrote:
> On Wed, Aug 26, 2026 at 3:13 PM Srinivas Kandagatla
> <srinivas.kandagatla@oss.qualcomm.com> wrote:
>>
>>
>>
>> On 8/26/26 10:39 AM, Harendra Gautam wrote:
>>>>> + * CIF (Codec Interface) VA TX DAI IDs -- capture from voice activity codec.
>>>>> + * WRDMA channels collect audio from the VA codec and write it to memory.
>>>>> + */
>>>>> +#define QAIF_CDC_DMA_VA_TX0 246
>>>>> +#define QAIF_CDC_DMA_VA_TX1 247
>>>>> +#define QAIF_CDC_DMA_VA_TX2 248
>>>>> +#define QAIF_CDC_DMA_VA_TX3 249
>>>>> +#define QAIF_CDC_DMA_VA_TX4 250
>>>>> +#define QAIF_CDC_DMA_VA_TX5 251
>>>>> +#define QAIF_CDC_DMA_VA_TX6 252
>>>>> +#define QAIF_CDC_DMA_VA_TX7 253
>>>>> +#define QAIF_CDC_DMA_VA_TX8 254
>>>>> +#define QAIF_CDC_DMA_VA_TX9 255
>>>>> +
>>>> These DAI IDs exceed the LPASS_MAX_PORT limit, which will cause sound
>>>> card registration to fail.
>>>>
>>>> Check sound/soc/qcom/common.c, as the current indices (246-255) are
>>>> beyond the supported LPASS port range.
>>>>
>>>> Best Regards,
>>>> Rafi.
>>> Thanks for pointing this out. We can either add the range check for
>>> min/max QAIF DAI IDs in qcom/common.c or introduce a common helper in
>>> qcom/common.h to validate the supported DAI IDs across Qualcomm
>>> platforms.
>>
>> You should add these ids to
>> include/dt-bindings/sound/qcom,q6dsp-lpass-ports.h instead to avoid
>> conflicts with common code.
>>
>> --srini
> Thanks for the suggestion. qcom,q6dsp-lpass-ports.h is specific to Q6
> DSP/AFE virtual port IDs. Since QAIF is a direct MMIO driver with no
> Q6 DSP involvement, would adding QAIF IDs there not be misleading?
These are IDs that will be reused across both dsp and non-dsp solution.
So it makes more sense to keep it in one single place to allow the
hardware description (DT) unchanged across different software solutions.
> would it be better to update the range check in common.c/common.h to
> accommodate both LPASS and QAIF DAI ID ranges instead?
No, that does not make sense because these numbering might conflicting
with other ports in future.
--srini
THat
> -Harendra
>>> -Harendra
>>
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH v3 1/9] ASoC: dt-bindings: qcom,qaif-cpu: Add binding
2026-08-26 10:01 ` Srinivas Kandagatla
@ 2026-08-26 10:06 ` Harendra Gautam
2026-08-26 10:25 ` Harendra Gautam
0 siblings, 1 reply; 32+ messages in thread
From: Harendra Gautam @ 2026-08-26 10:06 UTC (permalink / raw)
To: Srinivas Kandagatla
Cc: Srinivas Kandagatla, Mohammad Rafi Shaik, Mark Brown,
Liam Girdwood, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Jaroslav Kysela, Takashi Iwai, linux-sound, linux-arm-msm,
devicetree, linux-kernel, Prasad Kumpatla, Krzysztof Kozlowski,
Sarath Ganapathiraju, Kumar Anurag Singh
On Wed, Aug 26, 2026 at 3:31 PM Srinivas Kandagatla <srini@kernel.org> wrote:
>
>
>
> On 8/26/26 10:55 AM, Harendra Gautam wrote:
> > On Wed, Aug 26, 2026 at 3:13 PM Srinivas Kandagatla
> > <srinivas.kandagatla@oss.qualcomm.com> wrote:
> >>
> >>
> >>
> >> On 8/26/26 10:39 AM, Harendra Gautam wrote:
> >>>>> + * CIF (Codec Interface) VA TX DAI IDs -- capture from voice activity codec.
> >>>>> + * WRDMA channels collect audio from the VA codec and write it to memory.
> >>>>> + */
> >>>>> +#define QAIF_CDC_DMA_VA_TX0 246
> >>>>> +#define QAIF_CDC_DMA_VA_TX1 247
> >>>>> +#define QAIF_CDC_DMA_VA_TX2 248
> >>>>> +#define QAIF_CDC_DMA_VA_TX3 249
> >>>>> +#define QAIF_CDC_DMA_VA_TX4 250
> >>>>> +#define QAIF_CDC_DMA_VA_TX5 251
> >>>>> +#define QAIF_CDC_DMA_VA_TX6 252
> >>>>> +#define QAIF_CDC_DMA_VA_TX7 253
> >>>>> +#define QAIF_CDC_DMA_VA_TX8 254
> >>>>> +#define QAIF_CDC_DMA_VA_TX9 255
> >>>>> +
> >>>> These DAI IDs exceed the LPASS_MAX_PORT limit, which will cause sound
> >>>> card registration to fail.
> >>>>
> >>>> Check sound/soc/qcom/common.c, as the current indices (246-255) are
> >>>> beyond the supported LPASS port range.
> >>>>
> >>>> Best Regards,
> >>>> Rafi.
> >>> Thanks for pointing this out. We can either add the range check for
> >>> min/max QAIF DAI IDs in qcom/common.c or introduce a common helper in
> >>> qcom/common.h to validate the supported DAI IDs across Qualcomm
> >>> platforms.
> >>
> >> You should add these ids to
> >> include/dt-bindings/sound/qcom,q6dsp-lpass-ports.h instead to avoid
> >> conflicts with common code.
> >>
> >> --srini
> > Thanks for the suggestion. qcom,q6dsp-lpass-ports.h is specific to Q6
> > DSP/AFE virtual port IDs. Since QAIF is a direct MMIO driver with no
> > Q6 DSP involvement, would adding QAIF IDs there not be misleading?
>
> These are IDs that will be reused across both dsp and non-dsp solution.
> So it makes more sense to keep it in one single place to allow the
> hardware description (DT) unchanged across different software solutions.
>
>
> > would it be better to update the range check in common.c/common.h to
> > accommodate both LPASS and QAIF DAI ID ranges instead?
> No, that does not make sense because these numbering might conflicting
> with other ports in future.
>
> --srini
Thanks for the clarification. Will add QAIF DAI IDs in qcom,q6dsp-lpass-ports.h.
-Harendra
>
>
> THat
> > -Harendra
> >>> -Harendra
> >>
>
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH v3 8/9] ASoC: qcom: Add Shikra QAIF support
2026-08-26 8:58 ` Harendra Gautam
@ 2026-08-26 10:13 ` Srinivas Kandagatla
2026-08-26 10:37 ` Harendra Gautam
0 siblings, 1 reply; 32+ messages in thread
From: Srinivas Kandagatla @ 2026-08-26 10:13 UTC (permalink / raw)
To: Harendra Gautam, Mohammad Rafi Shaik
Cc: Srinivas Kandagatla, Mark Brown, Liam Girdwood, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Jaroslav Kysela, Takashi Iwai,
linux-sound, linux-arm-msm, devicetree, linux-kernel,
Prasad Kumpatla, Krzysztof Kozlowski, Sarath Ganapathiraju,
Kumar Anurag Singh
On 8/26/26 9:58 AM, Harendra Gautam wrote:
>>> + .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.
WCD naming is totally incorrect w.r.t this driver, WCD is external
codec, which can be connected to any dai. QAIF just exposes FE dais It
should not have any codec level information either as names or any other.
Pl remove and use the correct naming which reflect the dai name w.r.t to
QAIF.
--srini
> -Harendra
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH v3 1/9] ASoC: dt-bindings: qcom,qaif-cpu: Add binding
2026-08-26 10:06 ` Harendra Gautam
@ 2026-08-26 10:25 ` Harendra Gautam
0 siblings, 0 replies; 32+ messages in thread
From: Harendra Gautam @ 2026-08-26 10:25 UTC (permalink / raw)
To: Srinivas Kandagatla
Cc: Srinivas Kandagatla, Mohammad Rafi Shaik, Mark Brown,
Liam Girdwood, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Jaroslav Kysela, Takashi Iwai, linux-sound, linux-arm-msm,
devicetree, linux-kernel, Prasad Kumpatla, Krzysztof Kozlowski,
Sarath Ganapathiraju, Kumar Anurag Singh
On Wed, Aug 26, 2026 at 3:36 PM Harendra Gautam
<harendra.gautam@oss.qualcomm.com> wrote:
>
> On Wed, Aug 26, 2026 at 3:31 PM Srinivas Kandagatla <srini@kernel.org> wrote:
> >
> >
> >
> > On 8/26/26 10:55 AM, Harendra Gautam wrote:
> > > On Wed, Aug 26, 2026 at 3:13 PM Srinivas Kandagatla
> > > <srinivas.kandagatla@oss.qualcomm.com> wrote:
> > >>
> > >>
> > >>
> > >> On 8/26/26 10:39 AM, Harendra Gautam wrote:
> > >>>>> + * CIF (Codec Interface) VA TX DAI IDs -- capture from voice activity codec.
> > >>>>> + * WRDMA channels collect audio from the VA codec and write it to memory.
> > >>>>> + */
> > >>>>> +#define QAIF_CDC_DMA_VA_TX0 246
> > >>>>> +#define QAIF_CDC_DMA_VA_TX1 247
> > >>>>> +#define QAIF_CDC_DMA_VA_TX2 248
> > >>>>> +#define QAIF_CDC_DMA_VA_TX3 249
> > >>>>> +#define QAIF_CDC_DMA_VA_TX4 250
> > >>>>> +#define QAIF_CDC_DMA_VA_TX5 251
> > >>>>> +#define QAIF_CDC_DMA_VA_TX6 252
> > >>>>> +#define QAIF_CDC_DMA_VA_TX7 253
> > >>>>> +#define QAIF_CDC_DMA_VA_TX8 254
> > >>>>> +#define QAIF_CDC_DMA_VA_TX9 255
> > >>>>> +
> > >>>> These DAI IDs exceed the LPASS_MAX_PORT limit, which will cause sound
> > >>>> card registration to fail.
> > >>>>
> > >>>> Check sound/soc/qcom/common.c, as the current indices (246-255) are
> > >>>> beyond the supported LPASS port range.
> > >>>>
> > >>>> Best Regards,
> > >>>> Rafi.
> > >>> Thanks for pointing this out. We can either add the range check for
> > >>> min/max QAIF DAI IDs in qcom/common.c or introduce a common helper in
> > >>> qcom/common.h to validate the supported DAI IDs across Qualcomm
> > >>> platforms.
> > >>
> > >> You should add these ids to
> > >> include/dt-bindings/sound/qcom,q6dsp-lpass-ports.h instead to avoid
> > >> conflicts with common code.
> > >>
> > >> --srini
> > > Thanks for the suggestion. qcom,q6dsp-lpass-ports.h is specific to Q6
> > > DSP/AFE virtual port IDs. Since QAIF is a direct MMIO driver with no
> > > Q6 DSP involvement, would adding QAIF IDs there not be misleading?
> >
> > These are IDs that will be reused across both dsp and non-dsp solution.
> > So it makes more sense to keep it in one single place to allow the
> > hardware description (DT) unchanged across different software solutions.
> >
> >
> > > would it be better to update the range check in common.c/common.h to
> > > accommodate both LPASS and QAIF DAI ID ranges instead?
> > No, that does not make sense because these numbering might conflicting
> > with other ports in future.
> >
> > --srini
Just checked the code. If QAIF DAIs are added to
qcom,q6dsp-lpass-ports.h, LPASS_MAX_PORT becomes QAIF_CDC_DMA_VA_TX9 +
1, increasing q6afe_dai_data, q6apm_lpass_dai_data, and afe_port_map
by 56 entries. Is that acceptable?
-Harendra
> Thanks for the clarification. Will add QAIF DAI IDs in qcom,q6dsp-lpass-ports.h.
> -Harendra
> >
> >
> > THat
> > > -Harendra
> > >>> -Harendra
> > >>
> >
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH v3 8/9] ASoC: qcom: Add Shikra QAIF support
2026-08-26 10:13 ` Srinivas Kandagatla
@ 2026-08-26 10:37 ` Harendra Gautam
0 siblings, 0 replies; 32+ messages in thread
From: Harendra Gautam @ 2026-08-26 10:37 UTC (permalink / raw)
To: Srinivas Kandagatla
Cc: Mohammad Rafi Shaik, Srinivas Kandagatla, Mark Brown,
Liam Girdwood, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Jaroslav Kysela, Takashi Iwai, linux-sound, linux-arm-msm,
devicetree, linux-kernel, Prasad Kumpatla, Krzysztof Kozlowski,
Sarath Ganapathiraju, Kumar Anurag Singh
On Wed, Aug 26, 2026 at 3:43 PM Srinivas Kandagatla
<srinivas.kandagatla@oss.qualcomm.com> wrote:
>
> On 8/26/26 9:58 AM, Harendra Gautam wrote:
> >>> + .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.
>
> WCD naming is totally incorrect w.r.t this driver, WCD is external
> codec, which can be connected to any dai. QAIF just exposes FE dais It
> should not have any codec level information either as names or any other.
> Pl remove and use the correct naming which reflect the dai name w.r.t to
> QAIF.
>
> --srini
Thanks for the suggestion. Will have consistent and correct naming in
the next version.
-Harendra
>
> > -Harendra
>
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH v3 1/9] ASoC: dt-bindings: qcom,qaif-cpu: Add binding
2026-08-26 8:31 ` Mohammad Rafi Shaik
2026-08-26 9:39 ` Harendra Gautam
@ 2026-08-26 23:32 ` Mark Brown
2026-08-27 4:00 ` Harendra Gautam
1 sibling, 1 reply; 32+ messages in thread
From: Mark Brown @ 2026-08-26 23:32 UTC (permalink / raw)
To: Mohammad Rafi Shaik
Cc: Harendra Gautam, Srinivas Kandagatla, Liam Girdwood, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Jaroslav Kysela, Takashi Iwai,
linux-sound, linux-arm-msm, devicetree, linux-kernel,
Prasad Kumpatla, Krzysztof Kozlowski, Sarath Ganapathiraju,
Kumar Anurag Singh
[-- Attachment #1: Type: text/plain, Size: 716 bytes --]
On Wed, Aug 26, 2026 at 02:01:52PM +0530, Mohammad Rafi Shaik wrote:
>
>
> On 8/24/2026 12:06 PM, Harendra Gautam wrote:
> > QAIF routes audio between system memory, external PCM/TDM/MI2S serial
> > interfaces and the internal Bolero/WCD codec. Platform Devicetree files
> > need a binding to describe the controller resources, DAI cells and per-
> > interface AIF configuration, and named constants to avoid raw numeric IDs
> > in sound-dai references and child-node reg values.
Please delete unneeded context from mails when replying. Doing this
makes it much easier to find your reply in the message, helping ensure
it won't be missed by people scrolling through the irrelevant quoted
material.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH v3 1/9] ASoC: dt-bindings: qcom,qaif-cpu: Add binding
2026-08-26 23:32 ` Mark Brown
@ 2026-08-27 4:00 ` Harendra Gautam
0 siblings, 0 replies; 32+ messages in thread
From: Harendra Gautam @ 2026-08-27 4:00 UTC (permalink / raw)
To: Mark Brown
Cc: Mohammad Rafi Shaik, Srinivas Kandagatla, Liam Girdwood,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Jaroslav Kysela,
Takashi Iwai, linux-sound, linux-arm-msm, devicetree,
linux-kernel, Prasad Kumpatla, Krzysztof Kozlowski,
Sarath Ganapathiraju, Kumar Anurag Singh
On Thu, Aug 27, 2026 at 5:02 AM Mark Brown <broonie@kernel.org> wrote:
>
> On Wed, Aug 26, 2026 at 02:01:52PM +0530, Mohammad Rafi Shaik wrote:
> >
> >
> > On 8/24/2026 12:06 PM, Harendra Gautam wrote:
> > > QAIF routes audio between system memory, external PCM/TDM/MI2S serial
> > > interfaces and the internal Bolero/WCD codec. Platform Devicetree files
> > > need a binding to describe the controller resources, DAI cells and per-
> > > interface AIF configuration, and named constants to avoid raw numeric IDs
> > > in sound-dai references and child-node reg values.
>
> Please delete unneeded context from mails when replying. Doing this
> makes it much easier to find your reply in the message, helping ensure
> it won't be missed by people scrolling through the irrelevant quoted
> material.
Thanks for your suggestion, Will keep it in mind next time.
-Harendra
^ permalink raw reply [flat|nested] 32+ messages in thread
end of thread, other threads:[~2026-08-27 4:00 UTC | newest]
Thread overview: 32+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
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 ` [PATCH v3 2/9] ASoC: qcom: Add QAIF shared data structures and variant interface Harendra Gautam
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
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox