Skip to contentSkip to conversation

ASoC: QCOM: Add support for SC7180 lpass variant

PATCH Superseded Ajit Pandey 2 participants 21 messages Apr 11, 2020 – Apr 25, 2020

Subsystems (5)

v1 of 2 Superseded Latest is v2 →

lore
Share & tools
lore
#0 lore raw

cover ASoC: QCOM: Add support for SC7180 lpass variant

We've common ASoC cpu driver for QCOM LPASS soc varaints. This patch chain add support for new variant SC7180 soc by doing the required modification in existing common lpass-cpu driver. Below is a brief summary of patch series:

PATCH 01 ... 04: Update lpass-cpu driver files to make it more generic PATCH 05 ... 08: Add changes to support SC7180 specific configuration PATCH 09 ... 11: Add new drivers and documentation for SC7180 soc lpass

Ajit Pandey (11):
Documentation: device-tree: sound: Update lpass-cpu driver binding
ASoC: qcom: lpass: Add struct lpass_dai to store dai clocks pointer
ASoC: qcom: Add common array to initialize soc based core clocks
ASoC: qcom: lpass-cpu: Make "ahbix-clk" an optional clock.
ASoC: qcom: lpass: Add support for newer lpass version
dt-bindings: sound: Add bindings related to lpass-cpu configuration
Documentation: dt-bindings: sound: Add details for new dai properties
ASoC: qcom : lpass: Add support to configure dai's connection mode
device-tree: bindings: sound: lpass-cpu: Add new compatible soc
ASoC: qcom: lpass-sc7180: Add platform driver for lpass audio
ASoC: qcom: lpass-platform: Replace card->dev with component->dev

 .../devicetree/bindings/sound/qcom,lpass-cpu.txt   | 158 -------------
 .../devicetree/bindings/sound/qcom,lpass-cpu.yaml  | 159 +++++++++++++
 include/dt-bindings/sound/qcom,lpass.h             |  31 +++
 sound/soc/qcom/Kconfig                             |   5 +
 sound/soc/qcom/Makefile                            |   2 +
 sound/soc/qcom/lpass-apq8016.c                     |  39 ++-
 sound/soc/qcom/lpass-cpu.c                         | 263 ++++++++++++++-------
 sound/soc/qcom/lpass-lpaif-reg.h                   | 182 +++++++++++++-
 sound/soc/qcom/lpass-platform.c                    |  36 +--
 sound/soc/qcom/lpass-sc7180.c                      | 192 +++++++++++++++
 sound/soc/qcom/lpass.h                             |  40 +++-
 11 files changed, 808 insertions(+), 299 deletions(-)
 delete mode 100644 Documentation/devicetree/bindings/sound/qcom,lpass-cpu.txt
 create mode 100644 Documentation/devicetree/bindings/sound/qcom,lpass-cpu.yaml
 create mode 100644 include/dt-bindings/sound/qcom,lpass.h
 create mode 100644 sound/soc/qcom/lpass-sc7180.c
Signature · 1 line
1.9.1
#1 lore raw

PATCH 1/11 Documentation: device-tree: sound: Update lpass-cpu driver binding

Done the required cleanups to update lpass-cpu binding with newer yaml formats.

---
 .../devicetree/bindings/sound/qcom,lpass-cpu.txt   | 158 ---------------------
 .../devicetree/bindings/sound/qcom,lpass-cpu.yaml  | 103 ++++++++++++++
 2 files changed, 103 insertions(+), 158 deletions(-)
 delete mode 100644 Documentation/devicetree/bindings/sound/qcom,lpass-cpu.txt
 create mode 100644 Documentation/devicetree/bindings/sound/qcom,lpass-cpu.yaml
Documentation/devicetree/bindings/sound/qcom,lpass-cpu.txt deleted +0 -158
deleted file mode 100644
index a49b878..00000000
@@ -1,158 +0,0 @@
-* Qualcomm Technologies LPASS CPU DAI binding
-
-Low-Power Audio SubSystem (LPASS) consist of MI2S interfaces for audio data
-transfer on external codec. LPASS cpu driver is a common code to configure
-MI2S related CPU dai's across different version of LPASS architecture.
-
-- compatible:
-	Usage: required
-	Value type: <stringlist>
-	Definition: compatible string corresponds to lpass variants driver
-		    must be "qcom, lpass-cpu-sc7180" for sc7180 lpass
-		    must be "qcom,apq8016-lpass-cpu" for apq8016 lpass
-- reg:
-	Usage: required
-	Value type: <prop-encoded-array>
-	Definition: must specify the base address and size of the LPAIF CORE
-		    region of lpass variant.
-- reg-names:
-	Usage: required
-	Value type: <stringlist>
-	Definition: must be "lpass-lpaif"
-
-- iommus:
-        Usage: required for "qcom, lpass-cpu-sc7180" compatible string
-        Value type: <prop-encoded-array>
-        Definition: sid mask for lpaif memory region to apps_smmu
-                    must be <&apps_smmu 0x1020 0>
-
-- power-domains:
-	Usage: required for "qcom, lpass-cpu-sc7180" compatible string
-	Value type: <phandle>
-	Definition: reference to power-domains
-		    must be <&lpass_hm LPASS_CORE_HM_GDSCR>
-
-- clocks:
-        Usage: required
-	Value type: <phandle>
-	Definition: reference to the clocks that match clock-names
-
-- clock-names:
-	Usage: required
-	Value type: <stringlist>
-	Definition: The clocks needed depend on the compatible string:
-	qcom,lpass-cpu-apq8016:
-		must be "ahbix-clk", "mi2s-osr-clk", "mi2s-bit-clk0",
-		mi2s-bit-clk1", "mi2s-bit-clk2", "mi2s-bit-clk3",
-		"pcnoc-mport-clk", "pcnoc-sway-clk"
-	qcom, lpass-cpu-sc7180:
-		must be "noc", "audio-core", "mclk0", "sysnoc_mport",
-		"pri_ibit", "sec_ibit"
-
-- #sound-dai-cells
-	Usage: required
-	Value type: <u32>
-	Definition: Must be 1
-
-- interrupts:
-	Usage: required
-	Value type: <prop-encoded-array>
-	Definition: reference to the interrupts that match interrupt-names
-
-- interrupt-names:
-	Usage: required
-	Value type: <stringlist>
-	Definition: must be "lpass-irq-lpaif"
-
-- qcom,adsp:
-        Usage: optional
-        Value type: <phandle>
-	Definition: Phandle for the audio DSP node
-
-= MI2S DAIs (Digial Audio Interface)
-"dais" child node of the lpass node. It represents mi2s dais, each mi2s dai is
-subnode of "dais" representing board specific dai setup & required dai clocks.
-"dais" node should have following properties.
-
-- id:
-	Usage: required for mi2s interface
-	Value type: <u32>
-	Definition: Must be dai id defined in lpass bindings like MI2S_PRIMARY
-
-- qcom,bitclk-name:
-	Usage: required for mi2s interface
-	Value type: <stringlist>
-	Definition: bitclk name corresponds to MI2S of lpass version
-
-- qcom,mclk-name:
-        Usage: optional for mi2s interface
-        Value type: <stringlist>
-        Definition: external mclk name corresponds to MI2S of lpass version
-
-- qcom,osrclk-name:
-        Usage: optional for mi2s interface
-        Value type: <stringlist>
-        Definition: osrclk name corresponds to MI2S of lpass version
-
-- qcom,spkmode-mask:
-        Usage: optional for mi2s interface
-        Value type: <u32>
-        Definition: board specific property to change default spkmode mask
-                    of MI2S dai based on dataline connection on board.
-
-- qcom,micmode-mask:
-        Usage: optional for mi2s interface
-        Value type: <u32>
-        Definition: board specific property to change default micmode mask
-                    of MI2S dai based on dataline connection on board.
-
-- qcom,loopback-mask:
-        Usage: optional for mi2s interface
-        Value type: <u32>
-        Definition: board specific property to change default loopback mask
-                    of MI2S dai as per requirement.
-
-- qcom,wssrc-mask:
-        Usage: optional for mi2s interface
-        Value type: <u32>
-        Definition: board specific property to change default wssrc mask
-                    of MI2S dai based as per requirement.
-
-Example:
-
-lpass_cpu: lpass {
-	compatible = "qcom, lpass-cpu-sc7180";
-
-	reg = <0 0x62F00000 0 0x29000>;
-	reg-names = "lpass-lpaif";
-
-	iommus = <&apps_smmu 0x1020 0>;
-
-	power-domains = <&lpass_hm LPASS_CORE_HM_GDSCR>;
-
-	clocks = <&gcc GCC_LPASS_CFG_NOC_SWAY_CLK>,
-		 <&lpasscorecc LPASS_AUDIO_CORE_CORE_CLK>,
-		 <&lpasscorecc LPASS_AUDIO_CORE_EXT_MCLK0_CLK>,
-		 <&lpasscorecc LPASS_AUDIO_CORE_SYSNOC_MPORT_CORE_CLK>,
-		 <&lpasscorecc LPASS_AUDIO_CORE_LPAIF_PRI_IBIT_CLK>,
-		 <&lpasscorecc LPASS_AUDIO_CORE_LPAIF_SEC_IBIT_CLK>;
-
-	clock-names = "noc", "audio-core", "mclk0", "sysnoc_mport",
-		      "pri_ibit", "sec_ibit";
-
-	#sound-dai-cells = <1>;
-
-	interrupts = <0 160 IRQ_TYPE_LEVEL_HIGH>;
-	interrupt-names = "lpass-irq-lpaif";
-
-	prim-mi2s@0 {
-		id = <MI2S_PRIMARY>;
-		qcom,bitclk-name = "pri_ibit";
-		qcom,mclk-name = "mclk0";
-	};
-
-	sec-mi2s@1 {
-		id = <MI2S_SECONDARY>;
-		qcom,bitclk-name = "sec_ibit";
-	};
-};
Documentation/devicetree/bindings/sound/qcom,lpass-cpu.yaml new file +103 -0

103 lines not on this page · raw message

Signature · 1 line
1.9.1
#2 lore raw

Re: [PATCH 01/11] Documentation: device-tree: sound: Update lpass-cpu driver binding

Quoted 20 lines · Ajit Pandey

Done the required cleanups to update lpass-cpu binding with newer yaml formats.

---
  .../devicetree/bindings/sound/qcom,lpass-cpu.txt   | 158 ---------------------
  .../devicetree/bindings/sound/qcom,lpass-cpu.yaml  | 103 ++++++++++++++
  2 files changed, 103 insertions(+), 158 deletions(-)

delete mode 100644 Documentation/devicetree/bindings/sound/qcom,lpass-cpu.txt create mode 100644 Documentation/devicetree/bindings/sound/qcom,lpass-cpu.yaml

Documentation/devicetree/bindings/sound/qcom,lpass-cpu.txt deleted +0 -1
deleted file mode 100644
index a49b878..00000000
@@ -1,158 +0,0 @@
-* Qualcomm Technologies LPASS CPU DAI binding

Documentation/devicetree/bindings/sound/qcom,lpass-cpu.txt line 11

Quoted 10 lines
Documentation/devicetree/bindings/sound/qcom,lpass-cpu.txt deleted +0 -10
-
-Low-Power Audio SubSystem (LPASS) consist of MI2S interfaces for audio data
-transfer on external codec. LPASS cpu driver is a common code to configure
-MI2S related CPU dai's across different version of LPASS architecture.
-
-- compatible:
-	Usage: required
-	Value type: <stringlist>
-	Definition: compatible string corresponds to lpass variants driver
-		    must be "qcom, lpass-cpu-sc7180" for sc7180 lpass

This patch will not apply on mainline, looks like this was done on top of your local repo, please fix this!

Best thing would be rebase patches top of https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git/log/?h=for-next

Secondly, Split this patch into two,
1> converting in to yaml
2> adding new changes
so that it will be easy to see what exactly changed.

thanks,
srini

