ASoC: Add ak4619 codec support

Merge series from Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>:

This is v3 patch-set for ak4619 driver.
It was created by Khanh, and I updated/adjusted to upstream.
It was tested on Renesas V4M GrayH

Link: https://lore.kernel.org/r/877ceotnrg.wl-kuninori.morimoto.gx@renesas.com
Link: https://lore.kernel.org/r/87frtb3x4k.wl-kuninori.morimoto.gx@renesas.com
diff --git a/Documentation/devicetree/bindings/sound/ak4375.yaml b/Documentation/devicetree/bindings/sound/asahi-kasei,ak4375.yaml
similarity index 94%
rename from Documentation/devicetree/bindings/sound/ak4375.yaml
rename to Documentation/devicetree/bindings/sound/asahi-kasei,ak4375.yaml
index 587598e..bc07fcb 100644
--- a/Documentation/devicetree/bindings/sound/ak4375.yaml
+++ b/Documentation/devicetree/bindings/sound/asahi-kasei,ak4375.yaml
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
 %YAML 1.2
 ---
-$id: http://devicetree.org/schemas/sound/ak4375.yaml#
+$id: http://devicetree.org/schemas/sound/asahi-kasei,ak4375.yaml#
 $schema: http://devicetree.org/meta-schemas/core.yaml#
 
 title: AK4375 DAC and headphones amplifier
diff --git a/Documentation/devicetree/bindings/sound/ak4613.yaml b/Documentation/devicetree/bindings/sound/asahi-kasei,ak4613.yaml
similarity index 93%
rename from Documentation/devicetree/bindings/sound/ak4613.yaml
rename to Documentation/devicetree/bindings/sound/asahi-kasei,ak4613.yaml
index 75e1341..b49a6cf 100644
--- a/Documentation/devicetree/bindings/sound/ak4613.yaml
+++ b/Documentation/devicetree/bindings/sound/asahi-kasei,ak4613.yaml
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
 %YAML 1.2
 ---
-$id: http://devicetree.org/schemas/sound/ak4613.yaml#
+$id: http://devicetree.org/schemas/sound/asahi-kasei,ak4613.yaml#
 $schema: http://devicetree.org/meta-schemas/core.yaml#
 
 title: AK4613 I2C transmitter
diff --git a/Documentation/devicetree/bindings/sound/ak4642.yaml b/Documentation/devicetree/bindings/sound/asahi-kasei,ak4642.yaml
similarity index 93%
rename from Documentation/devicetree/bindings/sound/ak4642.yaml
rename to Documentation/devicetree/bindings/sound/asahi-kasei,ak4642.yaml
index 437fe5d..fc03f03 100644
--- a/Documentation/devicetree/bindings/sound/ak4642.yaml
+++ b/Documentation/devicetree/bindings/sound/asahi-kasei,ak4642.yaml
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 %YAML 1.2
 ---
-$id: http://devicetree.org/schemas/sound/ak4642.yaml#
+$id: http://devicetree.org/schemas/sound/asahi-kasei,ak4642.yaml#
 $schema: http://devicetree.org/meta-schemas/core.yaml#
 
 title: AK4642 I2C transmitter
diff --git a/Documentation/devicetree/bindings/sound/cirrus,cs530x.yaml b/Documentation/devicetree/bindings/sound/cirrus,cs530x.yaml
new file mode 100644
index 0000000..9582eb8
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/cirrus,cs530x.yaml
@@ -0,0 +1,85 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/cirrus,cs530x.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Cirrus Logic cs530x family of audio ADCs
+
+maintainers:
+  - Paul Handrigan <paulha@opensource.cirrus.com>
+  - patches@opensource.cirrus.com
+
+description:
+  The CS530X devices are a family of high performance audio ADCs.
+
+allOf:
+  - $ref: dai-common.yaml#
+
+properties:
+  compatible:
+    enum:
+      - cirrus,cs5302
+      - cirrus,cs5304
+      - cirrus,cs5308
+
+  reg:
+    maxItems: 1
+
+  '#sound-dai-cells':
+    const: 1
+
+  reset-gpios:
+    maxItems: 1
+
+  vdd-a-supply:
+    description: Analog power supply
+
+  vdd-io-supply:
+    description: Digital IO power supply
+
+  cirrus,in-hiz-pin12:
+    description:
+      Sets input channels one and two to high impedance.
+    type: boolean
+
+  cirrus,in-hiz-pin34:
+    description:
+      Sets input channels three and four to high impedance.
+    type: boolean
+
+  cirrus,in-hiz-pin56:
+    description:
+      Sets input channels five and six to high impedance.
+    type: boolean
+
+  cirrus,in-hiz-pin78:
+    description:
+      Sets input channels seven and eight to high impedance.
+    type: boolean
+
+required:
+  - compatible
+  - reg
+  - "#sound-dai-cells"
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/gpio/gpio.h>
+
+    i2c {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        cs5304: adc@48 {
+            compatible = "cirrus,cs5304";
+            reg = <0x48>;
+            #sound-dai-cells = <1>;
+            reset-gpios = <&gpio 110 GPIO_ACTIVE_LOW>;
+            vdd-a-supply = <&vreg>;
+            vdd-io-supply = <&vreg>;
+            cirrus,in-hiz-pin34;
+        };
+    };
diff --git a/Documentation/devicetree/bindings/sound/everest,es7134.txt b/Documentation/devicetree/bindings/sound/everest,es7134.txt
deleted file mode 100644
index 0916660..0000000
--- a/Documentation/devicetree/bindings/sound/everest,es7134.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-ES7134 i2s DA converter
-
-Required properties:
-- compatible : "everest,es7134" or
-               "everest,es7144" or
-	       "everest,es7154"
-- VDD-supply : regulator phandle for the VDD supply
-- PVDD-supply: regulator phandle for the PVDD supply for the es7154
-
-Example:
-
-i2s_codec: external-codec {
-	compatible = "everest,es7134";
-	VDD-supply = <&vcc_5v>;
-};
diff --git a/Documentation/devicetree/bindings/sound/everest,es71x4.yaml b/Documentation/devicetree/bindings/sound/everest,es71x4.yaml
new file mode 100644
index 0000000..fd1b328
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/everest,es71x4.yaml
@@ -0,0 +1,62 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/everest,es71x4.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Everest ES7134/7144/7154 2 channels I2S analog to digital converter
+
+maintainers:
+  - Neil Armstrong <neil.armstrong@linaro.org>
+
+properties:
+  compatible:
+    enum:
+      - everest,es7134
+      - everest,es7144
+      - everest,es7154
+
+  VDD-supply: true
+  PVDD-supply: true
+
+  '#sound-dai-cells':
+    const: 0
+
+required:
+  - compatible
+  - VDD-supply
+
+allOf:
+  - $ref: dai-common.yaml#
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - everest,es7134
+              - everest,es7144
+    then:
+      properties:
+        PVDD-supply: false
+
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - everest,es7154
+    then:
+      required:
+        - PVDD-supply
+
+unevaluatedProperties: false
+
+examples:
+  - |
+   codec {
+       compatible = "everest,es7134";
+       #sound-dai-cells = <0>;
+       VDD-supply = <&vdd_supply>;
+   };
+
+...
diff --git a/Documentation/devicetree/bindings/sound/everest,es7241.txt b/Documentation/devicetree/bindings/sound/everest,es7241.txt
deleted file mode 100644
index 28f82cf..0000000
--- a/Documentation/devicetree/bindings/sound/everest,es7241.txt
+++ /dev/null
@@ -1,28 +0,0 @@
-ES7241 i2s AD converter
-
-Required properties:
-- compatible : "everest,es7241"
-- VDDP-supply: regulator phandle for the VDDA supply
-- VDDA-supply: regulator phandle for the VDDP supply
-- VDDD-supply: regulator phandle for the VDDD supply
-
-Optional properties:
-- reset-gpios: gpio connected to the reset pin
-- m0-gpios   : gpio connected to the m0 pin
-- m1-gpios   : gpio connected to the m1 pin
-- everest,sdout-pull-down:
-   Format used by the serial interface is controlled by pulling
-   the sdout. If the sdout is pulled down, leftj format is used.
-   If this property is not provided, sdout is assumed to pulled
-   up and i2s format is used
-
-Example:
-
-linein: audio-codec@2 {
-	#sound-dai-cells = <0>;
-	compatible = "everest,es7241";
-	VDDA-supply = <&vcc_3v3>;
-	VDDP-supply = <&vcc_3v3>;
-	VDDD-supply = <&vcc_3v3>;
-	reset-gpios = <&gpio GPIOH_42>;
-};
diff --git a/Documentation/devicetree/bindings/sound/everest,es7241.yaml b/Documentation/devicetree/bindings/sound/everest,es7241.yaml
new file mode 100644
index 0000000..f179af7
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/everest,es7241.yaml
@@ -0,0 +1,67 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/everest,es7241.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Everest ES7241 2 channels I2S analog to digital converter
+
+maintainers:
+  - Neil Armstrong <neil.armstrong@linaro.org>
+
+properties:
+  compatible:
+    enum:
+      - everest,es7241
+
+  reset-gpios:
+    maxItems: 1
+    description: GPIO connected to the reset pin
+
+  m0-gpios:
+    maxItems: 1
+    description: GPIO connected to the m0 pin
+
+  m1-gpios:
+    maxItems: 1
+    description: GPIO connected to the m0 pin
+
+  everest,sdout-pull-down:
+    type: boolean
+    description:
+      Format used by the serial interface is controlled by pulling
+      the sdout. If the sdout is pulled down, leftj format is used.
+      If this property is not provided, sdout is assumed to pulled
+      up and i2s format is used
+
+  VDDP-supply: true
+  VDDA-supply: true
+  VDDD-supply: true
+
+  '#sound-dai-cells':
+    const: 0
+
+required:
+  - compatible
+  - VDDP-supply
+  - VDDA-supply
+  - VDDD-supply
+
+allOf:
+  - $ref: dai-common.yaml#
+
+unevaluatedProperties: false
+
+examples:
+  - |
+   #include <dt-bindings/gpio/gpio.h>
+   codec {
+       compatible = "everest,es7241";
+       #sound-dai-cells = <0>;
+       reset-gpios = <&gpio1 15 GPIO_ACTIVE_HIGH>;
+       VDDP-supply = <&vddp_supply>;
+       VDDA-supply = <&vdda_supply>;
+       VDDD-supply = <&vddd_supply>;
+   };
+
+...
diff --git a/Documentation/devicetree/bindings/sound/sgtl5000.yaml b/Documentation/devicetree/bindings/sound/fsl,sgtl5000.yaml
similarity index 97%
rename from Documentation/devicetree/bindings/sound/sgtl5000.yaml
rename to Documentation/devicetree/bindings/sound/fsl,sgtl5000.yaml
index 1353c05..c6ab1ca 100644
--- a/Documentation/devicetree/bindings/sound/sgtl5000.yaml
+++ b/Documentation/devicetree/bindings/sound/fsl,sgtl5000.yaml
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0-only
 %YAML 1.2
 ---
-$id: http://devicetree.org/schemas/sound/sgtl5000.yaml#
+$id: http://devicetree.org/schemas/sound/fsl,sgtl5000.yaml#
 $schema: http://devicetree.org/meta-schemas/core.yaml#
 
 title: Freescale SGTL5000 Stereo Codec
diff --git a/Documentation/devicetree/bindings/sound/zl38060.yaml b/Documentation/devicetree/bindings/sound/mscc,zl38060.yaml
similarity index 96%
rename from Documentation/devicetree/bindings/sound/zl38060.yaml
rename to Documentation/devicetree/bindings/sound/mscc,zl38060.yaml
index 8bd201e..994313f 100644
--- a/Documentation/devicetree/bindings/sound/zl38060.yaml
+++ b/Documentation/devicetree/bindings/sound/mscc,zl38060.yaml
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
 %YAML 1.2
 ---
-$id: http://devicetree.org/schemas/sound/zl38060.yaml#
+$id: http://devicetree.org/schemas/sound/mscc,zl38060.yaml#
 $schema: http://devicetree.org/meta-schemas/core.yaml#
 
 title: ZL38060 Connected Home Audio Processor from Microsemi.
diff --git a/Documentation/devicetree/bindings/sound/pcm512x.txt b/Documentation/devicetree/bindings/sound/pcm512x.txt
index 77006a4..47878a6 100644
--- a/Documentation/devicetree/bindings/sound/pcm512x.txt
+++ b/Documentation/devicetree/bindings/sound/pcm512x.txt
@@ -6,7 +6,7 @@
 Required properties:
 
   - compatible : One of "ti,pcm5121", "ti,pcm5122", "ti,pcm5141",
-                 "ti,pcm5142", "ti,tas5754" or "ti,tas5756"
+                 "ti,pcm5142", "ti,pcm5242", "ti,tas5754" or "ti,tas5756"
 
   - reg : the I2C address of the device for I2C, the chip select
           number for SPI.
diff --git a/Documentation/devicetree/bindings/sound/rt1019.yaml b/Documentation/devicetree/bindings/sound/realtek,rt1019.yaml
similarity index 90%
rename from Documentation/devicetree/bindings/sound/rt1019.yaml
rename to Documentation/devicetree/bindings/sound/realtek,rt1019.yaml
index 3d5a91a..adf5e38 100644
--- a/Documentation/devicetree/bindings/sound/rt1019.yaml
+++ b/Documentation/devicetree/bindings/sound/realtek,rt1019.yaml
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
 %YAML 1.2
 ---
-$id: http://devicetree.org/schemas/sound/rt1019.yaml#
+$id: http://devicetree.org/schemas/sound/realtek,rt1019.yaml#
 $schema: http://devicetree.org/meta-schemas/core.yaml#
 
 title: RT1019 Mono Class-D Audio Amplifier
diff --git a/Documentation/devicetree/bindings/sound/tas2562.yaml b/Documentation/devicetree/bindings/sound/ti,tas2562.yaml
similarity index 96%
rename from Documentation/devicetree/bindings/sound/tas2562.yaml
rename to Documentation/devicetree/bindings/sound/ti,tas2562.yaml
index d28c102..8bc3b0c 100644
--- a/Documentation/devicetree/bindings/sound/tas2562.yaml
+++ b/Documentation/devicetree/bindings/sound/ti,tas2562.yaml
@@ -2,7 +2,7 @@
 # Copyright (C) 2019 Texas Instruments Incorporated
 %YAML 1.2
 ---
-$id: http://devicetree.org/schemas/sound/tas2562.yaml#
+$id: http://devicetree.org/schemas/sound/ti,tas2562.yaml#
 $schema: http://devicetree.org/meta-schemas/core.yaml#
 
 title: Texas Instruments TAS2562 Smart PA
diff --git a/Documentation/devicetree/bindings/sound/tas2770.yaml b/Documentation/devicetree/bindings/sound/ti,tas2770.yaml
similarity index 97%
rename from Documentation/devicetree/bindings/sound/tas2770.yaml
rename to Documentation/devicetree/bindings/sound/ti,tas2770.yaml
index be2536e..362c2e6 100644
--- a/Documentation/devicetree/bindings/sound/tas2770.yaml
+++ b/Documentation/devicetree/bindings/sound/ti,tas2770.yaml
@@ -2,7 +2,7 @@
 # Copyright (C) 2019-20 Texas Instruments Incorporated
 %YAML 1.2
 ---
-$id: http://devicetree.org/schemas/sound/tas2770.yaml#
+$id: http://devicetree.org/schemas/sound/ti,tas2770.yaml#
 $schema: http://devicetree.org/meta-schemas/core.yaml#
 
 title: Texas Instruments TAS2770 Smart PA
diff --git a/Documentation/devicetree/bindings/sound/tas27xx.yaml b/Documentation/devicetree/bindings/sound/ti,tas27xx.yaml
similarity index 96%
rename from Documentation/devicetree/bindings/sound/tas27xx.yaml
rename to Documentation/devicetree/bindings/sound/ti,tas27xx.yaml
index f2d878f..530bc39 100644
--- a/Documentation/devicetree/bindings/sound/tas27xx.yaml
+++ b/Documentation/devicetree/bindings/sound/ti,tas27xx.yaml
@@ -2,7 +2,7 @@
 # Copyright (C) 2020-2022 Texas Instruments Incorporated
 %YAML 1.2
 ---
-$id: http://devicetree.org/schemas/sound/tas27xx.yaml#
+$id: http://devicetree.org/schemas/sound/ti,tas27xx.yaml#
 $schema: http://devicetree.org/meta-schemas/core.yaml#
 
 title: Texas Instruments TAS2764/TAS2780 Smart PA
diff --git a/Documentation/devicetree/bindings/sound/tas5805m.yaml b/Documentation/devicetree/bindings/sound/ti,tas5805m.yaml
similarity index 95%
rename from Documentation/devicetree/bindings/sound/tas5805m.yaml
rename to Documentation/devicetree/bindings/sound/ti,tas5805m.yaml
index 12c4197..c2c2835 100644
--- a/Documentation/devicetree/bindings/sound/tas5805m.yaml
+++ b/Documentation/devicetree/bindings/sound/ti,tas5805m.yaml
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
 %YAML 1.2
 ---
-$id: http://devicetree.org/schemas/sound/tas5805m.yaml#
+$id: http://devicetree.org/schemas/sound/ti,tas5805m.yaml#
 $schema: http://devicetree.org/meta-schemas/core.yaml#
 
 title: TAS5805M audio amplifier
diff --git a/Documentation/devicetree/bindings/sound/ti,tlv320adc3xxx.yaml b/Documentation/devicetree/bindings/sound/ti,tlv320adc3xxx.yaml
index 8ac741f..66b7665 100644
--- a/Documentation/devicetree/bindings/sound/ti,tlv320adc3xxx.yaml
+++ b/Documentation/devicetree/bindings/sound/ti,tlv320adc3xxx.yaml
@@ -82,6 +82,26 @@
       Note that there is currently no support for reading the GPIO pins as
       inputs.
 
+  ti,micbias1-gpo:
+    type: boolean
+    description: |
+      When set, the MICBIAS1 pin may be controlled via the GPIO framework,
+      as pin number 3 on the device.
+
+      In this mode, when the pin is activated, it will be set to the voltage
+      specified by the ti,micbias1-vg property. When deactivated, the pin will
+      float.
+
+  ti,micbias2-gpo:
+    type: boolean
+    description: |
+      When set, the MICBIAS2 pin may be controlled via the GPIO framework,
+      as pin number 4 on the device.
+
+      In this mode, when the pin is activated, it will be set to the voltage
+      specified by the ti,micbias2-vg property. When deactivated, the pin will
+      float.
+
   ti,micbias1-vg:
     $ref: /schemas/types.yaml#/definitions/uint32
     enum:
@@ -104,6 +124,10 @@
     description: |
       Mic bias voltage output on MICBIAS2 pin
 
+dependencies:
+  ti,micbias1-gpo: ['ti,micbias1-vg']
+  ti,micbias2-gpo: ['ti,micbias2-vg']
+
 required:
   - compatible
   - reg
diff --git a/Documentation/devicetree/bindings/sound/tlv320adcx140.yaml b/Documentation/devicetree/bindings/sound/ti,tlv320adcx140.yaml
similarity index 99%
rename from Documentation/devicetree/bindings/sound/tlv320adcx140.yaml
rename to Documentation/devicetree/bindings/sound/ti,tlv320adcx140.yaml
index f3274bc..876fa97 100644
--- a/Documentation/devicetree/bindings/sound/tlv320adcx140.yaml
+++ b/Documentation/devicetree/bindings/sound/ti,tlv320adcx140.yaml
@@ -2,7 +2,7 @@
 # Copyright (C) 2019 Texas Instruments Incorporated
 %YAML 1.2
 ---
-$id: http://devicetree.org/schemas/sound/tlv320adcx140.yaml#
+$id: http://devicetree.org/schemas/sound/ti,tlv320adcx140.yaml#
 $schema: http://devicetree.org/meta-schemas/core.yaml#
 
 title: Texas Instruments TLV320ADCX140 Quad Channel Analog-to-Digital Converter
diff --git a/Documentation/devicetree/bindings/sound/wm8750.yaml b/Documentation/devicetree/bindings/sound/wlf,wm8750.yaml
similarity index 92%
rename from Documentation/devicetree/bindings/sound/wm8750.yaml
rename to Documentation/devicetree/bindings/sound/wlf,wm8750.yaml
index 24246ac..96859e3 100644
--- a/Documentation/devicetree/bindings/sound/wm8750.yaml
+++ b/Documentation/devicetree/bindings/sound/wlf,wm8750.yaml
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
 %YAML 1.2
 ---
-$id: http://devicetree.org/schemas/sound/wm8750.yaml#
+$id: http://devicetree.org/schemas/sound/wlf,wm8750.yaml#
 $schema: http://devicetree.org/meta-schemas/core.yaml#
 
 title: WM8750 and WM8987 audio CODECs
diff --git a/MAINTAINERS b/MAINTAINERS
index aacccb3..c35c039 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -18210,6 +18210,7 @@
 M:	Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
 M:	Banajit Goswami <bgoswami@quicinc.com>
 L:	alsa-devel@alsa-project.org (moderated for non-subscribers)
+L:	linux-arm-msm@vger.kernel.org
 S:	Supported
 F:	Documentation/devicetree/bindings/soc/qcom/qcom,apr*
 F:	Documentation/devicetree/bindings/sound/qcom,*
diff --git a/include/sound/dmaengine_pcm.h b/include/sound/dmaengine_pcm.h
index c11aaf8..f6baa9a 100644
--- a/include/sound/dmaengine_pcm.h
+++ b/include/sound/dmaengine_pcm.h
@@ -36,6 +36,7 @@ snd_pcm_uframes_t snd_dmaengine_pcm_pointer_no_residue(struct snd_pcm_substream
 int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream,
 	struct dma_chan *chan);
 int snd_dmaengine_pcm_close(struct snd_pcm_substream *substream);
+int snd_dmaengine_pcm_sync_stop(struct snd_pcm_substream *substream);
 
 int snd_dmaengine_pcm_open_request_chan(struct snd_pcm_substream *substream,
 	dma_filter_fn filter_fn, void *filter_data);
diff --git a/include/sound/rt1318.h b/include/sound/rt1318.h
new file mode 100644
index 0000000..fe6bff0
--- /dev/null
+++ b/include/sound/rt1318.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * linux/sound/rt1318.h -- Platform data for RT1318
+ *
+ * Copyright 2024 Realtek Semiconductor Corp.
+ */
+
+#ifndef __LINUX_SND_RT1318_H
+#define __LINUX_SND_RT1318_H
+
+struct rt1318_platform_data {
+	unsigned int init_r0_l;
+	unsigned int init_r0_r;
+};
+
+#endif
diff --git a/sound/core/pcm_dmaengine.c b/sound/core/pcm_dmaengine.c
index 12aa1ce..ed07fa5 100644
--- a/sound/core/pcm_dmaengine.c
+++ b/sound/core/pcm_dmaengine.c
@@ -349,6 +349,16 @@ int snd_dmaengine_pcm_open_request_chan(struct snd_pcm_substream *substream,
 }
 EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_open_request_chan);
 
+int snd_dmaengine_pcm_sync_stop(struct snd_pcm_substream *substream)
+{
+	struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
+
+	dmaengine_synchronize(prtd->dma_chan);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_sync_stop);
+
 /**
  * snd_dmaengine_pcm_close - Close a dmaengine based PCM substream
  * @substream: PCM substream
diff --git a/sound/soc/amd/acp/acp-i2s.c b/sound/soc/amd/acp/acp-i2s.c
index 0bc8617..97258b4 100644
--- a/sound/soc/amd/acp/acp-i2s.c
+++ b/sound/soc/amd/acp/acp-i2s.c
@@ -369,12 +369,12 @@ static int acp_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct
 		}
 		writel(period_bytes, adata->acp_base + water_val);
 		writel(buf_size, adata->acp_base + buf_reg);
+		if (rsrc->soc_mclk)
+			acp_set_i2s_clk(adata, dai->driver->id);
 		val = readl(adata->acp_base + reg_val);
 		val = val | BIT(0);
 		writel(val, adata->acp_base + reg_val);
 		writel(1, adata->acp_base + ier_val);
-		if (rsrc->soc_mclk)
-			acp_set_i2s_clk(adata, dai->driver->id);
 		return 0;
 	case SNDRV_PCM_TRIGGER_STOP:
 	case SNDRV_PCM_TRIGGER_SUSPEND:
@@ -584,29 +584,7 @@ static int acp_i2s_startup(struct snd_pcm_substream *substream, struct snd_soc_d
 	return 0;
 }
 
-static int acp_i2s_probe(struct snd_soc_dai *dai)
-{
-	struct device *dev = dai->component->dev;
-	struct acp_dev_data *adata = dev_get_drvdata(dev);
-	struct acp_resource *rsrc = adata->rsrc;
-	unsigned int val;
-
-	if (!adata->acp_base) {
-		dev_err(dev, "I2S base is NULL\n");
-		return -EINVAL;
-	}
-
-	val = readl(adata->acp_base + rsrc->i2s_pin_cfg_offset);
-	if (val != rsrc->i2s_mode) {
-		dev_err(dev, "I2S Mode not supported val %x\n", val);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
 const struct snd_soc_dai_ops asoc_acp_cpu_dai_ops = {
-	.probe		= acp_i2s_probe,
 	.startup	= acp_i2s_startup,
 	.hw_params	= acp_i2s_hwparams,
 	.prepare	= acp_i2s_prepare,
diff --git a/sound/soc/amd/acp/acp-pci.c b/sound/soc/amd/acp/acp-pci.c
index 565623a..b0304b8 100644
--- a/sound/soc/amd/acp/acp-pci.c
+++ b/sound/soc/amd/acp/acp-pci.c
@@ -100,6 +100,7 @@ static int acp_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id
 		ret = -EINVAL;
 		goto release_regions;
 	}
+	chip->flag = flag;
 	dmic_dev = platform_device_register_data(dev, "dmic-codec", PLATFORM_DEVID_NONE, NULL, 0);
 	if (IS_ERR(dmic_dev)) {
 		dev_err(dev, "failed to create DMIC device\n");
@@ -139,7 +140,6 @@ static int acp_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id
 		}
 	}
 
-	chip->flag = flag;
 	memset(&pdevinfo, 0, sizeof(pdevinfo));
 
 	pdevinfo.name = chip->name;
@@ -199,10 +199,12 @@ static int __maybe_unused snd_acp_resume(struct device *dev)
 	ret = acp_init(chip);
 	if (ret)
 		dev_err(dev, "ACP init failed\n");
-	child = chip->chip_pdev->dev;
-	adata = dev_get_drvdata(&child);
-	if (adata)
-		acp_enable_interrupts(adata);
+	if (chip->chip_pdev) {
+		child = chip->chip_pdev->dev;
+		adata = dev_get_drvdata(&child);
+		if (adata)
+			acp_enable_interrupts(adata);
+	}
 	return ret;
 }
 
diff --git a/sound/soc/amd/acp/acp-platform.c b/sound/soc/amd/acp/acp-platform.c
index aaac8aa..4f409cd 100644
--- a/sound/soc/amd/acp/acp-platform.c
+++ b/sound/soc/amd/acp/acp-platform.c
@@ -197,6 +197,20 @@ static int acp_dma_open(struct snd_soc_component *component, struct snd_pcm_subs
 	else
 		runtime->hw = acp_pcm_hardware_capture;
 
+	ret = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, DMA_SIZE);
+	if (ret) {
+		dev_err(component->dev, "set hw constraint HW_PARAM_PERIOD_BYTES failed\n");
+		kfree(stream);
+		return ret;
+	}
+
+	ret = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, DMA_SIZE);
+	if (ret) {
+		dev_err(component->dev, "set hw constraint HW_PARAM_BUFFER_BYTES failed\n");
+		kfree(stream);
+		return ret;
+	}
+
 	ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
 	if (ret < 0) {
 		dev_err(component->dev, "set integer constraint failed\n");
diff --git a/sound/soc/amd/acp/acp-rembrandt.c b/sound/soc/amd/acp/acp-rembrandt.c
index 158f819..e19981c 100644
--- a/sound/soc/amd/acp/acp-rembrandt.c
+++ b/sound/soc/amd/acp/acp-rembrandt.c
@@ -39,8 +39,6 @@ static struct acp_resource rsrc = {
 	.irqp_used = 1,
 	.soc_mclk = true,
 	.irq_reg_offset = 0x1a00,
-	.i2s_pin_cfg_offset = 0x1440,
-	.i2s_mode = 0x0a,
 	.scratch_reg_offset = 0x12800,
 	.sram_pte_offset = 0x03802800,
 };
@@ -231,12 +229,13 @@ static int rembrandt_audio_probe(struct platform_device *pdev)
 	adata->rsrc = &rsrc;
 	adata->platform = REMBRANDT;
 	adata->flag = chip->flag;
+	adata->is_i2s_config = chip->is_i2s_config;
 	adata->machines = snd_soc_acpi_amd_rmb_acp_machines;
 	acp_machine_select(adata);
 
 	dev_set_drvdata(dev, adata);
 
-	if (chip->flag != FLAG_AMD_LEGACY_ONLY_DMIC) {
+	if (chip->is_i2s_config && rsrc.soc_mclk) {
 		ret = acp6x_master_clock_generate(dev);
 		if (ret)
 			return ret;
@@ -269,7 +268,7 @@ static int __maybe_unused rmb_pcm_resume(struct device *dev)
 	snd_pcm_uframes_t buf_in_frames;
 	u64 buf_size;
 
-	if (adata->flag != FLAG_AMD_LEGACY_ONLY_DMIC)
+	if (adata->is_i2s_config && adata->rsrc->soc_mclk)
 		acp6x_master_clock_generate(dev);
 
 	spin_lock(&adata->acp_lock);
diff --git a/sound/soc/amd/acp/acp-renoir.c b/sound/soc/amd/acp/acp-renoir.c
index b0e181c..db835ed 100644
--- a/sound/soc/amd/acp/acp-renoir.c
+++ b/sound/soc/amd/acp/acp-renoir.c
@@ -32,8 +32,6 @@ static struct acp_resource rsrc = {
 	.no_of_ctrls = 1,
 	.irqp_used = 0,
 	.irq_reg_offset = 0x1800,
-	.i2s_pin_cfg_offset = 0x1400,
-	.i2s_mode = 0x04,
 	.scratch_reg_offset = 0x12800,
 	.sram_pte_offset = 0x02052800,
 };
diff --git a/sound/soc/amd/acp/acp63.c b/sound/soc/amd/acp/acp63.c
index 4d34244..f340920 100644
--- a/sound/soc/amd/acp/acp63.c
+++ b/sound/soc/amd/acp/acp63.c
@@ -55,8 +55,6 @@ static struct acp_resource rsrc = {
 	.irqp_used = 1,
 	.soc_mclk = true,
 	.irq_reg_offset = 0x1a00,
-	.i2s_pin_cfg_offset = 0x1440,
-	.i2s_mode = 0x0a,
 	.scratch_reg_offset = 0x12800,
 	.sram_pte_offset = 0x03802800,
 };
@@ -241,11 +239,12 @@ static int acp63_audio_probe(struct platform_device *pdev)
 	adata->rsrc = &rsrc;
 	adata->platform = ACP63;
 	adata->flag = chip->flag;
+	adata->is_i2s_config = chip->is_i2s_config;
 	adata->machines = snd_soc_acpi_amd_acp63_acp_machines;
 	acp_machine_select(adata);
 	dev_set_drvdata(dev, adata);
 
-	if (chip->flag != FLAG_AMD_LEGACY_ONLY_DMIC) {
+	if (chip->is_i2s_config && rsrc.soc_mclk) {
 		ret = acp63_i2s_master_clock_generate(adata);
 		if (ret)
 			return ret;
@@ -278,7 +277,7 @@ static int __maybe_unused acp63_pcm_resume(struct device *dev)
 	snd_pcm_uframes_t buf_in_frames;
 	u64 buf_size;
 
-	if (adata->flag != FLAG_AMD_LEGACY_ONLY_DMIC)
+	if (adata->is_i2s_config && adata->rsrc->soc_mclk)
 		acp63_i2s_master_clock_generate(adata);
 
 	spin_lock(&adata->acp_lock);
diff --git a/sound/soc/amd/acp/acp70.c b/sound/soc/amd/acp/acp70.c
index 0d7cdd4..a2cbdcc 100644
--- a/sound/soc/amd/acp/acp70.c
+++ b/sound/soc/amd/acp/acp70.c
@@ -31,8 +31,6 @@ static struct acp_resource rsrc = {
 	.irqp_used = 1,
 	.soc_mclk = true,
 	.irq_reg_offset = 0x1a00,
-	.i2s_pin_cfg_offset = 0x1440,
-	.i2s_mode = 0x0a,
 	.scratch_reg_offset = 0x12800,
 	.sram_pte_offset = 0x03802800,
 };
diff --git a/sound/soc/amd/acp/amd.h b/sound/soc/amd/acp/amd.h
index d75b4eb..87a4813 100644
--- a/sound/soc/amd/acp/amd.h
+++ b/sound/soc/amd/acp/amd.h
@@ -162,8 +162,6 @@ struct acp_resource {
 	int irqp_used;
 	bool soc_mclk;
 	u32 irq_reg_offset;
-	u32 i2s_pin_cfg_offset;
-	int i2s_mode;
 	u64 scratch_reg_offset;
 	u64 sram_pte_offset;
 };
@@ -175,6 +173,7 @@ struct acp_dev_data {
 	unsigned int i2s_irq;
 
 	bool tdm_mode;
+	bool is_i2s_config;
 	/* SOC specific dais */
 	struct snd_soc_dai_driver *dai_driver;
 	int num_dai;
