[PATCH 00/11] 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
Done the required cleanups to update lpass-cpu binding with newer yaml formats.
Signed-off-by: Ajit Pandey ajitp@codeaurora.org --- .../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
diff --git a/Documentation/devicetree/bindings/sound/qcom,lpass-cpu.txt b/Documentation/devicetree/bindings/sound/qcom,lpass-cpu.txt deleted file mode 100644 index a49b878..00000000 --- a/Documentation/devicetree/bindings/sound/qcom,lpass-cpu.txt +++ /dev/null @@ -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"; - }; -}; diff --git a/Documentation/devicetree/bindings/sound/qcom,lpass-cpu.yaml b/Documentation/devicetree/bindings/sound/qcom,lpass-cpu.yaml new file mode 100644 index 00000000..a87a406 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/qcom,lpass-cpu.yaml @@ -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 srinivas.kandagatla@linaro.org + - Ajit Pandey ajitp@codeaurora.org + +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>; +
On 11/04/2020 09:02, Ajit Pandey wrote:
Done the required cleanups to update lpass-cpu binding with newer yaml formats.
Signed-off-by: Ajit Pandey ajitp@codeaurora.org
.../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
diff --git a/Documentation/devicetree/bindings/sound/qcom,lpass-cpu.txt b/Documentation/devicetree/bindings/sound/qcom,lpass-cpu.txt deleted file mode 100644 index a49b878..00000000 --- a/Documentation/devicetree/bindings/sound/qcom,lpass-cpu.txt +++ /dev/null @@ -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
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...
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
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";
- };
-}; diff --git a/Documentation/devicetree/bindings/sound/qcom,lpass-cpu.yaml b/Documentation/devicetree/bindings/sound/qcom,lpass-cpu.yaml new file mode 100644 index 00000000..a87a406 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/qcom,lpass-cpu.yaml @@ -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 srinivas.kandagatla@linaro.org
- Ajit Pandey ajitp@codeaurora.org
+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>;
On 4/16/2020 1:23 PM, Srinivas Kandagatla wrote:
On 11/04/2020 09:02, Ajit Pandey wrote:
Done the required cleanups to update lpass-cpu binding with newer yaml formats.
Signed-off-by: Ajit Pandey ajitp@codeaurora.org
.../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
diff --git a/Documentation/devicetree/bindings/sound/qcom,lpass-cpu.txt b/Documentation/devicetree/bindings/sound/qcom,lpass-cpu.txt deleted file mode 100644 index a49b878..00000000 --- a/Documentation/devicetree/bindings/sound/qcom,lpass-cpu.txt +++ /dev/null @@ -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
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...
Sure I'll rebase on top of mentioned tip during v2 patch chain submission
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
- 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"; - }; -}; diff --git a/Documentation/devicetree/bindings/sound/qcom,lpass-cpu.yaml b/Documentation/devicetree/bindings/sound/qcom,lpass-cpu.yaml new file mode 100644 index 00000000..a87a406 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/qcom,lpass-cpu.yaml @@ -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 srinivas.kandagatla@linaro.org + - Ajit Pandey ajitp@codeaurora.org
+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>;
lpass_dai will store clocks related to respective dai's and it will be initialized during probe based on variant clock names.
Signed-off-by: Ajit Pandey ajitp@codeaurora.org --- sound/soc/qcom/lpass-cpu.c | 89 ++++++++++++++++++++++++++-------------------- sound/soc/qcom/lpass.h | 18 +++++----- 2 files changed, 61 insertions(+), 46 deletions(-)
diff --git a/sound/soc/qcom/lpass-cpu.c b/sound/soc/qcom/lpass-cpu.c index dbce7e9..492f27b 100644 --- a/sound/soc/qcom/lpass-cpu.c +++ b/sound/soc/qcom/lpass-cpu.c @@ -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"); diff --git a/sound/soc/qcom/lpass.h b/sound/soc/qcom/lpass.h index 17113d3..b729686 100644 --- a/sound/soc/qcom/lpass.h +++ b/sound/soc/qcom/lpass.h @@ -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;
On 11/04/2020 09:02, Ajit Pandey wrote:
lpass_dai will store clocks related to respective dai's and it will be initialized during probe based on variant clock names.
Signed-off-by: Ajit Pandey ajitp@codeaurora.org
I dont understand why do we need this change? What is the advantage of doing this way vs the existing one?
--srini
sound/soc/qcom/lpass-cpu.c | 89 ++++++++++++++++++++++++++-------------------- sound/soc/qcom/lpass.h | 18 +++++----- 2 files changed, 61 insertions(+), 46 deletions(-)
diff --git a/sound/soc/qcom/lpass-cpu.c b/sound/soc/qcom/lpass-cpu.c index dbce7e9..492f27b 100644 --- a/sound/soc/qcom/lpass-cpu.c +++ b/sound/soc/qcom/lpass-cpu.c @@ -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]);
return ret; }clk_disable_unprepare(dai_data->osr_clk);
@@ -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");
diff --git a/sound/soc/qcom/lpass.h b/sound/soc/qcom/lpass.h index 17113d3..b729686 100644 --- a/sound/soc/qcom/lpass.h +++ b/sound/soc/qcom/lpass.h @@ -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;
On 4/16/2020 1:26 PM, Srinivas Kandagatla wrote:
On 11/04/2020 09:02, Ajit Pandey wrote:
lpass_dai will store clocks related to respective dai's and it will be initialized during probe based on variant clock names.
Signed-off-by: Ajit Pandey ajitp@codeaurora.org
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
sound/soc/qcom/lpass-cpu.c | 89 ++++++++++++++++++++++++++-------------------- sound/soc/qcom/lpass.h | 18 +++++----- 2 files changed, 61 insertions(+), 46 deletions(-)
diff --git a/sound/soc/qcom/lpass-cpu.c b/sound/soc/qcom/lpass-cpu.c index dbce7e9..492f27b 100644 --- a/sound/soc/qcom/lpass-cpu.c +++ b/sound/soc/qcom/lpass-cpu.c @@ -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"); diff --git a/sound/soc/qcom/lpass.h b/sound/soc/qcom/lpass.h index 17113d3..b729686 100644 --- a/sound/soc/qcom/lpass.h +++ b/sound/soc/qcom/lpass.h @@ -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;
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.
Signed-off-by: Ajit Pandey ajitp@codeaurora.org --- sound/soc/qcom/lpass-apq8016.c | 39 ++++++++++++++++++--------------------- sound/soc/qcom/lpass.h | 10 +++++++--- 2 files changed, 25 insertions(+), 24 deletions(-)
diff --git a/sound/soc/qcom/lpass-apq8016.c b/sound/soc/qcom/lpass-apq8016.c index 6575da5..cef4661 100644 --- a/sound/soc/qcom/lpass-apq8016.c +++ b/sound/soc/qcom/lpass-apq8016.c @@ -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 *[]) { diff --git a/sound/soc/qcom/lpass.h b/sound/soc/qcom/lpass.h index b729686..279cd02 100644 --- a/sound/soc/qcom/lpass.h +++ b/sound/soc/qcom/lpass.h @@ -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 */
AHB-I/X bus clocks inside LPASS coreis not a mandatory clocks for newer lpass variants, hence make it an optional one.
Signed-off-by: Ajit Pandey ajitp@codeaurora.org --- sound/soc/qcom/lpass-cpu.c | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-)
diff --git a/sound/soc/qcom/lpass-cpu.c b/sound/soc/qcom/lpass-cpu.c index 492f27b..f177932 100644 --- a/sound/soc/qcom/lpass-cpu.c +++ b/sound/soc/qcom/lpass-cpu.c @@ -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,
On 11/04/2020 09:02, Ajit Pandey wrote:
AHB-I/X bus clocks inside LPASS coreis not a mandatory clocks for
s/coreis/core is/
newer lpass variants, hence make it an optional one.
Can you add more detail on which version of IP would not have this clk.
Signed-off-by: Ajit Pandey ajitp@codeaurora.org
sound/soc/qcom/lpass-cpu.c | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-)
diff --git a/sound/soc/qcom/lpass-cpu.c b/sound/soc/qcom/lpass-cpu.c index 492f27b..f177932 100644 --- a/sound/soc/qcom/lpass-cpu.c +++ b/sound/soc/qcom/lpass-cpu.c @@ -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) {
No need for NULL checks here, clk apis already have checks.
--srini
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,
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.
Signed-off-by: Ajit Pandey ajitp@codeaurora.org --- 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(-)
diff --git a/sound/soc/qcom/lpass-cpu.c b/sound/soc/qcom/lpass-cpu.c index f177932..006ba5a 100644 --- a/sound/soc/qcom/lpass-cpu.c +++ b/sound/soc/qcom/lpass-cpu.c @@ -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, diff --git a/sound/soc/qcom/lpass-lpaif-reg.h b/sound/soc/qcom/lpass-lpaif-reg.h index 3d74ae1..4251aa6 100644 --- a/sound/soc/qcom/lpass-lpaif-reg.h +++ b/sound/soc/qcom/lpass-lpaif-reg.h @@ -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__ */ diff --git a/sound/soc/qcom/lpass-platform.c b/sound/soc/qcom/lpass-platform.c index b05091c2..821599e 100644 --- a/sound/soc/qcom/lpass-platform.c +++ b/sound/soc/qcom/lpass-platform.c @@ -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, diff --git a/sound/soc/qcom/lpass.h b/sound/soc/qcom/lpass.h index 279cd02..384f4b8 100644 --- a/sound/soc/qcom/lpass.h +++ b/sound/soc/qcom/lpass.h @@ -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 */
On 11/04/2020 09:02, Ajit Pandey wrote:
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.
Signed-off-by: Ajit Pandey ajitp@codeaurora.org
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(-)
diff --git a/sound/soc/qcom/lpass-cpu.c b/sound/soc/qcom/lpass-cpu.c index f177932..006ba5a 100644 --- a/sound/soc/qcom/lpass-cpu.c +++ b/sound/soc/qcom/lpass-cpu.c @@ -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;
break; case 24:regval |= LPAIF_I2SCTL(v, BITWIDTH_16);
regval |= LPAIF_I2SCTL_BITWIDTH_24;
break; case 32:regval |= LPAIF_I2SCTL(v, BITWIDTH_24);
regval |= LPAIF_I2SCTL_BITWIDTH_32;
break; default: dev_err(dai->dev, "invalid bitwidth given: %d\n", bitwidth);regval |= LPAIF_I2SCTL(v, BITWIDTH_32);
@@ -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);
case 2:regval |= LPAIF_I2SCTL(v, SPKMONO_MONO); break;
regval |= LPAIF_I2SCTL_SPKMODE_SD0;
regval |= LPAIF_I2SCTL_SPKMONO_STEREO;
regval |= LPAIF_I2SCTL(v, SPKMODE_SD0);
case 4:regval |= LPAIF_I2SCTL(v, SPKMONO_STEREO); break;
regval |= LPAIF_I2SCTL_SPKMODE_QUAD01;
regval |= LPAIF_I2SCTL_SPKMONO_STEREO;
regval |= LPAIF_I2SCTL(v, SPKMODE_QUAD01);
case 6:regval |= LPAIF_I2SCTL(v, SPKMONO_STEREO); break;
regval |= LPAIF_I2SCTL_SPKMODE_6CH;
regval |= LPAIF_I2SCTL_SPKMONO_STEREO;
regval |= LPAIF_I2SCTL(v, SPKMODE_6CH);
case 8:regval |= LPAIF_I2SCTL(v, SPKMONO_STEREO); break;
regval |= LPAIF_I2SCTL_SPKMODE_8CH;
regval |= LPAIF_I2SCTL_SPKMONO_STEREO;
regval |= LPAIF_I2SCTL(v, SPKMODE_8CH);
default: dev_err(dai->dev, "invalid channels given: %u\n",regval |= LPAIF_I2SCTL(v, SPKMONO_STEREO); break;
@@ -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);
case 2:regval |= LPAIF_I2SCTL(v, MICMONO_MONO); break;
regval |= LPAIF_I2SCTL_MICMODE_SD0;
regval |= LPAIF_I2SCTL_MICMONO_STEREO;
regval |= LPAIF_I2SCTL(v, MICMODE_SD0);
case 4:regval |= LPAIF_I2SCTL(v, MICMONO_STEREO); break;
regval |= LPAIF_I2SCTL_MICMODE_QUAD01;
regval |= LPAIF_I2SCTL_MICMONO_STEREO;
regval |= LPAIF_I2SCTL(v, MICMODE_QUAD01);
case 6:regval |= LPAIF_I2SCTL(v, MICMONO_STEREO); break;
regval |= LPAIF_I2SCTL_MICMODE_6CH;
regval |= LPAIF_I2SCTL_MICMONO_STEREO;
regval |= LPAIF_I2SCTL(v, MICMODE_6CH);
case 8:regval |= LPAIF_I2SCTL(v, MICMONO_STEREO); break;
regval |= LPAIF_I2SCTL_MICMODE_8CH;
regval |= LPAIF_I2SCTL_MICMONO_STEREO;
regval |= LPAIF_I2SCTL(v, MICMODE_8CH);
default: dev_err(dai->dev, "invalid channels given: %u\n",regval |= LPAIF_I2SCTL(v, MICMONO_STEREO); break;
@@ -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);
} else {mask = LPAIF_I2SCTL(v, SPKEN_MASK);
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);
} else {mask = LPAIF_I2SCTL(v, SPKEN_MASK);
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);
} else {mask = LPAIF_I2SCTL(v, SPKEN_MASK);
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,
diff --git a/sound/soc/qcom/lpass-lpaif-reg.h b/sound/soc/qcom/lpass-lpaif-reg.h index 3d74ae1..4251aa6 100644 --- a/sound/soc/qcom/lpass-lpaif-reg.h +++ b/sound/soc/qcom/lpass-lpaif-reg.h @@ -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__ */
diff --git a/sound/soc/qcom/lpass-platform.c b/sound/soc/qcom/lpass-platform.c index b05091c2..821599e 100644 --- a/sound/soc/qcom/lpass-platform.c +++ b/sound/soc/qcom/lpass-platform.c @@ -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;
case 4:regval |= LPAIF_DMACTL(v, WPSCNT_ONE); break;
regval |= LPAIF_DMACTL_WPSCNT_TWO;
case 6:regval |= LPAIF_DMACTL(v, WPSCNT_TWO); break;
regval |= LPAIF_DMACTL_WPSCNT_THREE;
case 8:regval |= LPAIF_DMACTL(v, WPSCNT_THREE); break;
regval |= LPAIF_DMACTL_WPSCNT_FOUR;
default: dev_err(soc_runtime->dev,regval |= LPAIF_DMACTL(v, WPSCNT_FOUR); break;
@@ -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;
case 2:regval |= LPAIF_DMACTL(v, WPSCNT_ONE); break;
regval |= LPAIF_DMACTL_WPSCNT_TWO;
case 4:regval |= LPAIF_DMACTL(v, WPSCNT_TWO); break;
regval |= LPAIF_DMACTL_WPSCNT_FOUR;
case 6:regval |= LPAIF_DMACTL(v, WPSCNT_FOUR); break;
regval |= LPAIF_DMACTL_WPSCNT_SIX;
case 8:regval |= LPAIF_DMACTL(v, WPSCNT_SIX); break;
regval |= LPAIF_DMACTL_WPSCNT_EIGHT;
default: dev_err(soc_runtime->dev,regval |= LPAIF_DMACTL(v, WPSCNT_EIGHT); break;
@@ -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);
if (ret) { dev_err(soc_runtime->dev, "error writing to rdmactl reg: %d\n", ret);LPAIF_DMACTL(v, ENABLE_MASK), LPAIF_DMACTL_ENABLE_ON);
@@ -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,
if (ret) { dev_err(soc_runtime->dev,LPAIF_DMACTL(v, ENABLE_MASK), LPAIF_DMACTL_ENABLE_ON);
@@ -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,
if (ret) { dev_err(soc_runtime->dev,LPAIF_DMACTL(v, ENABLE_MASK), LPAIF_DMACTL_ENABLE_OFF);
diff --git a/sound/soc/qcom/lpass.h b/sound/soc/qcom/lpass.h index 279cd02..384f4b8 100644 --- a/sound/soc/qcom/lpass.h +++ b/sound/soc/qcom/lpass.h @@ -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;
May be spelling this out like "version_id" would make it more readable.
thanks, srini
};
/* register the platform driver from the CPU DAI driver */
On 4/16/2020 1:26 PM, Srinivas Kandagatla wrote:
On 11/04/2020 09:02, Ajit Pandey wrote:
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
Signed-off-by: Ajit Pandey ajitp@codeaurora.org
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(-)
diff --git a/sound/soc/qcom/lpass-cpu.c b/sound/soc/qcom/lpass-cpu.c index f177932..006ba5a 100644 --- a/sound/soc/qcom/lpass-cpu.c +++ b/sound/soc/qcom/lpass-cpu.c @@ -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, diff --git a/sound/soc/qcom/lpass-lpaif-reg.h b/sound/soc/qcom/lpass-lpaif-reg.h index 3d74ae1..4251aa6 100644 --- a/sound/soc/qcom/lpass-lpaif-reg.h +++ b/sound/soc/qcom/lpass-lpaif-reg.h @@ -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__ */ diff --git a/sound/soc/qcom/lpass-platform.c b/sound/soc/qcom/lpass-platform.c index b05091c2..821599e 100644 --- a/sound/soc/qcom/lpass-platform.c +++ b/sound/soc/qcom/lpass-platform.c @@ -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, diff --git a/sound/soc/qcom/lpass.h b/sound/soc/qcom/lpass.h index 279cd02..384f4b8 100644 --- a/sound/soc/qcom/lpass.h +++ b/sound/soc/qcom/lpass.h @@ -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;
May be spelling this out like "version_id" would make it more readable.
thanks, srini
}; /* register the platform driver from the CPU DAI driver */
Add header defining dts properties related to lpass cpu MI2S dai's.
Signed-off-by: Ajit Pandey ajitp@codeaurora.org --- include/dt-bindings/sound/qcom,lpass.h | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 include/dt-bindings/sound/qcom,lpass.h
diff --git a/include/dt-bindings/sound/qcom,lpass.h b/include/dt-bindings/sound/qcom,lpass.h new file mode 100644 index 00000000..4e6c6bc --- /dev/null +++ b/include/dt-bindings/sound/qcom,lpass.h @@ -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__ */
Add changes related to new sub node defining MI2S dai's properties. Such properties needs to be configured via board specific dts files.
Signed-off-by: Ajit Pandey ajitp@codeaurora.org --- .../devicetree/bindings/sound/qcom,lpass-cpu.yaml | 33 ++++++++++++++++++++++ 1 file changed, 33 insertions(+)
diff --git a/Documentation/devicetree/bindings/sound/qcom,lpass-cpu.yaml b/Documentation/devicetree/bindings/sound/qcom,lpass-cpu.yaml index a87a406..727ec03 100644 --- a/Documentation/devicetree/bindings/sound/qcom,lpass-cpu.yaml +++ b/Documentation/devicetree/bindings/sound/qcom,lpass-cpu.yaml @@ -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>; + };
On 11/04/2020 09:02, Ajit Pandey wrote:
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
Signed-off-by: Ajit Pandey ajitp@codeaurora.org
.../devicetree/bindings/sound/qcom,lpass-cpu.yaml | 33 ++++++++++++++++++++++ 1 file changed, 33 insertions(+)
diff --git a/Documentation/devicetree/bindings/sound/qcom,lpass-cpu.yaml b/Documentation/devicetree/bindings/sound/qcom,lpass-cpu.yaml index a87a406..727ec03 100644 --- a/Documentation/devicetree/bindings/sound/qcom,lpass-cpu.yaml +++ b/Documentation/devicetree/bindings/sound/qcom,lpass-cpu.yaml @@ -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>;
- };
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.
Signed-off-by: Ajit Pandey ajitp@codeaurora.org --- sound/soc/qcom/lpass-cpu.c | 70 ++++++++++++++++++++++++++++++++++++++++++++-- sound/soc/qcom/lpass.h | 6 ++++ 2 files changed, 74 insertions(+), 2 deletions(-)
diff --git a/sound/soc/qcom/lpass-cpu.c b/sound/soc/qcom/lpass-cpu.c index 006ba5a..f96338f 100644 --- a/sound/soc/qcom/lpass-cpu.c +++ b/sound/soc/qcom/lpass-cpu.c @@ -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); diff --git a/sound/soc/qcom/lpass.h b/sound/soc/qcom/lpass.h index 384f4b8..960ee97 100644 --- a/sound/soc/qcom/lpass.h +++ b/sound/soc/qcom/lpass.h @@ -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 */
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.
Signed-off-by: Ajit Pandey ajitp@codeaurora.org --- .../devicetree/bindings/sound/qcom,lpass-cpu.yaml | 25 +++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/sound/qcom,lpass-cpu.yaml b/Documentation/devicetree/bindings/sound/qcom,lpass-cpu.yaml index 727ec03..84bd95c 100644 --- a/Documentation/devicetree/bindings/sound/qcom,lpass-cpu.yaml +++ b/Documentation/devicetree/bindings/sound/qcom,lpass-cpu.yaml @@ -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";
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.
Signed-off-by: Ajit Pandey ajitp@codeaurora.org --- 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
diff --git a/sound/soc/qcom/Kconfig b/sound/soc/qcom/Kconfig index 6008685..23fd9e6 100644 --- a/sound/soc/qcom/Kconfig +++ b/sound/soc/qcom/Kconfig @@ -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 diff --git a/sound/soc/qcom/Makefile b/sound/soc/qcom/Makefile index 41b2c7a..7972c94 100644 --- a/sound/soc/qcom/Makefile +++ b/sound/soc/qcom/Makefile @@ -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 diff --git a/sound/soc/qcom/lpass-sc7180.c b/sound/soc/qcom/lpass-sc7180.c new file mode 100644 index 00000000..879f3a5 --- /dev/null +++ b/sound/soc/qcom/lpass-sc7180.c @@ -0,0 +1,192 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + * + * lpass-sc7180.c -- ALSA SoC platform-machine driver for QTi LPASS + */ + +#include <linux/clk.h> +#include <linux/device.h> +#include <linux/err.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <sound/pcm.h> +#include <sound/soc.h> + +#include "lpass-lpaif-reg.h" +#include "lpass.h" + +static struct snd_soc_dai_driver sc7180_lpass_cpu_dai_driver[] = { + [MI2S_PRIMARY] = { + .id = MI2S_PRIMARY, + .name = "Primary MI2S", + .playback = { + .stream_name = "Primary Playback", + .formats = SNDRV_PCM_FMTBIT_S16, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .channels_min = 2, + .channels_max = 2, + }, + .capture = { + .stream_name = "Primary Capture", + .formats = SNDRV_PCM_FMTBIT_S16, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .channels_min = 2, + .channels_max = 2, + }, + .probe = &asoc_qcom_lpass_cpu_dai_probe, + .ops = &asoc_qcom_lpass_cpu_dai_ops, + }, + + [MI2S_SECONDARY] = { + .id = MI2S_SECONDARY, + .name = "Secondary MI2S", + .playback = { + .stream_name = "Secondary Playback", + .formats = SNDRV_PCM_FMTBIT_S16, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .channels_min = 2, + .channels_max = 2, + }, + .probe = &asoc_qcom_lpass_cpu_dai_probe, + .ops = &asoc_qcom_lpass_cpu_dai_ops, + }, +}; + +static int sc7180_lpass_alloc_dma_channel(struct lpass_data *drvdata, + int direction) +{ + struct lpass_variant *v = drvdata->variant; + int chan = 0; + + if (direction == SNDRV_PCM_STREAM_PLAYBACK) { + chan = find_first_zero_bit(&drvdata->dma_ch_bit_map, + v->rdma_channels); + + if (chan >= v->rdma_channels) + return -EBUSY; + } else { + chan = find_next_zero_bit(&drvdata->dma_ch_bit_map, + v->wrdma_channel_start + + v->wrdma_channels, + v->wrdma_channel_start); + + if (chan >= v->wrdma_channel_start + v->wrdma_channels) + return -EBUSY; + } + + set_bit(chan, &drvdata->dma_ch_bit_map); + + return chan; +} + +static int sc7180_lpass_free_dma_channel(struct lpass_data *drvdata, int chan) +{ + clear_bit(chan, &drvdata->dma_ch_bit_map); + + return 0; +} + +static int sc7180_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, i; + + 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 = devm_clk_bulk_get(dev, drvdata->num_clks, drvdata->clks); + if (ret) { + dev_err(dev, "Failed to get clocks %d\n", ret); + return ret; + } + + ret = clk_bulk_prepare_enable(drvdata->num_clks, drvdata->clks); + if (ret) { + dev_err(dev, "sc7180 clk_enable failed\n"); + return ret; + } + + return 0; +} + +static int sc7180_lpass_exit(struct platform_device *pdev) +{ + struct lpass_data *drvdata = platform_get_drvdata(pdev); + + clk_bulk_disable_unprepare(drvdata->num_clks, drvdata->clks); + + return 0; +} + +static struct lpass_variant sc7180_data = { + .i2sctrl_reg_base = 0x1000, + .i2sctrl_reg_stride = 0x1000, + .i2s_ports = 3, + .irq_reg_base = 0x9000, + .irq_reg_stride = 0x1000, + .irq_ports = 3, + .rdma_reg_base = 0xC000, + .rdma_reg_stride = 0x1000, + .rdma_channels = 5, + .dmactl_audif_start = 1, + .wrdma_reg_base = 0x18000, + .wrdma_reg_stride = 0x1000, + .wrdma_channel_start = 5, + .wrdma_channels = 4, + .id = LPASS_VARIANT_V2, + .clk_name = (const char*[]) { + "noc", + "audio-core", + "sysnoc_mport", + }, + .num_clks = 3, + .dai_driver = sc7180_lpass_cpu_dai_driver, + .num_dai = ARRAY_SIZE(sc7180_lpass_cpu_dai_driver), + .dai_osr_clk_names = (const char *[]) { + "mclk0", + "null", + }, + .dai_bit_clk_names = (const char *[]) { + "pri_ibit", + "sec_ibit", + }, + .init = sc7180_lpass_init, + .exit = sc7180_lpass_exit, + .alloc_dma_channel = sc7180_lpass_alloc_dma_channel, + .free_dma_channel = sc7180_lpass_free_dma_channel, + +}; + +static const struct of_device_id sc7180_lpass_cpu_device_id[] = { + {.compatible = "qcom,lpass-cpu-sc7180", .data = &sc7180_data}, + {} +}; + +static struct platform_driver sc7180_lpass_cpu_platform_driver = { + .driver = { + .name = "sc7180-lpass-cpu", + .of_match_table = of_match_ptr(sc7180_lpass_cpu_device_id), + }, + .probe = asoc_qcom_lpass_cpu_platform_probe, + .remove = asoc_qcom_lpass_cpu_platform_probe, +}; + +module_platform_driver(sc7180_lpass_cpu_platform_driver); + +MODULE_DESCRIPTION("SC7180 LPASS CPU DRIVER"); +MODULE_LICENSE("GPL v2");
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.
Signed-off-by: Ajit Pandey ajitp@codeaurora.org --- sound/soc/qcom/lpass-platform.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/sound/soc/qcom/lpass-platform.c b/sound/soc/qcom/lpass-platform.c index 821599e..9ab2dd5 100644 --- a/sound/soc/qcom/lpass-platform.c +++ b/sound/soc/qcom/lpass-platform.c @@ -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(
On 11/04/2020 09:02, Ajit Pandey wrote:
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.
Signed-off-by: Ajit Pandey ajitp@codeaurora.org
Probably a fixes tag here,
Fixes: c5c8635a0471("ASoC: qcom: Add LPASS platform driver")
Reviewed-by: Srinivas Kandagatla srinivas.kandagatla@linaro.org
sound/soc/qcom/lpass-platform.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/sound/soc/qcom/lpass-platform.c b/sound/soc/qcom/lpass-platform.c index 821599e..9ab2dd5 100644 --- a/sound/soc/qcom/lpass-platform.c +++ b/sound/soc/qcom/lpass-platform.c @@ -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(
participants (2)
-
Ajit Pandey
-
Srinivas Kandagatla