Quoted 257 lines
Documentation/devicetree/bindings/sound/qcom,lpass-cpu.txt deleted +0 -147
-		    must be "qcom,apq8016-lpass-cpu" for apq8016 lpass
-- reg:
-	Usage: required
-	Value type: <prop-encoded-array>
-	Definition: must specify the base address and size of the LPAIF CORE
-		    region of lpass variant.
-- reg-names:
-	Usage: required
-	Value type: <stringlist>
-	Definition: must be "lpass-lpaif"
-
-- iommus:
-        Usage: required for "qcom, lpass-cpu-sc7180" compatible string
-        Value type: <prop-encoded-array>
-        Definition: sid mask for lpaif memory region to apps_smmu
-                    must be <&apps_smmu 0x1020 0>
-
-- power-domains:
-	Usage: required for "qcom, lpass-cpu-sc7180" compatible string
-	Value type: <phandle>
-	Definition: reference to power-domains
-		    must be <&lpass_hm LPASS_CORE_HM_GDSCR>
-
-- clocks:
-        Usage: required
-	Value type: <phandle>
-	Definition: reference to the clocks that match clock-names
-
-- clock-names:
-	Usage: required
-	Value type: <stringlist>
-	Definition: The clocks needed depend on the compatible string:
-	qcom,lpass-cpu-apq8016:
-		must be "ahbix-clk", "mi2s-osr-clk", "mi2s-bit-clk0",
-		mi2s-bit-clk1", "mi2s-bit-clk2", "mi2s-bit-clk3",
-		"pcnoc-mport-clk", "pcnoc-sway-clk"
-	qcom, lpass-cpu-sc7180:
-		must be "noc", "audio-core", "mclk0", "sysnoc_mport",
-		"pri_ibit", "sec_ibit"
-
-- #sound-dai-cells
-	Usage: required
-	Value type: <u32>
-	Definition: Must be 1
-
-- interrupts:
-	Usage: required
-	Value type: <prop-encoded-array>
-	Definition: reference to the interrupts that match interrupt-names
-
-- interrupt-names:
-	Usage: required
-	Value type: <stringlist>
-	Definition: must be "lpass-irq-lpaif"
-
-- qcom,adsp:
-        Usage: optional
-        Value type: <phandle>
-	Definition: Phandle for the audio DSP node
-
-= MI2S DAIs (Digial Audio Interface)
-"dais" child node of the lpass node. It represents mi2s dais, each mi2s dai is
-subnode of "dais" representing board specific dai setup & required dai clocks.
-"dais" node should have following properties.
-
-- id:
-	Usage: required for mi2s interface
-	Value type: <u32>
-	Definition: Must be dai id defined in lpass bindings like MI2S_PRIMARY
-
-- qcom,bitclk-name:
-	Usage: required for mi2s interface
-	Value type: <stringlist>
-	Definition: bitclk name corresponds to MI2S of lpass version
-
-- qcom,mclk-name:
-        Usage: optional for mi2s interface
-        Value type: <stringlist>
-        Definition: external mclk name corresponds to MI2S of lpass version
-
-- qcom,osrclk-name:
-        Usage: optional for mi2s interface
-        Value type: <stringlist>
-        Definition: osrclk name corresponds to MI2S of lpass version
-
-- qcom,spkmode-mask:
-        Usage: optional for mi2s interface
-        Value type: <u32>
-        Definition: board specific property to change default spkmode mask
-                    of MI2S dai based on dataline connection on board.
-
-- qcom,micmode-mask:
-        Usage: optional for mi2s interface
-        Value type: <u32>
-        Definition: board specific property to change default micmode mask
-                    of MI2S dai based on dataline connection on board.
-
-- qcom,loopback-mask:
-        Usage: optional for mi2s interface
-        Value type: <u32>
-        Definition: board specific property to change default loopback mask
-                    of MI2S dai as per requirement.
-
-- qcom,wssrc-mask:
-        Usage: optional for mi2s interface
-        Value type: <u32>
-        Definition: board specific property to change default wssrc mask
-                    of MI2S dai based as per requirement.
-
-Example:
-
-lpass_cpu: lpass {
-	compatible = "qcom, lpass-cpu-sc7180";
-
-	reg = <0 0x62F00000 0 0x29000>;
-	reg-names = "lpass-lpaif";
-
-	iommus = <&apps_smmu 0x1020 0>;
-
-	power-domains = <&lpass_hm LPASS_CORE_HM_GDSCR>;
-
-	clocks = <&gcc GCC_LPASS_CFG_NOC_SWAY_CLK>,
-		 <&lpasscorecc LPASS_AUDIO_CORE_CORE_CLK>,
-		 <&lpasscorecc LPASS_AUDIO_CORE_EXT_MCLK0_CLK>,
-		 <&lpasscorecc LPASS_AUDIO_CORE_SYSNOC_MPORT_CORE_CLK>,
-		 <&lpasscorecc LPASS_AUDIO_CORE_LPAIF_PRI_IBIT_CLK>,
-		 <&lpasscorecc LPASS_AUDIO_CORE_LPAIF_SEC_IBIT_CLK>;
-
-	clock-names = "noc", "audio-core", "mclk0", "sysnoc_mport",
-		      "pri_ibit", "sec_ibit";
-
-	#sound-dai-cells = <1>;
-
-	interrupts = <0 160 IRQ_TYPE_LEVEL_HIGH>;
-	interrupt-names = "lpass-irq-lpaif";
-
-	prim-mi2s@0 {
-		id = <MI2S_PRIMARY>;
-		qcom,bitclk-name = "pri_ibit";
-		qcom,mclk-name = "mclk0";
-	};
-
-	sec-mi2s@1 {
-		id = <MI2S_SECONDARY>;
-		qcom,bitclk-name = "sec_ibit";
-	};
-};
Documentation/devicetree/bindings/sound/qcom,lpass-cpu.yaml new file +103 -0
new file mode 100644
index 00000000..a87a406
@@ -0,0 +1,103 @@
+# SPDX-License-Identifier: GPL-2.0-only
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/qcom,lpass-cpu.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm LPASS CPU dai driver bindings
+
+maintainers:
+  - Srinivas Kandagatla <[email protected]>
+  - Ajit Pandey <[email protected]>
+
+description: |
+  Qualcomm SOC Low-Power Audio SubSystem (LPASS) that consist of MI2S interface
+  for audio data transfer on external codecs. LPASS cpu driver is a module to
+  configure Low-Power Audio Interface(LPAIF) core registers across different
+  IP versions.
+
+properties:
+  compatible:
+    enum:
+      - qcom,lpass-cpu
+      - qcom,apq8016-lpass-cpu
+
+  reg:
+    items:
+      - description: LPAIF core registers
+
+  reg-names:
+    items:
+      - const: lpass-lpaif
+
+  clocks:
+    items:
+      - description: AHBIX core clock for IPQ806X
+      - description: oscillator clock for MI2S external interfaces
+      - description: Bit clock for single MI2S dai in IPQ806X
+      - description: Bit clock for MI2S_PRIMARY dai interface
+      - description: Bit clock for MI2S_SECONDARY dai interface
+      - description: Bit clock for MI2S_TERTIARY dai interface
+      - description: Bit clock for MI2S_QUATERNARY dai interface
+      - description: NOC MPORT clock of LPASS core
+      - description: NOC SWAY clock of LPASS core
+
+  clock-names:
+    items:
+      - const: ahbix-clk
+      - const: mi2s-osr-clk
+      - const: mi2s-bit-clk
+      - const: mi2s-bit-clk0
+      - const: mi2s-bit-clk1
+      - const: mi2s-bit-clk2
+      - const: mi2s-bit-clk3
+      - const: pcnoc-mport-clk
+      - const: pcnoc-sway-clk
+
+  interrupts:
+    items:
+      - description: LPAIF DMA buffer interrupt
+
+  interrupt-names:
+    items:
+      - const: lpass-irq-lpaif
+
+  qcom,adsp:
+    maxItems: 1
+    description: Phandle for the audio DSP node
+
+  '#sound-dai-cells':
+    const: 1
+
+required:
+  - compatible
+  - reg
+  - reg-names
+  - clocks
+  - clock-names
+  - interrupts
+  - interrupt-names
+  - sound-dai-cells
+
+optional:
+  - qcom,adsp
+
+examples:
+  lpass@28100000 {
+	compatible = "qcom,lpass-cpu";
+	clocks = <&lcc AHBIX_CLK>,
+		 <&lcc MI2S_OSR_CLK>,
+		 <&lcc MI2S_BIT_CLK>;
+
+	clock-names = "ahbix-clk",
+		      "mi2s-osr-clk",
+		      "mi2s-bit-clk";
+
+	interrupts = <0 85 1>;
+	interrupt-names = "lpass-irq-lpaif";
+
+	reg = <0x28100000 0x10000>;
+	reg-names = "lpass-lpaif";
+	#sound-dai-cells = <1>;
+	qcom,adsp = <&adsp>;
+
#3 lore raw

Re: [PATCH 01/11] Documentation: device-tree: sound: Update lpass-cpu driver binding

Quoted 39 lines · Srinivas Kandagatla
Quoted 27 lines · Ajit Pandey

Done the required cleanups to update lpass-cpu binding with newer yaml formats.

---
  .../devicetree/bindings/sound/qcom,lpass-cpu.txt   | 158
---------------------
  .../devicetree/bindings/sound/qcom,lpass-cpu.yaml  | 103
++++++++++++++

  2 files changed, 103 insertions(+), 158 deletions(-)

  delete mode 100644 Documentation/devicetree/bindings/sound/qcom,lpass-cpu.txt create mode 100644 Documentation/devicetree/bindings/sound/qcom,lpass-cpu.yaml

Documentation/devicetree/bindings/sound/qcom,lpass-cpu.txt deleted +0 -3
deleted file mode 100644
index a49b878..00000000
@@ -1,158 +0,0 @@
-* Qualcomm Technologies LPASS CPU DAI binding
-
-Low-Power Audio SubSystem (LPASS) consist of MI2S interfaces for 

audio data
-transfer on external codec. LPASS cpu driver is a common code to configure

Documentation/devicetree/bindings/sound/qcom,lpass-cpu.txt line 11

Quoted 7 lines
Documentation/devicetree/bindings/sound/qcom,lpass-cpu.txt deleted +0 -7
-MI2S related CPU dai's across different version of LPASS architecture.
-
-- compatible:
-    Usage: required
-    Value type: <stringlist>
-    Definition: compatible string corresponds to lpass variants driver
-            must be "qcom, lpass-cpu-sc7180" for sc7180 lpass

This patch will not apply on mainline, looks like this was done on top of your local repo, please fix this!

Quoted 1 line

Best thing would be rebase patches top of https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git/log/?h=for-next

Sure I'll rebase on top of mentioned tip during v2 patch chain submission

Quoted 9 lines

Secondly, Split this patch into two,
1> converting in to yaml
2> adding new changes
so that it will be easy to see what exactly changed.

thanks,
srini

I've not added any newer properties here just changed it to yaml format only

Thanks & Regards

Ajit

Quoted 269 lines
Quoted 269 lines

-            must be "qcom,apq8016-lpass-cpu" for apq8016 lpass -- reg:
-    Usage: required
-    Value type: <prop-encoded-array>
-    Definition: must specify the base address and size of the LPAIF CORE
-            region of lpass variant.
-- reg-names:
-    Usage: required
-    Value type: <stringlist>
-    Definition: must be "lpass-lpaif"

Documentation/devicetree/bindings/sound/qcom,lpass-cpu.txt deleted +0 -52
-
-- iommus:
-        Usage: required for "qcom, lpass-cpu-sc7180" compatible string
-        Value type: <prop-encoded-array>
-        Definition: sid mask for lpaif memory region to apps_smmu
-                    must be <&apps_smmu 0x1020 0>
-
-- power-domains:
-    Usage: required for "qcom, lpass-cpu-sc7180" compatible string
-    Value type: <phandle>
-    Definition: reference to power-domains
-            must be <&lpass_hm LPASS_CORE_HM_GDSCR>
-
-- clocks:
-        Usage: required
-    Value type: <phandle>
-    Definition: reference to the clocks that match clock-names
-
-- clock-names:
-    Usage: required
-    Value type: <stringlist>
-    Definition: The clocks needed depend on the compatible string:
-    qcom,lpass-cpu-apq8016:
-        must be "ahbix-clk", "mi2s-osr-clk", "mi2s-bit-clk0",
-        mi2s-bit-clk1", "mi2s-bit-clk2", "mi2s-bit-clk3",
-        "pcnoc-mport-clk", "pcnoc-sway-clk"
-    qcom, lpass-cpu-sc7180:
-        must be "noc", "audio-core", "mclk0", "sysnoc_mport",
-        "pri_ibit", "sec_ibit"
-
-- #sound-dai-cells
-    Usage: required
-    Value type: <u32>
-    Definition: Must be 1
-
-- interrupts:
-    Usage: required
-    Value type: <prop-encoded-array>
-    Definition: reference to the interrupts that match interrupt-names
-
-- interrupt-names:
-    Usage: required
-    Value type: <stringlist>
-    Definition: must be "lpass-irq-lpaif"
-
-- qcom,adsp:
-        Usage: optional
-        Value type: <phandle>
-    Definition: Phandle for the audio DSP node
-
-= MI2S DAIs (Digial Audio Interface)
-"dais" child node of the lpass node. It represents mi2s dais, each 

mi2s dai is
-subnode of "dais" representing board specific dai setup & required dai clocks.
-"dais" node should have following properties.
-
-- id:
-    Usage: required for mi2s interface
-    Value type: <u32>
-    Definition: Must be dai id defined in lpass bindings like MI2S_PRIMARY

Documentation/devicetree/bindings/sound/qcom,lpass-cpu.txt deleted +0 -10
-
-- qcom,bitclk-name:
-    Usage: required for mi2s interface
-    Value type: <stringlist>
-    Definition: bitclk name corresponds to MI2S of lpass version
-
-- qcom,mclk-name:
-        Usage: optional for mi2s interface
-        Value type: <stringlist>
-        Definition: external mclk name corresponds to MI2S of lpass 

version

Documentation/devicetree/bindings/sound/qcom,lpass-cpu.txt deleted +0 -10
-
-- qcom,osrclk-name:
-        Usage: optional for mi2s interface
-        Value type: <stringlist>
-        Definition: osrclk name corresponds to MI2S of lpass version
-
-- qcom,spkmode-mask:
-        Usage: optional for mi2s interface
-        Value type: <u32>
-        Definition: board specific property to change default 

spkmode mask
-                    of MI2S dai based on dataline connection on board. -
-- qcom,micmode-mask:
-        Usage: optional for mi2s interface
-        Value type: <u32>
-        Definition: board specific property to change default micmode mask
-                    of MI2S dai based on dataline connection on board. -
-- qcom,loopback-mask:
-        Usage: optional for mi2s interface
-        Value type: <u32>
-        Definition: board specific property to change default loopback mask
-                    of MI2S dai as per requirement.
-
-- qcom,wssrc-mask:
-        Usage: optional for mi2s interface
-        Value type: <u32>
-        Definition: board specific property to change default wssrc mask
-                    of MI2S dai based as per requirement.

Documentation/devicetree/bindings/sound/qcom,lpass-cpu.txt deleted +0 -39
-
-Example:
-
-lpass_cpu: lpass {
-    compatible = "qcom, lpass-cpu-sc7180";
-
-    reg = <0 0x62F00000 0 0x29000>;
-    reg-names = "lpass-lpaif";
-
-    iommus = <&apps_smmu 0x1020 0>;
-
-    power-domains = <&lpass_hm LPASS_CORE_HM_GDSCR>;
-
-    clocks = <&gcc GCC_LPASS_CFG_NOC_SWAY_CLK>,
-         <&lpasscorecc LPASS_AUDIO_CORE_CORE_CLK>,
-         <&lpasscorecc LPASS_AUDIO_CORE_EXT_MCLK0_CLK>,
-         <&lpasscorecc LPASS_AUDIO_CORE_SYSNOC_MPORT_CORE_CLK>,
-         <&lpasscorecc LPASS_AUDIO_CORE_LPAIF_PRI_IBIT_CLK>,
-         <&lpasscorecc LPASS_AUDIO_CORE_LPAIF_SEC_IBIT_CLK>;
-
-    clock-names = "noc", "audio-core", "mclk0", "sysnoc_mport",
-              "pri_ibit", "sec_ibit";
-
-    #sound-dai-cells = <1>;
-
-    interrupts = <0 160 IRQ_TYPE_LEVEL_HIGH>;
-    interrupt-names = "lpass-irq-lpaif";
-
-    prim-mi2s@0 {
-        id = <MI2S_PRIMARY>;
-        qcom,bitclk-name = "pri_ibit";
-        qcom,mclk-name = "mclk0";
-    };
-
-    sec-mi2s@1 {
-        id = <MI2S_SECONDARY>;
-        qcom,bitclk-name = "sec_ibit";
-    };
-};
Documentation/devicetree/bindings/sound/qcom,lpass-cpu.yaml new file +14 -0
new file mode 100644
index 00000000..a87a406
@@ -0,0 +1,103 @@
+# SPDX-License-Identifier: GPL-2.0-only
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/qcom,lpass-cpu.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm LPASS CPU dai driver bindings
+
+maintainers:
+  - Srinivas Kandagatla <[email protected]>
+  - Ajit Pandey <[email protected]>
+
+description: |
+  Qualcomm SOC Low-Power Audio SubSystem (LPASS) that consist of 

MI2S interface
+  for audio data transfer on external codecs. LPASS cpu driver is a module to
+  configure Low-Power Audio Interface(LPAIF) core registers across different
+  IP versions.

Documentation/devicetree/bindings/sound/qcom,lpass-cpu.yaml new file +86 -0
+
+properties:
+  compatible:
+    enum:
+      - qcom,lpass-cpu
+      - qcom,apq8016-lpass-cpu
+
+  reg:
+    items:
+      - description: LPAIF core registers
+
+  reg-names:
+    items:
+      - const: lpass-lpaif
+
+  clocks:
+    items:
+      - description: AHBIX core clock for IPQ806X
+      - description: oscillator clock for MI2S external interfaces
+      - description: Bit clock for single MI2S dai in IPQ806X
+      - description: Bit clock for MI2S_PRIMARY dai interface
+      - description: Bit clock for MI2S_SECONDARY dai interface
+      - description: Bit clock for MI2S_TERTIARY dai interface
+      - description: Bit clock for MI2S_QUATERNARY dai interface
+      - description: NOC MPORT clock of LPASS core
+      - description: NOC SWAY clock of LPASS core
+
+  clock-names:
+    items:
+      - const: ahbix-clk
+      - const: mi2s-osr-clk
+      - const: mi2s-bit-clk
+      - const: mi2s-bit-clk0
+      - const: mi2s-bit-clk1
+      - const: mi2s-bit-clk2
+      - const: mi2s-bit-clk3
+      - const: pcnoc-mport-clk
+      - const: pcnoc-sway-clk
+
+  interrupts:
+    items:
+      - description: LPAIF DMA buffer interrupt
+
+  interrupt-names:
+    items:
+      - const: lpass-irq-lpaif
+
+  qcom,adsp:
+    maxItems: 1
+    description: Phandle for the audio DSP node
+
+  '#sound-dai-cells':
+    const: 1
+
+required:
+  - compatible
+  - reg
+  - reg-names
+  - clocks
+  - clock-names
+  - interrupts
+  - interrupt-names
+  - sound-dai-cells
+
+optional:
+  - qcom,adsp
+
+examples:
+  lpass@28100000 {
+    compatible = "qcom,lpass-cpu";
+    clocks = <&lcc AHBIX_CLK>,
+         <&lcc MI2S_OSR_CLK>,
+         <&lcc MI2S_BIT_CLK>;
+
+    clock-names = "ahbix-clk",
+              "mi2s-osr-clk",
+              "mi2s-bit-clk";
+
+    interrupts = <0 85 1>;
+    interrupt-names = "lpass-irq-lpaif";
+
+    reg = <0x28100000 0x10000>;
+    reg-names = "lpass-lpaif";
+    #sound-dai-cells = <1>;
+    qcom,adsp = <&adsp>;
+
#4 lore raw

PATCH 2/11 ASoC: qcom: lpass: Add struct lpass_dai to store dai clocks pointer

In reply to Ajit Pandey

lpass_dai will store clocks related to respective dai's and it will be initialized during probe based on variant clock names.

---
 sound/soc/qcom/lpass-cpu.c | 89 ++++++++++++++++++++++++++--------------------
 sound/soc/qcom/lpass.h     | 18 +++++-----
 2 files changed, 61 insertions(+), 46 deletions(-)
sound/soc/qcom/lpass-cpu.c +51 -38
index dbce7e9..492f27b 100644
@@ -23,13 +23,15 @@ static int lpass_cpu_daiops_set_sysclk(struct snd_soc_dai *dai, int clk_id,
 		unsigned int freq, int dir)
 {
 	struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai);
-	int ret;
-
-	ret = clk_set_rate(drvdata->mi2s_osr_clk[dai->driver->id], freq);
-	if (ret)
-		dev_err(dai->dev, "error setting mi2s osrclk to %u: %d\n",
-			freq, ret);
+	struct lpass_dai *dai_data = drvdata->dai_priv[dai->driver->id];
+	int ret = 0;
 
+	if (dai_data->osr_clk != NULL) {
+		ret = clk_set_rate(dai_data->osr_clk, freq);
+		if (ret)
+			dev_err(dai->dev, "error setting mi2s osrclk to %u:%d\n",
+				freq, ret);
+	}
 	return ret;
 }
 
@@ -37,18 +39,22 @@ static int lpass_cpu_daiops_startup(struct snd_pcm_substream *substream,
 		struct snd_soc_dai *dai)
 {
 	struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai);
+	struct lpass_dai *dai_data = drvdata->dai_priv[dai->driver->id];
 	int ret;
 
-	ret = clk_prepare_enable(drvdata->mi2s_osr_clk[dai->driver->id]);
-	if (ret) {
-		dev_err(dai->dev, "error in enabling mi2s osr clk: %d\n", ret);
-		return ret;
+	if (dai_data->osr_clk != NULL) {
+		ret = clk_prepare_enable(dai_data->osr_clk);
+		if (ret) {
+			dev_err(dai->dev,
+				"error in enabling mi2s osr clk: %d\n", ret);
+			return ret;
+		}
 	}
 
-	ret = clk_prepare_enable(drvdata->mi2s_bit_clk[dai->driver->id]);
+	ret = clk_prepare_enable(dai_data->bit_clk);
 	if (ret) {
 		dev_err(dai->dev, "error in enabling mi2s bit clk: %d\n", ret);
-		clk_disable_unprepare(drvdata->mi2s_osr_clk[dai->driver->id]);
+		clk_disable_unprepare(dai_data->osr_clk);
 		return ret;
 	}
 
@@ -59,16 +65,18 @@ static void lpass_cpu_daiops_shutdown(struct snd_pcm_substream *substream,
 		struct snd_soc_dai *dai)
 {
 	struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai);
+	struct lpass_dai *dai_data = drvdata->dai_priv[dai->driver->id];
 
-	clk_disable_unprepare(drvdata->mi2s_bit_clk[dai->driver->id]);
+	clk_disable_unprepare(dai_data->bit_clk);
 
-	clk_disable_unprepare(drvdata->mi2s_osr_clk[dai->driver->id]);
+	clk_disable_unprepare(dai_data->osr_clk);
 }
 
 static int lpass_cpu_daiops_hw_params(struct snd_pcm_substream *substream,
 		struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
 {
 	struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai);
+	struct lpass_dai *dai_data = drvdata->dai_priv[dai->driver->id];
 	snd_pcm_format_t format = params_format(params);
 	unsigned int channels = params_channels(params);
 	unsigned int rate = params_rate(params);
@@ -163,8 +171,7 @@ static int lpass_cpu_daiops_hw_params(struct snd_pcm_substream *substream,
 		return ret;
 	}
 
-	ret = clk_set_rate(drvdata->mi2s_bit_clk[dai->driver->id],
-			   rate * bitwidth * 2);
+	ret = clk_set_rate(dai_data->bit_clk, rate * bitwidth * 2);
 	if (ret) {
 		dev_err(dai->dev, "error setting mi2s bitclk to %u: %d\n",
 			rate * bitwidth * 2, ret);
@@ -413,6 +420,25 @@ static bool lpass_cpu_regmap_volatile(struct device *dev, unsigned int reg)
 	.cache_type = REGCACHE_FLAT,
 };
 
+static int lpass_init_dai_clocks(struct device *dev,
+			   struct lpass_data *drvdata)
+{
+	struct lpass_dai *dai;
+	struct lpass_variant *v = drvdata->variant;
+	int i;
+
+	for (i = 0; i < v->num_dai; i++) {
+
+		dai = drvdata->dai_priv[i];
+
+		dai->osr_clk = devm_clk_get_optional(dev,
+						     v->dai_osr_clk_names[i]);
+		dai->bit_clk = devm_clk_get(dev, v->dai_bit_clk_names[i]);
+	}
+
+	return 0;
+}
+
 int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev)
 {
 	struct lpass_data *drvdata;
@@ -421,7 +447,7 @@ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev)
 	struct lpass_variant *variant;
 	struct device *dev = &pdev->dev;
 	const struct of_device_id *match;
-	int ret, i, dai_id;
+	int ret, i;
 
 	dsp_of_node = of_parse_phandle(pdev->dev.of_node, "qcom,adsp", 0);
 	if (dsp_of_node) {
@@ -467,28 +493,15 @@ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev)
 		variant->init(pdev);
 
 	for (i = 0; i < variant->num_dai; i++) {
-		dai_id = variant->dai_driver[i].id;
-		drvdata->mi2s_osr_clk[dai_id] = devm_clk_get(&pdev->dev,
-					     variant->dai_osr_clk_names[i]);
-		if (IS_ERR(drvdata->mi2s_osr_clk[dai_id])) {
-			dev_warn(&pdev->dev,
-				"%s() error getting optional %s: %ld\n",
-				__func__,
-				variant->dai_osr_clk_names[i],
-				PTR_ERR(drvdata->mi2s_osr_clk[dai_id]));
-
-			drvdata->mi2s_osr_clk[dai_id] = NULL;
-		}
+		drvdata->dai_priv[i] = devm_kzalloc(dev,
+						sizeof(struct lpass_dai),
+						GFP_KERNEL);
+	}
 
-		drvdata->mi2s_bit_clk[dai_id] = devm_clk_get(&pdev->dev,
-						variant->dai_bit_clk_names[i]);
-		if (IS_ERR(drvdata->mi2s_bit_clk[dai_id])) {
-			dev_err(&pdev->dev,
-				"error getting %s: %ld\n",
-				variant->dai_bit_clk_names[i],
-				PTR_ERR(drvdata->mi2s_bit_clk[dai_id]));
-			return PTR_ERR(drvdata->mi2s_bit_clk[dai_id]);
-		}
+	ret = lpass_init_dai_clocks(dev, drvdata);
+	if (ret) {
+		dev_err(&pdev->dev, "error intializing dai clock: %d\n", ret);
+		return ret;
 	}
 
 	drvdata->ahbix_clk = devm_clk_get(&pdev->dev, "ahbix-clk");
sound/soc/qcom/lpass.h +10 -8
index 17113d3..b729686 100644
@@ -13,9 +13,14 @@
 #include <linux/platform_device.h>
 #include <linux/regmap.h>
 
-#define LPASS_AHBIX_CLOCK_FREQUENCY		131072000
-#define LPASS_MAX_MI2S_PORTS			(8)
-#define LPASS_MAX_DMA_CHANNELS			(8)
+#define LPASS_AHBIX_CLOCK_FREQUENCY            131072000
+#define LPASS_MAX_MI2S_PORTS                   (8)
+#define LPASS_MAX_DMA_CHANNELS                 (8)
+
+struct lpass_dai {
+	struct clk *osr_clk;
+	struct clk *bit_clk;
+};
 
 /* Both the CPU DAI and platform drivers will access this data */
 struct lpass_data {
@@ -23,11 +28,8 @@ struct lpass_data {
 	/* AHB-I/X bus clocks inside the low-power audio subsystem (LPASS) */
 	struct clk *ahbix_clk;
 
-	/* MI2S system clock */
-	struct clk *mi2s_osr_clk[LPASS_MAX_MI2S_PORTS];
-
-	/* MI2S bit clock (derived from system clock by a divider */
-	struct clk *mi2s_bit_clk[LPASS_MAX_MI2S_PORTS];
+	/* MI2S dai specific configuration */
+	struct lpass_dai *dai_priv[LPASS_MAX_MI2S_PORTS];
 
 	/* low-power audio interface (LPAIF) registers */
 	void __iomem *lpaif;
Signature · 1 line
1.9.1
#5 lore raw

Re: [PATCH 02/11] ASoC: qcom: lpass: Add struct lpass_dai to store dai clocks pointer

Quoted 4 lines · Ajit Pandey

lpass_dai will store clocks related to respective dai's and it will be initialized during probe based on variant clock names.

I dont understand why do we need this change? What is the advantage of doing this way vs the existing one?

--srini

Quoted 200 lines
---
  sound/soc/qcom/lpass-cpu.c | 89 ++++++++++++++++++++++++++--------------------
  sound/soc/qcom/lpass.h     | 18 +++++-----
  2 files changed, 61 insertions(+), 46 deletions(-)
sound/soc/qcom/lpass-cpu.c +51 -38
index dbce7e9..492f27b 100644
@@ -23,13 +23,15 @@ static int lpass_cpu_daiops_set_sysclk(struct snd_soc_dai *dai, int clk_id,
  		unsigned int freq, int dir)
  {
  	struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai);
-	int ret;
-
-	ret = clk_set_rate(drvdata->mi2s_osr_clk[dai->driver->id], freq);
-	if (ret)
-		dev_err(dai->dev, "error setting mi2s osrclk to %u: %d\n",
-			freq, ret);
+	struct lpass_dai *dai_data = drvdata->dai_priv[dai->driver->id];
+	int ret = 0;
 
+	if (dai_data->osr_clk != NULL) {
+		ret = clk_set_rate(dai_data->osr_clk, freq);
+		if (ret)
+			dev_err(dai->dev, "error setting mi2s osrclk to %u:%d\n",
+				freq, ret);
+	}
  	return ret;
  }
 
@@ -37,18 +39,22 @@ static int lpass_cpu_daiops_startup(struct snd_pcm_substream *substream,
  		struct snd_soc_dai *dai)
  {
  	struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai);
+	struct lpass_dai *dai_data = drvdata->dai_priv[dai->driver->id];
  	int ret;
 
-	ret = clk_prepare_enable(drvdata->mi2s_osr_clk[dai->driver->id]);
-	if (ret) {
-		dev_err(dai->dev, "error in enabling mi2s osr clk: %d\n", ret);
-		return ret;
+	if (dai_data->osr_clk != NULL) {
+		ret = clk_prepare_enable(dai_data->osr_clk);
+		if (ret) {
+			dev_err(dai->dev,
+				"error in enabling mi2s osr clk: %d\n", ret);
+			return ret;
+		}
  	}
 
-	ret = clk_prepare_enable(drvdata->mi2s_bit_clk[dai->driver->id]);
+	ret = clk_prepare_enable(dai_data->bit_clk);
  	if (ret) {
  		dev_err(dai->dev, "error in enabling mi2s bit clk: %d\n", ret);
-		clk_disable_unprepare(drvdata->mi2s_osr_clk[dai->driver->id]);
+		clk_disable_unprepare(dai_data->osr_clk);
  		return ret;
  	}
 
@@ -59,16 +65,18 @@ static void lpass_cpu_daiops_shutdown(struct snd_pcm_substream *substream,
  		struct snd_soc_dai *dai)
  {
  	struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai);
+	struct lpass_dai *dai_data = drvdata->dai_priv[dai->driver->id];
 
-	clk_disable_unprepare(drvdata->mi2s_bit_clk[dai->driver->id]);
+	clk_disable_unprepare(dai_data->bit_clk);
 
-	clk_disable_unprepare(drvdata->mi2s_osr_clk[dai->driver->id]);
+	clk_disable_unprepare(dai_data->osr_clk);
  }
 
  static int lpass_cpu_daiops_hw_params(struct snd_pcm_substream *substream,
  		struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
  {
  	struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai);
+	struct lpass_dai *dai_data = drvdata->dai_priv[dai->driver->id];
  	snd_pcm_format_t format = params_format(params);
  	unsigned int channels = params_channels(params);
  	unsigned int rate = params_rate(params);
@@ -163,8 +171,7 @@ static int lpass_cpu_daiops_hw_params(struct snd_pcm_substream *substream,
  		return ret;
  	}
 
-	ret = clk_set_rate(drvdata->mi2s_bit_clk[dai->driver->id],
-			   rate * bitwidth * 2);
+	ret = clk_set_rate(dai_data->bit_clk, rate * bitwidth * 2);
  	if (ret) {
  		dev_err(dai->dev, "error setting mi2s bitclk to %u: %d\n",
  			rate * bitwidth * 2, ret);
@@ -413,6 +420,25 @@ static bool lpass_cpu_regmap_volatile(struct device *dev, unsigned int reg)
  	.cache_type = REGCACHE_FLAT,
  };
 
+static int lpass_init_dai_clocks(struct device *dev,
+			   struct lpass_data *drvdata)
+{
+	struct lpass_dai *dai;
+	struct lpass_variant *v = drvdata->variant;
+	int i;
+
+	for (i = 0; i < v->num_dai; i++) {
+
+		dai = drvdata->dai_priv[i];
+
+		dai->osr_clk = devm_clk_get_optional(dev,
+						     v->dai_osr_clk_names[i]);
+		dai->bit_clk = devm_clk_get(dev, v->dai_bit_clk_names[i]);
+	}
+
+	return 0;
+}
+
  int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev)
  {
  	struct lpass_data *drvdata;
@@ -421,7 +447,7 @@ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev)
  	struct lpass_variant *variant;
  	struct device *dev = &pdev->dev;
  	const struct of_device_id *match;
-	int ret, i, dai_id;
+	int ret, i;
 
  	dsp_of_node = of_parse_phandle(pdev->dev.of_node, "qcom,adsp", 0);
  	if (dsp_of_node) {
@@ -467,28 +493,15 @@ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev)
  		variant->init(pdev);
 
  	for (i = 0; i < variant->num_dai; i++) {
-		dai_id = variant->dai_driver[i].id;
-		drvdata->mi2s_osr_clk[dai_id] = devm_clk_get(&pdev->dev,
-					     variant->dai_osr_clk_names[i]);
-		if (IS_ERR(drvdata->mi2s_osr_clk[dai_id])) {
-			dev_warn(&pdev->dev,
-				"%s() error getting optional %s: %ld\n",
-				__func__,
-				variant->dai_osr_clk_names[i],
-				PTR_ERR(drvdata->mi2s_osr_clk[dai_id]));
-
-			drvdata->mi2s_osr_clk[dai_id] = NULL;
-		}
+		drvdata->dai_priv[i] = devm_kzalloc(dev,
+						sizeof(struct lpass_dai),
+						GFP_KERNEL);
+	}
 
-		drvdata->mi2s_bit_clk[dai_id] = devm_clk_get(&pdev->dev,
-						variant->dai_bit_clk_names[i]);
-		if (IS_ERR(drvdata->mi2s_bit_clk[dai_id])) {
-			dev_err(&pdev->dev,
-				"error getting %s: %ld\n",
-				variant->dai_bit_clk_names[i],
-				PTR_ERR(drvdata->mi2s_bit_clk[dai_id]));
-			return PTR_ERR(drvdata->mi2s_bit_clk[dai_id]);
-		}
+	ret = lpass_init_dai_clocks(dev, drvdata);
+	if (ret) {
+		dev_err(&pdev->dev, "error intializing dai clock: %d\n", ret);
+		return ret;
  	}
 
  	drvdata->ahbix_clk = devm_clk_get(&pdev->dev, "ahbix-clk");
sound/soc/qcom/lpass.h +10 -8
index 17113d3..b729686 100644
@@ -13,9 +13,14 @@
  #include <linux/platform_device.h>
  #include <linux/regmap.h>
 
-#define LPASS_AHBIX_CLOCK_FREQUENCY		131072000
-#define LPASS_MAX_MI2S_PORTS			(8)
-#define LPASS_MAX_DMA_CHANNELS			(8)
+#define LPASS_AHBIX_CLOCK_FREQUENCY            131072000
+#define LPASS_MAX_MI2S_PORTS                   (8)
+#define LPASS_MAX_DMA_CHANNELS                 (8)
+
+struct lpass_dai {
+	struct clk *osr_clk;
+	struct clk *bit_clk;
+};
 
  /* Both the CPU DAI and platform drivers will access this data */
  struct lpass_data {
@@ -23,11 +28,8 @@ struct lpass_data {
  	/* AHB-I/X bus clocks inside the low-power audio subsystem (LPASS) */
  	struct clk *ahbix_clk;
 
-	/* MI2S system clock */
-	struct clk *mi2s_osr_clk[LPASS_MAX_MI2S_PORTS];
-
-	/* MI2S bit clock (derived from system clock by a divider */
-	struct clk *mi2s_bit_clk[LPASS_MAX_MI2S_PORTS];
+	/* MI2S dai specific configuration */
+	struct lpass_dai *dai_priv[LPASS_MAX_MI2S_PORTS];
 
  	/* low-power audio interface (LPAIF) registers */
  	void __iomem *lpaif;
#6 lore raw

Re: [PATCH 02/11] ASoC: qcom: lpass: Add struct lpass_dai to store dai clocks pointer

Quoted 202 lines · Srinivas Kandagatla
Quoted 4 lines · Ajit Pandey

lpass_dai will store clocks related to respective dai's and it will be initialized during probe based on variant clock names.

I dont understand why do we need this change? What is the advantage of doing this way vs the existing one?

--srini

Actually I've kept this in chain to add dai modes properties later in chain in this struct but with adoption of Stephen patch now , i guess we don't have any significant advantage now. I'll probably drop this patch during v2 submission.      --Ajit

Quoted 188 lines

---
  sound/soc/qcom/lpass-cpu.c | 89
++++++++++++++++++++++++++--------------------
  sound/soc/qcom/lpass.h     | 18 +++++-----

  2 files changed, 61 insertions(+), 46 deletions(-)
sound/soc/qcom/lpass-cpu.c +7 -6
index dbce7e9..492f27b 100644
@@ -23,13 +23,15 @@ static int lpass_cpu_daiops_set_sysclk(struct 
 snd_soc_dai *dai, int clk_id,
           unsigned int freq, int dir)
   {
       struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai);
-    int ret;
-
-    ret = clk_set_rate(drvdata->mi2s_osr_clk[dai->driver->id], freq);
-    if (ret)
-        dev_err(dai->dev, "error setting mi2s osrclk to %u: %d\n",
-            freq, ret);
+    struct lpass_dai *dai_data = drvdata->dai_priv[dai->driver->id];
+    int ret = 0;
   +    if (dai_data->osr_clk != NULL) {
+        ret = clk_set_rate(dai_data->osr_clk, freq);
+        if (ret)
+            dev_err(dai->dev, "error setting mi2s osrclk to %u:%d\n",
+                freq, ret);
+    }
       return ret;
   }

  @@ -37,18 +39,22 @@ static int lpass_cpu_daiops_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
  {
      struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai);
+    struct lpass_dai *dai_data = drvdata->dai_priv[dai->driver->id];
      int ret;
  -    ret = clk_prepare_enable(drvdata->mi2s_osr_clk[dai->driver->id]);
-    if (ret) {
-        dev_err(dai->dev, "error in enabling mi2s osr clk: %d\n", ret);
-        return ret;
+    if (dai_data->osr_clk != NULL) {
+        ret = clk_prepare_enable(dai_data->osr_clk);
+        if (ret) {
+            dev_err(dai->dev,
+                "error in enabling mi2s osr clk: %d\n", ret);
+            return ret;
+        }
      }
  -    ret = clk_prepare_enable(drvdata->mi2s_bit_clk[dai->driver->id]);
+    ret = clk_prepare_enable(dai_data->bit_clk);
      if (ret) {
          dev_err(dai->dev, "error in enabling mi2s bit clk: %d\n", ret);
- clk_disable_unprepare(drvdata->mi2s_osr_clk[dai->driver->id]);
+        clk_disable_unprepare(dai_data->osr_clk);
          return ret;
      }
  @@ -59,16 +65,18 @@ static void lpass_cpu_daiops_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
  {
      struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai);
+    struct lpass_dai *dai_data = drvdata->dai_priv[dai->driver->id];
  - clk_disable_unprepare(drvdata->mi2s_bit_clk[dai->driver->id]);
+    clk_disable_unprepare(dai_data->bit_clk);
  - clk_disable_unprepare(drvdata->mi2s_osr_clk[dai->driver->id]);
+    clk_disable_unprepare(dai_data->osr_clk);
  }
    static int lpass_cpu_daiops_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
  {
      struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai);
+    struct lpass_dai *dai_data = drvdata->dai_priv[dai->driver->id]; snd_pcm_format_t format = params_format(params);
      unsigned int channels = params_channels(params);
      unsigned int rate = params_rate(params);

sound/soc/qcom/lpass-cpu.c +1 -1
@@ -163,8 +171,7 @@ static int lpass_cpu_daiops_hw_params(struct 
 snd_pcm_substream *substream,
           return ret;
       }
   -    ret = clk_set_rate(drvdata->mi2s_bit_clk[dai->driver->id],
-               rate * bitwidth * 2);
+    ret = clk_set_rate(dai_data->bit_clk, rate * bitwidth * 2);
       if (ret) {
           dev_err(dai->dev, "error setting mi2s bitclk to %u: %d\n",

              rate * bitwidth * 2, ret);

sound/soc/qcom/lpass-cpu.c +18 -0
@@ -413,6 +420,25 @@ static bool lpass_cpu_regmap_volatile(struct 
 device *dev, unsigned int reg)
       .cache_type = REGCACHE_FLAT,
   };
   +static int lpass_init_dai_clocks(struct device *dev,
+               struct lpass_data *drvdata)
+{
+    struct lpass_dai *dai;
+    struct lpass_variant *v = drvdata->variant;
+    int i;
+
+    for (i = 0; i < v->num_dai; i++) {
+
+        dai = drvdata->dai_priv[i];
+
+        dai->osr_clk = devm_clk_get_optional(dev,
+                             v->dai_osr_clk_names[i]);
+        dai->bit_clk = devm_clk_get(dev, v->dai_bit_clk_names[i]);
+    }
+
+    return 0;
+}
+
   int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev)
   {

      struct lpass_data *drvdata;

sound/soc/qcom/lpass-cpu.c +9 -21
@@ -421,7 +447,7 @@ int asoc_qcom_lpass_cpu_platform_probe(struct 
 platform_device *pdev)
       struct lpass_variant *variant;
       struct device *dev = &pdev->dev;
       const struct of_device_id *match;
-    int ret, i, dai_id;
+    int ret, i;
         dsp_of_node = of_parse_phandle(pdev->dev.of_node, "qcom,adsp", 0);
       if (dsp_of_node) {
@@ -467,28 +493,15 @@ int asoc_qcom_lpass_cpu_platform_probe(struct 
 platform_device *pdev)
           variant->init(pdev);
         for (i = 0; i < variant->num_dai; i++) {
-        dai_id = variant->dai_driver[i].id;
-        drvdata->mi2s_osr_clk[dai_id] = devm_clk_get(&pdev->dev,
-                         variant->dai_osr_clk_names[i]);
-        if (IS_ERR(drvdata->mi2s_osr_clk[dai_id])) {
-            dev_warn(&pdev->dev,
-                "%s() error getting optional %s: %ld\n",
-                __func__,
-                variant->dai_osr_clk_names[i],
-                PTR_ERR(drvdata->mi2s_osr_clk[dai_id]));
-
-            drvdata->mi2s_osr_clk[dai_id] = NULL;
-        }
+        drvdata->dai_priv[i] = devm_kzalloc(dev,
+                        sizeof(struct lpass_dai),
+                        GFP_KERNEL);
+    }
   -        drvdata->mi2s_bit_clk[dai_id] = devm_clk_get(&pdev->dev,
-                        variant->dai_bit_clk_names[i]);
-        if (IS_ERR(drvdata->mi2s_bit_clk[dai_id])) {
-            dev_err(&pdev->dev,
-                "error getting %s: %ld\n",
-                variant->dai_bit_clk_names[i],
-                PTR_ERR(drvdata->mi2s_bit_clk[dai_id]));
-            return PTR_ERR(drvdata->mi2s_bit_clk[dai_id]);
-        }
+    ret = lpass_init_dai_clocks(dev, drvdata);
+    if (ret) {
+        dev_err(&pdev->dev, "error intializing dai clock: %d\n", ret);
+        return ret;
       }
         drvdata->ahbix_clk = devm_clk_get(&pdev->dev, "ahbix-clk");
sound/soc/qcom/lpass.h +0 -0
index 17113d3..b729686 100644
@@ -13,9 +13,14 @@
   #include <linux/platform_device.h>
   #include <linux/regmap.h>

  -#define LPASS_AHBIX_CLOCK_FREQUENCY        131072000

sound/soc/qcom/lpass.h +8 -2
-#define LPASS_MAX_MI2S_PORTS            (8)
-#define LPASS_MAX_DMA_CHANNELS            (8)
+#define LPASS_AHBIX_CLOCK_FREQUENCY            131072000
+#define LPASS_MAX_MI2S_PORTS                   (8)
+#define LPASS_MAX_DMA_CHANNELS                 (8)
+
+struct lpass_dai {
+    struct clk *osr_clk;
+    struct clk *bit_clk;
+};

    /* Both the CPU DAI and platform drivers will access this data */ struct lpass_data {

sound/soc/qcom/lpass.h +0 -0
@@ -23,11 +28,8 @@ struct lpass_data {
       /* AHB-I/X bus clocks inside the low-power audio subsystem (LPASS) */
       struct clk *ahbix_clk;

  -    /* MI2S system clock */
-    struct clk *mi2s_osr_clk[LPASS_MAX_MI2S_PORTS];
-
-    /* MI2S bit clock (derived from system clock by a divider */ -    struct clk *mi2s_bit_clk[LPASS_MAX_MI2S_PORTS];
+    /* MI2S dai specific configuration */
+    struct lpass_dai *dai_priv[LPASS_MAX_MI2S_PORTS]; /* low-power audio interface (LPAIF) registers */ void __iomem *lpaif;

#7 lore raw

PATCH 3/11 ASoC: qcom: Add common array to initialize soc based core clocks

In reply to Ajit Pandey

lpass variants have their own soc specific clocks that needs to be enable for MI2S audio support. Added a common variable in drvdata to initialize such clocks using bulk clk api. Such clock names is still defined in variants specific data and needs to fetched during init.

---
 sound/soc/qcom/lpass-apq8016.c | 39 ++++++++++++++++++---------------------
 sound/soc/qcom/lpass.h         | 10 +++++++---
 2 files changed, 25 insertions(+), 24 deletions(-)
sound/soc/qcom/lpass-apq8016.c +18 -21
index 6575da5..cef4661 100644
@@ -161,33 +161,26 @@ static int apq8016_lpass_free_dma_channel(struct lpass_data *drvdata, int chan)
 static int apq8016_lpass_init(struct platform_device *pdev)
 {
 	struct lpass_data *drvdata = platform_get_drvdata(pdev);
+	struct lpass_variant *variant = drvdata->variant;
 	struct device *dev = &pdev->dev;
-	int ret;
+	int ret, i;
 
-	drvdata->pcnoc_mport_clk = devm_clk_get(dev, "pcnoc-mport-clk");
-	if (IS_ERR(drvdata->pcnoc_mport_clk)) {
-		dev_err(&pdev->dev, "error getting pcnoc-mport-clk: %ld\n",
-			PTR_ERR(drvdata->pcnoc_mport_clk));
-		return PTR_ERR(drvdata->pcnoc_mport_clk);
-	}
+	drvdata->clks = devm_kcalloc(dev, variant->num_clks,
+				     sizeof(*drvdata->clks), GFP_KERNEL);
+	drvdata->num_clks = variant->num_clks;
+
+	for (i = 0; i < drvdata->num_clks; i++)
+		drvdata->clks[i].id = variant->clk_name[i];
 
-	ret = clk_prepare_enable(drvdata->pcnoc_mport_clk);
+	ret = devm_clk_bulk_get(dev, drvdata->num_clks, drvdata->clks);
 	if (ret) {
-		dev_err(&pdev->dev, "Error enabling pcnoc-mport-clk: %d\n",
-			ret);
+		dev_err(dev, "Failed to get clocks %d\n", ret);
 		return ret;
 	}
 
-	drvdata->pcnoc_sway_clk = devm_clk_get(dev, "pcnoc-sway-clk");
-	if (IS_ERR(drvdata->pcnoc_sway_clk)) {
-		dev_err(&pdev->dev, "error getting pcnoc-sway-clk: %ld\n",
-			PTR_ERR(drvdata->pcnoc_sway_clk));
-		return PTR_ERR(drvdata->pcnoc_sway_clk);
-	}
-
-	ret = clk_prepare_enable(drvdata->pcnoc_sway_clk);
+	ret = clk_bulk_prepare_enable(drvdata->num_clks, drvdata->clks);
 	if (ret) {
-		dev_err(&pdev->dev, "Error enabling pcnoc_sway_clk: %d\n", ret);
+		dev_err(dev, "ao8016 clk_enable failed\n");
 		return ret;
 	}
 
@@ -198,8 +191,7 @@ static int apq8016_lpass_exit(struct platform_device *pdev)
 {
 	struct lpass_data *drvdata = platform_get_drvdata(pdev);
 
-	clk_disable_unprepare(drvdata->pcnoc_mport_clk);
-	clk_disable_unprepare(drvdata->pcnoc_sway_clk);
+	clk_bulk_disable_unprepare(drvdata->num_clks, drvdata->clks);
 
 	return 0;
 }
@@ -220,6 +212,11 @@ static int apq8016_lpass_exit(struct platform_device *pdev)
 	.wrdma_reg_stride	= 0x1000,
 	.wrdma_channel_start	= 5,
 	.wrdma_channels		= 2,
+	.clk_name		= (const char*[]) {
+				   "pcnoc-mport-clk",
+				   "pcnoc-sway-clk",
+				  },
+	.num_clks		= 2,
 	.dai_driver		= apq8016_lpass_cpu_dai_driver,
 	.num_dai		= ARRAY_SIZE(apq8016_lpass_cpu_dai_driver),
 	.dai_osr_clk_names	= (const char *[]) {
sound/soc/qcom/lpass.h +7 -3
index b729686..279cd02 100644
@@ -49,9 +49,9 @@ struct lpass_data {
 	/* used it for handling interrupt per dma channel */
 	struct snd_pcm_substream *substream[LPASS_MAX_DMA_CHANNELS];
 
-	/* 8016 specific */
-	struct clk *pcnoc_mport_clk;
-	struct clk *pcnoc_sway_clk;
+	/* SOC specific clock list */
+	struct clk_bulk_data *clks;
+	int num_clks;
 
 };
 
@@ -87,6 +87,10 @@ struct lpass_variant {
 	int num_dai;
 	const char * const *dai_osr_clk_names;
 	const char * const *dai_bit_clk_names;
+
+	/* SOC specific clocks configuration */
+	const char **clk_name;
+	int num_clks;
 };
 
 /* register the platform driver from the CPU DAI driver */
Signature · 1 line
1.9.1
#8 lore raw

PATCH 4/11 ASoC: qcom: lpass-cpu: Make "ahbix-clk" an optional clock.

In reply to Ajit Pandey

AHB-I/X bus clocks inside LPASS coreis not a mandatory clocks for newer lpass variants, hence make it an optional one.

---
 sound/soc/qcom/lpass-cpu.c | 31 ++++++++++++++++++-------------
 1 file changed, 18 insertions(+), 13 deletions(-)
sound/soc/qcom/lpass-cpu.c +18 -13
index 492f27b..f177932 100644
@@ -504,26 +504,31 @@ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev)
 		return ret;
 	}
 
-	drvdata->ahbix_clk = devm_clk_get(&pdev->dev, "ahbix-clk");
+	drvdata->ahbix_clk = devm_clk_get_optional(&pdev->dev, "ahbix-clk");
 	if (IS_ERR(drvdata->ahbix_clk)) {
 		dev_err(&pdev->dev, "error getting ahbix-clk: %ld\n",
 			PTR_ERR(drvdata->ahbix_clk));
 		return PTR_ERR(drvdata->ahbix_clk);
 	}
 
-	ret = clk_set_rate(drvdata->ahbix_clk, LPASS_AHBIX_CLOCK_FREQUENCY);
-	if (ret) {
-		dev_err(&pdev->dev, "error setting rate on ahbix_clk: %d\n",
-			ret);
-		return ret;
-	}
-	dev_dbg(&pdev->dev, "set ahbix_clk rate to %lu\n",
-		clk_get_rate(drvdata->ahbix_clk));
+	if (drvdata->ahbix_clk != NULL) {
+		ret = clk_set_rate(drvdata->ahbix_clk,
+				   LPASS_AHBIX_CLOCK_FREQUENCY);
+		if (ret) {
+			dev_err(&pdev->dev,
+				"error setting rate on ahbix_clk: %d\n", ret);
+			return ret;
+		}
 
-	ret = clk_prepare_enable(drvdata->ahbix_clk);
-	if (ret) {
-		dev_err(&pdev->dev, "error enabling ahbix_clk: %d\n", ret);
-		return ret;
+		dev_dbg(&pdev->dev, "set ahbix_clk rate to %lu\n",
+			clk_get_rate(drvdata->ahbix_clk));
+
+		ret = clk_prepare_enable(drvdata->ahbix_clk);
+		if (ret) {
+			dev_err(&pdev->dev,
+				"error enabling ahbix_clk: %d\n", ret);
+			return ret;
+		}
 	}
 
 	ret = devm_snd_soc_register_component(&pdev->dev,
Signature · 1 line
1.9.1
#9 lore raw

Re: [PATCH 04/11] ASoC: qcom: lpass-cpu: Make "ahbix-clk" an optional clock.

Quoted 1 line · Ajit Pandey

AHB-I/X bus clocks inside LPASS coreis not a mandatory clocks for

s/coreis/core is/

Quoted 2 lines

newer lpass variants, hence make it an optional one.

Can you add more detail on which version of IP would not have this clk.

Quoted 20 lines
---
  sound/soc/qcom/lpass-cpu.c | 31 ++++++++++++++++++-------------
  1 file changed, 18 insertions(+), 13 deletions(-)
sound/soc/qcom/lpass-cpu.c +1 -1
index 492f27b..f177932 100644
@@ -504,26 +504,31 @@ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev)
  		return ret;
  	}
 
-	drvdata->ahbix_clk = devm_clk_get(&pdev->dev, "ahbix-clk");
+	drvdata->ahbix_clk = devm_clk_get_optional(&pdev->dev, "ahbix-clk");
  	if (IS_ERR(drvdata->ahbix_clk)) {
  		dev_err(&pdev->dev, "error getting ahbix-clk: %ld\n",
  			PTR_ERR(drvdata->ahbix_clk));
  		return PTR_ERR(drvdata->ahbix_clk);
  	}

sound/soc/qcom/lpass-cpu.c int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev) · line 514

Quoted 10 lines
sound/soc/qcom/lpass-cpu.c +1 -8
 
-	ret = clk_set_rate(drvdata->ahbix_clk, LPASS_AHBIX_CLOCK_FREQUENCY);
-	if (ret) {
-		dev_err(&pdev->dev, "error setting rate on ahbix_clk: %d\n",
-			ret);
-		return ret;
-	}
-	dev_dbg(&pdev->dev, "set ahbix_clk rate to %lu\n",
-		clk_get_rate(drvdata->ahbix_clk));
+	if (drvdata->ahbix_clk != NULL) {

No need for NULL checks here, clk apis already have checks.

--srini

Quoted 25 lines
sound/soc/qcom/lpass-cpu.c +16 -4
+		ret = clk_set_rate(drvdata->ahbix_clk,
+				   LPASS_AHBIX_CLOCK_FREQUENCY);
+		if (ret) {
+			dev_err(&pdev->dev,
+				"error setting rate on ahbix_clk: %d\n", ret);
+			return ret;
+		}
 
-	ret = clk_prepare_enable(drvdata->ahbix_clk);
-	if (ret) {
-		dev_err(&pdev->dev, "error enabling ahbix_clk: %d\n", ret);
-		return ret;
+		dev_dbg(&pdev->dev, "set ahbix_clk rate to %lu\n",
+			clk_get_rate(drvdata->ahbix_clk));
+
+		ret = clk_prepare_enable(drvdata->ahbix_clk);
+		if (ret) {
+			dev_err(&pdev->dev,
+				"error enabling ahbix_clk: %d\n", ret);
+			return ret;
+		}
  	}
 
  	ret = devm_snd_soc_register_component(&pdev->dev,
#10 lore raw

PATCH 5/11 ASoC: qcom: lpass: Add support for newer lpass version

In reply to Ajit Pandey

Few control registers bit offset of lpaif in newer lpass variants are changed. Added "id" field in variant struct and changes macros configuration of registers to calculate bit mask & offset based on variant id.

---
 sound/soc/qcom/lpass-cpu.c       |  77 +++++++++--------
 sound/soc/qcom/lpass-lpaif-reg.h | 182 ++++++++++++++++++++++++++++++++++++++-
 sound/soc/qcom/lpass-platform.c  |  31 +++----
 sound/soc/qcom/lpass.h           |   6 ++
 4 files changed, 241 insertions(+), 55 deletions(-)
sound/soc/qcom/lpass-cpu.c +40 -37
index f177932..006ba5a 100644
@@ -77,6 +77,7 @@ static int lpass_cpu_daiops_hw_params(struct snd_pcm_substream *substream,
 {
 	struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai);
 	struct lpass_dai *dai_data = drvdata->dai_priv[dai->driver->id];
+	struct lpass_variant *v = drvdata->variant;
 	snd_pcm_format_t format = params_format(params);
 	unsigned int channels = params_channels(params);
 	unsigned int rate = params_rate(params);
@@ -89,18 +90,18 @@ static int lpass_cpu_daiops_hw_params(struct snd_pcm_substream *substream,
 		return bitwidth;
 	}
 
-	regval = LPAIF_I2SCTL_LOOPBACK_DISABLE |
-			LPAIF_I2SCTL_WSSRC_INTERNAL;
+	regval = LPAIF_I2SCTL(v, LOOPBACK_DISABLE);
+	regval |= LPAIF_I2SCTL(v, WSSRC_INTERNAL);
 
 	switch (bitwidth) {
 	case 16:
-		regval |= LPAIF_I2SCTL_BITWIDTH_16;
+		regval |= LPAIF_I2SCTL(v, BITWIDTH_16);
 		break;
 	case 24:
-		regval |= LPAIF_I2SCTL_BITWIDTH_24;
+		regval |= LPAIF_I2SCTL(v, BITWIDTH_24);
 		break;
 	case 32:
-		regval |= LPAIF_I2SCTL_BITWIDTH_32;
+		regval |= LPAIF_I2SCTL(v, BITWIDTH_32);
 		break;
 	default:
 		dev_err(dai->dev, "invalid bitwidth given: %d\n", bitwidth);
@@ -110,24 +111,24 @@ static int lpass_cpu_daiops_hw_params(struct snd_pcm_substream *substream,
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 		switch (channels) {
 		case 1:
-			regval |= LPAIF_I2SCTL_SPKMODE_SD0;
-			regval |= LPAIF_I2SCTL_SPKMONO_MONO;
+			regval |= LPAIF_I2SCTL(v, SPKMODE_SD0);
+			regval |= LPAIF_I2SCTL(v, SPKMONO_MONO);
 			break;
 		case 2:
-			regval |= LPAIF_I2SCTL_SPKMODE_SD0;
-			regval |= LPAIF_I2SCTL_SPKMONO_STEREO;
+			regval |= LPAIF_I2SCTL(v, SPKMODE_SD0);
+			regval |= LPAIF_I2SCTL(v, SPKMONO_STEREO);
 			break;
 		case 4:
-			regval |= LPAIF_I2SCTL_SPKMODE_QUAD01;
-			regval |= LPAIF_I2SCTL_SPKMONO_STEREO;
+			regval |= LPAIF_I2SCTL(v, SPKMODE_QUAD01);
+			regval |= LPAIF_I2SCTL(v, SPKMONO_STEREO);
 			break;
 		case 6:
-			regval |= LPAIF_I2SCTL_SPKMODE_6CH;
-			regval |= LPAIF_I2SCTL_SPKMONO_STEREO;
+			regval |= LPAIF_I2SCTL(v, SPKMODE_6CH);
+			regval |= LPAIF_I2SCTL(v, SPKMONO_STEREO);
 			break;
 		case 8:
-			regval |= LPAIF_I2SCTL_SPKMODE_8CH;
-			regval |= LPAIF_I2SCTL_SPKMONO_STEREO;
+			regval |= LPAIF_I2SCTL(v, SPKMODE_8CH);
+			regval |= LPAIF_I2SCTL(v, SPKMONO_STEREO);
 			break;
 		default:
 			dev_err(dai->dev, "invalid channels given: %u\n",
@@ -137,24 +138,24 @@ static int lpass_cpu_daiops_hw_params(struct snd_pcm_substream *substream,
 	} else {
 		switch (channels) {
 		case 1:
-			regval |= LPAIF_I2SCTL_MICMODE_SD0;
-			regval |= LPAIF_I2SCTL_MICMONO_MONO;
+			regval |= LPAIF_I2SCTL(v, MICMODE_SD0);
+			regval |= LPAIF_I2SCTL(v, MICMONO_MONO);
 			break;
 		case 2:
-			regval |= LPAIF_I2SCTL_MICMODE_SD0;
-			regval |= LPAIF_I2SCTL_MICMONO_STEREO;
+			regval |= LPAIF_I2SCTL(v, MICMODE_SD0);
+			regval |= LPAIF_I2SCTL(v, MICMONO_STEREO);
 			break;
 		case 4:
-			regval |= LPAIF_I2SCTL_MICMODE_QUAD01;
-			regval |= LPAIF_I2SCTL_MICMONO_STEREO;
+			regval |= LPAIF_I2SCTL(v, MICMODE_QUAD01);
+			regval |= LPAIF_I2SCTL(v, MICMONO_STEREO);
 			break;
 		case 6:
-			regval |= LPAIF_I2SCTL_MICMODE_6CH;
-			regval |= LPAIF_I2SCTL_MICMONO_STEREO;
+			regval |= LPAIF_I2SCTL(v, MICMODE_6CH);
+			regval |= LPAIF_I2SCTL(v, MICMONO_STEREO);
 			break;
 		case 8:
-			regval |= LPAIF_I2SCTL_MICMODE_8CH;
-			regval |= LPAIF_I2SCTL_MICMONO_STEREO;
+			regval |= LPAIF_I2SCTL(v, MICMODE_8CH);
+			regval |= LPAIF_I2SCTL(v, MICMONO_STEREO);
 			break;
 		default:
 			dev_err(dai->dev, "invalid channels given: %u\n",
@@ -200,15 +201,16 @@ static int lpass_cpu_daiops_prepare(struct snd_pcm_substream *substream,
 		struct snd_soc_dai *dai)
 {
 	struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai);
+	struct lpass_variant *v = drvdata->variant;
 	int ret;
 	unsigned int val, mask;
 
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-		val = LPAIF_I2SCTL_SPKEN_ENABLE;
-		mask = LPAIF_I2SCTL_SPKEN_MASK;
+		val = LPAIF_I2SCTL(v, SPKEN_ENABLE);
+		mask = LPAIF_I2SCTL(v, SPKEN_MASK);
 	} else  {
-		val = LPAIF_I2SCTL_MICEN_ENABLE;
-		mask = LPAIF_I2SCTL_MICEN_MASK;
+		val = LPAIF_I2SCTL(v, MICEN_ENABLE);
+		mask = LPAIF_I2SCTL(v, MICEN_MASK);
 	}
 
 	ret = regmap_update_bits(drvdata->lpaif_map,
@@ -224,6 +226,7 @@ static int lpass_cpu_daiops_trigger(struct snd_pcm_substream *substream,
 		int cmd, struct snd_soc_dai *dai)
 {
 	struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai);
+	struct lpass_variant *v = drvdata->variant;
 	int ret = -EINVAL;
 	unsigned int val, mask;
 
@@ -232,11 +235,11 @@ static int lpass_cpu_daiops_trigger(struct snd_pcm_substream *substream,
 	case SNDRV_PCM_TRIGGER_RESUME:
 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
 		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-			val = LPAIF_I2SCTL_SPKEN_ENABLE;
-			mask = LPAIF_I2SCTL_SPKEN_MASK;
+			val = LPAIF_I2SCTL(v, SPKEN_ENABLE);
+			mask = LPAIF_I2SCTL(v, SPKEN_MASK);
 		} else  {
-			val = LPAIF_I2SCTL_MICEN_ENABLE;
-			mask = LPAIF_I2SCTL_MICEN_MASK;
+			val = LPAIF_I2SCTL(v, MICEN_ENABLE);
+			mask = LPAIF_I2SCTL(v, MICEN_MASK);
 		}
 
 		ret = regmap_update_bits(drvdata->lpaif_map,
@@ -251,11 +254,11 @@ static int lpass_cpu_daiops_trigger(struct snd_pcm_substream *substream,
 	case SNDRV_PCM_TRIGGER_SUSPEND:
 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
 		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-			val = LPAIF_I2SCTL_SPKEN_DISABLE;
-			mask = LPAIF_I2SCTL_SPKEN_MASK;
+			val = LPAIF_I2SCTL(v, SPKEN_DISABLE);
+			mask = LPAIF_I2SCTL(v, SPKEN_MASK);
 		} else  {
-			val = LPAIF_I2SCTL_MICEN_DISABLE;
-			mask = LPAIF_I2SCTL_MICEN_MASK;
+			val = LPAIF_I2SCTL(v, MICEN_DISABLE);
+			mask = LPAIF_I2SCTL(v, MICEN_MASK);
 		}
 
 		ret = regmap_update_bits(drvdata->lpaif_map,
sound/soc/qcom/lpass-lpaif-reg.h +179 -3

253 lines not on this page · raw message

sound/soc/qcom/lpass-platform.c +16 -15
index b05091c2..821599e 100644
@@ -146,25 +146,26 @@ static int lpass_platform_pcmops_hw_params(struct snd_soc_component *component,
 		return bitwidth;
 	}
 
-	regval = LPAIF_DMACTL_BURSTEN_INCR4 |
-			LPAIF_DMACTL_AUDINTF(dma_port) |
-			LPAIF_DMACTL_FIFOWM_8;
+
+	regval = LPAIF_DMACTL(v, BURSTEN_INCR4);
+	regval |= LPAIF_DMACTL(v, FIFOWM_8);
+	regval |= LPAIF_DMACTL_AUD_INTF(v, dma_port);
 
 	switch (bitwidth) {
 	case 16:
 		switch (channels) {
 		case 1:
 		case 2:
-			regval |= LPAIF_DMACTL_WPSCNT_ONE;
+			regval |= LPAIF_DMACTL(v, WPSCNT_ONE);
 			break;
 		case 4:
-			regval |= LPAIF_DMACTL_WPSCNT_TWO;
+			regval |= LPAIF_DMACTL(v, WPSCNT_TWO);
 			break;
 		case 6:
-			regval |= LPAIF_DMACTL_WPSCNT_THREE;
+			regval |= LPAIF_DMACTL(v, WPSCNT_THREE);
 			break;
 		case 8:
-			regval |= LPAIF_DMACTL_WPSCNT_FOUR;
+			regval |= LPAIF_DMACTL(v, WPSCNT_FOUR);
 			break;
 		default:
 			dev_err(soc_runtime->dev,
@@ -177,19 +178,19 @@ static int lpass_platform_pcmops_hw_params(struct snd_soc_component *component,
 	case 32:
 		switch (channels) {
 		case 1:
-			regval |= LPAIF_DMACTL_WPSCNT_ONE;
+			regval |= LPAIF_DMACTL(v, WPSCNT_ONE);
 			break;
 		case 2:
-			regval |= LPAIF_DMACTL_WPSCNT_TWO;
+			regval |= LPAIF_DMACTL(v, WPSCNT_TWO);
 			break;
 		case 4:
-			regval |= LPAIF_DMACTL_WPSCNT_FOUR;
+			regval |= LPAIF_DMACTL(v, WPSCNT_FOUR);
 			break;
 		case 6:
-			regval |= LPAIF_DMACTL_WPSCNT_SIX;
+			regval |= LPAIF_DMACTL(v, WPSCNT_SIX);
 			break;
 		case 8:
-			regval |= LPAIF_DMACTL_WPSCNT_EIGHT;
+			regval |= LPAIF_DMACTL(v, WPSCNT_EIGHT);
 			break;
 		default:
 			dev_err(soc_runtime->dev,
@@ -277,7 +278,7 @@ static int lpass_platform_pcmops_prepare(struct snd_soc_component *component,
 
 	ret = regmap_update_bits(drvdata->lpaif_map,
 			LPAIF_DMACTL_REG(v, ch, dir),
-			LPAIF_DMACTL_ENABLE_MASK, LPAIF_DMACTL_ENABLE_ON);
+			LPAIF_DMACTL(v, ENABLE_MASK), LPAIF_DMACTL_ENABLE_ON);
 	if (ret) {
 		dev_err(soc_runtime->dev, "error writing to rdmactl reg: %d\n",
 			ret);
@@ -326,7 +327,7 @@ static int lpass_platform_pcmops_trigger(struct snd_soc_component *component,
 
 		ret = regmap_update_bits(drvdata->lpaif_map,
 				LPAIF_DMACTL_REG(v, ch, dir),
-				LPAIF_DMACTL_ENABLE_MASK,
+				LPAIF_DMACTL(v, ENABLE_MASK),
 				LPAIF_DMACTL_ENABLE_ON);
 		if (ret) {
 			dev_err(soc_runtime->dev,
@@ -339,7 +340,7 @@ static int lpass_platform_pcmops_trigger(struct snd_soc_component *component,
 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
 		ret = regmap_update_bits(drvdata->lpaif_map,
 				LPAIF_DMACTL_REG(v, ch, dir),
-				LPAIF_DMACTL_ENABLE_MASK,
+				LPAIF_DMACTL(v, ENABLE_MASK),
 				LPAIF_DMACTL_ENABLE_OFF);
 		if (ret) {
 			dev_err(soc_runtime->dev,
sound/soc/qcom/lpass.h +6 -0
index 279cd02..384f4b8 100644
@@ -17,6 +17,9 @@
 #define LPASS_MAX_MI2S_PORTS                   (8)
 #define LPASS_MAX_DMA_CHANNELS                 (8)
 
+#define LPASS_VARIANT				0
+#define LPASS_VARIANT_V2			1
+
 struct lpass_dai {
 	struct clk *osr_clk;
 	struct clk *bit_clk;
@@ -91,6 +94,9 @@ struct lpass_variant {
 	/* SOC specific clocks configuration */
 	const char **clk_name;
 	int num_clks;
+
+	/* LPASS Version id */
+	int id;
 };
 
 /* register the platform driver from the CPU DAI driver */
Signature · 1 line
1.9.1
#11 lore raw

Re: [PATCH 05/11] ASoC: qcom: lpass: Add support for newer lpass version

Quoted 5 lines · Ajit Pandey

Few control registers bit offset of lpaif in newer lpass variants are changed. Added "id" field in variant struct and changes macros configuration of registers to calculate bit mask & offset based on variant id.

These fields are handled much nicely with regmap_field, you should consider using that. If not we will add overhead of check for every mask.

Quoted 543 lines
---
  sound/soc/qcom/lpass-cpu.c       |  77 +++++++++--------
  sound/soc/qcom/lpass-lpaif-reg.h | 182 ++++++++++++++++++++++++++++++++++++++-
  sound/soc/qcom/lpass-platform.c  |  31 +++----
  sound/soc/qcom/lpass.h           |   6 ++
  4 files changed, 241 insertions(+), 55 deletions(-)
sound/soc/qcom/lpass-cpu.c +40 -37
index f177932..006ba5a 100644
@@ -77,6 +77,7 @@ static int lpass_cpu_daiops_hw_params(struct snd_pcm_substream *substream,
  {
  	struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai);
  	struct lpass_dai *dai_data = drvdata->dai_priv[dai->driver->id];
+	struct lpass_variant *v = drvdata->variant;
  	snd_pcm_format_t format = params_format(params);
  	unsigned int channels = params_channels(params);
  	unsigned int rate = params_rate(params);
@@ -89,18 +90,18 @@ static int lpass_cpu_daiops_hw_params(struct snd_pcm_substream *substream,
  		return bitwidth;
  	}
 
-	regval = LPAIF_I2SCTL_LOOPBACK_DISABLE |
-			LPAIF_I2SCTL_WSSRC_INTERNAL;
+	regval = LPAIF_I2SCTL(v, LOOPBACK_DISABLE);
+	regval |= LPAIF_I2SCTL(v, WSSRC_INTERNAL);
 
  	switch (bitwidth) {
  	case 16:
-		regval |= LPAIF_I2SCTL_BITWIDTH_16;
+		regval |= LPAIF_I2SCTL(v, BITWIDTH_16);
  		break;
  	case 24:
-		regval |= LPAIF_I2SCTL_BITWIDTH_24;
+		regval |= LPAIF_I2SCTL(v, BITWIDTH_24);
  		break;
  	case 32:
-		regval |= LPAIF_I2SCTL_BITWIDTH_32;
+		regval |= LPAIF_I2SCTL(v, BITWIDTH_32);
  		break;
  	default:
  		dev_err(dai->dev, "invalid bitwidth given: %d\n", bitwidth);
@@ -110,24 +111,24 @@ static int lpass_cpu_daiops_hw_params(struct snd_pcm_substream *substream,
  	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
  		switch (channels) {
  		case 1:
-			regval |= LPAIF_I2SCTL_SPKMODE_SD0;
-			regval |= LPAIF_I2SCTL_SPKMONO_MONO;
+			regval |= LPAIF_I2SCTL(v, SPKMODE_SD0);
+			regval |= LPAIF_I2SCTL(v, SPKMONO_MONO);
  			break;
  		case 2:
-			regval |= LPAIF_I2SCTL_SPKMODE_SD0;
-			regval |= LPAIF_I2SCTL_SPKMONO_STEREO;
+			regval |= LPAIF_I2SCTL(v, SPKMODE_SD0);
+			regval |= LPAIF_I2SCTL(v, SPKMONO_STEREO);
  			break;
  		case 4:
-			regval |= LPAIF_I2SCTL_SPKMODE_QUAD01;
-			regval |= LPAIF_I2SCTL_SPKMONO_STEREO;
+			regval |= LPAIF_I2SCTL(v, SPKMODE_QUAD01);
+			regval |= LPAIF_I2SCTL(v, SPKMONO_STEREO);
  			break;
  		case 6:
-			regval |= LPAIF_I2SCTL_SPKMODE_6CH;
-			regval |= LPAIF_I2SCTL_SPKMONO_STEREO;
+			regval |= LPAIF_I2SCTL(v, SPKMODE_6CH);
+			regval |= LPAIF_I2SCTL(v, SPKMONO_STEREO);
  			break;
  		case 8:
-			regval |= LPAIF_I2SCTL_SPKMODE_8CH;
-			regval |= LPAIF_I2SCTL_SPKMONO_STEREO;
+			regval |= LPAIF_I2SCTL(v, SPKMODE_8CH);
+			regval |= LPAIF_I2SCTL(v, SPKMONO_STEREO);
  			break;
  		default:
  			dev_err(dai->dev, "invalid channels given: %u\n",
@@ -137,24 +138,24 @@ static int lpass_cpu_daiops_hw_params(struct snd_pcm_substream *substream,
  	} else {
  		switch (channels) {
  		case 1:
-			regval |= LPAIF_I2SCTL_MICMODE_SD0;
-			regval |= LPAIF_I2SCTL_MICMONO_MONO;
+			regval |= LPAIF_I2SCTL(v, MICMODE_SD0);
+			regval |= LPAIF_I2SCTL(v, MICMONO_MONO);
  			break;
  		case 2:
-			regval |= LPAIF_I2SCTL_MICMODE_SD0;
-			regval |= LPAIF_I2SCTL_MICMONO_STEREO;
+			regval |= LPAIF_I2SCTL(v, MICMODE_SD0);
+			regval |= LPAIF_I2SCTL(v, MICMONO_STEREO);
  			break;
  		case 4:
-			regval |= LPAIF_I2SCTL_MICMODE_QUAD01;
-			regval |= LPAIF_I2SCTL_MICMONO_STEREO;
+			regval |= LPAIF_I2SCTL(v, MICMODE_QUAD01);
+			regval |= LPAIF_I2SCTL(v, MICMONO_STEREO);
  			break;
  		case 6:
-			regval |= LPAIF_I2SCTL_MICMODE_6CH;
-			regval |= LPAIF_I2SCTL_MICMONO_STEREO;
+			regval |= LPAIF_I2SCTL(v, MICMODE_6CH);
+			regval |= LPAIF_I2SCTL(v, MICMONO_STEREO);
  			break;
  		case 8:
-			regval |= LPAIF_I2SCTL_MICMODE_8CH;
-			regval |= LPAIF_I2SCTL_MICMONO_STEREO;
+			regval |= LPAIF_I2SCTL(v, MICMODE_8CH);
+			regval |= LPAIF_I2SCTL(v, MICMONO_STEREO);
  			break;
  		default:
  			dev_err(dai->dev, "invalid channels given: %u\n",
@@ -200,15 +201,16 @@ static int lpass_cpu_daiops_prepare(struct snd_pcm_substream *substream,
  		struct snd_soc_dai *dai)
  {
  	struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai);
+	struct lpass_variant *v = drvdata->variant;
  	int ret;
  	unsigned int val, mask;
 
  	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-		val = LPAIF_I2SCTL_SPKEN_ENABLE;
-		mask = LPAIF_I2SCTL_SPKEN_MASK;
+		val = LPAIF_I2SCTL(v, SPKEN_ENABLE);
+		mask = LPAIF_I2SCTL(v, SPKEN_MASK);
  	} else  {
-		val = LPAIF_I2SCTL_MICEN_ENABLE;
-		mask = LPAIF_I2SCTL_MICEN_MASK;
+		val = LPAIF_I2SCTL(v, MICEN_ENABLE);
+		mask = LPAIF_I2SCTL(v, MICEN_MASK);
  	}
 
  	ret = regmap_update_bits(drvdata->lpaif_map,
@@ -224,6 +226,7 @@ static int lpass_cpu_daiops_trigger(struct snd_pcm_substream *substream,
  		int cmd, struct snd_soc_dai *dai)
  {
  	struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai);
+	struct lpass_variant *v = drvdata->variant;
  	int ret = -EINVAL;
  	unsigned int val, mask;
 
@@ -232,11 +235,11 @@ static int lpass_cpu_daiops_trigger(struct snd_pcm_substream *substream,
  	case SNDRV_PCM_TRIGGER_RESUME:
  	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
  		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-			val = LPAIF_I2SCTL_SPKEN_ENABLE;
-			mask = LPAIF_I2SCTL_SPKEN_MASK;
+			val = LPAIF_I2SCTL(v, SPKEN_ENABLE);
+			mask = LPAIF_I2SCTL(v, SPKEN_MASK);
  		} else  {
-			val = LPAIF_I2SCTL_MICEN_ENABLE;
-			mask = LPAIF_I2SCTL_MICEN_MASK;
+			val = LPAIF_I2SCTL(v, MICEN_ENABLE);
+			mask = LPAIF_I2SCTL(v, MICEN_MASK);
  		}
 
  		ret = regmap_update_bits(drvdata->lpaif_map,
@@ -251,11 +254,11 @@ static int lpass_cpu_daiops_trigger(struct snd_pcm_substream *substream,
  	case SNDRV_PCM_TRIGGER_SUSPEND:
  	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
  		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-			val = LPAIF_I2SCTL_SPKEN_DISABLE;
-			mask = LPAIF_I2SCTL_SPKEN_MASK;
+			val = LPAIF_I2SCTL(v, SPKEN_DISABLE);
+			mask = LPAIF_I2SCTL(v, SPKEN_MASK);
  		} else  {
-			val = LPAIF_I2SCTL_MICEN_DISABLE;
-			mask = LPAIF_I2SCTL_MICEN_MASK;
+			val = LPAIF_I2SCTL(v, MICEN_DISABLE);
+			mask = LPAIF_I2SCTL(v, MICEN_MASK);
  		}
 
  		ret = regmap_update_bits(drvdata->lpaif_map,
sound/soc/qcom/lpass-lpaif-reg.h +179 -3
index 3d74ae1..4251aa6 100644
@@ -17,11 +17,28 @@
  #define LPAIF_I2SCTL_LOOPBACK_DISABLE	(0 << LPAIF_I2SCTL_LOOPBACK_SHIFT)
  #define LPAIF_I2SCTL_LOOPBACK_ENABLE	(1 << LPAIF_I2SCTL_LOOPBACK_SHIFT)
 
+#define LPAIF_I2SCTL_LOOPBACK_MASK_V2	 0x20000
+#define LPAIF_I2SCTL_LOOPBACK_SHIFT_V2	 17
+#define LPAIF_I2SCTL_LOOPBACK_DISABLE_V2 (0 << LPAIF_I2SCTL_LOOPBACK_SHIFT_V2)
+#define LPAIF_I2SCTL_LOOPBACK_ENABLE_V2	 (1 << LPAIF_I2SCTL_LOOPBACK_SHIFT_V2)
+
  #define LPAIF_I2SCTL_SPKEN_MASK		0x4000
  #define LPAIF_I2SCTL_SPKEN_SHIFT	14
  #define LPAIF_I2SCTL_SPKEN_DISABLE	(0 << LPAIF_I2SCTL_SPKEN_SHIFT)
  #define LPAIF_I2SCTL_SPKEN_ENABLE	(1 << LPAIF_I2SCTL_SPKEN_SHIFT)
 
+#define LPAIF_I2SCTL_SPKEN_MASK_V2	0x10000
+#define LPAIF_I2SCTL_SPKEN_SHIFT_V2	16
+#define LPAIF_I2SCTL_SPKEN_DISABLE_V2	(0 << LPAIF_I2SCTL_SPKEN_SHIFT_V2)
+#define LPAIF_I2SCTL_SPKEN_ENABLE_V2	(1 << LPAIF_I2SCTL_SPKEN_SHIFT_V2)
+
+#define __LPAIF_I2S_CTL(v, bit)  \
+	((v->id ==  LPASS_VARIANT_V2) ? \
+		LPAIF_I2SCTL_##bit##_V2 : \
+		LPAIF_I2SCTL_##bit)
+
+#define LPAIF_I2SCTL(v, bit)		__LPAIF_I2S_CTL(v, bit)
+
  #define LPAIF_I2SCTL_SPKMODE_MASK	0x3C00
  #define LPAIF_I2SCTL_SPKMODE_SHIFT	10
  #define LPAIF_I2SCTL_SPKMODE_NONE	(0 << LPAIF_I2SCTL_SPKMODE_SHIFT)
@@ -34,16 +51,49 @@
  #define LPAIF_I2SCTL_SPKMODE_6CH	(7 << LPAIF_I2SCTL_SPKMODE_SHIFT)
  #define LPAIF_I2SCTL_SPKMODE_8CH	(8 << LPAIF_I2SCTL_SPKMODE_SHIFT)
 
+#define LPAIF_I2SCTL_SPKMODE_MASK_V2	0xF800
+#define LPAIF_I2SCTL_SPKMODE_SHIFT_V2	11
+#define LPAIF_I2SCTL_SPKMODE_NONE_V2	(0 << LPAIF_I2SCTL_SPKMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_SPKMODE_SD0_V2	(1 << LPAIF_I2SCTL_SPKMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_SPKMODE_SD1_V2	(2 << LPAIF_I2SCTL_SPKMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_SPKMODE_SD2_V2	(3 << LPAIF_I2SCTL_SPKMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_SPKMODE_SD3_V2	(4 << LPAIF_I2SCTL_SPKMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_SPKMODE_QUAD01_V2	(5 << LPAIF_I2SCTL_SPKMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_SPKMODE_QUAD23_V2	(6 << LPAIF_I2SCTL_SPKMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_SPKMODE_6CH_V2	(7 << LPAIF_I2SCTL_SPKMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_SPKMODE_8CH_V2	(8 << LPAIF_I2SCTL_SPKMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_SPKMODE_10CH_V2	(9 << LPAIF_I2SCTL_SPKMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_SPKMODE_12CH_V2	(10 << LPAIF_I2SCTL_SPKMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_SPKMODE_14CH_V2	(11 << LPAIF_I2SCTL_SPKMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_SPKMODE_16CH_V2	(12 << LPAIF_I2SCTL_SPKMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_SPKMODE_SD4_V2	(13 << LPAIF_I2SCTL_SPKMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_SPKMODE_SD5_V2	(14 << LPAIF_I2SCTL_SPKMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_SPKMODE_SD6_V2	(15 << LPAIF_I2SCTL_SPKMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_SPKMODE_SD7_V2	(16 << LPAIF_I2SCTL_SPKMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_SPKMODE_QUAD45_V2	(17 << LPAIF_I2SCTL_SPKMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_SPKMODE_QUAD47_V2	(18 << LPAIF_I2SCTL_SPKMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_SPKMODE_8CH_2_V2	(19 << LPAIF_I2SCTL_SPKMODE_SHIFT_V2)
+
  #define LPAIF_I2SCTL_SPKMONO_MASK	0x0200
  #define LPAIF_I2SCTL_SPKMONO_SHIFT	9
  #define LPAIF_I2SCTL_SPKMONO_STEREO	(0 << LPAIF_I2SCTL_SPKMONO_SHIFT)
  #define LPAIF_I2SCTL_SPKMONO_MONO	(1 << LPAIF_I2SCTL_SPKMONO_SHIFT)
 
+#define LPAIF_I2SCTL_SPKMONO_MASK_V2	0x0400
+#define LPAIF_I2SCTL_SPKMONO_SHIFT_V2	10
+#define LPAIF_I2SCTL_SPKMONO_STEREO_V2	(0 << LPAIF_I2SCTL_SPKMONO_SHIFT_V2)
+#define LPAIF_I2SCTL_SPKMONO_MONO_V2	(1 << LPAIF_I2SCTL_SPKMONO_SHIFT_V2)
+
  #define LPAIF_I2SCTL_MICEN_MASK		GENMASK(8, 8)
  #define LPAIF_I2SCTL_MICEN_SHIFT	8
  #define LPAIF_I2SCTL_MICEN_DISABLE	(0 << LPAIF_I2SCTL_MICEN_SHIFT)
  #define LPAIF_I2SCTL_MICEN_ENABLE	(1 << LPAIF_I2SCTL_MICEN_SHIFT)
 
+#define LPAIF_I2SCTL_MICEN_MASK_V2	0x0200
+#define LPAIF_I2SCTL_MICEN_SHIFT_V2	9
+#define LPAIF_I2SCTL_MICEN_DISABLE_V2	(0 << LPAIF_I2SCTL_MICEN_SHIFT_V2)
+#define LPAIF_I2SCTL_MICEN_ENABLE_V2	(1 << LPAIF_I2SCTL_MICEN_SHIFT_V2)
+
  #define LPAIF_I2SCTL_MICMODE_MASK	GENMASK(7, 4)
  #define LPAIF_I2SCTL_MICMODE_SHIFT	4
  #define LPAIF_I2SCTL_MICMODE_NONE	(0 << LPAIF_I2SCTL_MICMODE_SHIFT)
@@ -56,22 +106,61 @@
  #define LPAIF_I2SCTL_MICMODE_6CH	(7 << LPAIF_I2SCTL_MICMODE_SHIFT)
  #define LPAIF_I2SCTL_MICMODE_8CH	(8 << LPAIF_I2SCTL_MICMODE_SHIFT)
 
+#define LPAIF_I2SCTL_MICMODE_MASK_V2	GENMASK(8, 4)
+#define LPAIF_I2SCTL_MICMODE_SHIFT_V2	4
+#define LPAIF_I2SCTL_MICMODE_NONE_V2	(0 << LPAIF_I2SCTL_MICMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_MICMODE_SD0_V2	(1 << LPAIF_I2SCTL_MICMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_MICMODE_SD1_V2	(2 << LPAIF_I2SCTL_MICMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_MICMODE_SD2_V2	(3 << LPAIF_I2SCTL_MICMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_MICMODE_SD3_V2	(4 << LPAIF_I2SCTL_MICMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_MICMODE_QUAD01_V2	(5 << LPAIF_I2SCTL_MICMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_MICMODE_QUAD23_V2	(6 << LPAIF_I2SCTL_MICMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_MICMODE_6CH_V2	(7 << LPAIF_I2SCTL_MICMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_MICMODE_8CH_V2	(8 << LPAIF_I2SCTL_MICMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_MICMODE_10CH_V2	(9 << LPAIF_I2SCTL_MICMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_MICMODE_12CH_V2	(10 << LPAIF_I2SCTL_MICMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_MICMODE_14CH_V2	(11 << LPAIF_I2SCTL_MICMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_MICMODE_16CH_V2	(12 << LPAIF_I2SCTL_MICMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_MICMODE_SD4_V2	(13 << LPAIF_I2SCTL_MICMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_MICMODE_SD5_V2	(14 << LPAIF_I2SCTL_MICMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_MICMODE_SD6_V2	(15 << LPAIF_I2SCTL_MICMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_MICMODE_SD7_V2	(16 << LPAIF_I2SCTL_MICMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_MICMODE_QUAD45_V2	(17 << LPAIF_I2SCTL_MICMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_MICMODE_QUAD47_V2	(18 << LPAIF_I2SCTL_MICMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_MICMODE_8CH_2_V2	(19 << LPAIF_I2SCTL_MICMODE_SHIFT_V2)
+
  #define LPAIF_I2SCTL_MIMONO_MASK	GENMASK(3, 3)
  #define LPAIF_I2SCTL_MICMONO_SHIFT	3
  #define LPAIF_I2SCTL_MICMONO_STEREO	(0 << LPAIF_I2SCTL_MICMONO_SHIFT)
  #define LPAIF_I2SCTL_MICMONO_MONO	(1 << LPAIF_I2SCTL_MICMONO_SHIFT)
 
+#define LPAIF_I2SCTL_MICMONO_MASK_V2	GENMASK(3, 3)
+#define LPAIF_I2SCTL_MICMONO_SHIFT_V2	3
+#define LPAIF_I2SCTL_MICMONO_STEREO_V2	(0 << LPAIF_I2SCTL_MICMONO_SHIFT_V2)
+#define LPAIF_I2SCTL_MICMONO_MONO_V2	(1 << LPAIF_I2SCTL_MICMONO_SHIFT_V2)
+
  #define LPAIF_I2SCTL_WSSRC_MASK		0x0004
  #define LPAIF_I2SCTL_WSSRC_SHIFT	2
  #define LPAIF_I2SCTL_WSSRC_INTERNAL	(0 << LPAIF_I2SCTL_WSSRC_SHIFT)
  #define LPAIF_I2SCTL_WSSRC_EXTERNAL	(1 << LPAIF_I2SCTL_WSSRC_SHIFT)
 
+#define LPAIF_I2SCTL_WSSRC_MASK_V2	0x0004
+#define LPAIF_I2SCTL_WSSRC_SHIFT_V2	2
+#define LPAIF_I2SCTL_WSSRC_INTERNAL_V2	(0 << LPAIF_I2SCTL_WSSRC_SHIFT_V2)
+#define LPAIF_I2SCTL_WSSRC_EXTERNAL_V2	(1 << LPAIF_I2SCTL_WSSRC_SHIFT_V2)
+
  #define LPAIF_I2SCTL_BITWIDTH_MASK	0x0003
  #define LPAIF_I2SCTL_BITWIDTH_SHIFT	0
  #define LPAIF_I2SCTL_BITWIDTH_16	(0 << LPAIF_I2SCTL_BITWIDTH_SHIFT)
  #define LPAIF_I2SCTL_BITWIDTH_24	(1 << LPAIF_I2SCTL_BITWIDTH_SHIFT)
  #define LPAIF_I2SCTL_BITWIDTH_32	(2 << LPAIF_I2SCTL_BITWIDTH_SHIFT)
 
+#define LPAIF_I2SCTL_BITWIDTH_MASK_V2	0x0003
+#define LPAIF_I2SCTL_BITWIDTH_SHIFT_V2	0
+#define LPAIF_I2SCTL_BITWIDTH_16_V2	(0 << LPAIF_I2SCTL_BITWIDTH_SHIFT_V2)
+#define LPAIF_I2SCTL_BITWIDTH_24_V2	(1 << LPAIF_I2SCTL_BITWIDTH_SHIFT_V2)
+#define LPAIF_I2SCTL_BITWIDTH_32_V2	(2 << LPAIF_I2SCTL_BITWIDTH_SHIFT_V2)
+
  /* LPAIF IRQ */
  #define LPAIF_IRQ_REG_ADDR(v, addr, port) \
  	(v->irq_reg_base + (addr) + v->irq_reg_stride * (port))
@@ -91,7 +180,6 @@
  #define LPAIF_IRQ_ALL(chan)		(7 << (LPAIF_IRQ_BITSTRIDE * (chan)))
 
  /* LPAIF DMA */
-
  #define LPAIF_RDMA_REG_ADDR(v, addr, chan) \
  	(v->rdma_reg_base + (addr) + v->rdma_reg_stride * (chan))
 
@@ -143,7 +231,7 @@
 
  #define LPAIF_DMACTL_AUDINTF_MASK	0x0F0
  #define LPAIF_DMACTL_AUDINTF_SHIFT	4
-#define LPAIF_DMACTL_AUDINTF(id)	(id << LPAIF_DMACTL_AUDINTF_SHIFT)
+#define LPAIF_DMACTL_AUDINTF(port)	(port << LPAIF_DMACTL_AUDINTF_SHIFT)
 
  #define LPAIF_DMACTL_FIFOWM_MASK	0x00E
  #define LPAIF_DMACTL_FIFOWM_SHIFT	1
@@ -158,11 +246,99 @@
 
  #define LPAIF_DMACTL_ENABLE_MASK	0x1
  #define LPAIF_DMACTL_ENABLE_SHIFT	0
-#define LPAIF_DMACTL_ENABLE_OFF	(0 << LPAIF_DMACTL_ENABLE_SHIFT)
+#define LPAIF_DMACTL_ENABLE_OFF		(0 << LPAIF_DMACTL_ENABLE_SHIFT)
  #define LPAIF_DMACTL_ENABLE_ON		(1 << LPAIF_DMACTL_ENABLE_SHIFT)
 
+#define LPAIF_IRQ_BITSTRIDE		3
+
+#define LPAIF_IRQ_PER(chan)		(1 << (LPAIF_IRQ_BITSTRIDE * (chan)))
+#define LPAIF_IRQ_XRUN(chan)		(2 << (LPAIF_IRQ_BITSTRIDE * (chan)))
+#define LPAIF_IRQ_ERR(chan)		(4 << (LPAIF_IRQ_BITSTRIDE * (chan)))
+
+#define LPAIF_IRQ_ALL(chan)		(7 << (LPAIF_IRQ_BITSTRIDE * (chan)))
+
  #define LPAIF_DMACTL_DYNCLK_MASK	BIT(12)
  #define LPAIF_DMACTL_DYNCLK_SHIFT	12
  #define LPAIF_DMACTL_DYNCLK_OFF	(0 << LPAIF_DMACTL_DYNCLK_SHIFT)
  #define LPAIF_DMACTL_DYNCLK_ON		(1 << LPAIF_DMACTL_DYNCLK_SHIFT)
+
+#define LPAIF_DMACTL_BURSTEN_MASK_V2	0x100000
+#define LPAIF_DMACTL_BURSTEN_SHIFT_V2	20
+#define LPAIF_DMACTL_BURSTEN_SINGLE_V2	(0 << LPAIF_DMACTL_BURSTEN_SHIFT_V2)
+#define LPAIF_DMACTL_BURSTEN_INCR4_V2	(1 << LPAIF_DMACTL_BURSTEN_SHIFT_V2)
+
+#define LPAIF_DMACTL_WPSCNT_MASK_V2	0xF0000
+#define LPAIF_DMACTL_WPSCNT_SHIFT_V2	16
+#define LPAIF_DMACTL_WPSCNT_ONE_V2	(0 << LPAIF_DMACTL_WPSCNT_SHIFT_V2)
+#define LPAIF_DMACTL_WPSCNT_TWO_V2	(1 << LPAIF_DMACTL_WPSCNT_SHIFT_V2)
+#define LPAIF_DMACTL_WPSCNT_THREE_V2	(2 << LPAIF_DMACTL_WPSCNT_SHIFT_V2)
+#define LPAIF_DMACTL_WPSCNT_FOUR_V2	(3 << LPAIF_DMACTL_WPSCNT_SHIFT_V2)
+#define LPAIF_DMACTL_WPSCNT_SIX_V2	(5 << LPAIF_DMACTL_WPSCNT_SHIFT_V2)
+#define LPAIF_DMACTL_WPSCNT_EIGHT_V2	(7 << LPAIF_DMACTL_WPSCNT_SHIFT_V2)
+#define LPAIF_DMACTL_WPSCNT_TEN_V2	(9 << LPAIF_DMACTL_WPSCNT_SHIFT_V2)
+#define LPAIF_DMACTL_WPSCNT_TWELVE_V2	(11 << LPAIF_DMACTL_WPSCNT_SHIFT_V2)
+#define LPAIF_DMACTL_WPSCNT_FOURTEEN_V2	(13 << LPAIF_DMACTL_WPSCNT_SHIFT_V2)
+#define LPAIF_DMACTL_WPSCNT_SIXTEEN_V2	(15 << LPAIF_DMACTL_WPSCNT_SHIFT_V2)
+
+#define LPAIF_DMACTL_AUDINTF_MASK_V2	0xF000
+#define LPAIF_DMACTL_AUDINTF_SHIFT_V2	12
+#define LPAIF_DMACTL_AUDINTF_V2(port)	(port << LPAIF_DMACTL_AUDINTF_SHIFT_V2)
+
+#define LPAIF_DMACTL_AUD_INTF(v, port)  \
+	((v->id ==  LPASS_VARIANT_V2) ? \
+		LPAIF_DMACTL_AUDINTF_V2(port) : \
+		LPAIF_DMACTL_AUDINTF(port))
+
+#define LPAIF_DMACTL_FIFOWM_MASK_V2	0x3E
+#define LPAIF_DMACTL_FIFOWM_SHIFT_V2	1
+#define LPAIF_DMACTL_FIFOWM_1_V2	(0 << LPAIF_DMACTL_FIFOWM_SHIFT_V2)
+#define LPAIF_DMACTL_FIFOWM_2_V2	(1 << LPAIF_DMACTL_FIFOWM_SHIFT_V2)
+#define LPAIF_DMACTL_FIFOWM_3_V2	(2 << LPAIF_DMACTL_FIFOWM_SHIFT_V2)
+#define LPAIF_DMACTL_FIFOWM_4_V2	(3 << LPAIF_DMACTL_FIFOWM_SHIFT_V2)
+#define LPAIF_DMACTL_FIFOWM_5_V2	(4 << LPAIF_DMACTL_FIFOWM_SHIFT_V2)
+#define LPAIF_DMACTL_FIFOWM_6_V2	(5 << LPAIF_DMACTL_FIFOWM_SHIFT_V2)
+#define LPAIF_DMACTL_FIFOWM_7_V2	(6 << LPAIF_DMACTL_FIFOWM_SHIFT_V2)
+#define LPAIF_DMACTL_FIFOWM_8_V2	(7 << LPAIF_DMACTL_FIFOWM_SHIFT_V2)
+#define LPAIF_DMACTL_FIFOWM_9_V2	(8 << LPAIF_DMACTL_FIFOWM_SHIFT_V2)
+#define LPAIF_DMACTL_FIFOWM_10_V2	(9 << LPAIF_DMACTL_FIFOWM_SHIFT_V2)
+#define LPAIF_DMACTL_FIFOWM_11_V2	(10 << LPAIF_DMACTL_FIFOWM_SHIFT_V2)
+#define LPAIF_DMACTL_FIFOWM_12_V2	(11 << LPAIF_DMACTL_FIFOWM_SHIFT_V2)
+#define LPAIF_DMACTL_FIFOWM_13_V2	(12 << LPAIF_DMACTL_FIFOWM_SHIFT_V2)
+#define LPAIF_DMACTL_FIFOWM_14_V2	(13 << LPAIF_DMACTL_FIFOWM_SHIFT_V2)
+#define LPAIF_DMACTL_FIFOWM_15_V2	(14 << LPAIF_DMACTL_FIFOWM_SHIFT_V2)
+#define LPAIF_DMACTL_FIFOWM_16_V2	(15 << LPAIF_DMACTL_FIFOWM_SHIFT_V2)
+#define LPAIF_DMACTL_FIFOWM_17_V2	(16 << LPAIF_DMACTL_FIFOWM_SHIFT_V2)
+#define LPAIF_DMACTL_FIFOWM_18_V2	(17 << LPAIF_DMACTL_FIFOWM_SHIFT_V2)
+#define LPAIF_DMACTL_FIFOWM_19_V2	(18 << LPAIF_DMACTL_FIFOWM_SHIFT_V2)
+#define LPAIF_DMACTL_FIFOWM_20_V2	(19 << LPAIF_DMACTL_FIFOWM_SHIFT_V2)
+#define LPAIF_DMACTL_FIFOWM_21_V2	(20 << LPAIF_DMACTL_FIFOWM_SHIFT_V2)
+#define LPAIF_DMACTL_FIFOWM_22_V2	(21 << LPAIF_DMACTL_FIFOWM_SHIFT_V2)
+#define LPAIF_DMACTL_FIFOWM_23_V2	(22 << LPAIF_DMACTL_FIFOWM_SHIFT_V2)
+#define LPAIF_DMACTL_FIFOWM_24_V2	(23 << LPAIF_DMACTL_FIFOWM_SHIFT_V2)
+#define LPAIF_DMACTL_FIFOWM_25_V2	(24 << LPAIF_DMACTL_FIFOWM_SHIFT_V2)
+#define LPAIF_DMACTL_FIFOWM_26_V2	(25 << LPAIF_DMACTL_FIFOWM_SHIFT_V2)
+#define LPAIF_DMACTL_FIFOWM_27_V2	(26 << LPAIF_DMACTL_FIFOWM_SHIFT_V2)
+#define LPAIF_DMACTL_FIFOWM_28_V2	(27 << LPAIF_DMACTL_FIFOWM_SHIFT_V2)
+#define LPAIF_DMACTL_FIFOWM_29_V2	(28 << LPAIF_DMACTL_FIFOWM_SHIFT_V2)
+#define LPAIF_DMACTL_FIFOWM_30_V2	(29 << LPAIF_DMACTL_FIFOWM_SHIFT_V2)
+#define LPAIF_DMACTL_FIFOWM_31_V2	(30 << LPAIF_DMACTL_FIFOWM_SHIFT_V2)
+#define LPAIF_DMACTL_FIFOWM_32_V2	(31 << LPAIF_DMACTL_FIFOWM_SHIFT_V2)
+
+#define LPAIF_DMACTL_ENABLE_MASK_V2	0x1
+#define LPAIF_DMACTL_ENABLE_SHIFT_V2	0
+#define LPAIF_DMACTL_ENABLE_OFF_V2	(0 << LPAIF_DMACTL_ENABLE_SHIFT_V2)
+#define LPAIF_DMACTL_ENABLE_ON_V2	(1 << LPAIF_DMACTL_ENABLE_SHIFT_V2)
+
+#define LPAIF_DMACTL_DYNCLK_MASK_V2	BIT(21)
+#define LPAIF_DMACTL_DYNCLK_SHIFT_V2	21
+#define LPAIF_DMACTL_DYNCLK_OFF_V2	(0 << LPAIF_DMACTL_DYNCLK_SHIFT_V2)
+#define LPAIF_DMACTL_DYNCLK_ON_V2	(1 << LPAIF_DMACTL_DYNCLK_SHIFT_V2)
+
+#define __LPAIF_DMA_CTL(v, bit)  \
+	((v->id ==  LPASS_VARIANT_V2) ? \
+		LPAIF_DMACTL_##bit##_V2 : \
+		LPAIF_DMACTL_##bit)
+
+#define LPAIF_DMACTL(v, bit)		__LPAIF_DMA_CTL(v, bit)
+
  #endif /* __LPASS_LPAIF_REG_H__ */
sound/soc/qcom/lpass-platform.c +16 -15
index b05091c2..821599e 100644
@@ -146,25 +146,26 @@ static int lpass_platform_pcmops_hw_params(struct snd_soc_component *component,
  		return bitwidth;
  	}
 
-	regval = LPAIF_DMACTL_BURSTEN_INCR4 |
-			LPAIF_DMACTL_AUDINTF(dma_port) |
-			LPAIF_DMACTL_FIFOWM_8;
+
+	regval = LPAIF_DMACTL(v, BURSTEN_INCR4);
+	regval |= LPAIF_DMACTL(v, FIFOWM_8);
+	regval |= LPAIF_DMACTL_AUD_INTF(v, dma_port);
 
  	switch (bitwidth) {
  	case 16:
  		switch (channels) {
  		case 1:
  		case 2:
-			regval |= LPAIF_DMACTL_WPSCNT_ONE;
+			regval |= LPAIF_DMACTL(v, WPSCNT_ONE);
  			break;
  		case 4:
-			regval |= LPAIF_DMACTL_WPSCNT_TWO;
+			regval |= LPAIF_DMACTL(v, WPSCNT_TWO);
  			break;
  		case 6:
-			regval |= LPAIF_DMACTL_WPSCNT_THREE;
+			regval |= LPAIF_DMACTL(v, WPSCNT_THREE);
  			break;
  		case 8:
-			regval |= LPAIF_DMACTL_WPSCNT_FOUR;
+			regval |= LPAIF_DMACTL(v, WPSCNT_FOUR);
  			break;
  		default:
  			dev_err(soc_runtime->dev,
@@ -177,19 +178,19 @@ static int lpass_platform_pcmops_hw_params(struct snd_soc_component *component,
  	case 32:
  		switch (channels) {
  		case 1:
-			regval |= LPAIF_DMACTL_WPSCNT_ONE;
+			regval |= LPAIF_DMACTL(v, WPSCNT_ONE);
  			break;
  		case 2:
-			regval |= LPAIF_DMACTL_WPSCNT_TWO;
+			regval |= LPAIF_DMACTL(v, WPSCNT_TWO);
  			break;
  		case 4:
-			regval |= LPAIF_DMACTL_WPSCNT_FOUR;
+			regval |= LPAIF_DMACTL(v, WPSCNT_FOUR);
  			break;
  		case 6:
-			regval |= LPAIF_DMACTL_WPSCNT_SIX;
+			regval |= LPAIF_DMACTL(v, WPSCNT_SIX);
  			break;
  		case 8:
-			regval |= LPAIF_DMACTL_WPSCNT_EIGHT;
+			regval |= LPAIF_DMACTL(v, WPSCNT_EIGHT);
  			break;
  		default:
  			dev_err(soc_runtime->dev,
@@ -277,7 +278,7 @@ static int lpass_platform_pcmops_prepare(struct snd_soc_component *component,
 
  	ret = regmap_update_bits(drvdata->lpaif_map,
  			LPAIF_DMACTL_REG(v, ch, dir),
-			LPAIF_DMACTL_ENABLE_MASK, LPAIF_DMACTL_ENABLE_ON);
+			LPAIF_DMACTL(v, ENABLE_MASK), LPAIF_DMACTL_ENABLE_ON);
  	if (ret) {
  		dev_err(soc_runtime->dev, "error writing to rdmactl reg: %d\n",
  			ret);
@@ -326,7 +327,7 @@ static int lpass_platform_pcmops_trigger(struct snd_soc_component *component,
 
  		ret = regmap_update_bits(drvdata->lpaif_map,
  				LPAIF_DMACTL_REG(v, ch, dir),
-				LPAIF_DMACTL_ENABLE_MASK,
+				LPAIF_DMACTL(v, ENABLE_MASK),
  				LPAIF_DMACTL_ENABLE_ON);
  		if (ret) {
  			dev_err(soc_runtime->dev,
@@ -339,7 +340,7 @@ static int lpass_platform_pcmops_trigger(struct snd_soc_component *component,
  	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
  		ret = regmap_update_bits(drvdata->lpaif_map,
  				LPAIF_DMACTL_REG(v, ch, dir),
-				LPAIF_DMACTL_ENABLE_MASK,
+				LPAIF_DMACTL(v, ENABLE_MASK),
  				LPAIF_DMACTL_ENABLE_OFF);
  		if (ret) {
  			dev_err(soc_runtime->dev,
sound/soc/qcom/lpass.h +3 -0
index 279cd02..384f4b8 100644
@@ -17,6 +17,9 @@
  #define LPASS_MAX_MI2S_PORTS                   (8)
  #define LPASS_MAX_DMA_CHANNELS                 (8)
 
+#define LPASS_VARIANT				0
+#define LPASS_VARIANT_V2			1
+
  struct lpass_dai {
  	struct clk *osr_clk;
  	struct clk *bit_clk;

sound/soc/qcom/lpass.h struct lpass_variant { · line 99

Quoted 6 lines
sound/soc/qcom/lpass.h +3 -0
@@ -91,6 +94,9 @@ struct lpass_variant {
  	/* SOC specific clocks configuration */
  	const char **clk_name;
  	int num_clks;
+
+	/* LPASS Version id */
+	int id;

May be spelling this out like "version_id" would make it more readable.

thanks,
srini

Quoted 4 lines
sound/soc/qcom/lpass.h +0 -0
  };
 
  /* register the platform driver from the CPU DAI driver */
#12 lore raw

Re: [PATCH 05/11] ASoC: qcom: lpass: Add support for newer lpass version

Quoted 10 lines · Srinivas Kandagatla
Quoted 5 lines · Ajit Pandey

Few control registers bit offset of lpaif in newer lpass variants are changed. Added "id" field in variant struct and changes macros configuration of registers to calculate bit mask & offset based on variant id.

These fields are handled much nicely with regmap_field, you should consider using that. If not we will add overhead of check for every mask.

Sure i'll try  to add this support using regmap_field API's during v2 patch chain

Thanks & Regards

Ajit

Quoted 647 lines
Quoted 631 lines

---
  sound/soc/qcom/lpass-cpu.c       |  77 +++++++++-------- sound/soc/qcom/lpass-lpaif-reg.h | 182
++++++++++++++++++++++++++++++++++++++-
  sound/soc/qcom/lpass-platform.c  |  31 +++---- sound/soc/qcom/lpass.h           |   6 ++

  4 files changed, 241 insertions(+), 55 deletions(-)
sound/soc/qcom/lpass-cpu.c +1 -0
index f177932..006ba5a 100644
@@ -77,6 +77,7 @@ static int lpass_cpu_daiops_hw_params(struct 
 snd_pcm_substream *substream,
   {
       struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai);
       struct lpass_dai *dai_data = drvdata->dai_priv[dai->driver->id];
+    struct lpass_variant *v = drvdata->variant;
       snd_pcm_format_t format = params_format(params);
       unsigned int channels = params_channels(params);

      unsigned int rate = params_rate(params);

sound/soc/qcom/lpass-cpu.c +0 -0
@@ -89,18 +90,18 @@ static int lpass_cpu_daiops_hw_params(struct 
 snd_pcm_substream *substream,
           return bitwidth;
       }

  -    regval = LPAIF_I2SCTL_LOOPBACK_DISABLE |
-            LPAIF_I2SCTL_WSSRC_INTERNAL;
+    regval = LPAIF_I2SCTL(v, LOOPBACK_DISABLE);
+    regval |= LPAIF_I2SCTL(v, WSSRC_INTERNAL);
        switch (bitwidth) {
      case 16:
-        regval |= LPAIF_I2SCTL_BITWIDTH_16;
+        regval |= LPAIF_I2SCTL(v, BITWIDTH_16);
          break;
      case 24:
-        regval |= LPAIF_I2SCTL_BITWIDTH_24;
+        regval |= LPAIF_I2SCTL(v, BITWIDTH_24);
          break;
      case 32:
-        regval |= LPAIF_I2SCTL_BITWIDTH_32;
+        regval |= LPAIF_I2SCTL(v, BITWIDTH_32);
          break;
      default:
          dev_err(dai->dev, "invalid bitwidth given: %d\n", bitwidth);

sound/soc/qcom/lpass-cpu.c +0 -0
@@ -110,24 +111,24 @@ static int lpass_cpu_daiops_hw_params(struct 
 snd_pcm_substream *substream,
       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
           switch (channels) {

          case 1:

-            regval |= LPAIF_I2SCTL_SPKMODE_SD0;
-            regval |= LPAIF_I2SCTL_SPKMONO_MONO;
+            regval |= LPAIF_I2SCTL(v, SPKMODE_SD0);
+            regval |= LPAIF_I2SCTL(v, SPKMONO_MONO);
              break;
          case 2:
-            regval |= LPAIF_I2SCTL_SPKMODE_SD0;
-            regval |= LPAIF_I2SCTL_SPKMONO_STEREO;
+            regval |= LPAIF_I2SCTL(v, SPKMODE_SD0);
+            regval |= LPAIF_I2SCTL(v, SPKMONO_STEREO);
              break;
          case 4:
-            regval |= LPAIF_I2SCTL_SPKMODE_QUAD01;
-            regval |= LPAIF_I2SCTL_SPKMONO_STEREO;
+            regval |= LPAIF_I2SCTL(v, SPKMODE_QUAD01);
+            regval |= LPAIF_I2SCTL(v, SPKMONO_STEREO);
              break;
          case 6:
-            regval |= LPAIF_I2SCTL_SPKMODE_6CH;
-            regval |= LPAIF_I2SCTL_SPKMONO_STEREO;
+            regval |= LPAIF_I2SCTL(v, SPKMODE_6CH);
+            regval |= LPAIF_I2SCTL(v, SPKMONO_STEREO);
              break;
          case 8:
-            regval |= LPAIF_I2SCTL_SPKMODE_8CH;
-            regval |= LPAIF_I2SCTL_SPKMONO_STEREO;
+            regval |= LPAIF_I2SCTL(v, SPKMODE_8CH);
+            regval |= LPAIF_I2SCTL(v, SPKMONO_STEREO);

              break;
          default:
              dev_err(dai->dev, "invalid channels given: %u\n",

sound/soc/qcom/lpass-cpu.c +0 -0
@@ -137,24 +138,24 @@ static int lpass_cpu_daiops_hw_params(struct 
 snd_pcm_substream *substream,
       } else {
           switch (channels) {

          case 1:

-            regval |= LPAIF_I2SCTL_MICMODE_SD0;
-            regval |= LPAIF_I2SCTL_MICMONO_MONO;
+            regval |= LPAIF_I2SCTL(v, MICMODE_SD0);
+            regval |= LPAIF_I2SCTL(v, MICMONO_MONO);
              break;
          case 2:
-            regval |= LPAIF_I2SCTL_MICMODE_SD0;
-            regval |= LPAIF_I2SCTL_MICMONO_STEREO;
+            regval |= LPAIF_I2SCTL(v, MICMODE_SD0);
+            regval |= LPAIF_I2SCTL(v, MICMONO_STEREO);
              break;
          case 4:
-            regval |= LPAIF_I2SCTL_MICMODE_QUAD01;
-            regval |= LPAIF_I2SCTL_MICMONO_STEREO;
+            regval |= LPAIF_I2SCTL(v, MICMODE_QUAD01);
+            regval |= LPAIF_I2SCTL(v, MICMONO_STEREO);
              break;
          case 6:
-            regval |= LPAIF_I2SCTL_MICMODE_6CH;
-            regval |= LPAIF_I2SCTL_MICMONO_STEREO;
+            regval |= LPAIF_I2SCTL(v, MICMODE_6CH);
+            regval |= LPAIF_I2SCTL(v, MICMONO_STEREO);
              break;
          case 8:
-            regval |= LPAIF_I2SCTL_MICMODE_8CH;
-            regval |= LPAIF_I2SCTL_MICMONO_STEREO;
+            regval |= LPAIF_I2SCTL(v, MICMODE_8CH);
+            regval |= LPAIF_I2SCTL(v, MICMONO_STEREO);

              break;
          default:
              dev_err(dai->dev, "invalid channels given: %u\n",

sound/soc/qcom/lpass-cpu.c +6 -4
@@ -200,15 +201,16 @@ static int lpass_cpu_daiops_prepare(struct 
 snd_pcm_substream *substream,
           struct snd_soc_dai *dai)
   {
       struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai);
+    struct lpass_variant *v = drvdata->variant;
       int ret;
       unsigned int val, mask;
         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-        val = LPAIF_I2SCTL_SPKEN_ENABLE;
-        mask = LPAIF_I2SCTL_SPKEN_MASK;
+        val = LPAIF_I2SCTL(v, SPKEN_ENABLE);
+        mask = LPAIF_I2SCTL(v, SPKEN_MASK);
       } else  {
-        val = LPAIF_I2SCTL_MICEN_ENABLE;
-        mask = LPAIF_I2SCTL_MICEN_MASK;
+        val = LPAIF_I2SCTL(v, MICEN_ENABLE);
+        mask = LPAIF_I2SCTL(v, MICEN_MASK);
       }
         ret = regmap_update_bits(drvdata->lpaif_map,
@@ -224,6 +226,7 @@ static int lpass_cpu_daiops_trigger(struct 
 snd_pcm_substream *substream,
           int cmd, struct snd_soc_dai *dai)
   {
       struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai);
+    struct lpass_variant *v = drvdata->variant;
       int ret = -EINVAL;
       unsigned int val, mask;

  @@ -232,11 +235,11 @@ static int lpass_cpu_daiops_trigger(struct snd_pcm_substream *substream, case SNDRV_PCM_TRIGGER_RESUME:
      case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
          if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-            val = LPAIF_I2SCTL_SPKEN_ENABLE;
-            mask = LPAIF_I2SCTL_SPKEN_MASK;
+            val = LPAIF_I2SCTL(v, SPKEN_ENABLE);
+            mask = LPAIF_I2SCTL(v, SPKEN_MASK);
          } else  {
-            val = LPAIF_I2SCTL_MICEN_ENABLE;
-            mask = LPAIF_I2SCTL_MICEN_MASK;
+            val = LPAIF_I2SCTL(v, MICEN_ENABLE);
+            mask = LPAIF_I2SCTL(v, MICEN_MASK);
          }
            ret = regmap_update_bits(drvdata->lpaif_map,

sound/soc/qcom/lpass-cpu.c +0 -0
@@ -251,11 +254,11 @@ static int lpass_cpu_daiops_trigger(struct 
 snd_pcm_substream *substream,

      case SNDRV_PCM_TRIGGER_SUSPEND:
      case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
          if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { -            val = LPAIF_I2SCTL_SPKEN_DISABLE;
-            mask = LPAIF_I2SCTL_SPKEN_MASK;
+            val = LPAIF_I2SCTL(v, SPKEN_DISABLE);
+            mask = LPAIF_I2SCTL(v, SPKEN_MASK);
          } else  {
-            val = LPAIF_I2SCTL_MICEN_DISABLE;
-            mask = LPAIF_I2SCTL_MICEN_MASK;
+            val = LPAIF_I2SCTL(v, MICEN_DISABLE);
+            mask = LPAIF_I2SCTL(v, MICEN_MASK);
          }
            ret = regmap_update_bits(drvdata->lpaif_map,

sound/soc/qcom/lpass-lpaif-reg.h +0 -0
index 3d74ae1..4251aa6 100644
@@ -17,11 +17,28 @@
   #define LPAIF_I2SCTL_LOOPBACK_DISABLE    (0 << LPAIF_I2SCTL_LOOPBACK_SHIFT)
   #define LPAIF_I2SCTL_LOOPBACK_ENABLE    (1 << LPAIF_I2SCTL_LOOPBACK_SHIFT)

  +#define LPAIF_I2SCTL_LOOPBACK_MASK_V2     0x20000

sound/soc/qcom/lpass-lpaif-reg.h +2 -0
+#define LPAIF_I2SCTL_LOOPBACK_SHIFT_V2     17
+#define LPAIF_I2SCTL_LOOPBACK_DISABLE_V2 (0 << 

LPAIF_I2SCTL_LOOPBACK_SHIFT_V2)
+#define LPAIF_I2SCTL_LOOPBACK_ENABLE_V2     (1 << LPAIF_I2SCTL_LOOPBACK_SHIFT_V2)
+
  #define LPAIF_I2SCTL_SPKEN_MASK        0x4000
  #define LPAIF_I2SCTL_SPKEN_SHIFT    14
  #define LPAIF_I2SCTL_SPKEN_DISABLE    (0 << LPAIF_I2SCTL_SPKEN_SHIFT) #define LPAIF_I2SCTL_SPKEN_ENABLE    (1 << LPAIF_I2SCTL_SPKEN_SHIFT) +#define LPAIF_I2SCTL_SPKEN_MASK_V2    0x10000

sound/soc/qcom/lpass-lpaif-reg.h +2 -0
+#define LPAIF_I2SCTL_SPKEN_SHIFT_V2    16
+#define LPAIF_I2SCTL_SPKEN_DISABLE_V2    (0 << 

LPAIF_I2SCTL_SPKEN_SHIFT_V2)
+#define LPAIF_I2SCTL_SPKEN_ENABLE_V2    (1 <<
LPAIF_I2SCTL_SPKEN_SHIFT_V2)

sound/soc/qcom/lpass-lpaif-reg.h +8 -0
+
+#define __LPAIF_I2S_CTL(v, bit)  \
+    ((v->id ==  LPASS_VARIANT_V2) ? \
+        LPAIF_I2SCTL_##bit##_V2 : \
+        LPAIF_I2SCTL_##bit)
+
+#define LPAIF_I2SCTL(v, bit)        __LPAIF_I2S_CTL(v, bit)
+

  #define LPAIF_I2SCTL_SPKMODE_MASK    0x3C00
  #define LPAIF_I2SCTL_SPKMODE_SHIFT    10
  #define LPAIF_I2SCTL_SPKMODE_NONE    (0 << LPAIF_I2SCTL_SPKMODE_SHIFT)

sound/soc/qcom/lpass-lpaif-reg.h +0 -0
@@ -34,16 +51,49 @@
   #define LPAIF_I2SCTL_SPKMODE_6CH    (7 << LPAIF_I2SCTL_SPKMODE_SHIFT)
   #define LPAIF_I2SCTL_SPKMODE_8CH    (8 << LPAIF_I2SCTL_SPKMODE_SHIFT)

  +#define LPAIF_I2SCTL_SPKMODE_MASK_V2    0xF800

sound/soc/qcom/lpass-lpaif-reg.h +2 -0
+#define LPAIF_I2SCTL_SPKMODE_SHIFT_V2    11
+#define LPAIF_I2SCTL_SPKMODE_NONE_V2    (0 << 

LPAIF_I2SCTL_SPKMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_SPKMODE_SD0_V2    (1 << LPAIF_I2SCTL_SPKMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_SPKMODE_SD1_V2    (2 << LPAIF_I2SCTL_SPKMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_SPKMODE_SD2_V2    (3 << LPAIF_I2SCTL_SPKMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_SPKMODE_SD3_V2    (4 << LPAIF_I2SCTL_SPKMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_SPKMODE_QUAD01_V2    (5 << LPAIF_I2SCTL_SPKMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_SPKMODE_QUAD23_V2    (6 << LPAIF_I2SCTL_SPKMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_SPKMODE_6CH_V2    (7 << LPAIF_I2SCTL_SPKMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_SPKMODE_8CH_V2    (8 << LPAIF_I2SCTL_SPKMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_SPKMODE_10CH_V2    (9 << LPAIF_I2SCTL_SPKMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_SPKMODE_12CH_V2    (10 << LPAIF_I2SCTL_SPKMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_SPKMODE_14CH_V2    (11 << LPAIF_I2SCTL_SPKMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_SPKMODE_16CH_V2    (12 << LPAIF_I2SCTL_SPKMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_SPKMODE_SD4_V2    (13 << LPAIF_I2SCTL_SPKMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_SPKMODE_SD5_V2    (14 << LPAIF_I2SCTL_SPKMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_SPKMODE_SD6_V2    (15 << LPAIF_I2SCTL_SPKMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_SPKMODE_SD7_V2    (16 << LPAIF_I2SCTL_SPKMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_SPKMODE_QUAD45_V2    (17 << LPAIF_I2SCTL_SPKMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_SPKMODE_QUAD47_V2    (18 << LPAIF_I2SCTL_SPKMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_SPKMODE_8CH_2_V2    (19 << LPAIF_I2SCTL_SPKMODE_SHIFT_V2)
+
  #define LPAIF_I2SCTL_SPKMONO_MASK    0x0200
  #define LPAIF_I2SCTL_SPKMONO_SHIFT    9
  #define LPAIF_I2SCTL_SPKMONO_STEREO    (0 << LPAIF_I2SCTL_SPKMONO_SHIFT) #define LPAIF_I2SCTL_SPKMONO_MONO    (1 << LPAIF_I2SCTL_SPKMONO_SHIFT) +#define LPAIF_I2SCTL_SPKMONO_MASK_V2    0x0400

sound/soc/qcom/lpass-lpaif-reg.h +2 -0
+#define LPAIF_I2SCTL_SPKMONO_SHIFT_V2    10
+#define LPAIF_I2SCTL_SPKMONO_STEREO_V2    (0 << 

LPAIF_I2SCTL_SPKMONO_SHIFT_V2)
+#define LPAIF_I2SCTL_SPKMONO_MONO_V2    (1 << LPAIF_I2SCTL_SPKMONO_SHIFT_V2)
+
  #define LPAIF_I2SCTL_MICEN_MASK        GENMASK(8, 8) #define LPAIF_I2SCTL_MICEN_SHIFT    8
  #define LPAIF_I2SCTL_MICEN_DISABLE    (0 << LPAIF_I2SCTL_MICEN_SHIFT) #define LPAIF_I2SCTL_MICEN_ENABLE    (1 << LPAIF_I2SCTL_MICEN_SHIFT) +#define LPAIF_I2SCTL_MICEN_MASK_V2    0x0200

sound/soc/qcom/lpass-lpaif-reg.h +2 -0
+#define LPAIF_I2SCTL_MICEN_SHIFT_V2    9
+#define LPAIF_I2SCTL_MICEN_DISABLE_V2    (0 << 

LPAIF_I2SCTL_MICEN_SHIFT_V2)
+#define LPAIF_I2SCTL_MICEN_ENABLE_V2    (1 << LPAIF_I2SCTL_MICEN_SHIFT_V2)
+
  #define LPAIF_I2SCTL_MICMODE_MASK    GENMASK(7, 4)
  #define LPAIF_I2SCTL_MICMODE_SHIFT    4
  #define LPAIF_I2SCTL_MICMODE_NONE    (0 << LPAIF_I2SCTL_MICMODE_SHIFT)

sound/soc/qcom/lpass-lpaif-reg.h +21 -0
@@ -56,22 +106,61 @@
   #define LPAIF_I2SCTL_MICMODE_6CH    (7 << LPAIF_I2SCTL_MICMODE_SHIFT)
   #define LPAIF_I2SCTL_MICMODE_8CH    (8 << LPAIF_I2SCTL_MICMODE_SHIFT)
   +#define LPAIF_I2SCTL_MICMODE_MASK_V2    GENMASK(8, 4)
+#define LPAIF_I2SCTL_MICMODE_SHIFT_V2    4
+#define LPAIF_I2SCTL_MICMODE_NONE_V2    (0 << 
 LPAIF_I2SCTL_MICMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_MICMODE_SD0_V2    (1 << 
 LPAIF_I2SCTL_MICMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_MICMODE_SD1_V2    (2 << 
 LPAIF_I2SCTL_MICMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_MICMODE_SD2_V2    (3 << 
 LPAIF_I2SCTL_MICMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_MICMODE_SD3_V2    (4 << 
 LPAIF_I2SCTL_MICMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_MICMODE_QUAD01_V2    (5 << 
 LPAIF_I2SCTL_MICMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_MICMODE_QUAD23_V2    (6 << 
 LPAIF_I2SCTL_MICMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_MICMODE_6CH_V2    (7 << 
 LPAIF_I2SCTL_MICMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_MICMODE_8CH_V2    (8 << 
 LPAIF_I2SCTL_MICMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_MICMODE_10CH_V2    (9 << 
 LPAIF_I2SCTL_MICMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_MICMODE_12CH_V2    (10 << 
 LPAIF_I2SCTL_MICMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_MICMODE_14CH_V2    (11 << 
 LPAIF_I2SCTL_MICMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_MICMODE_16CH_V2    (12 << 
 LPAIF_I2SCTL_MICMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_MICMODE_SD4_V2    (13 << 
 LPAIF_I2SCTL_MICMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_MICMODE_SD5_V2    (14 << 
 LPAIF_I2SCTL_MICMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_MICMODE_SD6_V2    (15 << 
 LPAIF_I2SCTL_MICMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_MICMODE_SD7_V2    (16 << 
 LPAIF_I2SCTL_MICMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_MICMODE_QUAD45_V2    (17 << 
 LPAIF_I2SCTL_MICMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_MICMODE_QUAD47_V2    (18 << 
 LPAIF_I2SCTL_MICMODE_SHIFT_V2)
+#define LPAIF_I2SCTL_MICMODE_8CH_2_V2    (19 << 

LPAIF_I2SCTL_MICMODE_SHIFT_V2)
+
  #define LPAIF_I2SCTL_MIMONO_MASK    GENMASK(3, 3)
  #define LPAIF_I2SCTL_MICMONO_SHIFT    3
  #define LPAIF_I2SCTL_MICMONO_STEREO    (0 << LPAIF_I2SCTL_MICMONO_SHIFT) #define LPAIF_I2SCTL_MICMONO_MONO    (1 << LPAIF_I2SCTL_MICMONO_SHIFT) +#define LPAIF_I2SCTL_MICMONO_MASK_V2    GENMASK(3, 3)

sound/soc/qcom/lpass-lpaif-reg.h +2 -0
+#define LPAIF_I2SCTL_MICMONO_SHIFT_V2    3
+#define LPAIF_I2SCTL_MICMONO_STEREO_V2    (0 << 

LPAIF_I2SCTL_MICMONO_SHIFT_V2)
+#define LPAIF_I2SCTL_MICMONO_MONO_V2    (1 << LPAIF_I2SCTL_MICMONO_SHIFT_V2)
+
  #define LPAIF_I2SCTL_WSSRC_MASK        0x0004
  #define LPAIF_I2SCTL_WSSRC_SHIFT    2
  #define LPAIF_I2SCTL_WSSRC_INTERNAL    (0 << LPAIF_I2SCTL_WSSRC_SHIFT) #define LPAIF_I2SCTL_WSSRC_EXTERNAL    (1 << LPAIF_I2SCTL_WSSRC_SHIFT) +#define LPAIF_I2SCTL_WSSRC_MASK_V2    0x0004

sound/soc/qcom/lpass-lpaif-reg.h +2 -0
+#define LPAIF_I2SCTL_WSSRC_SHIFT_V2    2
+#define LPAIF_I2SCTL_WSSRC_INTERNAL_V2    (0 << 

LPAIF_I2SCTL_WSSRC_SHIFT_V2)
+#define LPAIF_I2SCTL_WSSRC_EXTERNAL_V2    (1 << LPAIF_I2SCTL_WSSRC_SHIFT_V2)
+
  #define LPAIF_I2SCTL_BITWIDTH_MASK    0x0003
  #define LPAIF_I2SCTL_BITWIDTH_SHIFT    0
  #define LPAIF_I2SCTL_BITWIDTH_16    (0 << LPAIF_I2SCTL_BITWIDTH_SHIFT) #define LPAIF_I2SCTL_BITWIDTH_24    (1 << LPAIF_I2SCTL_BITWIDTH_SHIFT) #define LPAIF_I2SCTL_BITWIDTH_32    (2 << LPAIF_I2SCTL_BITWIDTH_SHIFT) +#define LPAIF_I2SCTL_BITWIDTH_MASK_V2    0x0003

sound/soc/qcom/lpass-lpaif-reg.h +2 -0
+#define LPAIF_I2SCTL_BITWIDTH_SHIFT_V2    0
+#define LPAIF_I2SCTL_BITWIDTH_16_V2    (0 << 

LPAIF_I2SCTL_BITWIDTH_SHIFT_V2)
+#define LPAIF_I2SCTL_BITWIDTH_24_V2    (1 << LPAIF_I2SCTL_BITWIDTH_SHIFT_V2)
+#define LPAIF_I2SCTL_BITWIDTH_32_V2    (2 << LPAIF_I2SCTL_BITWIDTH_SHIFT_V2)
+
  /* LPAIF IRQ */
  #define LPAIF_IRQ_REG_ADDR(v, addr, port) \
      (v->irq_reg_base + (addr) + v->irq_reg_stride * (port))

sound/soc/qcom/lpass-lpaif-reg.h +0 -1
@@ -91,7 +180,6 @@
   #define LPAIF_IRQ_ALL(chan)        (7 << (LPAIF_IRQ_BITSTRIDE * (chan)))
     /* LPAIF DMA */
-
   #define LPAIF_RDMA_REG_ADDR(v, addr, chan) \
       (v->rdma_reg_base + (addr) + v->rdma_reg_stride * (chan))

  @@ -143,7 +231,7 @@
    #define LPAIF_DMACTL_AUDINTF_MASK    0x0F0
  #define LPAIF_DMACTL_AUDINTF_SHIFT    4

sound/soc/qcom/lpass-lpaif-reg.h +1 -1
-#define LPAIF_DMACTL_AUDINTF(id)    (id << LPAIF_DMACTL_AUDINTF_SHIFT)
+#define LPAIF_DMACTL_AUDINTF(port)    (port << 

LPAIF_DMACTL_AUDINTF_SHIFT)
    #define LPAIF_DMACTL_FIFOWM_MASK    0x00E
  #define LPAIF_DMACTL_FIFOWM_SHIFT    1

sound/soc/qcom/lpass-lpaif-reg.h +1 -1
@@ -158,11 +246,99 @@
     #define LPAIF_DMACTL_ENABLE_MASK    0x1
   #define LPAIF_DMACTL_ENABLE_SHIFT    0
-#define LPAIF_DMACTL_ENABLE_OFF    (0 << LPAIF_DMACTL_ENABLE_SHIFT)
+#define LPAIF_DMACTL_ENABLE_OFF        (0 << LPAIF_DMACTL_ENABLE_SHIFT)
   #define LPAIF_DMACTL_ENABLE_ON        (1 << LPAIF_DMACTL_ENABLE_SHIFT)

  +#define LPAIF_IRQ_BITSTRIDE        3

sound/soc/qcom/lpass-lpaif-reg.h +2 -0
+
+#define LPAIF_IRQ_PER(chan)        (1 << (LPAIF_IRQ_BITSTRIDE * 

(chan)))
+#define LPAIF_IRQ_XRUN(chan)        (2 << (LPAIF_IRQ_BITSTRIDE * (chan)))
+#define LPAIF_IRQ_ERR(chan)        (4 << (LPAIF_IRQ_BITSTRIDE * (chan)))

sound/soc/qcom/lpass-lpaif-reg.h +2 -0
+
+#define LPAIF_IRQ_ALL(chan)        (7 << (LPAIF_IRQ_BITSTRIDE * 

(chan)))
+
  #define LPAIF_DMACTL_DYNCLK_MASK    BIT(12)
  #define LPAIF_DMACTL_DYNCLK_SHIFT    12
  #define LPAIF_DMACTL_DYNCLK_OFF    (0 << LPAIF_DMACTL_DYNCLK_SHIFT) #define LPAIF_DMACTL_DYNCLK_ON        (1 << LPAIF_DMACTL_DYNCLK_SHIFT)

sound/soc/qcom/lpass-lpaif-reg.h +4 -0
+
+#define LPAIF_DMACTL_BURSTEN_MASK_V2    0x100000
+#define LPAIF_DMACTL_BURSTEN_SHIFT_V2    20
+#define LPAIF_DMACTL_BURSTEN_SINGLE_V2    (0 << 

LPAIF_DMACTL_BURSTEN_SHIFT_V2)
+#define LPAIF_DMACTL_BURSTEN_INCR4_V2    (1 <<
LPAIF_DMACTL_BURSTEN_SHIFT_V2)

sound/soc/qcom/lpass-lpaif-reg.h +4 -0
+
+#define LPAIF_DMACTL_WPSCNT_MASK_V2    0xF0000
+#define LPAIF_DMACTL_WPSCNT_SHIFT_V2    16
+#define LPAIF_DMACTL_WPSCNT_ONE_V2    (0 << 

LPAIF_DMACTL_WPSCNT_SHIFT_V2)
+#define LPAIF_DMACTL_WPSCNT_TWO_V2    (1 << LPAIF_DMACTL_WPSCNT_SHIFT_V2)
+#define LPAIF_DMACTL_WPSCNT_THREE_V2    (2 << LPAIF_DMACTL_WPSCNT_SHIFT_V2)
+#define LPAIF_DMACTL_WPSCNT_FOUR_V2    (3 << LPAIF_DMACTL_WPSCNT_SHIFT_V2)
+#define LPAIF_DMACTL_WPSCNT_SIX_V2    (5 << LPAIF_DMACTL_WPSCNT_SHIFT_V2)
+#define LPAIF_DMACTL_WPSCNT_EIGHT_V2    (7 << LPAIF_DMACTL_WPSCNT_SHIFT_V2)
+#define LPAIF_DMACTL_WPSCNT_TEN_V2    (9 << LPAIF_DMACTL_WPSCNT_SHIFT_V2)
+#define LPAIF_DMACTL_WPSCNT_TWELVE_V2    (11 << LPAIF_DMACTL_WPSCNT_SHIFT_V2)
+#define LPAIF_DMACTL_WPSCNT_FOURTEEN_V2    (13 << LPAIF_DMACTL_WPSCNT_SHIFT_V2)
+#define LPAIF_DMACTL_WPSCNT_SIXTEEN_V2    (15 << LPAIF_DMACTL_WPSCNT_SHIFT_V2)

sound/soc/qcom/lpass-lpaif-reg.h +4 -0
+
+#define LPAIF_DMACTL_AUDINTF_MASK_V2    0xF000
+#define LPAIF_DMACTL_AUDINTF_SHIFT_V2    12
+#define LPAIF_DMACTL_AUDINTF_V2(port)    (port << 

LPAIF_DMACTL_AUDINTF_SHIFT_V2)

sound/soc/qcom/lpass-lpaif-reg.h +18 -0
+
+#define LPAIF_DMACTL_AUD_INTF(v, port)  \
+    ((v->id ==  LPASS_VARIANT_V2) ? \
+        LPAIF_DMACTL_AUDINTF_V2(port) : \
+        LPAIF_DMACTL_AUDINTF(port))
+
+#define LPAIF_DMACTL_FIFOWM_MASK_V2    0x3E
+#define LPAIF_DMACTL_FIFOWM_SHIFT_V2    1
+#define LPAIF_DMACTL_FIFOWM_1_V2    (0 << LPAIF_DMACTL_FIFOWM_SHIFT_V2)
+#define LPAIF_DMACTL_FIFOWM_2_V2    (1 << LPAIF_DMACTL_FIFOWM_SHIFT_V2)
+#define LPAIF_DMACTL_FIFOWM_3_V2    (2 << LPAIF_DMACTL_FIFOWM_SHIFT_V2)
+#define LPAIF_DMACTL_FIFOWM_4_V2    (3 << LPAIF_DMACTL_FIFOWM_SHIFT_V2)
+#define LPAIF_DMACTL_FIFOWM_5_V2    (4 << LPAIF_DMACTL_FIFOWM_SHIFT_V2)
+#define LPAIF_DMACTL_FIFOWM_6_V2    (5 << LPAIF_DMACTL_FIFOWM_SHIFT_V2)
+#define LPAIF_DMACTL_FIFOWM_7_V2    (6 << LPAIF_DMACTL_FIFOWM_SHIFT_V2)
+#define LPAIF_DMACTL_FIFOWM_8_V2    (7 << LPAIF_DMACTL_FIFOWM_SHIFT_V2)
+#define LPAIF_DMACTL_FIFOWM_9_V2    (8 << LPAIF_DMACTL_FIFOWM_SHIFT_V2)
+#define LPAIF_DMACTL_FIFOWM_10_V2    (9 << 

LPAIF_DMACTL_FIFOWM_SHIFT_V2)
+#define LPAIF_DMACTL_FIFOWM_11_V2    (10 <<
LPAIF_DMACTL_FIFOWM_SHIFT_V2)
+#define LPAIF_DMACTL_FIFOWM_12_V2    (11 <<
LPAIF_DMACTL_FIFOWM_SHIFT_V2)
+#define LPAIF_DMACTL_FIFOWM_13_V2    (12 <<
LPAIF_DMACTL_FIFOWM_SHIFT_V2)
+#define LPAIF_DMACTL_FIFOWM_14_V2    (13 <<
LPAIF_DMACTL_FIFOWM_SHIFT_V2)
+#define LPAIF_DMACTL_FIFOWM_15_V2    (14 <<
LPAIF_DMACTL_FIFOWM_SHIFT_V2)
+#define LPAIF_DMACTL_FIFOWM_16_V2    (15 <<
LPAIF_DMACTL_FIFOWM_SHIFT_V2)
+#define LPAIF_DMACTL_FIFOWM_17_V2    (16 <<
LPAIF_DMACTL_FIFOWM_SHIFT_V2)
+#define LPAIF_DMACTL_FIFOWM_18_V2    (17 <<
LPAIF_DMACTL_FIFOWM_SHIFT_V2)
+#define LPAIF_DMACTL_FIFOWM_19_V2    (18 <<
LPAIF_DMACTL_FIFOWM_SHIFT_V2)
+#define LPAIF_DMACTL_FIFOWM_20_V2    (19 <<
LPAIF_DMACTL_FIFOWM_SHIFT_V2)
+#define LPAIF_DMACTL_FIFOWM_21_V2    (20 <<
LPAIF_DMACTL_FIFOWM_SHIFT_V2)
+#define LPAIF_DMACTL_FIFOWM_22_V2    (21 <<
LPAIF_DMACTL_FIFOWM_SHIFT_V2)
+#define LPAIF_DMACTL_FIFOWM_23_V2    (22 <<
LPAIF_DMACTL_FIFOWM_SHIFT_V2)
+#define LPAIF_DMACTL_FIFOWM_24_V2    (23 <<
LPAIF_DMACTL_FIFOWM_SHIFT_V2)
+#define LPAIF_DMACTL_FIFOWM_25_V2    (24 <<
LPAIF_DMACTL_FIFOWM_SHIFT_V2)
+#define LPAIF_DMACTL_FIFOWM_26_V2    (25 <<
LPAIF_DMACTL_FIFOWM_SHIFT_V2)
+#define LPAIF_DMACTL_FIFOWM_27_V2    (26 <<
LPAIF_DMACTL_FIFOWM_SHIFT_V2)
+#define LPAIF_DMACTL_FIFOWM_28_V2    (27 <<
LPAIF_DMACTL_FIFOWM_SHIFT_V2)
+#define LPAIF_DMACTL_FIFOWM_29_V2    (28 <<
LPAIF_DMACTL_FIFOWM_SHIFT_V2)
+#define LPAIF_DMACTL_FIFOWM_30_V2    (29 <<
LPAIF_DMACTL_FIFOWM_SHIFT_V2)
+#define LPAIF_DMACTL_FIFOWM_31_V2    (30 <<
LPAIF_DMACTL_FIFOWM_SHIFT_V2)
+#define LPAIF_DMACTL_FIFOWM_32_V2    (31 <<
LPAIF_DMACTL_FIFOWM_SHIFT_V2)

sound/soc/qcom/lpass-lpaif-reg.h +4 -0
+
+#define LPAIF_DMACTL_ENABLE_MASK_V2    0x1
+#define LPAIF_DMACTL_ENABLE_SHIFT_V2    0
+#define LPAIF_DMACTL_ENABLE_OFF_V2    (0 << 

LPAIF_DMACTL_ENABLE_SHIFT_V2)
+#define LPAIF_DMACTL_ENABLE_ON_V2    (1 <<
LPAIF_DMACTL_ENABLE_SHIFT_V2)

sound/soc/qcom/lpass-lpaif-reg.h +4 -0
+
+#define LPAIF_DMACTL_DYNCLK_MASK_V2    BIT(21)
+#define LPAIF_DMACTL_DYNCLK_SHIFT_V2    21
+#define LPAIF_DMACTL_DYNCLK_OFF_V2    (0 << 

LPAIF_DMACTL_DYNCLK_SHIFT_V2)
+#define LPAIF_DMACTL_DYNCLK_ON_V2    (1 <<
LPAIF_DMACTL_DYNCLK_SHIFT_V2)

sound/soc/qcom/lpass-lpaif-reg.h +8 -0
+
+#define __LPAIF_DMA_CTL(v, bit)  \
+    ((v->id ==  LPASS_VARIANT_V2) ? \
+        LPAIF_DMACTL_##bit##_V2 : \
+        LPAIF_DMACTL_##bit)
+
+#define LPAIF_DMACTL(v, bit)        __LPAIF_DMA_CTL(v, bit)
+

  #endif /* __LPASS_LPAIF_REG_H__ */

sound/soc/qcom/lpass-platform.c +0 -0
index b05091c2..821599e 100644
@@ -146,25 +146,26 @@ static int 
 lpass_platform_pcmops_hw_params(struct snd_soc_component *component,
           return bitwidth;
       }

  -    regval = LPAIF_DMACTL_BURSTEN_INCR4 | -            LPAIF_DMACTL_AUDINTF(dma_port) | -            LPAIF_DMACTL_FIFOWM_8;
+
+    regval = LPAIF_DMACTL(v, BURSTEN_INCR4); +    regval |= LPAIF_DMACTL(v, FIFOWM_8);
+    regval |= LPAIF_DMACTL_AUD_INTF(v, dma_port); switch (bitwidth) {
      case 16:
          switch (channels) {
          case 1:
          case 2:
-            regval |= LPAIF_DMACTL_WPSCNT_ONE; +            regval |= LPAIF_DMACTL(v, WPSCNT_ONE); break;
          case 4:
-            regval |= LPAIF_DMACTL_WPSCNT_TWO; +            regval |= LPAIF_DMACTL(v, WPSCNT_TWO); break;
          case 6:
-            regval |= LPAIF_DMACTL_WPSCNT_THREE; +            regval |= LPAIF_DMACTL(v, WPSCNT_THREE); break;
          case 8:
-            regval |= LPAIF_DMACTL_WPSCNT_FOUR; +            regval |= LPAIF_DMACTL(v, WPSCNT_FOUR); break;
          default:
              dev_err(soc_runtime->dev,

sound/soc/qcom/lpass-platform.c +0 -0
@@ -177,19 +178,19 @@ static int 
 lpass_platform_pcmops_hw_params(struct snd_soc_component *component,

      case 32:
          switch (channels) {
          case 1:
-            regval |= LPAIF_DMACTL_WPSCNT_ONE; +            regval |= LPAIF_DMACTL(v, WPSCNT_ONE); break;
          case 2:
-            regval |= LPAIF_DMACTL_WPSCNT_TWO; +            regval |= LPAIF_DMACTL(v, WPSCNT_TWO); break;
          case 4:
-            regval |= LPAIF_DMACTL_WPSCNT_FOUR; +            regval |= LPAIF_DMACTL(v, WPSCNT_FOUR); break;
          case 6:
-            regval |= LPAIF_DMACTL_WPSCNT_SIX; +            regval |= LPAIF_DMACTL(v, WPSCNT_SIX); break;
          case 8:
-            regval |= LPAIF_DMACTL_WPSCNT_EIGHT; +            regval |= LPAIF_DMACTL(v, WPSCNT_EIGHT); break;
          default:
              dev_err(soc_runtime->dev,

sound/soc/qcom/lpass-platform.c +2 -2
@@ -277,7 +278,7 @@ static int lpass_platform_pcmops_prepare(struct 
 snd_soc_component *component,
         ret = regmap_update_bits(drvdata->lpaif_map,
               LPAIF_DMACTL_REG(v, ch, dir),
-            LPAIF_DMACTL_ENABLE_MASK, LPAIF_DMACTL_ENABLE_ON);
+            LPAIF_DMACTL(v, ENABLE_MASK), LPAIF_DMACTL_ENABLE_ON);
       if (ret) {
           dev_err(soc_runtime->dev, "error writing to rdmactl reg: %d\n",
               ret);
@@ -326,7 +327,7 @@ static int lpass_platform_pcmops_trigger(struct 
 snd_soc_component *component,
             ret = regmap_update_bits(drvdata->lpaif_map,
                   LPAIF_DMACTL_REG(v, ch, dir),
-                LPAIF_DMACTL_ENABLE_MASK,
+                LPAIF_DMACTL(v, ENABLE_MASK),
                   LPAIF_DMACTL_ENABLE_ON);
           if (ret) {
               dev_err(soc_runtime->dev,
@@ -339,7 +340,7 @@ static int lpass_platform_pcmops_trigger(struct 
 snd_soc_component *component,

      case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
          ret = regmap_update_bits(drvdata->lpaif_map, LPAIF_DMACTL_REG(v, ch, dir), -                LPAIF_DMACTL_ENABLE_MASK,
+                LPAIF_DMACTL(v, ENABLE_MASK), LPAIF_DMACTL_ENABLE_OFF); if (ret) { dev_err(soc_runtime->dev,

sound/soc/qcom/lpass.h +0 -0
index 279cd02..384f4b8 100644
@@ -17,6 +17,9 @@
   #define LPASS_MAX_MI2S_PORTS                   (8)
   #define LPASS_MAX_DMA_CHANNELS                 (8)

  +#define LPASS_VARIANT                0

sound/soc/qcom/lpass.h +2 -0
+#define LPASS_VARIANT_V2            1
+

  struct lpass_dai {
      struct clk *osr_clk;
      struct clk *bit_clk;

sound/soc/qcom/lpass.h struct lpass_variant { · line 99

Quoted 6 lines
sound/soc/qcom/lpass.h +3 -0
@@ -91,6 +94,9 @@ struct lpass_variant {
       /* SOC specific clocks configuration */
       const char **clk_name;
       int num_clks;
+
+    /* LPASS Version id */
+    int id;

May be spelling this out like "version_id" would make it more readable.

thanks,
srini

Quoted 3 lines
sound/soc/qcom/lpass.h +0 -0
   };
     /* register the platform driver from the CPU DAI driver */
 
#13 lore raw

PATCH 6/11 dt-bindings: sound: Add bindings related to lpass-cpu configuration

In reply to Ajit Pandey

Add header defining dts properties related to lpass cpu MI2S dai's.

---
 include/dt-bindings/sound/qcom,lpass.h | 31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)
 create mode 100644 include/dt-bindings/sound/qcom,lpass.h
include/dt-bindings/sound/qcom,lpass.h new file +31 -0
new file mode 100644
index 00000000..4e6c6bc
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ *
+ * lpass.h -- DT bindings properties related to LPASS MI2S dai's
+ */
+
+#ifndef _DT_BINDINGS_LPASS_H
+#define _DT_BINDINGS_LPASS_H
+
+/* MI2S dai id */
+#define MI2S_PRIMARY	0
+#define MI2S_SECONDARY	1
+#define MI2S_TERTIARY	2
+#define MI2S_QUATERNARY	3
+
+/* MI2S dai's data line mask */
+#define SD0		1
+#define SD1		2
+#define SD2		3
+#define SD3		4
+
+/*MI2S dai' loopback mask */
+#define DISABLE		0
+#define ENABLE		1
+
+/* MI2S dai's wssrc mask */
+#define INTERNAL	0
+#define EXTERNAL	1
+
+#endif /* __DT_BINDINGS_LPASS_H__ */
Signature · 1 line
1.9.1
#14 lore raw

PATCH 7/11 Documentation: dt-bindings: sound: Add details for new dai properties

In reply to Ajit Pandey

Add changes related to new sub node defining MI2S dai's properties. Such properties needs to be configured via board specific dts files.

---
 .../devicetree/bindings/sound/qcom,lpass-cpu.yaml  | 33 ++++++++++++++++++++++
 1 file changed, 33 insertions(+)
Documentation/devicetree/bindings/sound/qcom,lpass-cpu.yaml +33 -0
index a87a406..727ec03 100644
@@ -16,6 +16,8 @@ description: |
   configure Low-Power Audio Interface(LPAIF) core registers across different
   IP versions.
 
+  See also dt-bindings/sound/qcom,lpass.h.
+
 properties:
   compatible:
     enum:
@@ -69,6 +71,30 @@ properties:
   '#sound-dai-cells':
     const: 1
 
+  dai-name:
+    - description: Each node represents an MI2S dai and conatins dai specific
+        properties that may change with board layout & dai connections.
+    - type: object
+    - properties:
+      id:
+        - description: dai id among one of value defined in header
+        - type: u32
+      qcom,spkmode-mask:
+        - description: mask defining data lines used for speaker
+        - type: u32
+      qcom,micmode-mask:
+        - description: mask defining data lines used for mic
+        - type: u32
+      qcom,wssrc-mask:
+        - description: mask defining word-select source internal/extrnal on dai
+        - type: u32
+      qcom,loopback-mask:
+        - description: mask defining loopback enable/disable on dai
+        - type: u32
+
+      required:
+        - id
+
 required:
   - compatible
   - reg
@@ -101,3 +127,10 @@ examples:
 	#sound-dai-cells = <1>;
 	qcom,adsp = <&adsp>;
 
+        prim-mi2s@0 {
+		id = <MI2S_PRIMARY>;
+		qcom,spkmode-mask = <SD1>;
+		qcom,micmode-mask = <SD0>;
+                qcom,wssrc-mask = <INTERNAL>;
+                qcom,loopback-mask = <DISABLE>;
+	};
Signature · 1 line
1.9.1
#15 lore raw

Re: [PATCH 07/11] Documentation: dt-bindings: sound: Add details for new dai properties

Quoted 3 lines · Ajit Pandey

Add changes related to new sub node defining MI2S dai's properties. Such properties needs to be configured via board specific dts files.

+Adding Stephan Gerlhold

Have a look at https://www.spinics.net/lists/alsa-devel/msg107224.html patches from Stephan Gerlhold which has better version of specifying sd line mask and is inline with DSP based solution too.

--srini

Quoted 61 lines
---
  .../devicetree/bindings/sound/qcom,lpass-cpu.yaml  | 33 ++++++++++++++++++++++
  1 file changed, 33 insertions(+)
Documentation/devicetree/bindings/sound/qcom,lpass-cpu.yaml +33 -0
index a87a406..727ec03 100644
@@ -16,6 +16,8 @@ description: |
    configure Low-Power Audio Interface(LPAIF) core registers across different
    IP versions.
 
+  See also dt-bindings/sound/qcom,lpass.h.
+
  properties:
    compatible:
      enum:
@@ -69,6 +71,30 @@ properties:
    '#sound-dai-cells':
      const: 1
 
+  dai-name:
+    - description: Each node represents an MI2S dai and conatins dai specific
+        properties that may change with board layout & dai connections.
+    - type: object
+    - properties:
+      id:
+        - description: dai id among one of value defined in header
+        - type: u32
+      qcom,spkmode-mask:
+        - description: mask defining data lines used for speaker
+        - type: u32
+      qcom,micmode-mask:
+        - description: mask defining data lines used for mic
+        - type: u32
+      qcom,wssrc-mask:
+        - description: mask defining word-select source internal/extrnal on dai
+        - type: u32
+      qcom,loopback-mask:
+        - description: mask defining loopback enable/disable on dai
+        - type: u32
+
+      required:
+        - id
+
  required:
    - compatible
    - reg
@@ -101,3 +127,10 @@ examples:
  	#sound-dai-cells = <1>;
  	qcom,adsp = <&adsp>;
 
+        prim-mi2s@0 {
+		id = <MI2S_PRIMARY>;
+		qcom,spkmode-mask = <SD1>;
+		qcom,micmode-mask = <SD0>;
+                qcom,wssrc-mask = <INTERNAL>;
+                qcom,loopback-mask = <DISABLE>;
+	};
#16 lore raw

PATCH 8/11 ASoC: qcom : lpass: Add support to configure dai's connection mode

In reply to Ajit Pandey

Few dai configuration depends on board layout and use cases. Add new variables in dai_data to configure dai modes based on values defined in device tree configuration of board.

---
 sound/soc/qcom/lpass-cpu.c | 70 ++++++++++++++++++++++++++++++++++++++++++++--
 sound/soc/qcom/lpass.h     |  6 ++++
 2 files changed, 74 insertions(+), 2 deletions(-)
sound/soc/qcom/lpass-cpu.c +68 -2
index 006ba5a..f96338f 100644
@@ -90,8 +90,9 @@ static int lpass_cpu_daiops_hw_params(struct snd_pcm_substream *substream,
 		return bitwidth;
 	}
 
-	regval = LPAIF_I2SCTL(v, LOOPBACK_DISABLE);
-	regval |= LPAIF_I2SCTL(v, WSSRC_INTERNAL);
+	/* default to Loopback disable & wssrc internal */
+	regval = dai_data->loopback << (LPAIF_I2SCTL(v, LOOPBACK_SHIFT));
+	regval |= dai_data->wssrc << (LPAIF_I2SCTL(v, WSSRC_SHIFT));
 
 	switch (bitwidth) {
 	case 16:
@@ -172,6 +173,28 @@ static int lpass_cpu_daiops_hw_params(struct snd_pcm_substream *substream,
 		return ret;
 	}
 
+	/* Overwrite spk & mic mode bits with device tree value if specified */
+	if (dai_data->spkmode != 0) {
+		regval = dai_data->spkmode << (LPAIF_I2SCTL(v, SPKMODE_SHIFT));
+		ret = regmap_update_bits(drvdata->lpaif_map,
+			LPAIF_I2SCTL_REG(drvdata->variant, dai->driver->id),
+			LPAIF_I2SCTL(v, SPKMODE_MASK), regval);
+		if (ret)
+			dev_err(dai->dev, "error writing to i2sctl reg: %d\n",
+				ret);
+	}
+
+
+	if (dai_data->micmode != 0) {
+		regval = dai_data->micmode << (LPAIF_I2SCTL(v, MICMODE_SHIFT));
+		ret = regmap_update_bits(drvdata->lpaif_map,
+			LPAIF_I2SCTL_REG(drvdata->variant, dai->driver->id),
+			LPAIF_I2SCTL(v, MICMODE_MASK), regval);
+		if (ret)
+			dev_err(dai->dev, "error writing to i2sctl reg: %d\n",
+				ret);
+	}
+
 	ret = clk_set_rate(dai_data->bit_clk, rate * bitwidth * 2);
 	if (ret) {
 		dev_err(dai->dev, "error setting mi2s bitclk to %u: %d\n",
@@ -423,6 +446,46 @@ static bool lpass_cpu_regmap_volatile(struct device *dev, unsigned int reg)
 	.cache_type = REGCACHE_FLAT,
 };
 
+static void of_qcom_parse_dai_data(struct device *dev,
+				    struct lpass_data *drvdata)
+{
+	struct device_node *node;
+	struct lpass_dai *dai;
+	int ret;
+
+	for_each_child_of_node(dev->of_node, node) {
+		int id;
+
+		ret = of_property_read_u32(node, "id", &id);
+		if (ret || id < 0 || id >= LPASS_MAX_MI2S_PORTS) {
+			dev_err(dev, "valid dai id not found:%d\n", ret);
+			continue;
+		}
+
+		dai = drvdata->dai_priv[id];
+		switch (id) {
+		case MI2S_PRIMARY... MI2S_QUATERNARY:
+			 /* MI2S specific properties */
+			ret = of_property_read_u32(node, "qcom,spkmode-mask",
+						   &dai->spkmode);
+
+			ret = of_property_read_u32(node, "qcom,micmode-mask",
+						   &dai->micmode);
+
+			ret = of_property_read_u32(node, "qcom,wssrc-mask",
+						   &dai->wssrc);
+
+			ret = of_property_read_u32(node, "qcom,loopback-mask",
+						   &dai->loopback);
+
+			break;
+		default:
+			dev_err(dev, "valid dai not found:%d\n", id);
+			break;
+		}
+	}
+}
+
 static int lpass_init_dai_clocks(struct device *dev,
 			   struct lpass_data *drvdata)
 {
@@ -501,6 +564,9 @@ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev)
 						GFP_KERNEL);
 	}
 
+	/* parse dai data from dts */
+	of_qcom_parse_dai_data(dev, drvdata);
+
 	ret = lpass_init_dai_clocks(dev, drvdata);
 	if (ret) {
 		dev_err(&pdev->dev, "error intializing dai clock: %d\n", ret);
sound/soc/qcom/lpass.h +6 -0
index 384f4b8..960ee97 100644
@@ -12,6 +12,7 @@
 #include <linux/compiler.h>
 #include <linux/platform_device.h>
 #include <linux/regmap.h>
+#include <dt-bindings/sound/qcom,lpass.h>
 
 #define LPASS_AHBIX_CLOCK_FREQUENCY            131072000
 #define LPASS_MAX_MI2S_PORTS                   (8)
@@ -23,6 +24,11 @@
 struct lpass_dai {
 	struct clk *osr_clk;
 	struct clk *bit_clk;
+
+	uint32_t spkmode;
+	uint32_t micmode;
+	uint32_t wssrc;
+	uint32_t loopback;
 };
 
 /* Both the CPU DAI and platform drivers will access this data */
Signature · 1 line
1.9.1
#17 lore raw

PATCH 9/11 device-tree: bindings: sound: lpass-cpu: Add new compatible soc

In reply to Ajit Pandey

SC7180 soc varaints of LPASS uses lpass-cpu node but required few extra devictree configuration. Update bindings documents with sc7180 compatible string specific dts properties.

---
 .../devicetree/bindings/sound/qcom,lpass-cpu.yaml  | 25 +++++++++++++++++++++-
 1 file changed, 24 insertions(+), 1 deletion(-)
Documentation/devicetree/bindings/sound/qcom,lpass-cpu.yaml +24 -1
index 727ec03..84bd95c 100644
@@ -23,6 +23,7 @@ properties:
     enum:
       - qcom,lpass-cpu
       - qcom,apq8016-lpass-cpu
+      - qcom,lpass-cpu-sc7180
 
   reg:
     items:
@@ -68,6 +69,14 @@ properties:
     maxItems: 1
     description: Phandle for the audio DSP node
 
+  iommus:
+    maxItems: 1
+    description: Phandle to apps_smmu node with sid mask
+
+  power-domains:
+    maxItems: 1
+    description: Phandle for power domain node
+
   '#sound-dai-cells':
     const: 1
 
@@ -108,6 +117,17 @@ required:
 optional:
   - qcom,adsp
 
+if:
+  properties:
+    compatible:
+      contains:
+        const: qcom,lpass-cpu-sc7180
+
+then:
+  required:
+    - iommus
+    - power-domains
+
 examples:
   lpass@28100000 {
 	compatible = "qcom,lpass-cpu";
@@ -120,7 +140,10 @@ examples:
 		      "mi2s-bit-clk";
 
 	interrupts = <0 85 1>;
-	interrupt-names = "lpass-irq-lpaif";
+        interrupt-names = "lpass-irq-lpaif";
+
+	iommus = <&apps_smmu 0x1020 0>;
+	power-domains = <&lpass_hm LPASS_CORE_HM_GDSCR>;
 
 	reg = <0x28100000 0x10000>;
 	reg-names = "lpass-lpaif";
Signature · 1 line
1.9.1
#18 lore raw

PATCH 10/11 ASoC: qcom: lpass-sc7180: Add platform driver for lpass audio

In reply to Ajit Pandey

Create a platform driver for configuring sc7180 lpass core I2S and DMA configuration to support playback & capture to external codecs connected over primary & secondary MI2S interfaces.

---
 sound/soc/qcom/Kconfig        |   5 ++
 sound/soc/qcom/Makefile       |   2 +
 sound/soc/qcom/lpass-sc7180.c | 192 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 199 insertions(+)
 create mode 100644 sound/soc/qcom/lpass-sc7180.c
sound/soc/qcom/Kconfig +5 -0
index 6008685..23fd9e6 100644
@@ -24,6 +24,11 @@ config SND_SOC_LPASS_APQ8016
 	select SND_SOC_LPASS_CPU
 	select SND_SOC_LPASS_PLATFORM
 
+config SND_SOC_LPASS_SC7180
+	tristate
+	select SND_SOC_LPASS_CPU
+	select SND_SOC_LPASS_PLATFORM
+
 config SND_SOC_STORM
 	tristate "ASoC I2S support for Storm boards"
 	depends on SND_SOC_QCOM
sound/soc/qcom/Makefile +2 -0
index 41b2c7a..7972c94 100644
@@ -4,11 +4,13 @@ snd-soc-lpass-cpu-objs := lpass-cpu.o
 snd-soc-lpass-platform-objs := lpass-platform.o
 snd-soc-lpass-ipq806x-objs := lpass-ipq806x.o
 snd-soc-lpass-apq8016-objs := lpass-apq8016.o
+snd-soc-lpass-sc7180-objs := lpass-sc7180.o
 
 obj-$(CONFIG_SND_SOC_LPASS_CPU) += snd-soc-lpass-cpu.o
 obj-$(CONFIG_SND_SOC_LPASS_PLATFORM) += snd-soc-lpass-platform.o
 obj-$(CONFIG_SND_SOC_LPASS_IPQ806X) += snd-soc-lpass-ipq806x.o
 obj-$(CONFIG_SND_SOC_LPASS_APQ8016) += snd-soc-lpass-apq8016.o
+obj-$(CONFIG_SND_SOC_LPASS_SC7180) += snd-soc-lpass-sc7180.o
 
 # Machine
 snd-soc-storm-objs := storm.o
sound/soc/qcom/lpass-sc7180.c new file +192 -0

192 lines not on this page · raw message

Signature · 1 line
1.9.1
#19 lore raw

PATCH 11/11 ASoC: qcom: lpass-platform: Replace card->dev with component->dev

In reply to Ajit Pandey

We are allocating dma memory for component->dev but trying to mmap such memory for substream->pcm->card->dev. Replace device argument in mmap with component->dev to fix this.

---
 sound/soc/qcom/lpass-platform.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)
sound/soc/qcom/lpass-platform.c +2 -3
index 821599e..9ab2dd5 100644
@@ -401,9 +401,8 @@ static int lpass_platform_pcmops_mmap(struct snd_soc_component *component,
 {
 	struct snd_pcm_runtime *runtime = substream->runtime;
 
-	return dma_mmap_coherent(substream->pcm->card->dev, vma,
-			runtime->dma_area, runtime->dma_addr,
-			runtime->dma_bytes);
+	return dma_mmap_coherent(component->dev, vma, runtime->dma_area,
+				 runtime->dma_addr, runtime->dma_bytes);
 }
 
 static irqreturn_t lpass_dma_interrupt_handler(
Signature · 1 line
1.9.1
Reviewed-by on v1 11/11
#20 lore raw

Re: [PATCH 11/11] ASoC: qcom: lpass-platform: Replace card->dev with component->dev

Quoted 5 lines · Ajit Pandey

We are allocating dma memory for component->dev but trying to mmap such memory for substream->pcm->card->dev. Replace device argument in mmap with component->dev to fix this.

Probably a fixes tag here,

Fixes c5c8635a0471("ASoC: qcom: Add LPASS platform driver")
Quoted 21 lines
---
  sound/soc/qcom/lpass-platform.c | 5 ++---
  1 file changed, 2 insertions(+), 3 deletions(-)
sound/soc/qcom/lpass-platform.c +2 -3
index 821599e..9ab2dd5 100644
@@ -401,9 +401,8 @@ static int lpass_platform_pcmops_mmap(struct snd_soc_component *component,
  {
  	struct snd_pcm_runtime *runtime = substream->runtime;
 
-	return dma_mmap_coherent(substream->pcm->card->dev, vma,
-			runtime->dma_area, runtime->dma_addr,
-			runtime->dma_bytes);
+	return dma_mmap_coherent(component->dev, vma, runtime->dma_area,
+				 runtime->dma_addr, runtime->dma_bytes);
  }
 
  static irqreturn_t lpass_dma_interrupt_handler(