diff --git a/sound/soc/atmel/atmel-classd.c b/sound/soc/atmel/atmel-classd.c
index 6aed1ee..ba314b2 100644
--- a/sound/soc/atmel/atmel-classd.c
+++ b/sound/soc/atmel/atmel-classd.c
@@ -473,19 +473,22 @@ static int atmel_classd_asoc_card_init(struct device *dev,
 	if (!dai_link)
 		return -ENOMEM;
 
-	comp = devm_kzalloc(dev, sizeof(*comp), GFP_KERNEL);
+	comp = devm_kzalloc(dev, 2 * sizeof(*comp), GFP_KERNEL);
 	if (!comp)
 		return -ENOMEM;
 
-	dai_link->cpus		= comp;
+	dai_link->cpus		= &comp[0];
 	dai_link->codecs	= &snd_soc_dummy_dlc;
+	dai_link->platforms	= &comp[1];
 
 	dai_link->num_cpus	= 1;
 	dai_link->num_codecs	= 1;
+	dai_link->num_platforms = 1;
 
 	dai_link->name			= "CLASSD";
 	dai_link->stream_name		= "CLASSD PCM";
 	dai_link->cpus->dai_name	= dev_name(dev);
+	dai_link->platforms->name	= dev_name(dev);
 
 	card->dai_link	= dai_link;
 	card->num_links	= 1;
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 910303a..2019da1 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -100,6 +100,7 @@
 	imply SND_SOC_CS47L90
 	imply SND_SOC_CS47L92
 	imply SND_SOC_CS53L30
+	imply SND_SOC_CS530X_I2C
 	imply SND_SOC_CX20442
 	imply SND_SOC_CX2072X
 	imply SND_SOC_DA7210
@@ -222,6 +223,7 @@
 	imply SND_SOC_RT722_SDCA_SDW
 	imply SND_SOC_RT1308_SDW
 	imply SND_SOC_RT1316_SDW
+	imply SND_SOC_RT1318
 	imply SND_SOC_RT1318_SDW
 	imply SND_SOC_RT1320_SDW
 	imply SND_SOC_RT9120
@@ -1004,6 +1006,19 @@
 	tristate "Cirrus Logic CS53L30 CODEC"
 	depends on I2C
 
+config SND_SOC_CS530X
+	tristate
+
+config SND_SOC_CS530X_I2C
+	tristate "Cirrus Logic CS530x ADCs (I2C)"
+	depends on I2C
+	select REGMAP
+	select REGMAP_I2C
+	select SND_SOC_CS530X
+	help
+	  Enable support for Cirrus Logic CS530X ADCs
+	  with I2C control.
+
 config SND_SOC_CX20442
 	tristate
 	depends on TTY
@@ -1581,6 +1596,10 @@
 	depends on SOUNDWIRE
 	select REGMAP_SOUNDWIRE
 
+config SND_SOC_RT1318
+	tristate
+	depends on I2C
+
 config SND_SOC_RT1318_SDW
 	tristate "Realtek RT1318 Codec - SDW"
 	depends on SOUNDWIRE
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 2db7760d..5868007 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -108,6 +108,8 @@
 snd-soc-cs47l90-y := cs47l90.o
 snd-soc-cs47l92-y := cs47l92.o
 snd-soc-cs53l30-y := cs53l30.o
+snd-soc-cs530x-y := cs530x.o
+snd-soc-cs530x-i2c-y := cs530x-i2c.o
 snd-soc-cx20442-y := cx20442.o
 snd-soc-cx2072x-y := cx2072x.o
 snd-soc-da7210-y := da7210.o
@@ -223,6 +225,7 @@
 snd-soc-rt1308-y := rt1308.o
 snd-soc-rt1308-sdw-y := rt1308-sdw.o
 snd-soc-rt1316-sdw-y := rt1316-sdw.o
+snd-soc-rt1318-y := rt1318.o
 snd-soc-rt1318-sdw-y := rt1318-sdw.o
 snd-soc-rt1320-sdw-y := rt1320-sdw.o
 snd-soc-rt274-y := rt274.o
@@ -510,6 +513,8 @@
 obj-$(CONFIG_SND_SOC_CS47L90)	+= snd-soc-cs47l90.o
 obj-$(CONFIG_SND_SOC_CS47L92)	+= snd-soc-cs47l92.o
 obj-$(CONFIG_SND_SOC_CS53L30)	+= snd-soc-cs53l30.o
+obj-$(CONFIG_SND_SOC_CS530X)	+= snd-soc-cs530x.o
+obj-$(CONFIG_SND_SOC_CS530X_I2C)	+= snd-soc-cs530x-i2c.o
 obj-$(CONFIG_SND_SOC_CX20442)	+= snd-soc-cx20442.o
 obj-$(CONFIG_SND_SOC_CX2072X)	+= snd-soc-cx2072x.o
 obj-$(CONFIG_SND_SOC_DA7210)	+= snd-soc-da7210.o
@@ -620,6 +625,7 @@
 obj-$(CONFIG_SND_SOC_RT1308)	+= snd-soc-rt1308.o
 obj-$(CONFIG_SND_SOC_RT1308_SDW)	+= snd-soc-rt1308-sdw.o
 obj-$(CONFIG_SND_SOC_RT1316_SDW)	+= snd-soc-rt1316-sdw.o
+obj-$(CONFIG_SND_SOC_RT1318)	+= snd-soc-rt1318.o
 obj-$(CONFIG_SND_SOC_RT1318_SDW)	+= snd-soc-rt1318-sdw.o
 obj-$(CONFIG_SND_SOC_RT1320_SDW)	+= snd-soc-rt1320-sdw.o
 obj-$(CONFIG_SND_SOC_RT274)	+= snd-soc-rt274.o
diff --git a/sound/soc/codecs/cs35l56-shared.c b/sound/soc/codecs/cs35l56-shared.c
index e89027c..880228f 100644
--- a/sound/soc/codecs/cs35l56-shared.c
+++ b/sound/soc/codecs/cs35l56-shared.c
@@ -215,6 +215,10 @@ static const struct reg_sequence cs35l56_asp1_defaults[] = {
 	REG_SEQ0(CS35L56_ASP1_FRAME_CONTROL5,	0x00020100),
 	REG_SEQ0(CS35L56_ASP1_DATA_CONTROL1,	0x00000018),
 	REG_SEQ0(CS35L56_ASP1_DATA_CONTROL5,	0x00000018),
+	REG_SEQ0(CS35L56_ASP1TX1_INPUT,		0x00000000),
+	REG_SEQ0(CS35L56_ASP1TX2_INPUT,		0x00000000),
+	REG_SEQ0(CS35L56_ASP1TX3_INPUT,		0x00000000),
+	REG_SEQ0(CS35L56_ASP1TX4_INPUT,		0x00000000),
 };
 
 /*
@@ -393,7 +397,7 @@ int cs35l56_irq_request(struct cs35l56_base *cs35l56_base, int irq)
 {
 	int ret;
 
-	if (!irq)
+	if (irq < 1)
 		return 0;
 
 	ret = devm_request_threaded_irq(cs35l56_base->dev, irq, NULL, cs35l56_irq,
diff --git a/sound/soc/codecs/cs42l43-jack.c b/sound/soc/codecs/cs42l43-jack.c
index 901b9db..d9ab003 100644
--- a/sound/soc/codecs/cs42l43-jack.c
+++ b/sound/soc/codecs/cs42l43-jack.c
@@ -121,7 +121,7 @@ int cs42l43_set_jack(struct snd_soc_component *component,
 		priv->buttons[3] = 735;
 	}
 
-	ret = cs42l43_find_index(priv, "cirrus,detect-us", 1000, &priv->detect_us,
+	ret = cs42l43_find_index(priv, "cirrus,detect-us", 50000, &priv->detect_us,
 				 cs42l43_accdet_us, ARRAY_SIZE(cs42l43_accdet_us));
 	if (ret < 0)
 		goto error;
@@ -433,7 +433,7 @@ irqreturn_t cs42l43_button_press(int irq, void *data)
 
 	// Wait for 2 full cycles of comb filter to ensure good reading
 	queue_delayed_work(system_wq, &priv->button_press_work,
-			   msecs_to_jiffies(10));
+			   msecs_to_jiffies(20));
 
 	return IRQ_HANDLED;
 }
diff --git a/sound/soc/codecs/cs530x-i2c.c b/sound/soc/codecs/cs530x-i2c.c
new file mode 100644
index 0000000..56659bf
--- /dev/null
+++ b/sound/soc/codecs/cs530x-i2c.c
@@ -0,0 +1,72 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// CS530x CODEC driver
+//
+// Copyright (C) 2024 Cirrus Logic, Inc. and
+//                    Cirrus Logic International Semiconductor Ltd.
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/regmap.h>
+
+#include "cs530x.h"
+
+static const struct of_device_id cs530x_of_match[] = {
+	{
+		.compatible = "cirrus,cs5302",
+		.data = (void *)CS5302,
+	}, {
+		.compatible = "cirrus,cs5304",
+		.data = (void *)CS5304,
+	}, {
+		.compatible = "cirrus,cs5308",
+		.data = (void *)CS5308,
+	},
+	{}
+};
+MODULE_DEVICE_TABLE(of, cs530x_of_match);
+
+static const struct i2c_device_id cs530x_i2c_id[] = {
+	{ "cs5302", CS5302 },
+	{ "cs5304", CS5304 },
+	{ "cs5308", CS5308 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, cs530x_i2c_id);
+
+static int cs530x_i2c_probe(struct i2c_client *client)
+{
+	struct cs530x_priv *cs530x;
+
+	cs530x = devm_kzalloc(&client->dev, sizeof(*cs530x), GFP_KERNEL);
+	if (!cs530x)
+		return -ENOMEM;
+
+	i2c_set_clientdata(client, cs530x);
+
+	cs530x->regmap = devm_regmap_init_i2c(client, &cs530x_regmap);
+	if (IS_ERR(cs530x->regmap))
+		return dev_err_probe(&client->dev, PTR_ERR(cs530x->regmap),
+			      "Failed to allocate register map\n");
+
+	cs530x->devtype = (uintptr_t)i2c_get_match_data(client);
+	cs530x->dev = &client->dev;
+
+	return cs530x_probe(cs530x);
+}
+
+static struct i2c_driver cs530x_i2c_driver = {
+	.driver = {
+		.name = "cs530x",
+		.of_match_table = cs530x_of_match,
+	},
+	.probe = cs530x_i2c_probe,
+	.id_table = cs530x_i2c_id,
+};
+module_i2c_driver(cs530x_i2c_driver);
+
+MODULE_DESCRIPTION("I2C CS530X driver");
+MODULE_IMPORT_NS(SND_SOC_CS530X);
+MODULE_AUTHOR("Paul Handrigan, Cirrus Logic Inc, <paulha@opensource.cirrus.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/cs530x.c b/sound/soc/codecs/cs530x.c
new file mode 100644
index 0000000..036d0f4
--- /dev/null
+++ b/sound/soc/codecs/cs530x.c
@@ -0,0 +1,966 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// CS530x CODEC driver
+//
+// Copyright (C) 2024 Cirrus Logic, Inc. and
+//                    Cirrus Logic International Semiconductor Ltd.
+
+#include <sound/core.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <sound/initval.h>
+#include <linux/module.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <linux/pm.h>
+#include <linux/property.h>
+#include <linux/slab.h>
+#include <sound/soc.h>
+#include <sound/tlv.h>
+
+#include "cs530x.h"
+
+#define CS530X_MAX_ADC_CH	8
+#define CS530X_MIN_ADC_CH	2
+
+static const char *cs530x_supply_names[CS530X_NUM_SUPPLIES] = {
+	"vdd-a",
+	"vdd-io",
+};
+
+static const struct reg_default cs530x_reg_defaults[] = {
+	{ CS530X_CLK_CFG_0, 0x30 },
+	{ CS530X_CLK_CFG_1, 0x0001 },
+	{ CS530X_CHIP_ENABLE, 0 },
+	{ CS530X_ASP_CFG, 0 },
+	{ CS530X_SIGNAL_PATH_CFG, 0 },
+	{ CS530X_IN_ENABLES, 0 },
+	{ CS530X_IN_RAMP_SUM, 0x0022 },
+	{ CS530X_IN_FILTER, 0 },
+	{ CS530X_IN_HIZ, 0 },
+	{ CS530X_IN_INV, 0 },
+	{ CS530X_IN_VOL_CTRL1_0, 0x8000 },
+	{ CS530X_IN_VOL_CTRL1_1, 0x8000 },
+	{ CS530X_IN_VOL_CTRL2_0, 0x8000 },
+	{ CS530X_IN_VOL_CTRL2_1, 0x8000 },
+	{ CS530X_IN_VOL_CTRL3_0, 0x8000 },
+	{ CS530X_IN_VOL_CTRL3_1, 0x8000 },
+	{ CS530X_IN_VOL_CTRL4_0, 0x8000 },
+	{ CS530X_IN_VOL_CTRL4_1, 0x8000 },
+	{ CS530X_PAD_FN, 0 },
+	{ CS530X_PAD_LVL, 0 },
+};
+
+static bool cs530x_read_and_write_regs(unsigned int reg)
+{
+	switch (reg) {
+	case CS530X_CLK_CFG_0:
+	case CS530X_CLK_CFG_1:
+	case CS530X_CHIP_ENABLE:
+	case CS530X_ASP_CFG:
+	case CS530X_SIGNAL_PATH_CFG:
+	case CS530X_IN_ENABLES:
+	case CS530X_IN_RAMP_SUM:
+	case CS530X_IN_FILTER:
+	case CS530X_IN_HIZ:
+	case CS530X_IN_INV:
+	case CS530X_IN_VOL_CTRL1_0:
+	case CS530X_IN_VOL_CTRL1_1:
+	case CS530X_IN_VOL_CTRL2_0:
+	case CS530X_IN_VOL_CTRL2_1:
+	case CS530X_IN_VOL_CTRL3_0:
+	case CS530X_IN_VOL_CTRL3_1:
+	case CS530X_IN_VOL_CTRL4_0:
+	case CS530X_IN_VOL_CTRL4_1:
+	case CS530X_PAD_FN:
+	case CS530X_PAD_LVL:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool cs530x_readable_register(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case CS530X_DEVID:
+	case CS530X_REVID:
+		return true;
+	default:
+		return cs530x_read_and_write_regs(reg);
+	}
+}
+
+static bool cs530x_writeable_register(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case CS530X_SW_RESET:
+	case CS530X_IN_VOL_CTRL5:
+		return true;
+	default:
+		return cs530x_read_and_write_regs(reg);
+	}
+}
+
+static int cs530x_put_volsw_vu(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
+	struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
+	struct cs530x_priv *cs530x = snd_soc_component_get_drvdata(component);
+	struct regmap *regmap = cs530x->regmap;
+	int ret;
+
+	snd_soc_dapm_mutex_lock(dapm);
+
+	ret = snd_soc_put_volsw(kcontrol, ucontrol);
+	if (ret)
+		goto volsw_err;
+
+	/* Write IN_VU bit for the volume change to take effect */
+	regmap_write(regmap, CS530X_IN_VOL_CTRL5, CS530X_IN_VU);
+
+volsw_err:
+	snd_soc_dapm_mutex_unlock(dapm);
+
+	return ret;
+}
+
+static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -1270, 50, 0);
+
+static const char * const cs530x_in_hpf_text[] = {
+	"Min Phase Slow Roll-off",
+	"Min Phase Fast Roll-off",
+	"Linear Phase Slow Roll-off",
+	"Linear Phase Fast Roll-off",
+};
+
+static SOC_ENUM_SINGLE_DECL(cs530x_in_hpf_enum, CS530X_IN_FILTER,
+			    CS530X_IN_FILTER_SHIFT,
+			    cs530x_in_hpf_text);
+
+static const char * const cs530x_in_4ch_sum_text[] = {
+	"None",
+	"Groups of 2",
+	"Groups of 4",
+};
+
+static SOC_ENUM_SINGLE_DECL(cs530x_in_sum_ch4_enum, CS530X_IN_RAMP_SUM,
+			    CS530X_IN_SUM_MODE_SHIFT,
+			    cs530x_in_4ch_sum_text);
+
+static const struct snd_kcontrol_new cs530x_in_sum_4ch_controls[] = {
+SOC_ENUM("IN Sum Select", cs530x_in_sum_ch4_enum),
+};
+
+static const char * const cs530x_in_8ch_sum_text[] = {
+	"None",
+	"Groups of 2",
+	"Groups of 4",
+	"Groups of 8",
+};
+
+static SOC_ENUM_SINGLE_DECL(cs530x_in_sum_ch8_enum, CS530X_IN_RAMP_SUM,
+			    CS530X_IN_SUM_MODE_SHIFT,
+			    cs530x_in_8ch_sum_text);
+
+static const struct snd_kcontrol_new cs530x_in_sum_8ch_controls[] = {
+SOC_ENUM("IN Sum Select", cs530x_in_sum_ch8_enum),
+};
+
+
+static const char * const cs530x_vol_ramp_text[] = {
+	"0ms/6dB", "0.5ms/6dB", "1ms/6dB", "2ms/6dB", "4ms/6dB", "8ms/6dB",
+	"15ms/6dB", "30ms/6dB",
+};
+
+static SOC_ENUM_SINGLE_DECL(cs530x_ramp_inc_enum, CS530X_IN_RAMP_SUM,
+			    CS530X_RAMP_RATE_INC_SHIFT,
+			    cs530x_vol_ramp_text);
+
+static SOC_ENUM_SINGLE_DECL(cs530x_ramp_dec_enum, CS530X_IN_RAMP_SUM,
+			    CS530X_RAMP_RATE_DEC_SHIFT,
+			    cs530x_vol_ramp_text);
+
+static const struct snd_kcontrol_new cs530x_in_1_to_2_controls[] = {
+SOC_SINGLE_EXT_TLV("IN1 Volume", CS530X_IN_VOL_CTRL1_0, 0, 255, 1,
+		    snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv),
+SOC_SINGLE_EXT_TLV("IN2 Volume", CS530X_IN_VOL_CTRL1_1, 0, 255, 1,
+		    snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv),
+
+SOC_ENUM("IN HPF Select", cs530x_in_hpf_enum),
+SOC_ENUM("Input Ramp Up", cs530x_ramp_inc_enum),
+SOC_ENUM("Input Ramp Down", cs530x_ramp_dec_enum),
+
+SOC_SINGLE("ADC1 Invert Switch", CS530X_IN_INV, CS530X_IN1_INV_SHIFT, 1, 0),
+SOC_SINGLE("ADC2 Invert Switch", CS530X_IN_INV, CS530X_IN2_INV_SHIFT, 1, 0),
+};
+
+static const struct snd_kcontrol_new cs530x_in_3_to_4_controls[] = {
+SOC_SINGLE_EXT_TLV("IN3 Volume", CS530X_IN_VOL_CTRL2_0, 0, 255, 1,
+		    snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv),
+SOC_SINGLE_EXT_TLV("IN4 Volume", CS530X_IN_VOL_CTRL2_1, 0, 255, 1,
+		    snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv),
+
+SOC_SINGLE("ADC3 Invert Switch", CS530X_IN_INV, CS530X_IN3_INV_SHIFT, 1, 0),
+SOC_SINGLE("ADC4 Invert Switch", CS530X_IN_INV, CS530X_IN4_INV_SHIFT, 1, 0),
+};
+
+static const struct snd_kcontrol_new cs530x_in_5_to_8_controls[] = {
+SOC_SINGLE_EXT_TLV("IN5 Volume", CS530X_IN_VOL_CTRL3_0, 0, 255, 1,
+		    snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv),
+SOC_SINGLE_EXT_TLV("IN6 Volume", CS530X_IN_VOL_CTRL3_1, 0, 255, 1,
+		    snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv),
+SOC_SINGLE_EXT_TLV("IN7 Volume", CS530X_IN_VOL_CTRL4_0, 0, 255, 1,
+		    snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv),
+SOC_SINGLE_EXT_TLV("IN8 Volume", CS530X_IN_VOL_CTRL4_1, 0, 255, 1,
+		    snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv),
+
+SOC_SINGLE("ADC5 Invert Switch", CS530X_IN_INV, CS530X_IN5_INV_SHIFT, 1, 0),
+SOC_SINGLE("ADC6 Invert Switch", CS530X_IN_INV, CS530X_IN6_INV_SHIFT, 1, 0),
+SOC_SINGLE("ADC7 Invert Switch", CS530X_IN_INV, CS530X_IN7_INV_SHIFT, 1, 0),
+SOC_SINGLE("ADC8 Invert Switch", CS530X_IN_INV, CS530X_IN8_INV_SHIFT, 1, 0),
+};
+
+static int cs530x_adc_event(struct snd_soc_dapm_widget *w,
+			     struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
+	struct cs530x_priv *cs530x = snd_soc_component_get_drvdata(component);
+	struct regmap *regmap = cs530x->regmap;
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		cs530x->adc_pairs_count++;
+		break;
+	case SND_SOC_DAPM_POST_PMU:
+		regmap_clear_bits(regmap, CS530X_IN_VOL_CTRL1_0 +
+				 (w->shift * 2), CS530X_IN_MUTE);
+		regmap_clear_bits(regmap, CS530X_IN_VOL_CTRL1_0 +
+				 ((w->shift+1) * 2), CS530X_IN_MUTE);
+
+		cs530x->adc_pairs_count--;
+		if (!cs530x->adc_pairs_count) {
+			usleep_range(1000, 1100);
+			return regmap_write(regmap, CS530X_IN_VOL_CTRL5,
+					    CS530X_IN_VU);
+		}
+		break;
+	case SND_SOC_DAPM_PRE_PMD:
+		regmap_set_bits(regmap, CS530X_IN_VOL_CTRL1_0 +
+			       (w->shift * 2), CS530X_IN_MUTE);
+		regmap_set_bits(regmap, CS530X_IN_VOL_CTRL1_0 +
+			       ((w->shift+1) * 2), CS530X_IN_MUTE);
+		return regmap_write(regmap, CS530X_IN_VOL_CTRL5,
+				    CS530X_IN_VU);
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static const struct snd_kcontrol_new adc12_ctrl =
+	SOC_DAPM_SINGLE_VIRT("Switch", 1);
+
+static const struct snd_kcontrol_new adc34_ctrl =
+	SOC_DAPM_SINGLE_VIRT("Switch", 1);
+
+static const struct snd_kcontrol_new adc56_ctrl =
+	SOC_DAPM_SINGLE_VIRT("Switch", 1);
+
+static const struct snd_kcontrol_new adc78_ctrl =
+	SOC_DAPM_SINGLE_VIRT("Switch", 1);
+
+static const struct snd_kcontrol_new in_hpf_ctrl =
+	SOC_DAPM_SINGLE_VIRT("Switch", 1);
+
+/* General DAPM widgets for all devices */
+static const struct snd_soc_dapm_widget cs530x_gen_dapm_widgets[] = {
+SND_SOC_DAPM_SUPPLY("Global Enable", CS530X_CHIP_ENABLE, 0, 0, NULL, 0),
+};
+
+/* ADC's Channels 1 and 2 plus generic ADC DAPM events */
+static const struct snd_soc_dapm_widget cs530x_adc_ch12_dapm_widgets[] = {
+SND_SOC_DAPM_INPUT("IN1"),
+SND_SOC_DAPM_INPUT("IN2"),
+SND_SOC_DAPM_ADC_E("ADC1", NULL, CS530X_IN_ENABLES, 0, 0,
+		   cs530x_adc_event,
+		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU |
+		   SND_SOC_DAPM_PRE_PMU),
+SND_SOC_DAPM_ADC("ADC2", NULL, CS530X_IN_ENABLES, 1, 0),
+SND_SOC_DAPM_SWITCH("ADC12 Enable", SND_SOC_NOPM, 0, 0, &adc12_ctrl),
+SND_SOC_DAPM_SWITCH("IN HPF", CS530X_IN_FILTER, CS530X_IN_HPF_EN_SHIFT,
+		    0, &in_hpf_ctrl),
+};
+
+/* ADC's Channels 3 and 4 */
+static const struct snd_soc_dapm_widget cs530x_adc_ch34_dapm_widgets[] = {
+SND_SOC_DAPM_INPUT("IN3"),
+SND_SOC_DAPM_INPUT("IN4"),
+SND_SOC_DAPM_ADC_E("ADC3", NULL, CS530X_IN_ENABLES, 2, 0,
+		   cs530x_adc_event,
+		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU |
+		   SND_SOC_DAPM_PRE_PMU),
+SND_SOC_DAPM_ADC("ADC4", NULL, CS530X_IN_ENABLES, 3, 0),
+SND_SOC_DAPM_SWITCH("ADC34 Enable", SND_SOC_NOPM, 0, 0, &adc34_ctrl),
+};
+
+/* ADC's Channels 5 to 8 */
+static const struct snd_soc_dapm_widget cs530x_adc_ch58_dapm_widgets[] = {
+SND_SOC_DAPM_INPUT("IN5"),
+SND_SOC_DAPM_INPUT("IN6"),
+SND_SOC_DAPM_INPUT("IN7"),
+SND_SOC_DAPM_INPUT("IN8"),
+SND_SOC_DAPM_ADC_E("ADC5", NULL, CS530X_IN_ENABLES, 4, 0,
+		   cs530x_adc_event,
+		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU |
+		   SND_SOC_DAPM_PRE_PMU),
+SND_SOC_DAPM_ADC("ADC6", NULL, CS530X_IN_ENABLES, 5, 0),
+SND_SOC_DAPM_SWITCH("ADC56 Enable", SND_SOC_NOPM, 0, 0, &adc56_ctrl),
+SND_SOC_DAPM_ADC_E("ADC7", NULL, CS530X_IN_ENABLES, 6, 0,
+		   cs530x_adc_event,
+		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU |
+		   SND_SOC_DAPM_PRE_PMU),
+SND_SOC_DAPM_ADC("ADC8", NULL, CS530X_IN_ENABLES, 7, 0),
+SND_SOC_DAPM_SWITCH("ADC78 Enable", SND_SOC_NOPM, 0, 0, &adc78_ctrl),
+};
+
+static const struct snd_soc_dapm_route adc_ch1_2_routes[] = {
+	{ "ADC1", NULL, "Global Enable" },
+	{ "ADC2", NULL, "Global Enable" },
+
+	{ "ADC12 Enable", "Switch", "IN1" },
+	{ "ADC12 Enable", "Switch", "IN2" },
+	{ "ADC1", NULL, "ADC12 Enable" },
+	{ "ADC2", NULL, "ADC12 Enable" },
+	{ "IN HPF", "Switch", "ADC1" },
+	{ "IN HPF", "Switch", "ADC2" },
+
+	{ "AIF Capture", NULL, "IN HPF" },
+	{ "AIF Capture", NULL, "ADC1" },
+	{ "AIF Capture", NULL, "ADC2" },
+};
+
+static const struct snd_soc_dapm_route adc_ch3_4_routes[] = {
+	{ "ADC3", NULL, "Global Enable" },
+	{ "ADC4", NULL, "Global Enable" },
+
+	{ "ADC34 Enable", "Switch", "IN3" },
+	{ "ADC34 Enable", "Switch", "IN4" },
+	{ "ADC3", NULL, "ADC34 Enable" },
+	{ "ADC4", NULL, "ADC34 Enable" },
+	{ "IN HPF", "Switch", "ADC3" },
+	{ "IN HPF", "Switch", "ADC4" },
+
+	{ "AIF Capture", NULL, "ADC3" },
+	{ "AIF Capture", NULL, "ADC4" },
+};
+
+static const struct snd_soc_dapm_route adc_ch5_8_routes[] = {
+	{ "ADC5", NULL, "Global Enable" },
+	{ "ADC6", NULL, "Global Enable" },
+	{ "ADC7", NULL, "Global Enable" },
+	{ "ADC8", NULL, "Global Enable" },
+
+	{ "ADC56 Enable", "Switch", "IN5" },
+	{ "ADC56 Enable", "Switch", "IN6" },
+	{ "ADC5", NULL, "ADC56 Enable" },
+	{ "ADC6", NULL, "ADC56 Enable" },
+	{ "IN HPF", "Switch", "ADC5" },
+	{ "IN HPF", "Switch", "ADC6" },
+
+	{ "AIF Capture", NULL, "ADC5" },
+	{ "AIF Capture", NULL, "ADC6" },
+
+	{ "ADC78 Enable", "Switch", "IN7" },
+	{ "ADC78 Enable", "Switch", "IN8" },
+	{ "ADC7", NULL, "ADC78 Enable" },
+	{ "ADC8", NULL, "ADC78 Enable" },
+	{ "IN HPF", "Switch", "ADC7" },
+	{ "IN HPF", "Switch", "ADC8" },
+
+	{ "AIF Capture", NULL, "ADC7" },
+	{ "AIF Capture", NULL, "ADC8" },
+};
+
+static void cs530x_add_12_adc_widgets(struct snd_soc_component *component)
+{
+	struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
+
+	snd_soc_add_component_controls(component,
+				       cs530x_in_1_to_2_controls,
+				       ARRAY_SIZE(cs530x_in_1_to_2_controls));
+
+	snd_soc_dapm_new_controls(dapm, cs530x_adc_ch12_dapm_widgets,
+				  ARRAY_SIZE(cs530x_adc_ch12_dapm_widgets));
+
+	snd_soc_dapm_add_routes(dapm, adc_ch1_2_routes,
+				ARRAY_SIZE(adc_ch1_2_routes));
+}
+
+static void cs530x_add_34_adc_widgets(struct snd_soc_component *component)
+{
+	struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
+
+	snd_soc_add_component_controls(component,
+				       cs530x_in_3_to_4_controls,
+				       ARRAY_SIZE(cs530x_in_3_to_4_controls));
+
+	snd_soc_dapm_new_controls(dapm, cs530x_adc_ch34_dapm_widgets,
+				  ARRAY_SIZE(cs530x_adc_ch34_dapm_widgets));
+
+	snd_soc_dapm_add_routes(dapm, adc_ch3_4_routes,
+				ARRAY_SIZE(adc_ch3_4_routes));
+}
+
+static int cs530x_set_bclk(struct snd_soc_component *component)
+{
+	struct cs530x_priv *cs530x = snd_soc_component_get_drvdata(component);
+	struct regmap *regmap = cs530x->regmap;
+	unsigned int bclk_val;
+
+	switch (cs530x->bclk) {
+	case 2822400:
+	case 3072000:
+		bclk_val = CS530X_BCLK_2P822_3P072;
+		break;
+	case 5644800:
+	case 6144000:
+		bclk_val = CS530X_BCLK_5P6448_6P144;
+		break;
+	case 11289600:
+	case 12288000:
+		bclk_val = CS530X_BCLK_11P2896_12P288;
+		break;
+	case 22579200:
+	case 24576000:
+		bclk_val = CS530X_BCLK_24P5792_24P576;
+		break;
+	default:
+		dev_err(component->dev, "Invalid BCLK %d\n", cs530x->bclk);
+		return -EINVAL;
+	}
+
+	dev_dbg(component->dev, "BCLK is %d\n", cs530x->bclk);
+
+	return regmap_update_bits(regmap, CS530X_ASP_CFG,
+				  CS530X_ASP_BCLK_FREQ_MASK, bclk_val);
+}
+
+static int cs530x_set_pll_refclk(struct snd_soc_component *component,
+				  const unsigned int freq)
+{
+	struct cs530x_priv *priv = snd_soc_component_get_drvdata(component);
+	struct regmap *regmap = priv->regmap;
+	unsigned int refclk;
+
+	switch (freq) {
+	case 2822400:
+	case 3072000:
+		refclk = CS530X_REFCLK_2P822_3P072;
+		break;
+	case 5644800:
+	case 6144000:
+		refclk = CS530X_REFCLK_5P6448_6P144;
+		break;
+	case 11289600:
+	case 12288000:
+		refclk = CS530X_REFCLK_11P2896_12P288;
+		break;
+	case 22579200:
+	case 24576000:
+		refclk = CS530X_REFCLK_24P5792_24P576;
+		break;
+	default:
+		dev_err(component->dev, "Invalid PLL refclk %d\n", freq);
+		return -EINVAL;
+	}
+
+	return regmap_update_bits(regmap, CS530X_CLK_CFG_0,
+				  CS530X_PLL_REFCLK_FREQ_MASK, refclk);
+}
+
+static int cs530x_hw_params(struct snd_pcm_substream *substream,
+			    struct snd_pcm_hw_params *params,
+			    struct snd_soc_dai *dai)
+{
+	struct snd_soc_component *component = dai->component;
+	struct cs530x_priv *cs530x = snd_soc_component_get_drvdata(component);
+	struct regmap *regmap = cs530x->regmap;
+	int ret = 0, fs = params_rate(params);
+	unsigned int fs_val;
+
+
+	switch (fs) {
+	case 32000:
+		fs_val = CS530X_FS_32K;
+		break;
+	case 44100:
+	case 48000:
+		fs_val = CS530X_FS_48K_44P1K;
+		break;
+	case 88200:
+	case 96000:
+		fs_val = CS530X_FS_96K_88P2K;
+		break;
+	case 176400:
+	case 192000:
+		fs_val = CS530X_FS_192K_176P4K;
+		break;
+	case 356800:
+	case 384000:
+		fs_val = CS530X_FS_384K_356P8K;
+		break;
+	case 705600:
+	case 768000:
+		fs_val = CS530X_FS_768K_705P6K;
+		break;
+	default:
+		dev_err(component->dev, "Invalid sample rate %d\n", fs);
+		return -EINVAL;
+	}
+
+	cs530x->fs = fs;
+	regmap_update_bits(regmap, CS530X_CLK_CFG_1,
+			   CS530X_SAMPLE_RATE_MASK, fs_val);
+
+	if (cs530x->tdm_slots) {
+		dev_dbg(component->dev, "Configuring for %d %d bit TDM slots\n",
+			cs530x->tdm_slots, cs530x->tdm_width);
+		cs530x->bclk = snd_soc_calc_bclk(cs530x->fs,
+						 cs530x->tdm_width,
+						 params_channels(params),
+						 cs530x->tdm_slots);
+	} else {
+		cs530x->bclk = snd_soc_params_to_bclk(params);
+	}
+
+	if (!regmap_test_bits(regmap, CS530X_CLK_CFG_0,
+			     CS530X_PLL_REFCLK_SRC_MASK)) {
+		ret = cs530x_set_pll_refclk(component, cs530x->bclk);
+		if (ret)
+			return ret;
+	}
+
+	return cs530x_set_bclk(component);
+}
+
+static int cs530x_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+	struct snd_soc_component *component = dai->component;
+	struct cs530x_priv *priv = snd_soc_component_get_drvdata(component);
+	struct regmap *regmap = priv->regmap;
+	unsigned int asp_fmt, asp_cfg = 0;
+
+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+	case SND_SOC_DAIFMT_CBS_CFS:
+		break;
+	case SND_SOC_DAIFMT_CBM_CFM:
+		asp_cfg = CS530X_ASP_PRIMARY;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_DSP_A:
+		asp_fmt = CS530X_ASP_FMT_DSP_A;
+		break;
+	case SND_SOC_DAIFMT_I2S:
+		asp_fmt = CS530X_ASP_FMT_I2S;
+		break;
+	case SND_SOC_DAIFMT_LEFT_J:
+		asp_fmt = CS530X_ASP_FMT_LJ;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+	case SND_SOC_DAIFMT_NB_NF:
+		break;
+	case SND_SOC_DAIFMT_IB_IF:
+		asp_cfg |= CS530X_ASP_BCLK_INV;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	regmap_update_bits(regmap, CS530X_ASP_CFG,
+			   CS530X_ASP_PRIMARY | CS530X_ASP_BCLK_INV,
+			   asp_cfg);
+
+	return regmap_update_bits(regmap, CS530X_SIGNAL_PATH_CFG,
+				  CS530X_ASP_FMT_MASK, asp_fmt);
+}
+
+static bool cs530x_check_mclk_freq(struct snd_soc_component *component,
+				   const unsigned int freq)
+{
+	switch (freq) {
+	case 24576000:
+	case 22579200:
+	case 12288000:
+	case 11289600:
+		return true;
+	default:
+		dev_err(component->dev, "Invalid MCLK %d\n", freq);
+		return false;
+	}
+}
+
+static int cs530x_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
+				 unsigned int rx_mask, int slots, int slot_width)
+{
+	struct snd_soc_component *component = dai->component;
+	struct cs530x_priv *cs530x = snd_soc_component_get_drvdata(component);
+	struct regmap *regmap = cs530x->regmap;
+	unsigned int val;
+
+	switch (tx_mask) {
+	case CS530X_0_1_TDM_SLOT_MASK:
+	case CS530X_0_3_TDM_SLOT_MASK:
+	case CS530X_0_7_TDM_SLOT_MASK:
+		val = CS530X_0_7_TDM_SLOT_VAL;
+		break;
+	case CS530X_2_3_TDM_SLOT_MASK:
+		val = CS530X_2_3_TDM_SLOT_VAL;
+		break;
+	case CS530X_4_5_TDM_SLOT_MASK:
+	case CS530X_4_7_TDM_SLOT_MASK:
+		val = CS530X_4_7_TDM_SLOT_VAL;
+		break;
+	case CS530X_6_7_TDM_SLOT_MASK:
+		val = CS530X_6_7_TDM_SLOT_VAL;
+		break;
+	case CS530X_8_9_TDM_SLOT_MASK:
+	case CS530X_8_11_TDM_SLOT_MASK:
+	case CS530X_8_15_TDM_SLOT_MASK:
+		val = CS530X_8_15_TDM_SLOT_VAL;
+		break;
+	case CS530X_10_11_TDM_SLOT_MASK:
+		val = CS530X_10_11_TDM_SLOT_VAL;
+		break;
+	case CS530X_12_13_TDM_SLOT_MASK:
+	case CS530X_12_15_TDM_SLOT_MASK:
+		val = CS530X_12_15_TDM_SLOT_VAL;
+		break;
+	case CS530X_14_15_TDM_SLOT_MASK:
+		val = CS530X_14_15_TDM_SLOT_VAL;
+		break;
+	default:
+		dev_err(component->dev, "Invalid TX slot(s) 0x%x\n", tx_mask);
+		return -EINVAL;
+	}
+
+	return regmap_update_bits(regmap, CS530X_SIGNAL_PATH_CFG,
+				  CS530X_ASP_TDM_SLOT_MASK,
+				  val << CS530X_ASP_TDM_SLOT_SHIFT);
+}
+
+static const struct snd_soc_dai_ops cs530x_dai_ops = {
+	.set_fmt = cs530x_set_fmt,
+	.hw_params = cs530x_hw_params,
+	.set_tdm_slot = cs530x_set_tdm_slot,
+};
+
+static const struct snd_soc_dai_driver cs530x_dai = {
+	.name = "cs530x-dai",
+	.capture = {
+		.stream_name = "AIF Capture",
+		.channels_min = 2,
+		.channels_max = 8,
+		.rates = SNDRV_PCM_RATE_KNOT,
+		.formats = SNDRV_PCM_FMTBIT_S32_LE,
+	},
+	.ops = &cs530x_dai_ops,
+	.symmetric_rate = 1,
+	.symmetric_sample_bits = 1,
+};
+
+static int cs530x_set_pll(struct snd_soc_component *component, int pll_id,
+			   int source, unsigned int freq_in,
+			   unsigned int freq_out)
+{
+	struct cs530x_priv *cs530x = snd_soc_component_get_drvdata(component);
+	struct regmap *regmap = cs530x->regmap;
+	unsigned int sysclk_src;
+	int ret;
+
+	regmap_read(regmap, CS530X_CLK_CFG_0, &sysclk_src);
+
+	/* Check if the source is the PLL  */
+	if ((sysclk_src & CS530X_SYSCLK_SRC_MASK) == 0)
+		return 0;
+
+	switch (source) {
+	case CS530X_PLL_SRC_MCLK:
+		if (!cs530x_check_mclk_freq(component, freq_in))
+			return -EINVAL;
+
+		ret = cs530x_set_pll_refclk(component, freq_in);
+		if (ret)
+			return ret;
+
+		break;
+	case CS530X_PLL_SRC_BCLK:
+		break;
+	default:
+		dev_err(component->dev, "Invalid PLL source %d\n", source);
+		return -EINVAL;
+	}
+
+	return regmap_update_bits(regmap, CS530X_CLK_CFG_0,
+				  CS530X_PLL_REFCLK_SRC_MASK, source);
+}
+
+static int cs530x_component_probe(struct snd_soc_component *component)
+{
+	struct cs530x_priv *cs530x = snd_soc_component_get_drvdata(component);
+	struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
+	int num_widgets;
+
+	snd_soc_dapm_new_controls(dapm, cs530x_gen_dapm_widgets,
+				  ARRAY_SIZE(cs530x_gen_dapm_widgets));
+
+	switch (cs530x->devtype) {
+	case CS5302:
+		cs530x_add_12_adc_widgets(component);
+		break;
+	case CS5304:
+		cs530x_add_12_adc_widgets(component);
+		cs530x_add_34_adc_widgets(component);
+
+		num_widgets = ARRAY_SIZE(cs530x_in_sum_4ch_controls);
+		snd_soc_add_component_controls(component,
+					       cs530x_in_sum_4ch_controls,
+					       num_widgets);
+		break;
+
+	case CS5308:
+		cs530x_add_12_adc_widgets(component);
+		cs530x_add_34_adc_widgets(component);
+
+		num_widgets = ARRAY_SIZE(cs530x_in_5_to_8_controls);
+		snd_soc_add_component_controls(component,
+					       cs530x_in_5_to_8_controls,
+					       num_widgets);
+
+		num_widgets = ARRAY_SIZE(cs530x_in_sum_8ch_controls);
+		snd_soc_add_component_controls(component,
+					       cs530x_in_sum_8ch_controls,
+					       num_widgets);
+
+		num_widgets = ARRAY_SIZE(cs530x_adc_ch58_dapm_widgets);
+		snd_soc_dapm_new_controls(dapm, cs530x_adc_ch58_dapm_widgets,
+					  num_widgets);
+
+		snd_soc_dapm_add_routes(dapm, adc_ch5_8_routes,
+					ARRAY_SIZE(adc_ch5_8_routes));
+		break;
+	default:
+		dev_err(component->dev, "Invalid device type %d\n",
+			cs530x->devtype);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int cs530x_set_sysclk(struct snd_soc_component *component, int clk_id,
+				int source, unsigned int freq, int dir)
+{
+	struct cs530x_priv *cs530x = snd_soc_component_get_drvdata(component);
+	struct regmap *regmap = cs530x->regmap;
+
+	switch (source) {
+	case CS530X_SYSCLK_SRC_MCLK:
+		if (freq != 24560000 && freq != 22572000) {
+			dev_err(component->dev, "Invalid MCLK source rate %d\n",
+				freq);
+			return -EINVAL;
+		}
+
+		cs530x->mclk_rate = freq;
+		break;
+	case CS530X_SYSCLK_SRC_PLL:
+		break;
+	default:
+		dev_err(component->dev, "Invalid clock id %d\n", clk_id);
+		return -EINVAL;
+	}
+
+	return regmap_update_bits(regmap, CS530X_CLK_CFG_0,
+				  CS530X_SYSCLK_SRC_MASK,
+				  source << CS530X_SYSCLK_SRC_SHIFT);
+}
+
+static const struct snd_soc_component_driver soc_component_dev_cs530x = {
+	.probe			= cs530x_component_probe,
+	.set_sysclk		= cs530x_set_sysclk,
+	.set_pll		= cs530x_set_pll,
+	.endianness		= 1,
+};
+
+const struct regmap_config cs530x_regmap = {
+	.reg_bits = 16,
+	.val_bits = 16,
+
+	.max_register = CS530X_MAX_REGISTER,
+	.readable_reg = cs530x_readable_register,
+	.writeable_reg = cs530x_writeable_register,
+
+	.cache_type = REGCACHE_MAPLE,
+	.reg_defaults = cs530x_reg_defaults,
+	.num_reg_defaults = ARRAY_SIZE(cs530x_reg_defaults),
+};
+EXPORT_SYMBOL_NS_GPL(cs530x_regmap, SND_SOC_CS530X);
+
+static int cs530x_check_device_id(struct cs530x_priv *cs530x)
+{
+	struct device *dev = cs530x->dev;
+	unsigned int dev_id, rev;
+	int ret;
+
+	ret = regmap_read(cs530x->regmap, CS530X_DEVID, &dev_id);
+	if (ret)
+		return dev_err_probe(dev, ret, "Can't read device ID\n");
+
+	ret = regmap_read(cs530x->regmap, CS530X_REVID, &rev);
+	if (ret)
+		return dev_err_probe(dev, ret, "Can't read REV ID\n");
+
+	dev_dbg(dev, "Device ID 0x%x Rev ID 0x%x\n", dev_id, rev);
+
+	switch (dev_id) {
+	case CS530X_2CH_ADC_DEV_ID:
+		cs530x->num_adcs = 2;
+		break;
+	case CS530X_4CH_ADC_DEV_ID:
+		cs530x->num_adcs = 4;
+		break;
+	case CS530X_8CH_ADC_DEV_ID:
+		cs530x->num_adcs = 8;
+		break;
+	default:
+		return dev_err_probe(dev, -EINVAL, "Invalid device ID 0x%x\n",
+				     dev_id);
+	}
+
+	return 0;
+}
+
+static int cs530x_parse_device_properties(struct cs530x_priv *cs530x)
+{
+	struct regmap *regmap = cs530x->regmap;
+	struct device *dev = cs530x->dev;
+	unsigned int val = 0;
+
+	switch (cs530x->num_adcs) {
+	case 8:
+		if (device_property_read_bool(dev, "cirrus,in-hiz-pin78"))
+			val = CS530X_IN78_HIZ;
+
+		if (device_property_read_bool(dev, "cirrus,in-hiz-pin56"))
+			val |= CS530X_IN56_HIZ;
+
+		fallthrough;
+	case 4:
+		if (device_property_read_bool(dev, "cirrus,in-hiz-pin34"))
+			val |= CS530X_IN34_HIZ;
+
+		fallthrough;
+	case 2:
+		if (device_property_read_bool(dev, "cirrus,in-hiz-pin12"))
+			val |= CS530X_IN12_HIZ;
+
+		return regmap_set_bits(regmap, CS530X_IN_HIZ, val);
+	default:
+		return dev_err_probe(dev, -EINVAL,
+				     "Invalid number of adcs %d\n",
+				     cs530x->num_adcs);
+	}
+}
+
+int cs530x_probe(struct cs530x_priv *cs530x)
+{
+	struct device *dev = cs530x->dev;
+	int ret, i;
+
+	cs530x->dev_dai = devm_kmemdup(dev, &cs530x_dai,
+					sizeof(*(cs530x->dev_dai)),
+					GFP_KERNEL);
+	if (!cs530x->dev_dai)
+		return -ENOMEM;
+
+	for (i = 0; i < ARRAY_SIZE(cs530x->supplies); i++)
+		cs530x->supplies[i].supply = cs530x_supply_names[i];
+
+	ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(cs530x->supplies),
+				      cs530x->supplies);
+	if (ret != 0)
+		return dev_err_probe(dev, ret, "Failed to request supplies");
+
+	ret = regulator_bulk_enable(ARRAY_SIZE(cs530x->supplies),
+				    cs530x->supplies);
+	if (ret != 0)
+		return dev_err_probe(dev, ret, "Failed to enable supplies");
+
+	cs530x->reset_gpio = devm_gpiod_get_optional(dev, "reset",
+						      GPIOD_OUT_HIGH);
+	if (IS_ERR(cs530x->reset_gpio)) {
+		ret = dev_err_probe(dev, PTR_ERR(cs530x->reset_gpio),
+			      "Reset gpio not available\n");
+		goto err_regulator;
+	}
+
+	if (cs530x->reset_gpio) {
+		usleep_range(2000, 2100);
+		gpiod_set_value_cansleep(cs530x->reset_gpio, 0);
+	}
+
+	usleep_range(5000, 5100);
+	ret = cs530x_check_device_id(cs530x);
+	if (ret)
+		goto err_reset;
+
+	if (!cs530x->reset_gpio) {
+		ret = regmap_write(cs530x->regmap, CS530X_SW_RESET,
+				   CS530X_SW_RST_VAL);
+		if (ret) {
+			dev_err_probe(dev, ret, "Soft Reset Failed\n");
+			goto err_reset;
+		}
+	}
+
+	ret = cs530x_parse_device_properties(cs530x);
+	if (ret)
+		goto err_reset;
+
+	cs530x->dev_dai->capture.channels_max = cs530x->num_adcs;
+
+	ret = devm_snd_soc_register_component(dev,
+			&soc_component_dev_cs530x, cs530x->dev_dai, 1);
+	if (ret) {
+		dev_err_probe(dev, ret, "Can't register cs530x component\n");
+		goto err_reset;
+	}
+
+	return 0;
+
+err_reset:
+	gpiod_set_value_cansleep(cs530x->reset_gpio, 1);
+
+err_regulator:
+	regulator_bulk_disable(ARRAY_SIZE(cs530x->supplies),
+			       cs530x->supplies);
+
+	return ret;
+}
+EXPORT_SYMBOL_NS_GPL(cs530x_probe, SND_SOC_CS530X);
+
+MODULE_DESCRIPTION("CS530X CODEC Driver");
+MODULE_AUTHOR("Paul Handrigan <paulha@opensource.cirrus.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/cs530x.h b/sound/soc/codecs/cs530x.h
new file mode 100644
index 0000000..1c85310
--- /dev/null
+++ b/sound/soc/codecs/cs530x.h
@@ -0,0 +1,223 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * CS530x CODEC driver internal data
+ *
+ * Copyright (C) 2023-2024 Cirrus Logic, Inc. and
+ *                         Cirrus Logic International Semiconductor Ltd.
+ */
+
+#ifndef _CS530X_H
+#define _CS530X_H
+
+#include <linux/device.h>
+#include <linux/gpio/consumer.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+
+/* Devices */
+#define CS530X_2CH_ADC_DEV_ID		 0x5302
+#define CS530X_4CH_ADC_DEV_ID		 0x5304
+#define CS530X_8CH_ADC_DEV_ID		 0x5308
+
+/* Registers */
+
+#define CS530X_DEVID			0x0000000
+#define CS530X_REVID			0x0000004
+#define CS530X_SW_RESET			0x0000022
+
+#define CS530X_CLK_CFG_0		0x0000040
+#define CS530X_CLK_CFG_1		0x0000042
+#define CS530X_CHIP_ENABLE		0x0000044
+#define CS530X_ASP_CFG			0x0000048
+#define CS530X_SIGNAL_PATH_CFG		0x0000050
+#define CS530X_IN_ENABLES		0x0000080
+#define CS530X_IN_RAMP_SUM		0x0000082
+#define CS530X_IN_FILTER		0x0000086
+#define CS530X_IN_HIZ			0x0000088
+#define CS530X_IN_INV			0x000008A
+#define CS530X_IN_VOL_CTRL1_0	        0x0000090
+#define CS530X_IN_VOL_CTRL1_1	        0x0000092
+#define CS530X_IN_VOL_CTRL2_0	        0x0000094
+#define CS530X_IN_VOL_CTRL2_1	        0x0000096
+#define CS530X_IN_VOL_CTRL3_0	        0x0000098
+#define CS530X_IN_VOL_CTRL3_1	        0x000009A
+#define CS530X_IN_VOL_CTRL4_0	        0x000009C
+#define CS530X_IN_VOL_CTRL4_1	        0x000009E
+#define CS530X_IN_VOL_CTRL5		0x00000A0
+
+#define CS530X_PAD_FN			0x0003D24
+#define CS530X_PAD_LVL			0x0003D28
+
+#define CS530X_MAX_REGISTER		CS530X_PAD_LVL
+
+/* Register Fields */
+
+/* REVID */
+#define CS530X_MTLREVID			GENMASK(3, 0)
+#define CS530X_AREVID			GENMASK(7, 4)
+
+/* SW_RESET */
+#define CS530X_SW_RST_SHIFT		8
+#define CS530X_SW_RST_VAL		(0x5A << CS530X_SW_RST_SHIFT)
+
+/* CLK_CFG_0 */
+#define CS530X_PLL_REFCLK_SRC_MASK	BIT(0)
+#define CS530X_PLL_REFCLK_FREQ_MASK	GENMASK(5, 4)
+#define CS530X_SYSCLK_SRC_MASK		BIT(12)
+#define CS530X_SYSCLK_SRC_SHIFT		12
+#define CS530X_REFCLK_2P822_3P072	0
+#define CS530X_REFCLK_5P6448_6P144	0x10
+#define CS530X_REFCLK_11P2896_12P288	0x20
+#define CS530X_REFCLK_24P5792_24P576	0x30
+
+/* CLK_CFG_1 */
+#define CS530X_SAMPLE_RATE_MASK		GENMASK(2, 0)
+#define CS530X_FS_32K			0
+#define CS530X_FS_48K_44P1K		1
+#define CS530X_FS_96K_88P2K		2
+#define CS530X_FS_192K_176P4K		3
+#define CS530X_FS_384K_356P8K		4
+#define CS530X_FS_768K_705P6K		5
+
+/* CHIP_ENABLE */
+#define CS530X_GLOBAL_EN		BIT(0)
+
+/* ASP_CFG */
+#define CS530X_ASP_BCLK_FREQ_MASK	GENMASK(1, 0)
+#define CS530X_ASP_PRIMARY		BIT(5)
+#define CS530X_ASP_BCLK_INV		BIT(6)
+#define CS530X_BCLK_2P822_3P072		0
+#define CS530X_BCLK_5P6448_6P144	1
+#define CS530X_BCLK_11P2896_12P288	2
+#define CS530X_BCLK_24P5792_24P576	3
+
+/* SIGNAL_PATH_CFG */
+#define CS530X_ASP_FMT_MASK		GENMASK(2, 0)
+#define CS530X_ASP_TDM_SLOT_MASK	GENMASK(5, 3)
+#define CS530X_ASP_TDM_SLOT_SHIFT	3
+#define CS530X_ASP_CH_REVERSE		BIT(9)
+#define CS530X_ASP_FMT_I2S		0
+#define CS530X_ASP_FMT_LJ		1
+#define CS530X_ASP_FMT_DSP_A		0x6
+
+/* TDM Slots */
+#define CS530X_0_1_TDM_SLOT_MASK	GENMASK(1, 0)
+#define CS530X_0_3_TDM_SLOT_MASK	GENMASK(3, 0)
+#define CS530X_0_7_TDM_SLOT_MASK	GENMASK(7, 0)
+#define CS530X_0_7_TDM_SLOT_VAL		0
+
+#define CS530X_2_3_TDM_SLOT_MASK	GENMASK(3, 2)
+#define CS530X_2_3_TDM_SLOT_VAL		1
+
+#define CS530X_4_5_TDM_SLOT_MASK	GENMASK(5, 4)
+#define CS530X_4_7_TDM_SLOT_MASK	GENMASK(7, 4)
+#define CS530X_4_7_TDM_SLOT_VAL		2
+
+#define CS530X_6_7_TDM_SLOT_MASK	GENMASK(7, 6)
+#define CS530X_6_7_TDM_SLOT_VAL		3
+
+#define CS530X_8_9_TDM_SLOT_MASK	GENMASK(9, 8)
+#define CS530X_8_11_TDM_SLOT_MASK	GENMASK(11, 8)
+#define CS530X_8_15_TDM_SLOT_MASK	GENMASK(15, 8)
+#define CS530X_8_15_TDM_SLOT_VAL	4
+
+#define CS530X_10_11_TDM_SLOT_MASK	GENMASK(11, 10)
+#define CS530X_10_11_TDM_SLOT_VAL	5
+
+#define CS530X_12_13_TDM_SLOT_MASK	GENMASK(13, 12)
+#define CS530X_12_15_TDM_SLOT_MASK	GENMASK(15, 12)
+#define CS530X_12_15_TDM_SLOT_VAL	6
+
+#define CS530X_14_15_TDM_SLOT_MASK	GENMASK(15, 14)
+#define CS530X_14_15_TDM_SLOT_VAL	7
+
+/* IN_RAMP_SUM */
+#define CS530X_RAMP_RATE_INC_SHIFT	0
+#define CS530X_RAMP_RATE_DEC_SHIFT	4
+#define CS530X_IN_SUM_MODE_SHIFT	13
+
+/* IN_FILTER */
+#define CS530X_IN_FILTER_SHIFT		8
+#define CS530X_IN_HPF_EN_SHIFT		12
+
+/* IN_HIZ */
+#define CS530X_IN12_HIZ			BIT(0)
+#define CS530X_IN34_HIZ			BIT(1)
+#define CS530X_IN56_HIZ			BIT(2)
+#define CS530X_IN78_HIZ			BIT(3)
+
+/* IN_INV */
+#define CS530X_IN1_INV_SHIFT		0
+#define CS530X_IN2_INV_SHIFT		1
+#define CS530X_IN3_INV_SHIFT		2
+#define CS530X_IN4_INV_SHIFT		3
+#define CS530X_IN5_INV_SHIFT		4
+#define CS530X_IN6_INV_SHIFT		5
+#define CS530X_IN7_INV_SHIFT		6
+#define CS530X_IN8_INV_SHIFT		7
+
+/* IN_VOL_CTLy_z */
+#define CS530X_IN_MUTE			BIT(15)
+
+/* IN_VOL_CTL5 */
+#define CS530X_IN_VU			BIT(0)
+
+/* PAD_FN */
+#define CS530X_DOUT2_FN			BIT(0)
+#define CS530X_DOUT3_FN			BIT(1)
+#define CS530X_DOUT4_FN			BIT(2)
+#define CS530X_SPI_CS_FN		BIT(3)
+#define CS530X_CONFIG2_FN		BIT(6)
+#define CS530X_CONFIG3_FN		BIT(7)
+#define CS530X_CONFIG4_FN		BIT(8)
+#define CS530X_CONFIG5_FN		BIT(9)
+
+/* PAD_LVL */
+#define CS530X_CONFIG2_LVL		BIT(6)
+#define CS530X_CONFIG3_LVL		BIT(7)
+#define CS530X_CONFIG4_LVL		BIT(8)
+#define CS530X_CONFIG5_LVL		BIT(9)
+
+/* System Clock Source */
+#define CS530X_SYSCLK_SRC_MCLK		0
+#define CS530X_SYSCLK_SRC_PLL		1
+
+/* PLL Reference Clock Source */
+#define CS530X_PLL_SRC_BCLK		0
+#define CS530X_PLL_SRC_MCLK		1
+
+#define CS530X_NUM_SUPPLIES		2
+
+enum cs530x_type {
+	CS5302,
+	CS5304,
+	CS5308,
+};
+
+/* codec private data */
+struct cs530x_priv {
+	struct regmap *regmap;
+	struct device *dev;
+	struct snd_soc_dai_driver *dev_dai;
+
+	enum cs530x_type devtype;
+	int num_adcs;
+	int num_dacs;
+
+	struct regulator_bulk_data supplies[CS530X_NUM_SUPPLIES];
+
+	unsigned int mclk_rate;
+
+	int tdm_width;
+	int tdm_slots;
+	int bclk;
+	int fs;
+	int adc_pairs_count;
+
+	struct gpio_desc *reset_gpio;
+};
+
+extern const struct regmap_config cs530x_regmap;
+int cs530x_probe(struct cs530x_priv *cs530x);
+
+#endif
diff --git a/sound/soc/codecs/es8326.c b/sound/soc/codecs/es8326.c
index 03b539b..6a4e42e 100644
--- a/sound/soc/codecs/es8326.c
+++ b/sound/soc/codecs/es8326.c
@@ -857,12 +857,16 @@ static void es8326_jack_detect_handler(struct work_struct *work)
 			 * set auto-check mode, then restart jack_detect_work after 400ms.
 			 * Don't report jack status.
 			 */
-			regmap_write(es8326->regmap, ES8326_INT_SOURCE,
-					(ES8326_INT_SRC_PIN9 | ES8326_INT_SRC_BUTTON));
+			regmap_write(es8326->regmap, ES8326_INT_SOURCE, 0x00);
 			regmap_update_bits(es8326->regmap, ES8326_HPDET_TYPE, 0x03, 0x01);
+			regmap_update_bits(es8326->regmap, ES8326_HPDET_TYPE, 0x10, 0x00);
 			es8326_enable_micbias(es8326->component);
 			usleep_range(50000, 70000);
 			regmap_update_bits(es8326->regmap, ES8326_HPDET_TYPE, 0x03, 0x00);
+			regmap_update_bits(es8326->regmap, ES8326_HPDET_TYPE, 0x10, 0x10);
+			usleep_range(50000, 70000);
+			regmap_write(es8326->regmap, ES8326_INT_SOURCE,
+					(ES8326_INT_SRC_PIN9 | ES8326_INT_SRC_BUTTON));
 			regmap_write(es8326->regmap, ES8326_SYS_BIAS, 0x1f);
 			regmap_update_bits(es8326->regmap, ES8326_HP_DRIVER_REF, 0x0f, 0x08);
 			queue_delayed_work(system_wq, &es8326->jack_detect_work,
diff --git a/sound/soc/codecs/pcm512x-i2c.c b/sound/soc/codecs/pcm512x-i2c.c
index 4be476a..92bcf51 100644
--- a/sound/soc/codecs/pcm512x-i2c.c
+++ b/sound/soc/codecs/pcm512x-i2c.c
@@ -39,6 +39,7 @@ static const struct i2c_device_id pcm512x_i2c_id[] = {
 	{ "pcm5122", },
 	{ "pcm5141", },
 	{ "pcm5142", },
+	{ "pcm5242", },
 	{ "tas5754", },
 	{ "tas5756", },
 	{ }
@@ -51,6 +52,7 @@ static const struct of_device_id pcm512x_of_match[] = {
 	{ .compatible = "ti,pcm5122", },
 	{ .compatible = "ti,pcm5141", },
 	{ .compatible = "ti,pcm5142", },
+	{ .compatible = "ti,pcm5242", },
 	{ .compatible = "ti,tas5754", },
 	{ .compatible = "ti,tas5756", },
 	{ }
diff --git a/sound/soc/codecs/pcm512x-spi.c b/sound/soc/codecs/pcm512x-spi.c
index 4d29e71..6629b86 100644
--- a/sound/soc/codecs/pcm512x-spi.c
+++ b/sound/soc/codecs/pcm512x-spi.c
@@ -36,6 +36,7 @@ static const struct spi_device_id pcm512x_spi_id[] = {
 	{ "pcm5122", },
 	{ "pcm5141", },
 	{ "pcm5142", },
+	{ "pcm5242", },
 	{ },
 };
 MODULE_DEVICE_TABLE(spi, pcm512x_spi_id);
@@ -45,6 +46,7 @@ static const struct of_device_id pcm512x_of_match[] = {
 	{ .compatible = "ti,pcm5122", },
 	{ .compatible = "ti,pcm5141", },
 	{ .compatible = "ti,pcm5142", },
+	{ .compatible = "ti,pcm5242", },
 	{ }
 };
 MODULE_DEVICE_TABLE(of, pcm512x_of_match);
diff --git a/sound/soc/codecs/pcm6240.c b/sound/soc/codecs/pcm6240.c
index 86e1267..8f7057e 100644
--- a/sound/soc/codecs/pcm6240.c
+++ b/sound/soc/codecs/pcm6240.c
@@ -2087,10 +2087,8 @@ static int pcmdevice_i2c_probe(struct i2c_client *i2c)
 #endif
 
 	pcm_dev = devm_kzalloc(&i2c->dev, sizeof(*pcm_dev), GFP_KERNEL);
-	if (!pcm_dev) {
-		ret = -ENOMEM;
-		goto out;
-	}
+	if (!pcm_dev)
+		return -ENOMEM;
 
 	pcm_dev->chip_id = (id != NULL) ? id->driver_data : 0;
 
diff --git a/sound/soc/codecs/rt1318.c b/sound/soc/codecs/rt1318.c
new file mode 100644
index 0000000..4e47db4
--- /dev/null
+++ b/sound/soc/codecs/rt1318.c
@@ -0,0 +1,1354 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// rt1318.c  --  RT1318 ALSA SoC audio amplifier driver
+// Author: Jack Yu <jack.yu@realtek.com>
+//
+// Copyright(c) 2024 Realtek Semiconductor Corp.
+//
+//
+
+#include <linux/acpi.h>
+#include <linux/fs.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/regmap.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <linux/firmware.h>
+#include <linux/gpio.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+#include <sound/rt1318.h>
+
+#include "rt1318.h"
+
+static struct reg_sequence init_list[] = {
+	{ 0x0000C000, 0x01},
+	{ 0x0000F20D, 0x00},
+	{ 0x0000F212, 0x3E},
+	{ 0x0000C001, 0x02},
+	{ 0x0000C003, 0x22},
+	{ 0x0000C004, 0x44},
+	{ 0x0000C005, 0x44},
+	{ 0x0000C007, 0x64},
+	{ 0x0000C00E, 0xE7},
+	{ 0x0000F223, 0x7F},
+	{ 0x0000F224, 0xDB},
+	{ 0x0000F225, 0xEE},
+	{ 0x0000F226, 0x3F},
+	{ 0x0000F227, 0x0F},
+	{ 0x0000F21A, 0x78},
+	{ 0x0000F242, 0x3C},
+	{ 0x0000C120, 0x40},
+	{ 0x0000C125, 0x03},
+	{ 0x0000C321, 0x0A},
+	{ 0x0000C200, 0xD8},
+	{ 0x0000C201, 0x27},
+	{ 0x0000C202, 0x0F},
+	{ 0x0000C400, 0x0E},
+	{ 0x0000C401, 0x43},
+	{ 0x0000C402, 0xE0},
+	{ 0x0000C403, 0x00},
+	{ 0x0000C404, 0x4C},
+	{ 0x0000C406, 0x40},
+	{ 0x0000C407, 0x02},
+	{ 0x0000C408, 0x3F},
+	{ 0x0000C300, 0x01},
+	{ 0x0000C125, 0x03},
+	{ 0x0000DF00, 0x10},
+	{ 0x0000F20B, 0x2A},
+	{ 0x0000DF5F, 0x01},
+	{ 0x0000DF60, 0xA7},
+	{ 0x0000C203, 0x84},
+	{ 0x0000C206, 0x78},
+	{ 0x0000F10A, 0x09},
+	{ 0x0000F10B, 0x4C},
+	{ 0x0000F104, 0xF4},
+	{ 0x0000F105, 0x03},
+	{ 0x0000F109, 0xE0},
+	{ 0x0000F10B, 0x5C},
+	{ 0x0000F104, 0xF4},
+	{ 0x0000F105, 0x04},
+	{ 0x0000F109, 0x65},
+	{ 0x0000F10B, 0x5C},
+	{ 0x0000F104, 0xF4},
+	{ 0x0000F105, 0x02},
+	{ 0x0000F109, 0x30},
+	{ 0x0000F10B, 0x5C},
+	{ 0x0000E706, 0x0F},
+	{ 0x0000E707, 0x30},
+	{ 0x0000E806, 0x0F},
+	{ 0x0000E807, 0x30},
+	{ 0x0000CE04, 0x03},
+	{ 0x0000CE05, 0x5F},
+	{ 0x0000CE06, 0xA2},
+	{ 0x0000CE07, 0x6B},
+	{ 0x0000CF04, 0x03},
+	{ 0x0000CF05, 0x5F},
+	{ 0x0000CF06, 0xA2},
+	{ 0x0000CF07, 0x6B},
+	{ 0x0000CE60, 0xE3},
+	{ 0x0000C130, 0x51},
+	{ 0x0000E000, 0xA8},
+	{ 0x0000F102, 0x00},
+	{ 0x0000F103, 0x00},
+	{ 0x0000F104, 0xF5},
+	{ 0x0000F105, 0x23},
+	{ 0x0000F109, 0x04},
+	{ 0x0000F10A, 0x0B},
+	{ 0x0000F10B, 0x4C},
+	{ 0x0000F10B, 0x5C},
+	{ 0x41001888, 0x00},
+	{ 0x0000C121, 0x0B},
+	{ 0x0000F102, 0x00},
+	{ 0x0000F103, 0x00},
+	{ 0x0000F104, 0xF5},
+	{ 0x0000F105, 0x23},
+	{ 0x0000F109, 0x00},
+	{ 0x0000F10A, 0x0B},
+	{ 0x0000F10B, 0x4C},
+	{ 0x0000F10B, 0x5C},
+	{ 0x0000F800, 0x20},
+	{ 0x0000CA00, 0x80},
+	{ 0x0000CA10, 0x00},
+	{ 0x0000CA02, 0x78},
+	{ 0x0000CA12, 0x78},
+	{ 0x0000ED00, 0x90},
+	{ 0x0000E604, 0x00},
+	{ 0x0000DB00, 0x0C},
+	{ 0x0000DD00, 0x0C},
+	{ 0x0000DC19, 0x00},
+	{ 0x0000DC1A, 0x6A},
+	{ 0x0000DC1B, 0xAA},
+	{ 0x0000DC1C, 0xAB},
+	{ 0x0000DC1D, 0x00},
+	{ 0x0000DC1E, 0x16},
+	{ 0x0000DC1F, 0xDB},
+	{ 0x0000DC20, 0x6D},
+	{ 0x0000DE19, 0x00},
+	{ 0x0000DE1A, 0x6A},
+	{ 0x0000DE1B, 0xAA},
+	{ 0x0000DE1C, 0xAB},
+	{ 0x0000DE1D, 0x00},
+	{ 0x0000DE1E, 0x16},
+	{ 0x0000DE1F, 0xDB},
+	{ 0x0000DE20, 0x6D},
+	{ 0x0000DB32, 0x00},
+	{ 0x0000DD32, 0x00},
+	{ 0x0000DB33, 0x0A},
+	{ 0x0000DD33, 0x0A},
+	{ 0x0000DB34, 0x1A},
+	{ 0x0000DD34, 0x1A},
+	{ 0x0000DB15, 0xEF},
+	{ 0x0000DD15, 0xEF},
+	{ 0x0000DB17, 0xEF},
+	{ 0x0000DD17, 0xEF},
+	{ 0x0000DB94, 0x70},
+	{ 0x0000DD94, 0x70},
+	{ 0x0000DB19, 0x40},
+	{ 0x0000DD19, 0x40},
+	{ 0x0000DB12, 0xC0},
+	{ 0x0000DD12, 0xC0},
+	{ 0x0000DB00, 0x4C},
+	{ 0x0000DB04, 0x05},
+	{ 0x0000DB05, 0x03},
+	{ 0x0000DD04, 0x05},
+	{ 0x0000DD05, 0x03},
+	{ 0x0000DBBB, 0x09},
+	{ 0x0000DBBC, 0x30},
+	{ 0x0000DBBD, 0xF0},
+	{ 0x0000DBBE, 0xF1},
+	{ 0x0000DDBB, 0x09},
+	{ 0x0000DDBC, 0x30},
+	{ 0x0000DDBD, 0xF0},
+	{ 0x0000DDBE, 0xF1},
+	{ 0x0000DB01, 0x79},
+	{ 0x0000DD01, 0x79},
+	{ 0x0000DB08, 0x40},
+	{ 0x0000DD08, 0x40},
+	{ 0x0000DC52, 0xEF},
+	{ 0x0000DE52, 0xEF},
+	{ 0x0000DB00, 0xCC},
+	{ 0x0000CC2C, 0x00},
+	{ 0x0000CC2D, 0x2A},
+	{ 0x0000CC2E, 0x83},
+	{ 0x0000CC2F, 0xA8},
+	{ 0x0000CD2C, 0x00},
+	{ 0x0000CD2D, 0x2A},
+	{ 0x0000CD2E, 0x83},
+	{ 0x0000CD2F, 0xA8},
+	{ 0x0000CC24, 0x00},
+	{ 0x0000CC25, 0x51},
+	{ 0x0000CC26, 0xEB},
+	{ 0x0000CC27, 0x85},
+	{ 0x0000CD24, 0x00},
+	{ 0x0000CD25, 0x51},
+	{ 0x0000CD26, 0xEB},
+	{ 0x0000CD27, 0x85},
+	{ 0x0000CC20, 0x00},
+	{ 0x0000CC21, 0x00},
+	{ 0x0000CC22, 0x43},
+	{ 0x0000CD20, 0x00},
+	{ 0x0000CD21, 0x00},
+	{ 0x0000CD22, 0x43},
+	{ 0x0000CC16, 0x0F},
+	{ 0x0000CC17, 0x00},
+	{ 0x0000CD16, 0x0F},
+	{ 0x0000CD17, 0x00},
+	{ 0x0000CC29, 0x5D},
+	{ 0x0000CC2A, 0xC0},
+	{ 0x0000CD29, 0x5D},
+	{ 0x0000CD2A, 0xC0},
+	{ 0x0000CC31, 0x20},
+	{ 0x0000CC32, 0x00},
+	{ 0x0000CC33, 0x00},
+	{ 0x0000CC34, 0x00},
+	{ 0x0000CD31, 0x20},
+	{ 0x0000CD32, 0x00},
+	{ 0x0000CD33, 0x00},
+	{ 0x0000CD34, 0x00},
+	{ 0x0000CC36, 0x79},
+	{ 0x0000CC37, 0x99},
+	{ 0x0000CC38, 0x99},
+	{ 0x0000CC39, 0x99},
+	{ 0x0000CD36, 0x79},
+	{ 0x0000CD37, 0x99},
+	{ 0x0000CD38, 0x99},
+	{ 0x0000CD39, 0x99},
+	{ 0x0000CC09, 0x00},
+	{ 0x0000CC0A, 0x07},
+	{ 0x0000CC0B, 0x5F},
+	{ 0x0000CC0C, 0x6F},
+	{ 0x0000CD09, 0x00},
+	{ 0x0000CD0A, 0x07},
+	{ 0x0000CD0B, 0x5F},
+	{ 0x0000CD0C, 0x6F},
+	{ 0x0000CC0E, 0x00},
+	{ 0x0000CC0F, 0x03},
+	{ 0x0000CC10, 0xAF},
+	{ 0x0000CC11, 0xB7},
+	{ 0x0000CD0E, 0x00},
+	{ 0x0000CD0F, 0x03},
+	{ 0x0000CD10, 0xAF},
+	{ 0x0000CD11, 0xB7},
+	{ 0x0000CCD6, 0x00},
+	{ 0x0000CCD7, 0x03},
+	{ 0x0000CDD6, 0x00},
+	{ 0x0000CDD7, 0x03},
+	{ 0x0000CCD8, 0x00},
+	{ 0x0000CCD9, 0x03},
+	{ 0x0000CDD8, 0x00},
+	{ 0x0000CDD9, 0x03},
+	{ 0x0000CCDA, 0x00},
+	{ 0x0000CCDB, 0x03},
+	{ 0x0000CDDA, 0x00},
+	{ 0x0000CDDB, 0x03},
+	{ 0x0000C320, 0x20},
+	{ 0x0000C203, 0x9C},
+};
+#define rt1318_INIT_REG_LEN ARRAY_SIZE(init_list)
+
+static const struct reg_default rt1318_reg[] = {
+	{ 0xc000, 0x00 },
+	{ 0xc001, 0x43 },
+	{ 0xc003, 0x22 },
+	{ 0xc004, 0x44 },
+	{ 0xc005, 0x44 },
+	{ 0xc006, 0x33 },
+	{ 0xc007, 0x64 },
+	{ 0xc008, 0x05 },
+	{ 0xc00a, 0xfc },
+	{ 0xc00b, 0x0f },
+	{ 0xc00c, 0x0e },
+	{ 0xc00d, 0xef },
+	{ 0xc00e, 0xe5 },
+	{ 0xc00f, 0xff },
+	{ 0xc120, 0xc0 },
+	{ 0xc121, 0x00 },
+	{ 0xc122, 0x00 },
+	{ 0xc123, 0x14 },
+	{ 0xc125, 0x00 },
+	{ 0xc130, 0x59 },
+	{ 0xc200, 0x00 },
+	{ 0xc201, 0x00 },
+	{ 0xc202, 0x00 },
+	{ 0xc203, 0x04 },
+	{ 0xc204, 0x00 },
+	{ 0xc205, 0x00 },
+	{ 0xc206, 0x68 },
+	{ 0xc207, 0x70 },
+	{ 0xc208, 0x00 },
+	{ 0xc20a, 0x00 },
+	{ 0xc20b, 0x01 },
+	{ 0xc20c, 0x7f },
+	{ 0xc20d, 0x01 },
+	{ 0xc20e, 0x7f },
+	{ 0xc300, 0x00 },
+	{ 0xc301, 0x00 },
+	{ 0xc303, 0x80 },
+	{ 0xc320, 0x00 },
+	{ 0xc321, 0x09 },
+	{ 0xc322, 0x02 },
+	{ 0xc400, 0x00 },
+	{ 0xc401, 0x00 },
+	{ 0xc402, 0x00 },
+	{ 0xc403, 0x00 },
+	{ 0xc404, 0x00 },
+	{ 0xc405, 0x00 },
+	{ 0xc406, 0x00 },
+	{ 0xc407, 0x00 },
+	{ 0xc408, 0x00 },
+	{ 0xc410, 0x04 },
+	{ 0xc430, 0x00 },
+	{ 0xc431, 0x00 },
+	{ 0xca00, 0x10 },
+	{ 0xca01, 0x00 },
+	{ 0xca02, 0x0b },
+	{ 0xca10, 0x10 },
+	{ 0xca11, 0x00 },
+	{ 0xca12, 0x0b },
+	{ 0xce04, 0x08 },
+	{ 0xce05, 0x00 },
+	{ 0xce06, 0x00 },
+	{ 0xce07, 0x00 },
+	{ 0xce60, 0x63 },
+	{ 0xcf04, 0x08 },
+	{ 0xcf05, 0x00 },
+	{ 0xcf06, 0x00 },
+	{ 0xcf07, 0x00 },
+	{ 0xdb00, 0x00 },
+	{ 0xdb08, 0x40 },
+	{ 0xdb12, 0x00 },
+	{ 0xdb35, 0x00 },
+	{ 0xdbb5, 0x00 },
+	{ 0xdbb6, 0x40 },
+	{ 0xdbb7, 0x00 },
+	{ 0xdbb8, 0x00 },
+	{ 0xdbc5, 0x00 },
+	{ 0xdbc6, 0x00 },
+	{ 0xdbc7, 0x00 },
+	{ 0xdbc8, 0x00 },
+	{ 0xdd08, 0x40 },
+	{ 0xdd12, 0x00 },
+	{ 0xdd35, 0x00 },
+	{ 0xddb5, 0x00 },
+	{ 0xddb6, 0x40 },
+	{ 0xddb7, 0x00 },
+	{ 0xddb8, 0x00 },
+	{ 0xddc5, 0x00 },
+	{ 0xddc6, 0x00 },
+	{ 0xddc7, 0x00 },
+	{ 0xddc8, 0x00 },
+	{ 0xdd93, 0x00 },
+	{ 0xdd94, 0x64 },
+	{ 0xdf00, 0x00 },
+	{ 0xdf5f, 0x00 },
+	{ 0xdf60, 0x00 },
+	{ 0xe000, 0x08 },
+	{ 0xe300, 0xa0 },
+	{ 0xe400, 0x22 },
+	{ 0xe706, 0x2f },
+	{ 0xe707, 0x2f },
+	{ 0xe806, 0x2f },
+	{ 0xe807, 0x2f },
+	{ 0xea00, 0x43 },
+	{ 0xed00, 0x80 },
+	{ 0xed01, 0x0f },
+	{ 0xed02, 0xff },
+	{ 0xed03, 0x00 },
+	{ 0xed04, 0x00 },
+	{ 0xed05, 0x0f },
+	{ 0xed06, 0xff },
+	{ 0xf010, 0x10 },
+	{ 0xf011, 0xec },
+	{ 0xf012, 0x68 },
+	{ 0xf013, 0x21 },
+	{ 0xf102, 0x00 },
+	{ 0xf103, 0x00 },
+	{ 0xf104, 0x00 },
+	{ 0xf105, 0x00 },
+	{ 0xf106, 0x00 },
+	{ 0xf107, 0x00 },
+	{ 0xf108, 0x00 },
+	{ 0xf109, 0x00 },
+	{ 0xf10a, 0x03 },
+	{ 0xf10b, 0x40 },
+	{ 0xf20b, 0x28 },
+	{ 0xf20d, 0x00 },
+	{ 0xf212, 0x00 },
+	{ 0xf21a, 0x00 },
+	{ 0xf223, 0x40 },
+	{ 0xf224, 0x00 },
+	{ 0xf225, 0x00 },
+	{ 0xf226, 0x00 },
+	{ 0xf227, 0x00 },
+	{ 0xf242, 0x0c },
+	{ 0xf800, 0x00 },
+	{ 0xf801, 0x12 },
+	{ 0xf802, 0xe0 },
+	{ 0xf803, 0x2f },
+	{ 0xf804, 0x00 },
+	{ 0xf805, 0x00 },
+	{ 0xf806, 0x07 },
+	{ 0xf807, 0xff },
+};
+
+static bool rt1318_volatile_register(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case 0xc000:
+	case 0xc301:
+	case 0xc410:
+	case 0xc430 ... 0xc431:
+	case 0xdb06:
+	case 0xdb12:
+	case 0xdb1d ... 0xdb1f:
+	case 0xdb35:
+	case 0xdb37:
+	case 0xdb8a ... 0xdb92:
+	case 0xdbc5 ... 0xdbc8:
+	case 0xdc2b ... 0xdc49:
+	case 0xdd0b:
+	case 0xdd12:
+	case 0xdd1d ... 0xdd1f:
+	case 0xdd35:
+	case 0xdd8a ... 0xdd92:
+	case 0xddc5 ... 0xddc8:
+	case 0xde2b ... 0xde44:
+	case 0xdf4a ... 0xdf55:
+	case 0xe224 ... 0xe23b:
+	case 0xea01:
+	case 0xebc5:
+	case 0xebc8:
+	case 0xebcb ... 0xebcc:
+	case 0xed03 ... 0xed06:
+	case 0xf010 ... 0xf014:
+		return true;
+
+	default:
+		return false;
+	}
+}
+
+static bool rt1318_readable_register(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case 0xc000 ... 0xc00f:
+	case 0xc120 ... 0xc130:
+	case 0xc200 ... 0xc20e:
+	case 0xc300 ... 0xc303:
+	case 0xc320 ... 0xc322:
+	case 0xc400 ... 0xc408:
+	case 0xc430 ... 0xc431:
+	case 0xca00 ... 0xca02:
+	case 0xca10 ... 0xca12:
+	case 0xcb00 ... 0xcb0b:
+	case 0xcc00 ... 0xcce5:
+	case 0xcd00 ... 0xcde5:
+	case 0xce00 ... 0xce6a:
+	case 0xcf00 ... 0xcf53:
+	case 0xd000 ... 0xd0cc:
+	case 0xd100 ... 0xd1b9:
+	case 0xdb00 ... 0xdc53:
+	case 0xdd00 ... 0xde53:
+	case 0xdf00 ... 0xdf6b:
+	case 0xe000:
+	case 0xe300:
+	case 0xe400:
+	case 0xe706 ... 0xe707:
+	case 0xe806 ... 0xe807:
+	case 0xea00:
+	case 0xeb00 ... 0xebcc:
+	case 0xec00 ... 0xecb9:
+	case 0xed00 ... 0xed06:
+	case 0xf010 ... 0xf014:
+	case 0xf102 ... 0xf10b:
+	case 0xf20b:
+	case 0xf20d ... 0xf242:
+	case 0xf800 ... 0xf807:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static int rt1318_dac_event(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
+	struct rt1318_priv *rt1318 = snd_soc_component_get_drvdata(component);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		regmap_update_bits(rt1318->regmap, RT1318_PWR_STA1,
+				RT1318_PDB_CTRL_MASK, RT1318_PDB_CTRL_HIGH);
+		break;
+
+	case SND_SOC_DAPM_POST_PMD:
+		regmap_update_bits(rt1318->regmap, RT1318_PWR_STA1,
+				RT1318_PDB_CTRL_MASK, RT1318_PDB_CTRL_LOW);
+		break;
+
+	default:
+		break;
+	}
+	return 0;
+}
+
+static int rt1318_dvol_put(struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
+	struct rt1318_priv *rt1318 = snd_soc_component_get_drvdata(component);
+
+	rt1318->rt1318_dvol = ucontrol->value.integer.value[0];
+
+	if (rt1318->rt1318_dvol <= RT1318_DVOL_STEP && rt1318->rt1318_dvol >= 0) {
+		regmap_write(rt1318->regmap, RT1318_DA_VOL_L_8,
+			rt1318->rt1318_dvol >> 8);
+		regmap_write(rt1318->regmap, RT1318_DA_VOL_L_1_7,
+			rt1318->rt1318_dvol & 0xff);
+		regmap_write(rt1318->regmap, RT1318_DA_VOL_R_8,
+			rt1318->rt1318_dvol >> 8);
+		regmap_write(rt1318->regmap, RT1318_DA_VOL_R_1_7,
+			rt1318->rt1318_dvol & 0xff);
+		return 1;
+	}
+
+	return 0;
+}
+
+static int rt1318_dvol_get(struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
+	struct rt1318_priv *rt1318 = snd_soc_component_get_drvdata(component);
+
+	ucontrol->value.integer.value[0] = rt1318->rt1318_dvol;
+
+	return 0;
+}
+
+static const struct snd_kcontrol_new rt1318_snd_controls[] = {
+	SOC_SINGLE_EXT("Amp Playback Volume", SND_SOC_NOPM, 0, 383, 0,
+		rt1318_dvol_get, rt1318_dvol_put),
+};
+
+static const struct snd_soc_dapm_widget rt1318_dapm_widgets[] = {
+	/* Audio Interface */
+	SND_SOC_DAPM_AIF_IN("AIF1RX", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
+	/* DACs */
+	SND_SOC_DAPM_DAC_E("DAC", NULL, SND_SOC_NOPM, 0, 0,
+		rt1318_dac_event, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+	/* Output Lines */
+	SND_SOC_DAPM_OUTPUT("Amp"),
+};
+
+static const struct snd_soc_dapm_route rt1318_dapm_routes[] = {
+	{"DAC", NULL, "AIF1RX"},
+	{"Amp", NULL, "DAC"},
+};
+
+static int rt1318_get_clk_info(int sclk, int rate)
+{
+	int i, pd[] = {1, 2, 4, 8, 16, 24};
+
+	if (sclk <= 0 || rate <= 0)
+		return -EINVAL;
+
+	rate = rate << 8;
+	for (i = 0; i < ARRAY_SIZE(pd); i++)
+		if (sclk == rate * pd[i])
+			return i;
+
+	return -EINVAL;
+}
+
+static int rt1318_clk_ip_info(struct snd_soc_component *component, int lrclk)
+{
+	struct rt1318_priv *rt1318 = snd_soc_component_get_drvdata(component);
+
+	switch (lrclk) {
+	case RT1318_LRCLK_48000:
+	case RT1318_LRCLK_44100:
+	case RT1318_LRCLK_16000:
+		regmap_update_bits(rt1318->regmap, RT1318_SRC_TCON,
+				RT1318_SRCIN_F12288_MASK | RT1318_SRCIN_DACLK_MASK,
+				RT1318_SRCIN_TCON4 | RT1318_DACLK_TCON4);
+		break;
+	case RT1318_LRCLK_96000:
+		regmap_update_bits(rt1318->regmap, RT1318_SRC_TCON,
+				RT1318_SRCIN_F12288_MASK | RT1318_SRCIN_DACLK_MASK,
+				RT1318_SRCIN_TCON4 | RT1318_DACLK_TCON2);
+		break;
+	case RT1318_LRCLK_192000:
+		regmap_update_bits(rt1318->regmap, RT1318_SRC_TCON,
+				RT1318_SRCIN_F12288_MASK | RT1318_SRCIN_DACLK_MASK,
+				RT1318_SRCIN_TCON4 | RT1318_DACLK_TCON1);
+		break;
+	default:
+		dev_err(component->dev, "Unsupported clock rate.\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int rt1318_hw_params(struct snd_pcm_substream *substream,
+	struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
+{
+	struct snd_soc_component *component = dai->component;
+	struct rt1318_priv *rt1318 = snd_soc_component_get_drvdata(component);
+	int data_len = 0, ch_len = 0;
+	int pre_div, ret;
+
+	rt1318->lrck = params_rate(params);
+	pre_div = rt1318_get_clk_info(rt1318->sysclk, rt1318->lrck);
+	if (pre_div < 0) {
+		dev_err(component->dev, "Unsupported clock setting\n");
+		return -EINVAL;
+	}
+	ret = rt1318_clk_ip_info(component, rt1318->lrck);
+	if (ret < 0) {
+		dev_err(component->dev, "Unsupported clock setting\n");
+		return -EINVAL;
+	}
+
+	switch (params_width(params)) {
+	case 16:
+		break;
+	case 20:
+		data_len = RT1318_I2S_DL_20;
+		ch_len = RT1318_I2S_DL_20;
+		break;
+	case 24:
+		data_len = RT1318_I2S_DL_24;
+		ch_len = RT1318_I2S_DL_24;
+		break;
+	case 32:
+		data_len = RT1318_I2S_DL_32;
+		ch_len = RT1318_I2S_DL_32;
+		break;
+	case 8:
+		data_len = RT1318_I2S_DL_8;
+		ch_len = RT1318_I2S_DL_8;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	regmap_update_bits(rt1318->regmap, RT1318_CLK2,
+				RT1318_DIV_AP_MASK | RT1318_DIV_DAMOD_MASK,
+				pre_div << RT1318_DIV_AP_SFT |
+				pre_div << RT1318_DIV_DAMOD_SFT);
+	regmap_update_bits(rt1318->regmap, RT1318_CLK3,
+				RT1318_AD_STO1_MASK | RT1318_AD_STO2_MASK,
+				pre_div << RT1318_AD_STO1_SFT |
+				pre_div << RT1318_AD_STO2_SFT);
+	regmap_update_bits(rt1318->regmap, RT1318_CLK4,
+				RT1318_AD_ANA_STO1_MASK | RT1318_AD_ANA_STO2_MASK,
+				pre_div << RT1318_AD_ANA_STO1_SFT |
+				pre_div << RT1318_AD_ANA_STO2_SFT);
+	regmap_update_bits(rt1318->regmap, RT1318_CLK5,
+				RT1318_DIV_FIFO_IN_MASK | RT1318_DIV_FIFO_OUT_MASK,
+				pre_div << RT1318_DIV_FIFO_IN_SFT |
+				pre_div << RT1318_DIV_FIFO_OUT_SFT);
+	regmap_update_bits(rt1318->regmap, RT1318_CLK6,
+				RT1318_DIV_NLMS_MASK | RT1318_DIV_AD_MONO_MASK |
+				RT1318_DIV_POST_G_MASK,  pre_div << RT1318_DIV_NLMS_SFT |
+				pre_div << RT1318_DIV_AD_MONO_SFT |
+				pre_div << RT1318_DIV_POST_G_SFT);
+
+	regmap_update_bits(rt1318->regmap, RT1318_TDM_CTRL2,
+				RT1318_I2S_DL_MASK, data_len << RT1318_I2S_DL_SFT);
+	regmap_update_bits(rt1318->regmap, RT1318_TDM_CTRL3,
+				RT1318_I2S_TX_CHL_MASK | RT1318_I2S_RX_CHL_MASK,
+				ch_len << RT1318_I2S_TX_CHL_SFT |
+				ch_len << RT1318_I2S_RX_CHL_SFT);
+
+	return 0;
+}
+
+static int rt1318_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+	struct snd_soc_component *component = dai->component;
+	struct rt1318_priv *rt1318 = snd_soc_component_get_drvdata(component);
+	unsigned int reg_val = 0, reg_val2 = 0;
+
+	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+	case SND_SOC_DAIFMT_NB_NF:
+		break;
+	case SND_SOC_DAIFMT_IB_NF:
+		reg_val2 |= RT1318_TDM_BCLK_INV;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_I2S:
+		break;
+
+	case SND_SOC_DAIFMT_LEFT_J:
+		reg_val |= RT1318_FMT_LEFT_J;
+		break;
+
+	case SND_SOC_DAIFMT_DSP_A:
+		reg_val |= RT1318_FMT_PCM_A_R;
+		break;
+
+	case SND_SOC_DAIFMT_DSP_B:
+		reg_val |= RT1318_FMT_PCM_B_R;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	regmap_update_bits(rt1318->regmap, RT1318_TDM_CTRL1,
+			RT1318_I2S_FMT_MASK, reg_val);
+	regmap_update_bits(rt1318->regmap, RT1318_TDM_CTRL1,
+			RT1318_TDM_BCLK_MASK, reg_val2);
+
+	return 0;
+}
+
+static int rt1318_set_dai_sysclk(struct snd_soc_dai *dai,
+		int clk_id, unsigned int freq, int dir)
+{
+	struct snd_soc_component *component = dai->component;
+	struct rt1318_priv *rt1318 = snd_soc_component_get_drvdata(component);
+	int reg_val = 0;
+
+	if (freq == rt1318->sysclk && clk_id == rt1318->sysclk_src)
+		return 0;
+
+	switch (clk_id) {
+	case RT1318_SCLK_S_BCLK:
+		reg_val |= RT1318_SYSCLK_BCLK;
+		break;
+	case RT1318_SCLK_S_SDW:
+		reg_val |= RT1318_SYSCLK_SDW;
+		break;
+	case RT1318_SCLK_S_PLL2F:
+		reg_val |= RT1318_SYSCLK_PLL2F;
+		break;
+	case RT1318_SCLK_S_PLL2B:
+		reg_val |= RT1318_SYSCLK_PLL2B;
+		break;
+	case RT1318_SCLK_S_MCLK:
+		reg_val |= RT1318_SYSCLK_MCLK;
+		break;
+	case RT1318_SCLK_S_RC0:
+		reg_val |= RT1318_SYSCLK_RC1;
+		break;
+	case RT1318_SCLK_S_RC1:
+		reg_val |= RT1318_SYSCLK_RC2;
+		break;
+	case RT1318_SCLK_S_RC2:
+		reg_val |= RT1318_SYSCLK_RC3;
+		break;
+	default:
+		dev_err(component->dev, "Invalid clock id (%d)\n", clk_id);
+		return -EINVAL;
+	}
+
+	rt1318->sysclk = freq;
+	rt1318->sysclk_src = clk_id;
+	dev_dbg(dai->dev, "Sysclk is %dHz and clock id is %d\n", freq, clk_id);
+	regmap_update_bits(rt1318->regmap, RT1318_CLK1,
+			RT1318_SYSCLK_SEL_MASK, reg_val);
+
+	return 0;
+}
+
+static const struct pll_calc_map pll_preset_table[] = {
+	{512000, 4096000, 22, 190, 0, true, false},
+	{1024000, 4096000, 22, 94, 0, true, false},
+	{1024000, 16384000, 4, 190, 0, true, false},
+	{1411200, 11289600, 6, 62, 0, true, false},
+	{1536000, 12288000, 6, 62, 0, true, false},
+	{2822400, 11289600, 6, 62, 0, true, false},
+	{2822400, 45158400, 0, 62, 0, true, false},
+	{2822400, 49152000, 0, 62, 0, true, false},
+	{3072000, 12288000, 6, 62, 0, true, false},
+	{3072000, 24576000, 2, 62, 0, true, false},
+	{3072000, 49152000, 0, 62, 0, true, false},
+	{6144000, 24576000, 2, 94, 4, false, false},
+	{6144000, 49152000, 0, 30, 0, true, false},
+	{6144000, 98304000, 0, 94, 4, false, true},
+	{12288000, 49152000, 0, 62, 6, false, false},
+};
+
+static int rt1318_pll_calc(const unsigned int freq_in,
+	const unsigned int freq_out, struct rt1318_pll_code *pll_code)
+{
+	int max_n = RT1318_PLL_N_MAX, max_m = RT1318_PLL_M_MAX;
+	int i, k, red, n_t, pll_out, in_t, out_t;
+	int n = 0, m = 0, m_t = 0;
+	int red_t = abs(freq_out - freq_in);
+	bool m_bypass = false, k_bypass = false;
+
+	if (RT1318_PLL_INP_MAX < freq_in || RT1318_PLL_INP_MIN > freq_in)
+		return -EINVAL;
+
+	for (i = 0; i < ARRAY_SIZE(pll_preset_table); i++) {
+		if (freq_in == pll_preset_table[i].pll_in &&
+			freq_out == pll_preset_table[i].pll_out) {
+			k = pll_preset_table[i].k;
+			m = pll_preset_table[i].m;
+			n = pll_preset_table[i].n;
+			m_bypass = pll_preset_table[i].m_bp;
+			k_bypass = pll_preset_table[i].k_bp;
+			goto code_find;
+		}
+	}
+
+	k = 100000000 / freq_out - 2;
+	if (k > RT1318_PLL_K_MAX)
+		k = RT1318_PLL_K_MAX;
+	if (k < 0) {
+		k = 0;
+		k_bypass = true;
+	}
+	for (n_t = 0; n_t <= max_n; n_t++) {
+		in_t = freq_in / (k_bypass ? 1 : (k + 2));
+		pll_out = freq_out / (n_t + 2);
+		if (in_t < 0)
+			continue;
+		if (in_t == pll_out) {
+			m_bypass = true;
+			n = n_t;
+			goto code_find;
+		}
+		red = abs(in_t - pll_out);
+		if (red < red_t) {
+			m_bypass = true;
+			n = n_t;
+			m = m_t;
+			if (red == 0)
+				goto code_find;
+			red_t = red;
+		}
+		for (m_t = 0; m_t <= max_m; m_t++) {
+			out_t = in_t / (m_t + 2);
+			red = abs(out_t - pll_out);
+			if (red < red_t) {
+				m_bypass = false;
+				n = n_t;
+				m = m_t;
+				if (red == 0)
+					goto code_find;
+				red_t = red;
+			}
+		}
+	}
+	pr_debug("Only get approximation about PLL\n");
+
+code_find:
+
+	pll_code->m_bp = m_bypass;
+	pll_code->k_bp = k_bypass;
+	pll_code->m_code = m;
+	pll_code->n_code = n;
+	pll_code->k_code = k;
+	return 0;
+}
+
+static int rt1318_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source,
+			unsigned int freq_in, unsigned int freq_out)
+{
+	struct snd_soc_component *component = dai->component;
+	struct rt1318_priv *rt1318 = snd_soc_component_get_drvdata(component);
+	struct rt1318_pll_code pll_code;
+	int ret;
+
+	if (!freq_in || !freq_out) {
+		dev_dbg(component->dev, "PLL disabled\n");
+		rt1318->pll_in = 0;
+		rt1318->pll_out = 0;
+		return 0;
+	}
+
+	if (source == rt1318->pll_src && freq_in == rt1318->pll_in &&
+		freq_out == rt1318->pll_out)
+		return 0;
+
+	switch (source) {
+	case RT1318_PLL_S_BCLK0:
+		regmap_update_bits(rt1318->regmap, RT1318_CLK1,
+			RT1318_PLLIN_MASK, RT1318_PLLIN_BCLK0);
+		break;
+	case RT1318_PLL_S_BCLK1:
+		regmap_update_bits(rt1318->regmap, RT1318_CLK1,
+			RT1318_PLLIN_MASK, RT1318_PLLIN_BCLK1);
+		break;
+	case RT1318_PLL_S_RC:
+		regmap_update_bits(rt1318->regmap, RT1318_CLK1,
+			RT1318_PLLIN_MASK, RT1318_PLLIN_RC);
+		break;
+	case RT1318_PLL_S_MCLK:
+		regmap_update_bits(rt1318->regmap, RT1318_CLK1,
+			RT1318_PLLIN_MASK, RT1318_PLLIN_MCLK);
+		break;
+	case RT1318_PLL_S_SDW_IN_PLL:
+		regmap_update_bits(rt1318->regmap, RT1318_CLK1,
+			RT1318_PLLIN_MASK, RT1318_PLLIN_SDW1);
+		break;
+	case RT1318_PLL_S_SDW_0:
+		regmap_update_bits(rt1318->regmap, RT1318_CLK1,
+			RT1318_PLLIN_MASK, RT1318_PLLIN_SDW2);
+		break;
+	case RT1318_PLL_S_SDW_1:
+		regmap_update_bits(rt1318->regmap, RT1318_CLK1,
+			RT1318_PLLIN_MASK, RT1318_PLLIN_SDW3);
+		break;
+	case RT1318_PLL_S_SDW_2:
+		regmap_update_bits(rt1318->regmap, RT1318_CLK1,
+			RT1318_PLLIN_MASK, RT1318_PLLIN_SDW4);
+		break;
+	default:
+		dev_err(component->dev, "Unknown PLL source %d\n", source);
+		return -EINVAL;
+	}
+
+	ret = rt1318_pll_calc(freq_in, freq_out, &pll_code);
+	if (ret < 0) {
+		dev_err(component->dev, "Unsupport input clock %d\n", freq_in);
+		return ret;
+	}
+
+	dev_dbg(component->dev, "bypass=%d m=%d n=%d k=%d\n",
+		pll_code.m_bp, (pll_code.m_bp ? 0 : pll_code.m_code),
+		pll_code.n_code, pll_code.k_code);
+
+	regmap_update_bits(rt1318->regmap, RT1318_PLL1_K,
+			RT1318_K_PLL1_MASK, pll_code.k_code);
+	regmap_update_bits(rt1318->regmap, RT1318_PLL1_M,
+			RT1318_M_PLL1_MASK, (pll_code.m_bp ? 0 : pll_code.m_code));
+	regmap_update_bits(rt1318->regmap, RT1318_PLL1_N_8,
+			RT1318_N_8_PLL1_MASK, pll_code.n_code >> 8);
+	regmap_update_bits(rt1318->regmap, RT1318_PLL1_N_7_0,
+			RT1318_N_7_0_PLL1_MASK, pll_code.n_code);
+
+	rt1318->pll_in = freq_in;
+	rt1318->pll_out = freq_out;
+	rt1318->pll_src = source;
+
+	return 0;
+}
+
+static int rt1318_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
+			unsigned int rx_mask, int slots, int slot_width)
+{
+	struct snd_soc_component *component = dai->component;
+	struct rt1318_priv *rt1318 = snd_soc_component_get_drvdata(component);
+	unsigned int cn = 0, cl = 0, rx_slotnum;
+	int ret = 0, first_bit;
+
+	switch (slots) {
+	case 4:
+		cn |= RT1318_I2S_CH_TX_4CH;
+		cn |= RT1318_I2S_CH_RX_4CH;
+		break;
+	case 6:
+		cn |= RT1318_I2S_CH_TX_6CH;
+		cn |= RT1318_I2S_CH_RX_6CH;
+		break;
+	case 8:
+		cn |= RT1318_I2S_CH_TX_8CH;
+		cn |= RT1318_I2S_CH_RX_8CH;
+		break;
+	case 2:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (slot_width) {
+	case 20:
+		cl |= RT1318_I2S_TX_CHL_20;
+		cl |= RT1318_I2S_RX_CHL_20;
+		break;
+	case 24:
+		cl |= RT1318_I2S_TX_CHL_24;
+		cl |= RT1318_I2S_RX_CHL_24;
+		break;
+	case 32:
+		cl |= RT1318_I2S_TX_CHL_32;
+		cl |= RT1318_I2S_RX_CHL_32;
+		break;
+	case 8:
+		cl |= RT1318_I2S_TX_CHL_8;
+		cl |= RT1318_I2S_RX_CHL_8;
+		break;
+	case 16:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* Rx slot configuration */
+	rx_slotnum = hweight_long(rx_mask);
+	if (rx_slotnum != 1) {
+		ret = -EINVAL;
+		dev_err(component->dev, "too many rx slots or zero slot\n");
+		goto _set_tdm_err_;
+	}
+
+	first_bit = __ffs(rx_mask);
+	switch (first_bit) {
+	case 0:
+	case 2:
+	case 4:
+	case 6:
+		regmap_update_bits(rt1318->regmap,
+			RT1318_TDM_CTRL9,
+			RT1318_TDM_I2S_TX_L_DAC1_1_MASK |
+			RT1318_TDM_I2S_TX_R_DAC1_1_MASK,
+			(first_bit << RT1318_TDM_I2S_TX_L_DAC1_1_SFT) |
+			((first_bit + 1) << RT1318_TDM_I2S_TX_R_DAC1_1_SFT));
+		break;
+	case 1:
+	case 3:
+	case 5:
+	case 7:
+		regmap_update_bits(rt1318->regmap,
+			RT1318_TDM_CTRL9,
+			RT1318_TDM_I2S_TX_L_DAC1_1_MASK |
+			RT1318_TDM_I2S_TX_R_DAC1_1_MASK,
+			((first_bit - 1) << RT1318_TDM_I2S_TX_L_DAC1_1_SFT) |
+			(first_bit << RT1318_TDM_I2S_TX_R_DAC1_1_SFT));
+		break;
+	default:
+		ret = -EINVAL;
+		goto _set_tdm_err_;
+	}
+
+	regmap_update_bits(rt1318->regmap, RT1318_TDM_CTRL2,
+			RT1318_I2S_CH_TX_MASK | RT1318_I2S_CH_RX_MASK, cn);
+	regmap_update_bits(rt1318->regmap, RT1318_TDM_CTRL3,
+			RT1318_I2S_TX_CHL_MASK | RT1318_I2S_RX_CHL_MASK, cl);
+
+_set_tdm_err_:
+	return ret;
+}
+
+static int rt1318_probe(struct snd_soc_component *component)
+{
+	struct rt1318_priv *rt1318 = snd_soc_component_get_drvdata(component);
+
+	rt1318->component = component;
+
+	schedule_work(&rt1318->cali_work);
+	rt1318->rt1318_dvol = RT1318_DVOL_STEP;
+
+	return 0;
+}
+
+static void rt1318_remove(struct snd_soc_component *component)
+{
+	struct rt1318_priv *rt1318 = snd_soc_component_get_drvdata(component);
+
+	cancel_work_sync(&rt1318->cali_work);
+}
+
+#ifdef CONFIG_PM
+static int rt1318_suspend(struct snd_soc_component *component)
+{
+	struct rt1318_priv *rt1318 = snd_soc_component_get_drvdata(component);
+
+	regcache_cache_only(rt1318->regmap, true);
+	regcache_mark_dirty(rt1318->regmap);
+	return 0;
+}
+
+static int rt1318_resume(struct snd_soc_component *component)
+{
+	struct rt1318_priv *rt1318 = snd_soc_component_get_drvdata(component);
+
+	regcache_cache_only(rt1318->regmap, false);
+	regcache_sync(rt1318->regmap);
+	return 0;
+}
+#else
+#define rt1318_suspend NULL
+#define rt1318_resume NULL
+#endif
+
+#define RT1318_STEREO_RATES SNDRV_PCM_RATE_8000_192000
+#define RT1318_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
+			SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8)
+
+static const struct snd_soc_dai_ops rt1318_aif_dai_ops = {
+	.hw_params = rt1318_hw_params,
+	.set_fmt = rt1318_set_dai_fmt,
+	.set_sysclk = rt1318_set_dai_sysclk,
+	.set_pll = rt1318_set_dai_pll,
+	.set_tdm_slot = rt1318_set_tdm_slot,
+};
+
+static struct snd_soc_dai_driver rt1318_dai[] = {
+	{
+		.name = "rt1318-aif",
+		.id = 0,
+		.playback = {
+			.stream_name = "AIF1 Playback",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = RT1318_STEREO_RATES,
+			.formats = RT1318_FORMATS,
+		},
+		.ops = &rt1318_aif_dai_ops,
+	}
+};
+
+static const struct snd_soc_component_driver soc_component_dev_rt1318 = {
+	.probe = rt1318_probe,
+	.remove = rt1318_remove,
+	.suspend = rt1318_suspend,
+	.resume = rt1318_resume,
+	.controls = rt1318_snd_controls,
+	.num_controls = ARRAY_SIZE(rt1318_snd_controls),
+	.dapm_widgets = rt1318_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(rt1318_dapm_widgets),
+	.dapm_routes = rt1318_dapm_routes,
+	.num_dapm_routes = ARRAY_SIZE(rt1318_dapm_routes),
+	.use_pmdown_time = 1,
+	.endianness = 1,
+};
+
+static const struct regmap_config rt1318_regmap = {
+	.reg_bits = 32,
+	.val_bits = 8,
+	.readable_reg = rt1318_readable_register,
+	.volatile_reg = rt1318_volatile_register,
+	.max_register = 0x41001888,
+	.reg_defaults = rt1318_reg,
+	.num_reg_defaults = ARRAY_SIZE(rt1318_reg),
+	.cache_type = REGCACHE_RBTREE,
+	.use_single_read = true,
+	.use_single_write = true,
+};
+
+static const struct i2c_device_id rt1318_i2c_id[] = {
+	{ "rt1318", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, rt1318_i2c_id);
+
+static const struct of_device_id rt1318_of_match[] = {
+	{ .compatible = "realtek,rt1318", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, rt1318_of_match);
+
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id rt1318_acpi_match[] = {
+	{ "10EC1318", 0},
+	{ },
+};
+MODULE_DEVICE_TABLE(acpi, rt1318_acpi_match);
+#endif
+
+static int rt1318_parse_dt(struct rt1318_priv *rt1318, struct device *dev)
+{
+	device_property_read_u32(dev, "realtek,r0_l",
+		&rt1318->pdata.init_r0_l);
+	device_property_read_u32(dev, "realtek,r0_r",
+		&rt1318->pdata.init_r0_r);
+
+	return 0;
+}
+
+static void rt1318_calibration_sequence(struct rt1318_priv *rt1318)
+{
+	regmap_write(rt1318->regmap, RT1318_CLK1, 0x22);
+	regmap_write(rt1318->regmap, RT1318_PLL1_N_7_0, 0x06);
+	regmap_write(rt1318->regmap, RT1318_STP_TEMP_L, 0xCC);
+	regmap_write(rt1318->regmap, RT1318_STP_SEL_L, 0x40);
+	regmap_write(rt1318->regmap, RT1318_STP_SEL_R, 0x40);
+	regmap_write(rt1318->regmap, RT1318_SINE_GEN0, 0x20);
+	regmap_write(rt1318->regmap, RT1318_SPK_VOL_TH, 0x00);
+	regmap_write(rt1318->regmap, RT1318_FEEDBACK_PATH, 0x0B);
+	regmap_write(rt1318->regmap, RT1318_TCON, 0x1C);
+	regmap_write(rt1318->regmap, RT1318_TCON_RELATE, 0x58);
+	regmap_write(rt1318->regmap, RT1318_TCON_RELATE, 0x78);
+	regmap_write(rt1318->regmap, RT1318_STP_R0_EN_L, 0xC2);
+}
+
+static void rt1318_r0_calculate(struct rt1318_priv *rt1318)
+{
+	unsigned int r0_l, r0_l_byte0, r0_l_byte1, r0_l_byte2, r0_l_byte3;
+	unsigned int r0_r, r0_r_byte0, r0_r_byte1, r0_r_byte2, r0_r_byte3;
+	unsigned int r0_l_integer, r0_l_factor, r0_r_integer, r0_r_factor;
+	unsigned int format = 16777216; /* 2^24 */
+
+	regmap_read(rt1318->regmap, RT1318_R0_L_24, &r0_l_byte0);
+	regmap_read(rt1318->regmap, RT1318_R0_L_23_16, &r0_l_byte1);
+	regmap_read(rt1318->regmap, RT1318_R0_L_15_8, &r0_l_byte2);
+	regmap_read(rt1318->regmap, RT1318_R0_L_7_0, &r0_l_byte3);
+	r0_l = r0_l_byte0 << 24 | r0_l_byte1 << 16 | r0_l_byte2 << 8 | r0_l_byte3;
+	r0_l_integer = format / r0_l;
+	r0_l_factor = (format * 10) / r0_l - r0_l_integer * 10;
+
+	regmap_read(rt1318->regmap, RT1318_R0_R_24, &r0_r_byte0);
+	regmap_read(rt1318->regmap, RT1318_R0_R_23_16, &r0_r_byte1);
+	regmap_read(rt1318->regmap, RT1318_R0_R_15_8, &r0_r_byte2);
+	regmap_read(rt1318->regmap, RT1318_R0_R_7_0, &r0_r_byte3);
+	r0_r = r0_r_byte0 << 24 | r0_r_byte1 << 16 | r0_r_byte2 << 8 | r0_r_byte3;
+	r0_r_integer = format / r0_r;
+	r0_r_factor = (format * 10) / r0_r - r0_r_integer * 10;
+
+	dev_dbg(rt1318->component->dev, "r0_l_ch:%d.%d ohm\n", r0_l_integer, r0_l_factor);
+	dev_dbg(rt1318->component->dev, "r0_r_ch:%d.%d ohm\n", r0_r_integer, r0_r_factor);
+}
+
+static void rt1318_r0_restore(struct rt1318_priv *rt1318)
+{
+	regmap_write(rt1318->regmap, RT1318_PRE_R0_L_24,
+		(rt1318->pdata.init_r0_l >> 24) & 0xff);
+	regmap_write(rt1318->regmap, RT1318_PRE_R0_L_23_16,
+		(rt1318->pdata.init_r0_l >> 16) & 0xff);
+	regmap_write(rt1318->regmap, RT1318_PRE_R0_L_15_8,
+		(rt1318->pdata.init_r0_l >> 8) & 0xff);
+	regmap_write(rt1318->regmap, RT1318_PRE_R0_L_7_0,
+		(rt1318->pdata.init_r0_l >> 0) & 0xff);
+	regmap_write(rt1318->regmap, RT1318_PRE_R0_R_24,
+		(rt1318->pdata.init_r0_r >> 24) & 0xff);
+	regmap_write(rt1318->regmap, RT1318_PRE_R0_R_23_16,
+		(rt1318->pdata.init_r0_r >> 16) & 0xff);
+	regmap_write(rt1318->regmap, RT1318_PRE_R0_R_15_8,
+		(rt1318->pdata.init_r0_r >> 8) & 0xff);
+	regmap_write(rt1318->regmap, RT1318_PRE_R0_R_7_0,
+		(rt1318->pdata.init_r0_r >> 0) & 0xff);
+	regmap_write(rt1318->regmap, RT1318_STP_SEL_L, 0x80);
+	regmap_write(rt1318->regmap, RT1318_STP_SEL_R, 0x80);
+	regmap_write(rt1318->regmap, RT1318_R0_CMP_L_FLAG, 0xc0);
+	regmap_write(rt1318->regmap, RT1318_R0_CMP_R_FLAG, 0xc0);
+	regmap_write(rt1318->regmap, RT1318_STP_R0_EN_L, 0xc0);
+	regmap_write(rt1318->regmap, RT1318_STP_R0_EN_R, 0xc0);
+	regmap_write(rt1318->regmap, RT1318_STP_TEMP_L, 0xcc);
+	regmap_write(rt1318->regmap, RT1318_TCON, 0x9c);
+}
+
+static int rt1318_calibrate(struct rt1318_priv *rt1318)
+{
+	int chk_cnt = 30, count = 0;
+	int val, val2;
+
+	regmap_write(rt1318->regmap, RT1318_PWR_STA1, 0x1);
+	usleep_range(0, 10000);
+	rt1318_calibration_sequence(rt1318);
+
+	while (count < chk_cnt) {
+		msleep(100);
+		regmap_read(rt1318->regmap, RT1318_R0_CMP_L_FLAG, &val);
+		regmap_read(rt1318->regmap, RT1318_R0_CMP_R_FLAG, &val2);
+		val = (val >> 1) & 0x1;
+		val2 = (val2 >> 1) & 0x1;
+		if (val & val2) {
+			dev_dbg(rt1318->component->dev, "Calibration done.\n");
+			break;
+		}
+		count++;
+		if (count == chk_cnt) {
+			regmap_write(rt1318->regmap, RT1318_PWR_STA1, 0x0);
+			return RT1318_R0_CALIB_NOT_DONE;
+		}
+	}
+	regmap_write(rt1318->regmap, RT1318_PWR_STA1, 0x0);
+	regmap_read(rt1318->regmap, RT1318_R0_CMP_L_FLAG, &val);
+	regmap_read(rt1318->regmap, RT1318_R0_CMP_R_FLAG, &val2);
+	if ((val & 0x1) & (val2 & 0x1))
+		return RT1318_R0_IN_RANGE;
+	else
+		return RT1318_R0_OUT_OF_RANGE;
+}
+
+static void rt1318_calibration_work(struct work_struct *work)
+{
+	struct rt1318_priv *rt1318 =
+		container_of(work, struct rt1318_priv, cali_work);
+	int ret;
+
+	if (rt1318->pdata.init_r0_l && rt1318->pdata.init_r0_r)
+		rt1318_r0_restore(rt1318);
+	else {
+		ret = rt1318_calibrate(rt1318);
+		if (ret == RT1318_R0_IN_RANGE)
+			rt1318_r0_calculate(rt1318);
+		dev_dbg(rt1318->component->dev, "Calibrate R0 result:%d\n", ret);
+	}
+}
+
+static int rt1318_i2c_probe(struct i2c_client *i2c)
+{
+	struct rt1318_platform_data *pdata = dev_get_platdata(&i2c->dev);
+	struct rt1318_priv *rt1318;
+	int ret, val, val2, dev_id;
+
+	rt1318 = devm_kzalloc(&i2c->dev, sizeof(struct rt1318_priv),
+				GFP_KERNEL);
+	if (!rt1318)
+		return -ENOMEM;
+
+	i2c_set_clientdata(i2c, rt1318);
+
+	if (pdata)
+		rt1318->pdata = *pdata;
+	else
+		rt1318_parse_dt(rt1318, &i2c->dev);
+
+	rt1318->regmap = devm_regmap_init_i2c(i2c, &rt1318_regmap);
+	if (IS_ERR(rt1318->regmap)) {
+		ret = PTR_ERR(rt1318->regmap);
+		dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
+			ret);
+		return ret;
+	}
+
+	regmap_read(rt1318->regmap, RT1318_DEV_ID1, &val);
+	regmap_read(rt1318->regmap, RT1318_DEV_ID2, &val2);
+	dev_id = (val << 8) | val2;
+	if (dev_id != 0x6821) {
+		dev_err(&i2c->dev,
+			"Device with ID register %#x is not rt1318\n",
+			dev_id);
+		return -ENODEV;
+	}
+
+	ret = regmap_register_patch(rt1318->regmap, init_list,
+				    ARRAY_SIZE(init_list));
+	if (ret != 0)
+		dev_warn(&i2c->dev, "Failed to apply regmap patch: %d\n", ret);
+
+	INIT_WORK(&rt1318->cali_work, rt1318_calibration_work);
+
+	return devm_snd_soc_register_component(&i2c->dev,
+		&soc_component_dev_rt1318, rt1318_dai, ARRAY_SIZE(rt1318_dai));
+}
+
+static struct i2c_driver rt1318_i2c_driver = {
+	.driver = {
+		.name = "rt1318",
+		.of_match_table = of_match_ptr(rt1318_of_match),
+		.acpi_match_table = ACPI_PTR(rt1318_acpi_match),
+	},
+	.probe = rt1318_i2c_probe,
+	.id_table = rt1318_i2c_id,
+};
+module_i2c_driver(rt1318_i2c_driver);
+
+MODULE_DESCRIPTION("ASoC RT1318 driver");
+MODULE_AUTHOR("Jack Yu <jack.yu@realtek.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/rt1318.h b/sound/soc/codecs/rt1318.h
new file mode 100644
index 0000000..cec40b4
--- /dev/null
+++ b/sound/soc/codecs/rt1318.h
@@ -0,0 +1,342 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * rt1318.h -- Platform data for RT1318
+ *
+ * Copyright 2024 Realtek Semiconductor Corp.
+ */
+#include <sound/rt1318.h>
+
+#ifndef __RT1318_H__
+#define __RT1318_H__
+
+struct rt1318_priv {
+	struct snd_soc_component *component;
+	struct rt1318_platform_data pdata;
+	struct work_struct cali_work;
+	struct regmap *regmap;
+
+	unsigned int r0_l_integer;
+	unsigned int r0_l_factor;
+	unsigned int r0_r_integer;
+	unsigned int r0_r_factor;
+	int rt1318_init;
+	int rt1318_dvol;
+	int sysclk_src;
+	int sysclk;
+	int lrck;
+	int bclk;
+	int master;
+	int pll_src;
+	int pll_in;
+	int pll_out;
+};
+
+#define RT1318_PLL_INP_MAX	40000000
+#define RT1318_PLL_INP_MIN	256000
+#define RT1318_PLL_N_MAX	0x1ff
+#define RT1318_PLL_K_MAX	0x1f
+#define RT1318_PLL_M_MAX	0x1f
+
+#define RT1318_LRCLK_192000 192000
+#define RT1318_LRCLK_96000 96000
+#define RT1318_LRCLK_48000 48000
+#define RT1318_LRCLK_44100 44100
+#define RT1318_LRCLK_16000 16000
+#define RT1318_DVOL_STEP 383
+
+#define RT1318_CLK1				0xc001
+#define RT1318_CLK2				0xc003
+#define RT1318_CLK3				0xc004
+#define RT1318_CLK4				0xc005
+#define RT1318_CLK5				0xc006
+#define RT1318_CLK6				0xc007
+#define RT1318_CLK7				0xc008
+#define RT1318_PWR_STA1				0xc121
+#define RT1318_SPK_VOL_TH			0xc130
+#define RT1318_TCON				0xc203
+#define RT1318_SRC_TCON				0xc204
+#define RT1318_TCON_RELATE			0xc206
+#define RT1318_DA_VOL_L_8			0xc20b
+#define RT1318_DA_VOL_L_1_7			0xc20c
+#define RT1318_DA_VOL_R_8			0xc20d
+#define RT1318_DA_VOL_R_1_7			0xc20e
+#define RT1318_FEEDBACK_PATH			0xc321
+#define RT1318_STP_TEMP_L			0xdb00
+#define RT1318_STP_SEL_L			0xdb08
+#define RT1318_STP_R0_EN_L			0xdb12
+#define RT1318_R0_CMP_L_FLAG			0xdb35
+#define RT1318_PRE_R0_L_24			0xdbb5
+#define RT1318_PRE_R0_L_23_16			0xdbb6
+#define RT1318_PRE_R0_L_15_8			0xdbb7
+#define RT1318_PRE_R0_L_7_0			0xdbb8
+#define RT1318_R0_L_24				0xdbc5
+#define RT1318_R0_L_23_16			0xdbc6
+#define RT1318_R0_L_15_8			0xdbc7
+#define RT1318_R0_L_7_0				0xdbc8
+#define RT1318_STP_SEL_R			0xdd08
+#define RT1318_STP_R0_EN_R			0xdd12
+#define RT1318_R0_CMP_R_FLAG			0xdd35
+#define RT1318_PRE_R0_R_24			0xddb5
+#define RT1318_PRE_R0_R_23_16			0xddb6
+#define RT1318_PRE_R0_R_15_8			0xddb7
+#define RT1318_PRE_R0_R_7_0			0xddb8
+#define RT1318_R0_R_24				0xddc5
+#define RT1318_R0_R_23_16			0xddc6
+#define RT1318_R0_R_15_8			0xddc7
+#define RT1318_R0_R_7_0				0xddc8
+#define RT1318_DEV_ID1				0xf012
+#define RT1318_DEV_ID2				0xf013
+#define RT1318_PLL1_K				0xf20d
+#define RT1318_PLL1_M				0xf20f
+#define RT1318_PLL1_N_8				0xf211
+#define RT1318_PLL1_N_7_0			0xf212
+#define RT1318_SINE_GEN0			0xf800
+#define RT1318_TDM_CTRL1			0xf900
+#define RT1318_TDM_CTRL2			0xf901
+#define RT1318_TDM_CTRL3			0xf902
+#define RT1318_TDM_CTRL9			0xf908
+
+
+/* Clock-1  (0xC001) */
+#define RT1318_PLLIN_MASK			(0x7 << 4)
+#define RT1318_PLLIN_BCLK0			(0x0 << 4)
+#define RT1318_PLLIN_BCLK1			(0x1 << 4)
+#define RT1318_PLLIN_RC				(0x2 << 4)
+#define RT1318_PLLIN_MCLK			(0x3 << 4)
+#define RT1318_PLLIN_SDW1			(0x4 << 4)
+#define RT1318_PLLIN_SDW2			(0x5 << 4)
+#define RT1318_PLLIN_SDW3			(0x6 << 4)
+#define RT1318_PLLIN_SDW4			(0x7 << 4)
+#define RT1318_SYSCLK_SEL_MASK			(0x7 << 0)
+#define RT1318_SYSCLK_BCLK			(0x0 << 0)
+#define RT1318_SYSCLK_SDW			(0x1 << 0)
+#define RT1318_SYSCLK_PLL2F			(0x2 << 0)
+#define RT1318_SYSCLK_PLL2B			(0x3 << 0)
+#define RT1318_SYSCLK_MCLK			(0x4 << 0)
+#define RT1318_SYSCLK_RC1			(0x5 << 0)
+#define RT1318_SYSCLK_RC2			(0x6 << 0)
+#define RT1318_SYSCLK_RC3			(0x7 << 0)
+/* Clock-2  (0xC003) */
+#define RT1318_DIV_AP_MASK			(0x3 << 4)
+#define RT1318_DIV_AP_SFT			4
+#define RT1318_DIV_AP_DIV1			(0x0 << 4)
+#define RT1318_DIV_AP_DIV2			(0x1 << 4)
+#define RT1318_DIV_AP_DIV4			(0x2 << 4)
+#define RT1318_DIV_AP_DIV8			(0x3 << 4)
+#define RT1318_DIV_DAMOD_MASK			(0x3 << 0)
+#define RT1318_DIV_DAMOD_SFT			0
+#define RT1318_DIV_DAMOD_DIV1			(0x0 << 0)
+#define RT1318_DIV_DAMOD_DIV2			(0x1 << 0)
+#define RT1318_DIV_DAMOD_DIV4			(0x2 << 0)
+#define RT1318_DIV_DAMOD_DIV8			(0x3 << 0)
+/* Clock-3  (0xC004) */
+#define RT1318_AD_STO1_MASK			(0x7 << 4)
+#define RT1318_AD_STO1_SFT			4
+#define RT1318_AD_STO1_DIV1			(0x0 << 4)
+#define RT1318_AD_STO1_DIV2			(0x1 << 4)
+#define RT1318_AD_STO1_DIV4			(0x2 << 4)
+#define RT1318_AD_STO1_DIV8			(0x3 << 4)
+#define RT1318_AD_STO1_DIV16			(0x4 << 4)
+#define RT1318_AD_STO2_MASK			(0x7 << 0)
+#define RT1318_AD_STO2_SFT			0
+#define RT1318_AD_STO2_DIV1			(0x0 << 0)
+#define RT1318_AD_STO2_DIV2			(0x1 << 0)
+#define RT1318_AD_STO2_DIV4			(0x2 << 0)
+#define RT1318_AD_STO2_DIV8			(0x3 << 0)
+#define RT1318_AD_STO2_DIV16			(0x4 << 0)
+#define RT1318_AD_STO2_SFT			0
+/* Clock-4  (0xC005) */
+#define RT1318_AD_ANA_STO1_MASK			(0x7 << 4)
+#define RT1318_AD_ANA_STO1_SFT			4
+#define RT1318_AD_ANA_STO1_DIV1			(0x0 << 4)
+#define RT1318_AD_ANA_STO1_DIV2			(0x1 << 4)
+#define RT1318_AD_ANA_STO1_DIV4			(0x2 << 4)
+#define RT1318_AD_ANA_STO1_DIV8			(0x3 << 4)
+#define RT1318_AD_ANA_STO1_DIV16		(0x4 << 4)
+#define RT1318_AD_ANA_STO2_MASK			(0x7 << 0)
+#define RT1318_AD_ANA_STO2_DIV1			(0x0 << 0)
+#define RT1318_AD_ANA_STO2_DIV2			(0x1 << 0)
+#define RT1318_AD_ANA_STO2_DIV4			(0x2 << 0)
+#define RT1318_AD_ANA_STO2_DIV8			(0x3 << 0)
+#define RT1318_AD_ANA_STO2_DIV16		(0x4 << 0)
+#define RT1318_AD_ANA_STO2_SFT			0
+/* Clock-5  (0xC006) */
+#define RT1318_DIV_FIFO_IN_MASK			(0x3 << 4)
+#define RT1318_DIV_FIFO_IN_SFT			4
+#define RT1318_DIV_FIFO_IN_DIV1			(0x0 << 4)
+#define RT1318_DIV_FIFO_IN_DIV2			(0x1 << 4)
+#define RT1318_DIV_FIFO_IN_DIV4			(0x2 << 4)
+#define RT1318_DIV_FIFO_IN_DIV8			(0x3 << 4)
+#define RT1318_DIV_FIFO_OUT_MASK		(0x3 << 0)
+#define RT1318_DIV_FIFO_OUT_DIV1		(0x0 << 0)
+#define RT1318_DIV_FIFO_OUT_DIV2		(0x1 << 0)
+#define RT1318_DIV_FIFO_OUT_DIV4		(0x2 << 0)
+#define RT1318_DIV_FIFO_OUT_DIV8		(0x3 << 0)
+#define RT1318_DIV_FIFO_OUT_SFT			0
+/* Clock-6  (0xC007) */
+#define RT1318_DIV_NLMS_MASK			(0x3 << 6)
+#define RT1318_DIV_NLMS_SFT				6
+#define RT1318_DIV_NLMS_DIV1			(0x0 << 6)
+#define RT1318_DIV_NLMS_DIV2			(0x1 << 6)
+#define RT1318_DIV_NLMS_DIV4			(0x2 << 6)
+#define RT1318_DIV_NLMS_DIV8			(0x3 << 6)
+#define RT1318_DIV_AD_MONO_MASK			(0x7 << 3)
+#define RT1318_DIV_AD_MONO_SFT			3
+#define RT1318_DIV_AD_MONO_DIV1			(0x0 << 3)
+#define RT1318_DIV_AD_MONO_DIV2			(0x1 << 3)
+#define RT1318_DIV_AD_MONO_DIV4			(0x2 << 3)
+#define RT1318_DIV_AD_MONO_DIV8			(0x3 << 3)
+#define RT1318_DIV_AD_MONO_DIV16		(0x4 << 3)
+#define RT1318_DIV_POST_G_MASK			(0x7 << 0)
+#define RT1318_DIV_POST_G_SFT			0
+#define RT1318_DIV_POST_G_DIV1			(0x0 << 0)
+#define RT1318_DIV_POST_G_DIV2			(0x1 << 0)
+#define RT1318_DIV_POST_G_DIV4			(0x2 << 0)
+#define RT1318_DIV_POST_G_DIV8			(0x3 << 0)
+#define RT1318_DIV_POST_G_DIV16			(0x4 << 0)
+/* Power Status 1  (0xC121) */
+#define RT1318_PDB_CTRL_MASK			(0x1)
+#define RT1318_PDB_CTRL_LOW			(0x0)
+#define RT1318_PDB_CTRL_HIGH			(0x1)
+#define RT1318_PDB_CTRL_SFT			0
+/* SRC Tcon(0xc204) */
+#define RT1318_SRCIN_IN_SEL_MASK		(0x3 << 6)
+#define RT1318_SRCIN_IN_48K			(0x0 << 6)
+#define RT1318_SRCIN_IN_44P1			(0x1 << 6)
+#define RT1318_SRCIN_IN_32K			(0x2 << 6)
+#define RT1318_SRCIN_IN_16K			(0x3 << 6)
+#define RT1318_SRCIN_F12288_MASK		(0x3 << 4)
+#define RT1318_SRCIN_TCON1			(0x0 << 4)
+#define RT1318_SRCIN_TCON2			(0x1 << 4)
+#define RT1318_SRCIN_TCON4			(0x2 << 4)
+#define RT1318_SRCIN_TCON8			(0x3 << 4)
+#define RT1318_SRCIN_DACLK_MASK			(0x3 << 2)
+#define RT1318_DACLK_TCON1			(0x0 << 2)
+#define RT1318_DACLK_TCON2			(0x1 << 2)
+#define RT1318_DACLK_TCON4			(0x2 << 2)
+#define RT1318_DACLK_TCON8			(0x3 << 2)
+/* R0 Compare Flag  (0xDB35) */
+#define RT1318_R0_RANGE_MASK			(0x1)
+#define RT1318_R0_OUTOFRANGE			(0x0)
+#define RT1318_R0_INRANGE			(0x1)
+/* PLL internal setting (0xF20D), K value */
+#define RT1318_K_PLL1_MASK			(0x1f << 0)
+/* PLL internal setting (0xF20F), M value */
+#define RT1318_M_PLL1_MASK			(0x1f << 0)
+/* PLL internal setting (0xF211), N_8 value */
+#define RT1318_N_8_PLL1_MASK			(0x1 << 0)
+/* PLL internal setting (0xF212), N_7_0 value */
+#define RT1318_N_7_0_PLL1_MASK			(0xff << 0)
+/* TDM CTRL 1  (0xf900) */
+#define RT1318_TDM_BCLK_MASK			(0x1 << 7)
+#define RT1318_TDM_BCLK_NORM			(0x0 << 7)
+#define RT1318_TDM_BCLK_INV			(0x1 << 7)
+#define RT1318_I2S_FMT_MASK			(0x7 << 0)
+#define RT1318_FMT_I2S				(0x0 << 0)
+#define RT1318_FMT_LEFT_J			(0x1 << 0)
+#define RT1318_FMT_PCM_A_R			(0x2 << 0)
+#define RT1318_FMT_PCM_B_R			(0x3 << 0)
+#define RT1318_FMT_PCM_A_F			(0x6 << 0)
+#define RT1318_FMT_PCM_B_F			(0x7 << 0)
+#define RT1318_I2S_FMT_SFT			0
+/* TDM CTRL 2  (0xf901) */
+#define RT1318_I2S_CH_TX_MASK			(0x3 << 6)
+#define RT1318_I2S_CH_TX_2CH			(0x0 << 6)
+#define RT1318_I2S_CH_TX_4CH			(0x1 << 6)
+#define RT1318_I2S_CH_TX_6CH			(0x2 << 6)
+#define RT1318_I2S_CH_TX_8CH			(0x3 << 6)
+#define RT1318_I2S_CH_RX_MASK			(0x3 << 4)
+#define RT1318_I2S_CH_RX_2CH			(0x0 << 4)
+#define RT1318_I2S_CH_RX_4CH			(0x1 << 4)
+#define RT1318_I2S_CH_RX_6CH			(0x2 << 4)
+#define RT1318_I2S_CH_RX_8CH			(0x3 << 4)
+#define RT1318_I2S_DL_MASK			0x7
+#define RT1318_I2S_DL_SFT			0
+#define RT1318_I2S_DL_16			0x0
+#define RT1318_I2S_DL_20			0x1
+#define RT1318_I2S_DL_24			0x2
+#define RT1318_I2S_DL_32			0x3
+#define RT1318_I2S_DL_8				0x4
+/* TDM CTRL 3  (0xf902) */
+#define RT1318_I2S_TX_CHL_MASK			(0x7 << 4)
+#define RT1318_I2S_TX_CHL_SFT			4
+#define RT1318_I2S_TX_CHL_16			(0x0 << 4)
+#define RT1318_I2S_TX_CHL_20			(0x1 << 4)
+#define RT1318_I2S_TX_CHL_24			(0x2 << 4)
+#define RT1318_I2S_TX_CHL_32			(0x3 << 4)
+#define RT1318_I2S_TX_CHL_8			(0x4 << 4)
+#define RT1318_I2S_RX_CHL_MASK			(0x7 << 0)
+#define RT1318_I2S_RX_CHL_SFT			0
+#define RT1318_I2S_RX_CHL_16			(0x0 << 0)
+#define RT1318_I2S_RX_CHL_20			(0x1 << 0)
+#define RT1318_I2S_RX_CHL_24			(0x2 << 0)
+#define RT1318_I2S_RX_CHL_32			(0x3 << 0)
+#define RT1318_I2S_RX_CHL_8			(0x4 << 0)
+/* TDM CTRL 9  (0xf908) */
+#define RT1318_TDM_I2S_TX_L_DAC1_1_MASK		(0x7 << 4)
+#define RT1318_TDM_I2S_TX_R_DAC1_1_MASK		0x7
+#define RT1318_TDM_I2S_TX_L_DAC1_1_SFT		4
+#define RT1318_TDM_I2S_TX_R_DAC1_1_SFT		0
+
+#define RT1318_REG_DISP_LEN 23
+
+/* System Clock Source */
+enum {
+	RT1318_SCLK_S_BCLK,
+	RT1318_SCLK_S_SDW,
+	RT1318_SCLK_S_PLL2F,
+	RT1318_SCLK_S_PLL2B,
+	RT1318_SCLK_S_MCLK,
+	RT1318_SCLK_S_RC0,
+	RT1318_SCLK_S_RC1,
+	RT1318_SCLK_S_RC2,
+};
+
+/* PLL Source */
+enum {
+	RT1318_PLL_S_BCLK0,
+	RT1318_PLL_S_BCLK1,
+	RT1318_PLL_S_RC,
+	RT1318_PLL_S_MCLK,
+	RT1318_PLL_S_SDW_IN_PLL,
+	RT1318_PLL_S_SDW_0,
+	RT1318_PLL_S_SDW_1,
+	RT1318_PLL_S_SDW_2,
+};
+
+/* TDM channel */
+enum {
+	RT1318_2CH,
+	RT1318_4CH,
+	RT1318_6CH,
+	RT1318_8CH,
+};
+
+/* R0 calibration result */
+enum {
+	RT1318_R0_OUT_OF_RANGE,
+	RT1318_R0_IN_RANGE,
+	RT1318_R0_CALIB_NOT_DONE,
+};
+
+/* PLL pre-defined M/N/K */
+
+struct pll_calc_map {
+	unsigned int pll_in;
+	unsigned int pll_out;
+	int k;
+	int n;
+	int m;
+	bool m_bp;
+	bool k_bp;
+};
+
+struct rt1318_pll_code {
+	bool m_bp; /* Indicates bypass m code or not. */
+	bool k_bp; /* Indicates bypass k code or not. */
+	int m_code;
+	int n_code;
+	int k_code;
+};
+
+#endif /* __RT1318_H__ */
diff --git a/sound/soc/codecs/rt722-sdca-sdw.c b/sound/soc/codecs/rt722-sdca-sdw.c
index b33da22..87354bb 100644
--- a/sound/soc/codecs/rt722-sdca-sdw.c
+++ b/sound/soc/codecs/rt722-sdca-sdw.c
@@ -68,6 +68,7 @@ static bool rt722_sdca_mbq_readable_register(struct device *dev, unsigned int re
 	case 0x200007f:
 	case 0x2000082 ... 0x200008e:
 	case 0x2000090 ... 0x2000094:
+	case 0x3110000:
 	case 0x5300000 ... 0x5300002:
 	case 0x5400002:
 	case 0x5600000 ... 0x5600007:
@@ -125,6 +126,7 @@ static bool rt722_sdca_mbq_volatile_register(struct device *dev, unsigned int re
 	case 0x2000067:
 	case 0x2000084:
 	case 0x2000086:
+	case 0x3110000:
 		return true;
 	default:
 		return false;
@@ -350,7 +352,7 @@ static int rt722_sdca_interrupt_callback(struct sdw_slave *slave,
 
 	if (status->sdca_cascade && !rt722->disable_irq)
 		mod_delayed_work(system_power_efficient_wq,
-			&rt722->jack_detect_work, msecs_to_jiffies(30));
+			&rt722->jack_detect_work, msecs_to_jiffies(280));
 
 	mutex_unlock(&rt722->disable_irq_lock);
 
diff --git a/sound/soc/codecs/tlv320adc3xxx.c b/sound/soc/codecs/tlv320adc3xxx.c
index eb180df..7073b9d 100644
--- a/sound/soc/codecs/tlv320adc3xxx.c
+++ b/sound/soc/codecs/tlv320adc3xxx.c
@@ -39,9 +39,10 @@
  */
 
 #define ADC3XXX_MICBIAS_PINS		2
+#define ADC3XXX_GPIO_PINS		2
 
 /* Number of GPIO pins exposed via the gpiolib interface */
-#define ADC3XXX_GPIOS_MAX		2
+#define ADC3XXX_GPIOS_MAX		(ADC3XXX_MICBIAS_PINS + ADC3XXX_GPIO_PINS)
 
 #define ADC3XXX_RATES		SNDRV_PCM_RATE_8000_96000
 #define ADC3XXX_FORMATS		(SNDRV_PCM_FMTBIT_S16_LE | \
@@ -320,7 +321,8 @@ struct adc3xxx {
 	struct gpio_desc *rst_pin;
 	unsigned int pll_mode;
 	unsigned int sysclk;
-	unsigned int gpio_cfg[ADC3XXX_GPIOS_MAX]; /* value+1 (0 => not set)  */
+	unsigned int gpio_cfg[ADC3XXX_GPIO_PINS]; /* value+1 (0 => not set)  */
+	unsigned int micbias_gpo[ADC3XXX_MICBIAS_PINS]; /* 1 => pin is GPO */
 	unsigned int micbias_vg[ADC3XXX_MICBIAS_PINS];
 	int master;
 	u8 page_no;
@@ -328,7 +330,7 @@ struct adc3xxx {
 	struct gpio_chip gpio_chip;
 };
 
-static const unsigned int adc3xxx_gpio_ctrl_reg[ADC3XXX_GPIOS_MAX] = {
+static const unsigned int adc3xxx_gpio_ctrl_reg[ADC3XXX_GPIO_PINS] = {
 	ADC3XXX_GPIO1_CTRL,
 	ADC3XXX_GPIO2_CTRL
 };
@@ -959,14 +961,23 @@ static int adc3xxx_gpio_request(struct gpio_chip *chip, unsigned int offset)
 	if (offset >= ADC3XXX_GPIOS_MAX)
 		return -EINVAL;
 
-	/* GPIO1 is offset 0, GPIO2 is offset 1 */
-	/* We check here that the GPIO pins are either not configured in the
-	 * DT, or that they purposely are set as outputs.
-	 * (Input mode not yet implemented).
-	 */
-	if (adc3xxx->gpio_cfg[offset] != 0 &&
-	    adc3xxx->gpio_cfg[offset] != ADC3XXX_GPIO_GPO + 1)
-		return -EINVAL;
+	if (offset >= 0 && offset < ADC3XXX_GPIO_PINS) {
+		/* GPIO1 is offset 0, GPIO2 is offset 1 */
+		/* We check here that the GPIO pins are either not configured
+		 * in the DT, or that they purposely are set as outputs.
+		 * (Input mode not yet implemented).
+		 */
+		if (adc3xxx->gpio_cfg[offset] != 0 &&
+		    adc3xxx->gpio_cfg[offset] != ADC3XXX_GPIO_GPO + 1)
+			return -EINVAL;
+	} else if (offset >= ADC3XXX_GPIO_PINS && offset < ADC3XXX_GPIOS_MAX) {
+		/* MICBIAS1 is offset 2, MICBIAS2 is offset 3 */
+		/* We check here if the MICBIAS pins are in fact configured
+		 * as GPOs.
+		 */
+		if (!adc3xxx->micbias_gpo[offset - ADC3XXX_GPIO_PINS])
+			return -EINVAL;
+	}
 
 	return 0;
 }
@@ -976,6 +987,21 @@ static int adc3xxx_gpio_direction_out(struct gpio_chip *chip,
 {
 	struct adc3xxx *adc3xxx = gpiochip_get_data(chip);
 
+	/* For the MICBIAS pins, they are by definition outputs. */
+	if (offset >= ADC3XXX_GPIO_PINS) {
+		unsigned int vg;
+		unsigned int micbias = offset - ADC3XXX_GPIO_PINS;
+
+		if (value)
+			vg = adc3xxx->micbias_vg[micbias];
+		else
+			vg = ADC3XXX_MICBIAS_OFF;
+		return regmap_update_bits(adc3xxx->regmap,
+					   ADC3XXX_MICBIAS_CTRL,
+					   ADC3XXX_MICBIAS_MASK << adc3xxx_micbias_shift[micbias],
+					   vg << adc3xxx_micbias_shift[micbias]);
+	}
+
 	/* Set GPIO output function. */
 	return regmap_update_bits(adc3xxx->regmap,
 				  adc3xxx_gpio_ctrl_reg[offset],
@@ -1004,9 +1030,17 @@ static int adc3xxx_gpio_get(struct gpio_chip *chip, unsigned int offset)
 	unsigned int regval;
 	int ret;
 
-	/* We only allow output pins, so just read the value set in the output
-	 * pin register field.
-	 */
+	/* We only allow output pins, so just read the value prevously set. */
+	if (offset >= ADC3XXX_GPIO_PINS) {
+		/* MICBIAS pins */
+		unsigned int micbias = offset - ADC3XXX_GPIO_PINS;
+
+		ret = regmap_read(adc3xxx->regmap, ADC3XXX_MICBIAS_CTRL, &regval);
+		if (ret)
+			return ret;
+		return ((regval >> adc3xxx_micbias_shift[micbias]) & ADC3XXX_MICBIAS_MASK) !=
+		       ADC3XXX_MICBIAS_OFF;
+	}
 	ret = regmap_read(adc3xxx->regmap, adc3xxx_gpio_ctrl_reg[offset], &regval);
 	if (ret)
 		return ret;
@@ -1048,7 +1082,7 @@ static void adc3xxx_init_gpio(struct adc3xxx *adc3xxx)
 	 * This allows us to set up things which are not software
 	 * controllable GPIOs, such as PDM microphone I/O,
 	 */
-	for (gpio = 0; gpio < ADC3XXX_GPIOS_MAX; gpio++) {
+	for (gpio = 0; gpio < ADC3XXX_GPIO_PINS; gpio++) {
 		unsigned int cfg = adc3xxx->gpio_cfg[gpio];
 
 		if (cfg) {
@@ -1060,9 +1094,15 @@ static void adc3xxx_init_gpio(struct adc3xxx *adc3xxx)
 		}
 	}
 
-	/* Set up micbias voltage */
+	/* Set up micbias voltage. */
+	/* If pin is configured as GPO, set off initially. */
 	for (micbias = 0; micbias < ADC3XXX_MICBIAS_PINS; micbias++) {
-		unsigned int vg = adc3xxx->micbias_vg[micbias];
+		unsigned int vg;
+
+		if (adc3xxx->micbias_gpo[micbias])
+			vg = ADC3XXX_MICBIAS_OFF;
+		else
+			vg = adc3xxx->micbias_vg[micbias];
 
 		regmap_update_bits(adc3xxx->regmap,
 				   ADC3XXX_MICBIAS_CTRL,
@@ -1090,8 +1130,19 @@ static int adc3xxx_parse_dt_gpio(struct adc3xxx *adc3xxx,
 	return 0;
 }
 
-static int adc3xxx_parse_dt_micbias(struct adc3xxx *adc3xxx,
-				    const char *propname, unsigned int *vg)
+static int adc3xxx_parse_dt_micbias_gpo(struct adc3xxx *adc3xxx,
+					const char *propname,
+					unsigned int *cfg)
+{
+	struct device *dev = adc3xxx->dev;
+	struct device_node *np = dev->of_node;
+
+	*cfg = of_property_read_bool(np, propname);
+	return 0;
+}
+
+static int adc3xxx_parse_dt_micbias_vg(struct adc3xxx *adc3xxx,
+				       const char *propname, unsigned int *vg)
 {
 	struct device *dev = adc3xxx->dev;
 	struct device_node *np = dev->of_node;
@@ -1382,16 +1433,28 @@ static int adc3xxx_i2c_probe(struct i2c_client *i2c)
 		dev_dbg(dev, "Enabled MCLK, freq %lu Hz\n", clk_get_rate(adc3xxx->mclk));
 	}
 
+	/* Configure mode for DMDIN/GPIO1 pin */
 	ret = adc3xxx_parse_dt_gpio(adc3xxx, "ti,dmdin-gpio1", &adc3xxx->gpio_cfg[0]);
 	if (ret < 0)
 		goto err_unprepare_mclk;
+	/* Configure mode for DMCLK/GPIO2 pin */
 	ret = adc3xxx_parse_dt_gpio(adc3xxx, "ti,dmclk-gpio2", &adc3xxx->gpio_cfg[1]);
 	if (ret < 0)
 		goto err_unprepare_mclk;
-	ret = adc3xxx_parse_dt_micbias(adc3xxx, "ti,micbias1-vg", &adc3xxx->micbias_vg[0]);
+	/* Configure mode for MICBIAS1: as Mic Bias output or GPO */
+	ret = adc3xxx_parse_dt_micbias_gpo(adc3xxx, "ti,micbias1-gpo", &adc3xxx->micbias_gpo[0]);
 	if (ret < 0)
 		goto err_unprepare_mclk;
-	ret = adc3xxx_parse_dt_micbias(adc3xxx, "ti,micbias2-vg", &adc3xxx->micbias_vg[1]);
+	/* Configure mode for MICBIAS2: as Mic Bias output or GPO */
+	ret = adc3xxx_parse_dt_micbias_gpo(adc3xxx, "ti,micbias2-gpo", &adc3xxx->micbias_gpo[1]);
+	if (ret < 0)
+		goto err_unprepare_mclk;
+	/* Configure voltage for MICBIAS1 pin (ON voltage when used as GPO) */
+	ret = adc3xxx_parse_dt_micbias_vg(adc3xxx, "ti,micbias1-vg", &adc3xxx->micbias_vg[0]);
+	if (ret < 0)
+		goto err_unprepare_mclk;
+	/* Configure voltage for MICBIAS2 pin (ON voltage when used as GPO) */
+	ret = adc3xxx_parse_dt_micbias_vg(adc3xxx, "ti,micbias2-vg", &adc3xxx->micbias_vg[1]);
 	if (ret < 0)
 		goto err_unprepare_mclk;
 
diff --git a/sound/soc/codecs/wcd-mbhc-v2.c b/sound/soc/codecs/wcd-mbhc-v2.c
index 0e6218e..d589a212 100644
--- a/sound/soc/codecs/wcd-mbhc-v2.c
+++ b/sound/soc/codecs/wcd-mbhc-v2.c
@@ -50,7 +50,7 @@ struct wcd_mbhc {
 	struct wcd_mbhc_config *cfg;
 	const struct wcd_mbhc_cb *mbhc_cb;
 	const struct wcd_mbhc_intr *intr_ids;
-	struct wcd_mbhc_field *fields;
+	const struct wcd_mbhc_field *fields;
 	/* Delayed work to report long button press */
 	struct delayed_work mbhc_btn_dwork;
 	/* Work to handle plug report */
@@ -1505,7 +1505,7 @@ EXPORT_SYMBOL(wcd_dt_parse_mbhc_data);
 struct wcd_mbhc *wcd_mbhc_init(struct snd_soc_component *component,
 			       const struct wcd_mbhc_cb *mbhc_cb,
 			       const struct wcd_mbhc_intr *intr_ids,
-			       struct wcd_mbhc_field *fields,
+			       const struct wcd_mbhc_field *fields,
 			       bool impedance_det_en)
 {
 	struct device *dev = component->dev;
diff --git a/sound/soc/codecs/wcd-mbhc-v2.h b/sound/soc/codecs/wcd-mbhc-v2.h
index df68e99c..b977e8f 100644
--- a/sound/soc/codecs/wcd-mbhc-v2.h
+++ b/sound/soc/codecs/wcd-mbhc-v2.h
@@ -279,7 +279,7 @@ int wcd_mbhc_typec_report_unplug(struct wcd_mbhc *mbhc);
 struct wcd_mbhc *wcd_mbhc_init(struct snd_soc_component *component,
 		      const struct wcd_mbhc_cb *mbhc_cb,
 		      const struct wcd_mbhc_intr *mbhc_cdc_intr_ids,
-		      struct wcd_mbhc_field *fields,
+		      const struct wcd_mbhc_field *fields,
 		      bool impedance_det_en);
 int wcd_mbhc_get_impedance(struct wcd_mbhc *mbhc, uint32_t *zl,
 			   uint32_t *zr);
@@ -300,7 +300,7 @@ static inline void wcd_mbhc_stop(struct wcd_mbhc *mbhc)
 static inline struct wcd_mbhc *wcd_mbhc_init(struct snd_soc_component *component,
 		      const struct wcd_mbhc_cb *mbhc_cb,
 		      const struct wcd_mbhc_intr *mbhc_cdc_intr_ids,
-		      struct wcd_mbhc_field *fields,
+		      const struct wcd_mbhc_field *fields,
 		      bool impedance_det_en)
 {
 	return ERR_PTR(-ENOTSUPP);
diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c
index 42a9997..f5fe258 100644
--- a/sound/soc/codecs/wcd9335.c
+++ b/sound/soc/codecs/wcd9335.c
@@ -297,7 +297,6 @@ struct wcd9335_codec {
 	struct clk *mclk;
 	struct clk *native_clk;
 	u32 mclk_rate;
-	u8 version;
 
 	struct slim_device *slim;
 	struct slim_device *slim_ifc_dev;
@@ -345,10 +344,6 @@ struct wcd9335_codec {
 	int dmic_0_1_clk_cnt;
 	int dmic_2_3_clk_cnt;
 	int dmic_4_5_clk_cnt;
-	int dmic_sample_rate;
-	int mad_dmic_sample_rate;
-
-	int native_clk_users;
 };
 
 struct wcd9335_irq {
@@ -397,13 +392,13 @@ struct interp_sample_rate {
 	int rate_val;
 };
 
-static struct interp_sample_rate int_mix_rate_val[] = {
+static const struct interp_sample_rate int_mix_rate_val[] = {
 	{48000, 0x4},	/* 48K */
 	{96000, 0x5},	/* 96K */
 	{192000, 0x6},	/* 192K */
 };
 
-static struct interp_sample_rate int_prim_rate_val[] = {
+static const struct interp_sample_rate int_prim_rate_val[] = {
 	{8000, 0x0},	/* 8K */
 	{16000, 0x1},	/* 16K */
 	{24000, -EINVAL},/* 24K */
@@ -2847,56 +2842,15 @@ static int wcd9335_codec_enable_dec(struct snd_soc_dapm_widget *w,
 }
 
 static u8 wcd9335_get_dmic_clk_val(struct snd_soc_component *component,
-				 u32 mclk_rate, u32 dmic_clk_rate)
+				 u32 mclk_rate)
 {
-	u32 div_factor;
 	u8 dmic_ctl_val;
 
-	dev_err(component->dev,
-		"%s: mclk_rate = %d, dmic_sample_rate = %d\n",
-		__func__, mclk_rate, dmic_clk_rate);
-
-	/* Default value to return in case of error */
 	if (mclk_rate == WCD9335_MCLK_CLK_9P6MHZ)
 		dmic_ctl_val = WCD9335_DMIC_CLK_DIV_2;
 	else
 		dmic_ctl_val = WCD9335_DMIC_CLK_DIV_3;
 
-	if (dmic_clk_rate == 0) {
-		dev_err(component->dev,
-			"%s: dmic_sample_rate cannot be 0\n",
-			__func__);
-		goto done;
-	}
-
-	div_factor = mclk_rate / dmic_clk_rate;
-	switch (div_factor) {
-	case 2:
-		dmic_ctl_val = WCD9335_DMIC_CLK_DIV_2;
-		break;
-	case 3:
-		dmic_ctl_val = WCD9335_DMIC_CLK_DIV_3;
-		break;
-	case 4:
-		dmic_ctl_val = WCD9335_DMIC_CLK_DIV_4;
-		break;
-	case 6:
-		dmic_ctl_val = WCD9335_DMIC_CLK_DIV_6;
-		break;
-	case 8:
-		dmic_ctl_val = WCD9335_DMIC_CLK_DIV_8;
-		break;
-	case 16:
-		dmic_ctl_val = WCD9335_DMIC_CLK_DIV_16;
-		break;
-	default:
-		dev_err(component->dev,
-			"%s: Invalid div_factor %u, clk_rate(%u), dmic_rate(%u)\n",
-			__func__, div_factor, mclk_rate, dmic_clk_rate);
-		break;
-	}
-
-done:
 	return dmic_ctl_val;
 }
 
@@ -2950,11 +2904,7 @@ static int wcd9335_codec_enable_dmic(struct snd_soc_dapm_widget *w,
 
 	switch (event) {
 	case SND_SOC_DAPM_PRE_PMU:
-		dmic_rate_val =
-			wcd9335_get_dmic_clk_val(comp,
-					wcd->mclk_rate,
-					wcd->dmic_sample_rate);
-
+		dmic_rate_val = wcd9335_get_dmic_clk_val(comp, wcd->mclk_rate);
 		(*dmic_clk_cnt)++;
 		if (*dmic_clk_cnt == 1) {
 			snd_soc_component_update_bits(comp, dmic_clk_reg,
@@ -2966,10 +2916,7 @@ static int wcd9335_codec_enable_dmic(struct snd_soc_dapm_widget *w,
 
 		break;
 	case SND_SOC_DAPM_POST_PMD:
-		dmic_rate_val =
-			wcd9335_get_dmic_clk_val(comp,
-					wcd->mclk_rate,
-					wcd->mad_dmic_sample_rate);
+		dmic_rate_val = wcd9335_get_dmic_clk_val(comp, wcd->mclk_rate);
 		(*dmic_clk_cnt)--;
 		if (*dmic_clk_cnt  == 0) {
 			snd_soc_component_update_bits(comp, dmic_clk_reg,
@@ -4026,7 +3973,7 @@ static irqreturn_t wcd9335_slimbus_irq(int irq, void *data)
 	return ret;
 }
 
-static struct wcd9335_irq wcd9335_irqs[] = {
+static const struct wcd9335_irq wcd9335_irqs[] = {
 	{
 		.irq = WCD9335_IRQ_SLIMBUS,
 		.handler = wcd9335_slimbus_irq,
@@ -4963,7 +4910,7 @@ static bool wcd9335_is_volatile_register(struct device *dev, unsigned int reg)
 	}
 }
 
-static struct regmap_config wcd9335_regmap_config = {
+static const struct regmap_config wcd9335_regmap_config = {
 	.reg_bits = 16,
 	.val_bits = 8,
 	.cache_type = REGCACHE_MAPLE,
@@ -4987,7 +4934,7 @@ static const struct regmap_range_cfg wcd9335_ifc_ranges[] = {
 	},
 };
 
-static struct regmap_config wcd9335_ifc_regmap_config = {
+static const struct regmap_config wcd9335_ifc_regmap_config = {
 	.reg_bits = 16,
 	.val_bits = 8,
 	.can_multi_write = true,
@@ -5034,22 +4981,16 @@ static int wcd9335_parse_dt(struct wcd9335_codec *wcd)
 	int ret;
 
 	wcd->reset_gpio = of_get_named_gpio(np,	"reset-gpios", 0);
-	if (wcd->reset_gpio < 0) {
-		dev_err(dev, "Reset GPIO missing from DT\n");
-		return wcd->reset_gpio;
-	}
+	if (wcd->reset_gpio < 0)
+		return dev_err_probe(dev, wcd->reset_gpio, "Reset GPIO missing from DT\n");
 
 	wcd->mclk = devm_clk_get(dev, "mclk");
-	if (IS_ERR(wcd->mclk)) {
-		dev_err(dev, "mclk not found\n");
-		return PTR_ERR(wcd->mclk);
-	}
+	if (IS_ERR(wcd->mclk))
+		return dev_err_probe(dev, PTR_ERR(wcd->mclk), "mclk not found\n");
 
 	wcd->native_clk = devm_clk_get(dev, "slimbus");
-	if (IS_ERR(wcd->native_clk)) {
-		dev_err(dev, "slimbus clock not found\n");
-		return PTR_ERR(wcd->native_clk);
-	}
+	if (IS_ERR(wcd->native_clk))
+		return dev_err_probe(dev, PTR_ERR(wcd->native_clk), "slimbus clock not found\n");
 
 	wcd->supplies[0].supply = "vdd-buck";
 	wcd->supplies[1].supply = "vdd-buck-sido";
@@ -5058,10 +4999,8 @@ static int wcd9335_parse_dt(struct wcd9335_codec *wcd)
 	wcd->supplies[4].supply = "vdd-io";
 
 	ret = regulator_bulk_get(dev, WCD9335_MAX_SUPPLY, wcd->supplies);
-	if (ret) {
-		dev_err(dev, "Failed to get supplies: err = %d\n", ret);
-		return ret;
-	}
+	if (ret)
+		return dev_err_probe(dev, ret, "Failed to get supplies\n");
 
 	return 0;
 }
@@ -5109,7 +5048,6 @@ static int wcd9335_bring_up(struct wcd9335_codec *wcd)
 
 	if (byte0 == 0x1) {
 		dev_info(wcd->dev, "WCD9335 CODEC version is v2.0\n");
-		wcd->version = WCD9335_VERSION_2_0;
 		regmap_write(rm, WCD9335_CODEC_RPM_RST_CTL, 0x01);
 		regmap_write(rm, WCD9335_SIDO_SIDO_TEST_2, 0x00);
 		regmap_write(rm, WCD9335_SIDO_SIDO_CCL_8, 0x6F);
@@ -5161,10 +5099,8 @@ static int wcd9335_slim_probe(struct slim_device *slim)
 
 	wcd->dev = dev;
 	ret = wcd9335_parse_dt(wcd);
-	if (ret) {
-		dev_err(dev, "Error parsing DT: %d\n", ret);
+	if (ret)
 		return ret;
-	}
 
 	ret = wcd9335_power_on_reset(wcd);
 	if (ret)
diff --git a/sound/soc/codecs/wcd934x.c b/sound/soc/codecs/wcd934x.c
index fcad2c9..d1bbc96 100644
--- a/sound/soc/codecs/wcd934x.c
+++ b/sound/soc/codecs/wcd934x.c
@@ -475,17 +475,12 @@ enum {
 	INTn_2_INP_SEL_PROXIMITY,
 };
 
-enum {
-	INTERP_MAIN_PATH,
-	INTERP_MIX_PATH,
-};
-
 struct interp_sample_rate {
 	int sample_rate;
 	int rate_val;
 };
 
-static struct interp_sample_rate sr_val_tbl[] = {
+static const struct interp_sample_rate sr_val_tbl[] = {
 	{8000, 0x0},
 	{16000, 0x1},
 	{32000, 0x3},
@@ -527,7 +522,7 @@ static const struct regmap_range_cfg wcd934x_ifc_ranges[] = {
 	},
 };
 
-static struct regmap_config wcd934x_ifc_regmap_config = {
+static const struct regmap_config wcd934x_ifc_regmap_config = {
 	.reg_bits = 16,
 	.val_bits = 8,
 	.max_register = 0xffff,
@@ -571,10 +566,7 @@ struct wcd934x_codec {
 	struct mutex micb_lock;
 	u32 micb_ref[WCD934X_MAX_MICBIAS];
 	u32 pullup_ref[WCD934X_MAX_MICBIAS];
-	u32 micb1_mv;
 	u32 micb2_mv;
-	u32 micb3_mv;
-	u32 micb4_mv;
 };
 
 #define to_wcd934x_codec(_hw) container_of(_hw, struct wcd934x_codec, hw)
@@ -1217,7 +1209,7 @@ static const struct soc_enum cdc_if_tx13_mux_enum =
 	SOC_ENUM_SINGLE(WCD934X_DATA_HUB_SB_TX13_INP_CFG, 0,
 			ARRAY_SIZE(cdc_if_tx13_mux_text), cdc_if_tx13_mux_text);
 
-static struct wcd_mbhc_field wcd_mbhc_fields[WCD_MBHC_REG_FUNC_MAX] = {
+static const struct wcd_mbhc_field wcd_mbhc_fields[WCD_MBHC_REG_FUNC_MAX] = {
 	WCD_MBHC_FIELD(WCD_MBHC_L_DET_EN, WCD934X_ANA_MBHC_MECH, 0x80),
 	WCD_MBHC_FIELD(WCD_MBHC_GND_DET_EN, WCD934X_ANA_MBHC_MECH, 0x40),
 	WCD_MBHC_FIELD(WCD_MBHC_MECH_DETECTION_TYPE, WCD934X_ANA_MBHC_MECH, 0x20),
@@ -2208,7 +2200,8 @@ static int wcd934x_get_micbias_val(struct device *dev, const char *micbias,
 		mv = WCD934X_DEF_MICBIAS_MV;
 	}
 
-	*micb_mv = mv;
+	if (micb_mv)
+		*micb_mv = mv;
 
 	return (mv - 1000) / 50;
 }
@@ -2220,17 +2213,14 @@ static int wcd934x_init_dmic(struct snd_soc_component *comp)
 	u32 def_dmic_rate, dmic_clk_drv;
 
 	vout_ctl_1 = wcd934x_get_micbias_val(comp->dev,
-					     "qcom,micbias1-microvolt",
-					     &wcd->micb1_mv);
+					     "qcom,micbias1-microvolt", NULL);
 	vout_ctl_2 = wcd934x_get_micbias_val(comp->dev,
 					     "qcom,micbias2-microvolt",
 					     &wcd->micb2_mv);
 	vout_ctl_3 = wcd934x_get_micbias_val(comp->dev,
-					     "qcom,micbias3-microvolt",
-					     &wcd->micb3_mv);
+					     "qcom,micbias3-microvolt", NULL);
 	vout_ctl_4 = wcd934x_get_micbias_val(comp->dev,
-					     "qcom,micbias4-microvolt",
-					     &wcd->micb4_mv);
+					     "qcom,micbias4-microvolt", NULL);
 
 	snd_soc_component_update_bits(comp, WCD934X_ANA_MICB1,
 				      WCD934X_MICB_VAL_MASK, vout_ctl_1);
@@ -5866,17 +5856,13 @@ static int wcd934x_codec_parse_data(struct wcd934x_codec *wcd)
 	struct device_node *ifc_dev_np;
 
 	ifc_dev_np = of_parse_phandle(dev->of_node, "slim-ifc-dev", 0);
-	if (!ifc_dev_np) {
-		dev_err(dev, "No Interface device found\n");
-		return -EINVAL;
-	}
+	if (!ifc_dev_np)
+		return dev_err_probe(dev, -EINVAL, "No Interface device found\n");
 
 	wcd->sidev = of_slim_get_device(wcd->sdev->ctrl, ifc_dev_np);
 	of_node_put(ifc_dev_np);
-	if (!wcd->sidev) {
-		dev_err(dev, "Unable to get SLIM Interface device\n");
-		return -EINVAL;
-	}
+	if (!wcd->sidev)
+		return dev_err_probe(dev, -EINVAL, "Unable to get SLIM Interface device\n");
 
 	slim_get_logical_addr(wcd->sidev);
 	wcd->if_regmap = regmap_init_slimbus(wcd->sidev,
@@ -5922,10 +5908,8 @@ static int wcd934x_codec_probe(struct platform_device *pdev)
 	mutex_init(&wcd->micb_lock);
 
 	ret = wcd934x_codec_parse_data(wcd);
-	if (ret) {
-		dev_err(wcd->dev, "Failed to get SLIM IRQ\n");
+	if (ret)
 		return ret;
-	}
 
 	/* set default rate 9P6MHz */
 	regmap_update_bits(wcd->regmap, WCD934X_CODEC_RPM_CLK_MCLK_CFG,
diff --git a/sound/soc/codecs/wcd937x-sdw.c b/sound/soc/codecs/wcd937x-sdw.c
index a45025b..a24d6c6 100644
--- a/sound/soc/codecs/wcd937x-sdw.c
+++ b/sound/soc/codecs/wcd937x-sdw.c
@@ -19,7 +19,7 @@
 #include <sound/soc.h>
 #include "wcd937x.h"
 
-static struct wcd937x_sdw_ch_info wcd937x_sdw_rx_ch_info[] = {
+static const struct wcd937x_sdw_ch_info wcd937x_sdw_rx_ch_info[] = {
 	WCD_SDW_CH(WCD937X_HPH_L, WCD937X_HPH_PORT, BIT(0)),
 	WCD_SDW_CH(WCD937X_HPH_R, WCD937X_HPH_PORT, BIT(1)),
 	WCD_SDW_CH(WCD937X_CLSH, WCD937X_CLSH_PORT, BIT(0)),
@@ -30,7 +30,7 @@ static struct wcd937x_sdw_ch_info wcd937x_sdw_rx_ch_info[] = {
 	WCD_SDW_CH(WCD937X_DSD_R, WCD937X_DSD_PORT, BIT(1)),
 };
 
-static struct wcd937x_sdw_ch_info wcd937x_sdw_tx_ch_info[] = {
+static const struct wcd937x_sdw_ch_info wcd937x_sdw_tx_ch_info[] = {
 	WCD_SDW_CH(WCD937X_ADC1, WCD937X_ADC_1_PORT, BIT(0)),
 	WCD_SDW_CH(WCD937X_ADC2, WCD937X_ADC_2_3_PORT, BIT(0)),
 	WCD_SDW_CH(WCD937X_ADC3, WCD937X_ADC_2_3_PORT, BIT(0)),
diff --git a/sound/soc/codecs/wcd937x.c b/sound/soc/codecs/wcd937x.c
index ef649ed..4beb70b 100644
--- a/sound/soc/codecs/wcd937x.c
+++ b/sound/soc/codecs/wcd937x.c
@@ -99,11 +99,9 @@ struct wcd937x_priv {
 	s32 pullup_ref[WCD937X_MAX_MICBIAS];
 	u32 hph_mode;
 	int ear_rx_path;
-	u32 chipid;
 	u32 micb1_mv;
 	u32 micb2_mv;
 	u32 micb3_mv;
-	u32 micb4_mv; /* 9375 only */
 	int hphr_pdm_wd_int;
 	int hphl_pdm_wd_int;
 	int aux_pdm_wd_int;
@@ -113,9 +111,6 @@ struct wcd937x_priv {
 	struct gpio_desc *us_euro_gpio;
 	struct gpio_desc *reset_gpio;
 
-	int dmic_0_1_clk_cnt;
-	int dmic_2_3_clk_cnt;
-	int dmic_4_5_clk_cnt;
 	atomic_t rx_clk_cnt;
 	atomic_t ana_clk_count;
 };
@@ -133,7 +128,7 @@ struct wcd937x_mbhc_zdet_param {
 	u16 btn7;
 };
 
-static struct wcd_mbhc_field wcd_mbhc_fields[WCD_MBHC_REG_FUNC_MAX] = {
+static const struct wcd_mbhc_field wcd_mbhc_fields[WCD_MBHC_REG_FUNC_MAX] = {
 	WCD_MBHC_FIELD(WCD_MBHC_L_DET_EN, WCD937X_ANA_MBHC_MECH, 0x80),
 	WCD_MBHC_FIELD(WCD_MBHC_GND_DET_EN, WCD937X_ANA_MBHC_MECH, 0x40),
 	WCD_MBHC_FIELD(WCD_MBHC_MECH_DETECTION_TYPE, WCD937X_ANA_MBHC_MECH, 0x20),
@@ -227,7 +222,7 @@ static const u32 wcd937x_config_regs[] = {
 	WCD937X_DIGITAL_INTR_LEVEL_0,
 };
 
-static struct regmap_irq_chip wcd937x_regmap_irq_chip = {
+static const struct regmap_irq_chip wcd937x_regmap_irq_chip = {
 	.name = "wcd937x",
 	.irqs = wcd937x_irqs,
 	.num_irqs = ARRAY_SIZE(wcd937x_irqs),
@@ -1244,7 +1239,7 @@ static int wcd937x_codec_enable_micbias_pullup(struct snd_soc_dapm_widget *w,
 static int wcd937x_connect_port(struct wcd937x_sdw_priv *wcd, u8 port_idx, u8 ch_id, bool enable)
 {
 	struct sdw_port_config *port_config = &wcd->port_config[port_idx - 1];
-	struct wcd937x_sdw_ch_info *ch_info = &wcd->ch_info[ch_id];
+	const struct wcd937x_sdw_ch_info *ch_info = &wcd->ch_info[ch_id];
 	u8 port_num = ch_info->port_num;
 	u8 ch_mask = ch_info->ch_mask;
 
@@ -2503,7 +2498,7 @@ static irqreturn_t wcd937x_wd_handle_irq(int irq, void *data)
 	return IRQ_HANDLED;
 }
 
-static struct irq_chip wcd_irq_chip = {
+static const struct irq_chip wcd_irq_chip = {
 	.name = "WCD937x",
 };
 
@@ -2543,6 +2538,7 @@ static int wcd937x_soc_codec_probe(struct snd_soc_component *component)
 	struct device *dev = component->dev;
 	unsigned long time_left;
 	int i, ret;
+	u32 chipid;
 
 	time_left = wait_for_completion_timeout(&tx_sdw_dev->initialization_complete,
 						msecs_to_jiffies(5000));
@@ -2556,11 +2552,10 @@ static int wcd937x_soc_codec_probe(struct snd_soc_component *component)
 	if (ret < 0)
 		return ret;
 
-	wcd937x->chipid = (snd_soc_component_read(component,
-				WCD937X_DIGITAL_EFUSE_REG_0) & 0x1e) >> 1;
-	if (wcd937x->chipid != CHIPID_WCD9370 &&
-	    wcd937x->chipid != CHIPID_WCD9375) {
-		dev_err(dev, "Got unknown chip id: 0x%x\n", wcd937x->chipid);
+	chipid = (snd_soc_component_read(component,
+					 WCD937X_DIGITAL_EFUSE_REG_0) & 0x1e) >> 1;
+	if (chipid != CHIPID_WCD9370 && chipid != CHIPID_WCD9375) {
+		dev_err(dev, "Got unknown chip id: 0x%x\n", chipid);
 		pm_runtime_put(dev);
 		return -EINVAL;
 	}
@@ -2609,7 +2604,7 @@ static int wcd937x_soc_codec_probe(struct snd_soc_component *component)
 	disable_irq_nosync(wcd937x->hphl_pdm_wd_int);
 	disable_irq_nosync(wcd937x->aux_pdm_wd_int);
 
-	if (wcd937x->chipid == CHIPID_WCD9375) {
+	if (chipid == CHIPID_WCD9375) {
 		ret = snd_soc_dapm_new_controls(dapm, wcd9375_dapm_widgets,
 						ARRAY_SIZE(wcd9375_dapm_widgets));
 		if (ret < 0) {
diff --git a/sound/soc/codecs/wcd937x.h b/sound/soc/codecs/wcd937x.h
index e6e1ad5..f267c66 100644
--- a/sound/soc/codecs/wcd937x.h
+++ b/sound/soc/codecs/wcd937x.h
@@ -488,23 +488,6 @@
 #define WCD937X_MAX_SWR_PORTS			5
 #define WCD937X_MAX_SWR_CH_IDS			15
 
-/* Convert from vout ctl to micbias voltage in mV */
-#define WCD_VOUT_CTL_TO_MICB(v)	(1000 + (v) * 50)
-#define MAX_PORT 8
-#define MAX_CH_PER_PORT 8
-#define MAX_TX_PWR_CH 2
-#define SWR_NUM_PORTS 4
-
-#define WCD937X_MAX_SLAVE_PORT_TYPES 10
-
-struct codec_port_info {
-	u32 slave_port_type;
-	u32 master_port_type;
-	u32 ch_mask;
-	u32 num_ch;
-	u32 ch_rate;
-};
-
 struct wcd937x_sdw_ch_info {
 	int port_num;
 	unsigned int ch_mask;
@@ -522,10 +505,9 @@ struct wcd937x_sdw_priv {
 	struct sdw_stream_config sconfig;
 	struct sdw_stream_runtime *sruntime;
 	struct sdw_port_config port_config[WCD937X_MAX_SWR_PORTS];
-	struct wcd937x_sdw_ch_info *ch_info;
+	const struct wcd937x_sdw_ch_info *ch_info;
 	bool port_enable[WCD937X_MAX_SWR_CH_IDS];
 	int active_ports;
-	int num_ports;
 	bool is_tx;
 	struct wcd937x_priv *wcd937x;
 	struct irq_domain *slave_irq;
@@ -571,12 +553,6 @@ int wcd937x_sdw_hw_params(struct wcd937x_sdw_priv *wcd,
 #endif
 
 enum {
-	WCD_RX1,
-	WCD_RX2,
-	WCD_RX3
-};
-
-enum {
 	/* INTR_CTRL_INT_MASK_0 */
 	WCD937X_IRQ_MBHC_BUTTON_PRESS_DET = 0,
 	WCD937X_IRQ_MBHC_BUTTON_RELEASE_DET,
@@ -645,9 +621,4 @@ enum wcd937x_rx_sdw_channels {
 	WCD937X_DSD_L,
 };
 
-enum {
-	WCD937X_SDW_DIR_RX,
-	WCD937X_SDW_DIR_TX,
-};
-
 #endif
diff --git a/sound/soc/codecs/wcd938x-sdw.c b/sound/soc/codecs/wcd938x-sdw.c
index a1f04010..c995bcc 100644
--- a/sound/soc/codecs/wcd938x-sdw.c
+++ b/sound/soc/codecs/wcd938x-sdw.c
@@ -21,7 +21,7 @@
 
 #define SWRS_SCP_HOST_CLK_DIV2_CTL_BANK(m) (0xE0 + 0x10 * (m))
 
-static struct wcd938x_sdw_ch_info wcd938x_sdw_rx_ch_info[] = {
+static const struct wcd938x_sdw_ch_info wcd938x_sdw_rx_ch_info[] = {
 	WCD_SDW_CH(WCD938X_HPH_L, WCD938X_HPH_PORT, BIT(0)),
 	WCD_SDW_CH(WCD938X_HPH_R, WCD938X_HPH_PORT, BIT(1)),
 	WCD_SDW_CH(WCD938X_CLSH, WCD938X_CLSH_PORT, BIT(0)),
@@ -32,7 +32,7 @@ static struct wcd938x_sdw_ch_info wcd938x_sdw_rx_ch_info[] = {
 	WCD_SDW_CH(WCD938X_DSD_R, WCD938X_DSD_PORT, BIT(1)),
 };
 
-static struct wcd938x_sdw_ch_info wcd938x_sdw_tx_ch_info[] = {
+static const struct wcd938x_sdw_ch_info wcd938x_sdw_tx_ch_info[] = {
 	WCD_SDW_CH(WCD938X_ADC1, WCD938X_ADC_1_2_PORT, BIT(0)),
 	WCD_SDW_CH(WCD938X_ADC2, WCD938X_ADC_1_2_PORT, BIT(1)),
 	WCD_SDW_CH(WCD938X_ADC3, WCD938X_ADC_3_4_PORT, BIT(0)),
diff --git a/sound/soc/codecs/wcd938x.c b/sound/soc/codecs/wcd938x.c
index 7338715..12b32d5 100644
--- a/sound/soc/codecs/wcd938x.c
+++ b/sound/soc/codecs/wcd938x.c
@@ -221,7 +221,7 @@ struct wcd938x_mbhc_zdet_param {
 	u16 btn7;
 };
 
-static struct wcd_mbhc_field wcd_mbhc_fields[WCD_MBHC_REG_FUNC_MAX] = {
+static const struct wcd_mbhc_field wcd_mbhc_fields[WCD_MBHC_REG_FUNC_MAX] = {
 	WCD_MBHC_FIELD(WCD_MBHC_L_DET_EN, WCD938X_ANA_MBHC_MECH, 0x80),
 	WCD_MBHC_FIELD(WCD_MBHC_GND_DET_EN, WCD938X_ANA_MBHC_MECH, 0x40),
 	WCD_MBHC_FIELD(WCD_MBHC_MECH_DETECTION_TYPE, WCD938X_ANA_MBHC_MECH, 0x20),
@@ -418,7 +418,7 @@ static int wcd938x_io_init(struct wcd938x_priv *wcd938x)
 
 }
 
-static int wcd938x_sdw_connect_port(struct wcd938x_sdw_ch_info *ch_info,
+static int wcd938x_sdw_connect_port(const struct wcd938x_sdw_ch_info *ch_info,
 				    struct sdw_port_config *port_config,
 				    u8 enable)
 {
@@ -3027,7 +3027,7 @@ static irqreturn_t wcd938x_wd_handle_irq(int irq, void *data)
 	return IRQ_HANDLED;
 }
 
-static struct irq_chip wcd_irq_chip = {
+static const struct irq_chip wcd_irq_chip = {
 	.name = "WCD938x",
 };
 
diff --git a/sound/soc/codecs/wcd938x.h b/sound/soc/codecs/wcd938x.h
index 0d332cb..b2ad980 100644
--- a/sound/soc/codecs/wcd938x.h
+++ b/sound/soc/codecs/wcd938x.h
@@ -642,10 +642,6 @@ enum wcd938x_rx_sdw_channels {
 	WCD938X_DSD_R,
 	WCD938X_DSD_L,
 };
-enum {
-	WCD938X_SDW_DIR_RX,
-	WCD938X_SDW_DIR_TX,
-};
 
 struct wcd938x_priv;
 struct wcd938x_sdw_priv {
@@ -653,10 +649,9 @@ struct wcd938x_sdw_priv {
 	struct sdw_stream_config sconfig;
 	struct sdw_stream_runtime *sruntime;
 	struct sdw_port_config port_config[WCD938X_MAX_SWR_PORTS];
-	struct wcd938x_sdw_ch_info *ch_info;
+	const struct wcd938x_sdw_ch_info *ch_info;
 	bool port_enable[WCD938X_MAX_SWR_CH_IDS];
 	int active_ports;
-	int num_ports;
 	bool is_tx;
 	struct wcd938x_priv *wcd938x;
 	struct irq_domain *slave_irq;
diff --git a/sound/soc/codecs/wcd939x-sdw.c b/sound/soc/codecs/wcd939x-sdw.c
index 8acb565..94b1e99 100644
--- a/sound/soc/codecs/wcd939x-sdw.c
+++ b/sound/soc/codecs/wcd939x-sdw.c
@@ -23,7 +23,7 @@
 
 #define SWRS_SCP_HOST_CLK_DIV2_CTL_BANK(m) (0xE0 + 0x10 * (m))
 
-static struct wcd939x_sdw_ch_info wcd939x_sdw_rx_ch_info[] = {
+static const struct wcd939x_sdw_ch_info wcd939x_sdw_rx_ch_info[] = {
 	WCD_SDW_CH(WCD939X_HPH_L, WCD939X_HPH_PORT, BIT(0)),
 	WCD_SDW_CH(WCD939X_HPH_R, WCD939X_HPH_PORT, BIT(1)),
 	WCD_SDW_CH(WCD939X_CLSH, WCD939X_CLSH_PORT, BIT(0)),
@@ -36,7 +36,7 @@ static struct wcd939x_sdw_ch_info wcd939x_sdw_rx_ch_info[] = {
 	WCD_SDW_CH(WCD939X_HIFI_PCM_R, WCD939X_HIFI_PCM_PORT, BIT(1)),
 };
 
-static struct wcd939x_sdw_ch_info wcd939x_sdw_tx_ch_info[] = {
+static const struct wcd939x_sdw_ch_info wcd939x_sdw_tx_ch_info[] = {
 	WCD_SDW_CH(WCD939X_ADC1, WCD939X_ADC_1_4_PORT, BIT(0)),
 	WCD_SDW_CH(WCD939X_ADC2, WCD939X_ADC_1_4_PORT, BIT(1)),
 	WCD_SDW_CH(WCD939X_ADC3, WCD939X_ADC_1_4_PORT, BIT(2)),
diff --git a/sound/soc/codecs/wcd939x.c b/sound/soc/codecs/wcd939x.c
index 72d8a6a..66af035 100644
--- a/sound/soc/codecs/wcd939x.c
+++ b/sound/soc/codecs/wcd939x.c
@@ -220,7 +220,7 @@ static const SNDRV_CTL_TLVD_DECLARE_DB_MINMAX(ear_pa_gain, 600, -1800);
 static const DECLARE_TLV_DB_SCALE(line_gain, 0, 7, 1);
 static const DECLARE_TLV_DB_SCALE(analog_gain, 0, 25, 1);
 
-static struct wcd_mbhc_field wcd_mbhc_fields[WCD_MBHC_REG_FUNC_MAX] = {
+static const struct wcd_mbhc_field wcd_mbhc_fields[WCD_MBHC_REG_FUNC_MAX] = {
 	WCD_MBHC_FIELD(WCD_MBHC_L_DET_EN, WCD939X_ANA_MBHC_MECH, 0x80),
 	WCD_MBHC_FIELD(WCD_MBHC_GND_DET_EN, WCD939X_ANA_MBHC_MECH, 0x40),
 	WCD_MBHC_FIELD(WCD_MBHC_MECH_DETECTION_TYPE, WCD939X_ANA_MBHC_MECH, 0x20),
@@ -291,7 +291,7 @@ static const struct regmap_irq wcd939x_irqs[WCD939X_NUM_IRQS] = {
 	REGMAP_IRQ_REG(WCD939X_IRQ_HPHR_SURGE_DET_INT, 2, 0x08),
 };
 
-static struct regmap_irq_chip wcd939x_regmap_irq_chip = {
+static const struct regmap_irq_chip wcd939x_regmap_irq_chip = {
 	.name = "wcd939x",
 	.irqs = wcd939x_irqs,
 	.num_irqs = ARRAY_SIZE(wcd939x_irqs),
@@ -414,7 +414,7 @@ static int wcd939x_io_init(struct snd_soc_component *component)
 	return 0;
 }
 
-static int wcd939x_sdw_connect_port(struct wcd939x_sdw_ch_info *ch_info,
+static int wcd939x_sdw_connect_port(const struct wcd939x_sdw_ch_info *ch_info,
 				    struct sdw_port_config *port_config,
 				    u8 enable)
 {
@@ -2957,7 +2957,7 @@ static irqreturn_t wcd939x_wd_handle_irq(int irq, void *data)
  *     \- regmap_irq_thread()
  *         \- handle_nested_irq(i)
  */
-static struct irq_chip wcd_irq_chip = {
+static const struct irq_chip wcd_irq_chip = {
 	.name = "WCD939x",
 };
 
diff --git a/sound/soc/codecs/wcd939x.h b/sound/soc/codecs/wcd939x.h
index 756f497..1571c21 100644
--- a/sound/soc/codecs/wcd939x.h
+++ b/sound/soc/codecs/wcd939x.h
@@ -903,21 +903,15 @@ enum wcd939x_rx_sdw_channels {
 	WCD939X_HIFI_PCM_R,
 };
 
-enum {
-	WCD939X_SDW_DIR_RX,
-	WCD939X_SDW_DIR_TX,
-};
-
 struct wcd939x_priv;
 struct wcd939x_sdw_priv {
 	struct sdw_slave *sdev;
 	struct sdw_stream_config sconfig;
 	struct sdw_stream_runtime *sruntime;
 	struct sdw_port_config port_config[WCD939X_MAX_SWR_PORTS];
-	struct wcd939x_sdw_ch_info *ch_info;
+	const struct wcd939x_sdw_ch_info *ch_info;
 	bool port_enable[WCD939X_MAX_SWR_CH_IDS];
 	int active_ports;
-	int num_ports;
 	bool is_tx;
 	struct wcd939x_priv *wcd939x;
 	struct irq_domain *slave_irq;
diff --git a/sound/soc/fsl/fsl-asoc-card.c b/sound/soc/fsl/fsl-asoc-card.c
index 5ddc0c2..eb67689 100644
--- a/sound/soc/fsl/fsl-asoc-card.c
+++ b/sound/soc/fsl/fsl-asoc-card.c
@@ -559,6 +559,8 @@ static int fsl_asoc_card_probe(struct platform_device *pdev)
 	if (!priv)
 		return -ENOMEM;
 
+	priv->pdev = pdev;
+
 	cpu_np = of_parse_phandle(np, "audio-cpu", 0);
 	/* Give a chance to old DT binding */
 	if (!cpu_np)
@@ -787,7 +789,6 @@ static int fsl_asoc_card_probe(struct platform_device *pdev)
 	}
 
 	/* Initialize sound card */
-	priv->pdev = pdev;
 	priv->card.dev = &pdev->dev;
 	priv->card.owner = THIS_MODULE;
 	ret = snd_soc_of_parse_card_name(&priv->card, "model");
diff --git a/sound/soc/fsl/imx-pcm-dma.c b/sound/soc/fsl/imx-pcm-dma.c
index 14e9427..4fa208d 100644
--- a/sound/soc/fsl/imx-pcm-dma.c
+++ b/sound/soc/fsl/imx-pcm-dma.c
@@ -50,4 +50,5 @@ int imx_pcm_dma_init(struct platform_device *pdev)
 }
 EXPORT_SYMBOL_GPL(imx_pcm_dma_init);
 
+MODULE_DESCRIPTION("Freescale i.MX PCM DMA interface");
 MODULE_LICENSE("GPL");
diff --git a/sound/soc/intel/avs/topology.c b/sound/soc/intel/avs/topology.c
index 35381a8..5cda5270 100644
--- a/sound/soc/intel/avs/topology.c
+++ b/sound/soc/intel/avs/topology.c
@@ -1545,8 +1545,8 @@ static int avs_route_load(struct snd_soc_component *comp, int index,
 {
 	struct snd_soc_acpi_mach *mach = dev_get_platdata(comp->card->dev);
 	size_t len = SNDRV_CTL_ELEM_ID_NAME_MAXLEN;
-	char buf[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
 	int ssp_port, tdm_slot;
+	char *buf;
 
 	/* See parse_link_formatted_string() for dynamic naming when(s). */
 	if (!avs_mach_singular_ssp(mach))
@@ -1557,13 +1557,24 @@ static int avs_route_load(struct snd_soc_component *comp, int index,
 		return 0;
 	tdm_slot = avs_mach_ssp_tdm(mach, ssp_port);
 
+	buf = devm_kzalloc(comp->card->dev, len, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
 	avs_ssp_sprint(buf, len, route->source, ssp_port, tdm_slot);
-	strscpy((char *)route->source, buf, len);
+	route->source = buf;
+
+	buf = devm_kzalloc(comp->card->dev, len, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
 	avs_ssp_sprint(buf, len, route->sink, ssp_port, tdm_slot);
-	strscpy((char *)route->sink, buf, len);
+	route->sink = buf;
+
 	if (route->control) {
+		buf = devm_kzalloc(comp->card->dev, len, GFP_KERNEL);
+		if (!buf)
+			return -ENOMEM;
 		avs_ssp_sprint(buf, len, route->control, ssp_port, tdm_slot);
-		strscpy((char *)route->control, buf, len);
+		route->control = buf;
 	}
 
 	return 0;
diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c
index b41a1147..a64d198 100644
--- a/sound/soc/intel/boards/bytcr_rt5640.c
+++ b/sound/soc/intel/boards/bytcr_rt5640.c
@@ -613,6 +613,17 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = {
 	{
 		.matches = {
 			DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ARCHOS"),
+			DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ARCHOS 101 CESIUM"),
+		},
+		.driver_data = (void *)(BYTCR_INPUT_DEFAULTS |
+					BYT_RT5640_JD_NOT_INV |
+					BYT_RT5640_DIFF_MIC |
+					BYT_RT5640_SSP0_AIF1 |
+					BYT_RT5640_MCLK_EN),
+	},
+	{
+		.matches = {
+			DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ARCHOS"),
 			DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ARCHOS 140 CESIUM"),
 		},
 		.driver_data = (void *)(BYT_RT5640_IN1_MAP |
diff --git a/sound/soc/intel/common/soc-acpi-intel-mtl-match.c b/sound/soc/intel/common/soc-acpi-intel-mtl-match.c
index 48252fa9..8e0ae36 100644
--- a/sound/soc/intel/common/soc-acpi-intel-mtl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-mtl-match.c
@@ -293,7 +293,7 @@ static const struct snd_soc_acpi_adr_device rt1318_1_single_adr[] = {
 		.adr = 0x000130025D131801,
 		.num_endpoints = 1,
 		.endpoints = &single_endpoint,
-		.name_prefix = "rt1318"
+		.name_prefix = "rt1318-1"
 	}
 };
 
diff --git a/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c b/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c
index acaf81f..f848e14 100644
--- a/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c
+++ b/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c
@@ -31,7 +31,7 @@ struct mt8183_da7219_max98357_priv {
 
 static struct snd_soc_jack_pin mt8183_da7219_max98357_jack_pins[] = {
 	{
-		.pin	= "Headphone",
+		.pin	= "Headphones",
 		.mask	= SND_JACK_HEADPHONE,
 	},
 	{
@@ -626,7 +626,7 @@ static struct snd_soc_codec_conf mt6358_codec_conf[] = {
 };
 
 static const struct snd_kcontrol_new mt8183_da7219_max98357_snd_controls[] = {
-	SOC_DAPM_PIN_SWITCH("Headphone"),
+	SOC_DAPM_PIN_SWITCH("Headphones"),
 	SOC_DAPM_PIN_SWITCH("Headset Mic"),
 	SOC_DAPM_PIN_SWITCH("Speakers"),
 	SOC_DAPM_PIN_SWITCH("Line Out"),
@@ -634,7 +634,7 @@ static const struct snd_kcontrol_new mt8183_da7219_max98357_snd_controls[] = {
 
 static const
 struct snd_soc_dapm_widget mt8183_da7219_max98357_dapm_widgets[] = {
-	SND_SOC_DAPM_HP("Headphone", NULL),
+	SND_SOC_DAPM_HP("Headphones", NULL),
 	SND_SOC_DAPM_MIC("Headset Mic", NULL),
 	SND_SOC_DAPM_SPK("Speakers", NULL),
 	SND_SOC_DAPM_SPK("Line Out", NULL),
@@ -680,7 +680,7 @@ static struct snd_soc_codec_conf mt8183_da7219_rt1015_codec_conf[] = {
 };
 
 static const struct snd_kcontrol_new mt8183_da7219_rt1015_snd_controls[] = {
-	SOC_DAPM_PIN_SWITCH("Headphone"),
+	SOC_DAPM_PIN_SWITCH("Headphones"),
 	SOC_DAPM_PIN_SWITCH("Headset Mic"),
 	SOC_DAPM_PIN_SWITCH("Left Spk"),
 	SOC_DAPM_PIN_SWITCH("Right Spk"),
@@ -689,7 +689,7 @@ static const struct snd_kcontrol_new mt8183_da7219_rt1015_snd_controls[] = {
 
 static const
 struct snd_soc_dapm_widget mt8183_da7219_rt1015_dapm_widgets[] = {
-	SND_SOC_DAPM_HP("Headphone", NULL),
+	SND_SOC_DAPM_HP("Headphones", NULL),
 	SND_SOC_DAPM_MIC("Headset Mic", NULL),
 	SND_SOC_DAPM_SPK("Left Spk", NULL),
 	SND_SOC_DAPM_SPK("Right Spk", NULL),
diff --git a/sound/soc/mxs/mxs-pcm.c b/sound/soc/mxs/mxs-pcm.c
index df2e4be..9bb08ca 100644
--- a/sound/soc/mxs/mxs-pcm.c
+++ b/sound/soc/mxs/mxs-pcm.c
@@ -43,4 +43,5 @@ int mxs_pcm_platform_register(struct device *dev)
 }
 EXPORT_SYMBOL_GPL(mxs_pcm_platform_register);
 
+MODULE_DESCRIPTION("MXS ASoC PCM driver");
 MODULE_LICENSE("GPL");
diff --git a/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c b/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c
index ba28ec9..9c98a35 100644
--- a/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c
+++ b/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c
@@ -146,14 +146,17 @@ static void q6apm_lpass_dai_shutdown(struct snd_pcm_substream *substream, struct
 	struct q6apm_lpass_dai_data *dai_data = dev_get_drvdata(dai->dev);
 	int rc;
 
-	if (!dai_data->is_port_started[dai->id])
-		return;
-	rc = q6apm_graph_stop(dai_data->graph[dai->id]);
-	if (rc < 0)
-		dev_err(dai->dev, "fail to close APM port (%d)\n", rc);
+	if (dai_data->is_port_started[dai->id]) {
+		rc = q6apm_graph_stop(dai_data->graph[dai->id]);
+		dai_data->is_port_started[dai->id] = false;
+		if (rc < 0)
+			dev_err(dai->dev, "fail to close APM port (%d)\n", rc);
+	}
 
-	q6apm_graph_close(dai_data->graph[dai->id]);
-	dai_data->is_port_started[dai->id] = false;
+	if (dai_data->graph[dai->id]) {
+		q6apm_graph_close(dai_data->graph[dai->id]);
+		dai_data->graph[dai->id] = NULL;
+	}
 }
 
 static int q6apm_lpass_dai_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
@@ -168,8 +171,10 @@ static int q6apm_lpass_dai_prepare(struct snd_pcm_substream *substream, struct s
 		q6apm_graph_stop(dai_data->graph[dai->id]);
 		dai_data->is_port_started[dai->id] = false;
 
-		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 			q6apm_graph_close(dai_data->graph[dai->id]);
+			dai_data->graph[dai->id] = NULL;
+		}
 	}
 
 	/**
@@ -188,26 +193,29 @@ static int q6apm_lpass_dai_prepare(struct snd_pcm_substream *substream, struct s
 
 	cfg->direction = substream->stream;
 	rc = q6apm_graph_media_format_pcm(dai_data->graph[dai->id], cfg);
-
 	if (rc) {
 		dev_err(dai->dev, "Failed to set media format %d\n", rc);
-		return rc;
+		goto err;
 	}
 
 	rc = q6apm_graph_prepare(dai_data->graph[dai->id]);
 	if (rc) {
 		dev_err(dai->dev, "Failed to prepare Graph %d\n", rc);
-		return rc;
+		goto err;
 	}
 
 	rc = q6apm_graph_start(dai_data->graph[dai->id]);
 	if (rc < 0) {
 		dev_err(dai->dev, "fail to start APM port %x\n", dai->id);
-		return rc;
+		goto err;
 	}
 	dai_data->is_port_started[dai->id] = true;
 
 	return 0;
+err:
+	q6apm_graph_close(dai_data->graph[dai->id]);
+	dai_data->graph[dai->id] = NULL;
+	return rc;
 }
 
 static int q6apm_lpass_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
diff --git a/sound/soc/qcom/sdw.c b/sound/soc/qcom/sdw.c
index eaa8bb0..f2eda2f 100644
--- a/sound/soc/qcom/sdw.c
+++ b/sound/soc/qcom/sdw.c
@@ -160,4 +160,5 @@ int qcom_snd_sdw_hw_free(struct snd_pcm_substream *substream,
 	return 0;
 }
 EXPORT_SYMBOL_GPL(qcom_snd_sdw_hw_free);
+MODULE_DESCRIPTION("Qualcomm ASoC SoundWire helper functions");
 MODULE_LICENSE("GPL");
diff --git a/sound/soc/rockchip/rockchip_i2s_tdm.c b/sound/soc/rockchip/rockchip_i2s_tdm.c
index 9fa020e..ee517d7 100644
--- a/sound/soc/rockchip/rockchip_i2s_tdm.c
+++ b/sound/soc/rockchip/rockchip_i2s_tdm.c
@@ -655,8 +655,17 @@ static int rockchip_i2s_tdm_hw_params(struct snd_pcm_substream *substream,
 	int err;
 
 	if (i2s_tdm->is_master_mode) {
-		struct clk *mclk = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
-			i2s_tdm->mclk_tx : i2s_tdm->mclk_rx;
+		struct clk *mclk;
+
+		if (i2s_tdm->clk_trcm == TRCM_TX) {
+			mclk = i2s_tdm->mclk_tx;
+		} else if (i2s_tdm->clk_trcm == TRCM_RX) {
+			mclk = i2s_tdm->mclk_rx;
+		} else if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+			mclk = i2s_tdm->mclk_tx;
+		} else {
+			mclk = i2s_tdm->mclk_rx;
+		}
 
 		err = clk_set_rate(mclk, DEFAULT_MCLK_FS * params_rate(params));
 		if (err)
diff --git a/sound/soc/soc-generic-dmaengine-pcm.c b/sound/soc/soc-generic-dmaengine-pcm.c
index ea3bc93..a63e942 100644
--- a/sound/soc/soc-generic-dmaengine-pcm.c
+++ b/sound/soc/soc-generic-dmaengine-pcm.c
@@ -318,6 +318,12 @@ static int dmaengine_copy(struct snd_soc_component *component,
 	return 0;
 }
 
+static int dmaengine_pcm_sync_stop(struct snd_soc_component *component,
+				   struct snd_pcm_substream *substream)
+{
+	return snd_dmaengine_pcm_sync_stop(substream);
+}
+
 static const struct snd_soc_component_driver dmaengine_pcm_component = {
 	.name		= SND_DMAENGINE_PCM_DRV_NAME,
 	.probe_order	= SND_SOC_COMP_ORDER_LATE,
@@ -327,6 +333,7 @@ static const struct snd_soc_component_driver dmaengine_pcm_component = {
 	.trigger	= dmaengine_pcm_trigger,
 	.pointer	= dmaengine_pcm_pointer,
 	.pcm_construct	= dmaengine_pcm_new,
+	.sync_stop	= dmaengine_pcm_sync_stop,
 };
 
 static const struct snd_soc_component_driver dmaengine_pcm_component_process = {
@@ -339,6 +346,7 @@ static const struct snd_soc_component_driver dmaengine_pcm_component_process = {
 	.pointer	= dmaengine_pcm_pointer,
 	.copy		= dmaengine_copy,
 	.pcm_construct	= dmaengine_pcm_new,
+	.sync_stop	= dmaengine_pcm_sync_stop,
 };
 
 static const char * const dmaengine_pcm_dma_channel_names[] = {
diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c
index b00ec01..4b16629 100644
--- a/sound/soc/soc-topology.c
+++ b/sound/soc/soc-topology.c
@@ -1021,6 +1021,7 @@ static int soc_tplg_dapm_graph_elems_load(struct soc_tplg *tplg,
 	struct snd_soc_tplg_hdr *hdr)
 {
 	struct snd_soc_dapm_context *dapm = &tplg->comp->dapm;
+	const size_t maxlen = SNDRV_CTL_ELEM_ID_NAME_MAXLEN;
 	struct snd_soc_tplg_dapm_graph_elem *elem;
 	struct snd_soc_dapm_route *route;
 	int count, i;
@@ -1044,31 +1045,27 @@ static int soc_tplg_dapm_graph_elems_load(struct soc_tplg *tplg,
 		tplg->pos += sizeof(struct snd_soc_tplg_dapm_graph_elem);
 
 		/* validate routes */
-		if (strnlen(elem->source, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) ==
-			    SNDRV_CTL_ELEM_ID_NAME_MAXLEN) {
-			ret = -EINVAL;
-			break;
-		}
-		if (strnlen(elem->sink, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) ==
-			    SNDRV_CTL_ELEM_ID_NAME_MAXLEN) {
-			ret = -EINVAL;
-			break;
-		}
-		if (strnlen(elem->control, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) ==
-			    SNDRV_CTL_ELEM_ID_NAME_MAXLEN) {
+		if ((strnlen(elem->source, maxlen) == maxlen) ||
+		    (strnlen(elem->sink, maxlen) == maxlen) ||
+		    (strnlen(elem->control, maxlen) == maxlen)) {
 			ret = -EINVAL;
 			break;
 		}
 
-		route->source = elem->source;
-		route->sink = elem->sink;
+		route->source = devm_kstrdup(tplg->dev, elem->source, GFP_KERNEL);
+		route->sink = devm_kstrdup(tplg->dev, elem->sink, GFP_KERNEL);
+		if (!route->source || !route->sink) {
+			ret = -ENOMEM;
+			break;
+		}
 
-		/* set to NULL atm for tplg users */
-		route->connected = NULL;
-		if (strnlen(elem->control, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == 0)
-			route->control = NULL;
-		else
-			route->control = elem->control;
+		if (strnlen(elem->control, maxlen) != 0) {
+			route->control = devm_kstrdup(tplg->dev, elem->control, GFP_KERNEL);
+			if (!route->control) {
+				ret = -ENOMEM;
+				break;
+			}
+		}
 
 		/* add route dobj to dobj_list */
 		route->dobj.type = SND_SOC_DOBJ_GRAPH;
diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c
index ce675c2..c61d298 100644
--- a/sound/soc/sof/intel/hda-dai.c
+++ b/sound/soc/sof/intel/hda-dai.c
@@ -379,7 +379,7 @@ static int non_hda_dai_hw_params_data(struct snd_pcm_substream *substream,
 
 	sdev = widget_to_sdev(w);
 	if (sdev->dspless_mode_selected)
-		goto skip_tlv;
+		return 0;
 
 	/* get stream_id */
 	hext_stream = ops->get_hext_stream(sdev, cpu_dai, substream);
@@ -423,7 +423,6 @@ static int non_hda_dai_hw_params_data(struct snd_pcm_substream *substream,
 	dma_config->dma_stream_channel_map.device_count = 1;
 	dma_config->dma_priv_config_size = 0;
 
-skip_tlv:
 	return 0;
 }
 
@@ -525,6 +524,9 @@ int sdw_hda_dai_hw_params(struct snd_pcm_substream *substream,
 		return ret;
 	}
 
+	if (sdev->dspless_mode_selected)
+		return 0;
+
 	ipc4_copier = widget_to_copier(w);
 	dma_config_tlv = &ipc4_copier->dma_config_tlv[cpu_dai_id];
 	dma_config = &dma_config_tlv->dma_config;
diff --git a/sound/soc/sof/sof-audio.c b/sound/soc/sof/sof-audio.c
index 881eec3..9a52781 100644
--- a/sound/soc/sof/sof-audio.c
+++ b/sound/soc/sof/sof-audio.c
@@ -485,7 +485,7 @@ sof_prepare_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget
 			if (ret < 0) {
 				/* unprepare the source widget */
 				if (widget_ops[widget->id].ipc_unprepare &&
-				    swidget && swidget->prepared) {
+				    swidget && swidget->prepared && swidget->use_count == 0) {
 					widget_ops[widget->id].ipc_unprepare(swidget);
 					swidget->prepared = false;
 				}
diff --git a/sound/soc/ti/davinci-mcasp.c b/sound/soc/ti/davinci-mcasp.c
index 1e760c3..2b1ed91 100644
--- a/sound/soc/ti/davinci-mcasp.c
+++ b/sound/soc/ti/davinci-mcasp.c
@@ -1472,10 +1472,11 @@ static int davinci_mcasp_hw_rule_min_periodsize(
 {
 	struct snd_interval *period_size = hw_param_interval(params,
 						SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
+	u8 numevt = *((u8 *)rule->private);
 	struct snd_interval frames;
 
 	snd_interval_any(&frames);
-	frames.min = 64;
+	frames.min = numevt;
 	frames.integer = 1;
 
 	return snd_interval_refine(period_size, &frames);
@@ -1490,6 +1491,7 @@ static int davinci_mcasp_startup(struct snd_pcm_substream *substream,
 	u32 max_channels = 0;
 	int i, dir, ret;
 	int tdm_slots = mcasp->tdm_slots;
+	u8 *numevt;
 
 	/* Do not allow more then one stream per direction */
 	if (mcasp->substreams[substream->stream])
@@ -1589,9 +1591,12 @@ static int davinci_mcasp_startup(struct snd_pcm_substream *substream,
 			return ret;
 	}
 
+	numevt = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
+			 &mcasp->txnumevt :
+			 &mcasp->rxnumevt;
 	snd_pcm_hw_rule_add(substream->runtime, 0,
 			    SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
-			    davinci_mcasp_hw_rule_min_periodsize, NULL,
+			    davinci_mcasp_hw_rule_min_periodsize, numevt,
 			    SNDRV_PCM_HW_PARAM_PERIOD_SIZE, -1);
 
 	return 0;
diff --git a/sound/soc/ti/omap-hdmi.c b/sound/soc/ti/omap-hdmi.c
index 639bc83..cf43ac1 100644
--- a/sound/soc/ti/omap-hdmi.c
+++ b/sound/soc/ti/omap-hdmi.c
@@ -354,11 +354,7 @@ static int omap_hdmi_audio_probe(struct platform_device *pdev)
 	if (!card)
 		return -ENOMEM;
 
-	card->name = devm_kasprintf(dev, GFP_KERNEL,
-				    "HDMI %s", dev_name(ad->dssdev));
-	if (!card->name)
-		return -ENOMEM;
-
+	card->name = "HDMI";
 	card->owner = THIS_MODULE;
 	card->dai_link =
 		devm_kzalloc(dev, sizeof(*(card->dai_link)), GFP_KERNEL);