summary refs log tree commit diff
path: root/sound
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2021-02-17 18:52:26 +0000
committerMark Brown <broonie@kernel.org>2021-02-17 18:52:26 +0000
commit0969db0d8d15caee41cd817154670c38d9ed7f61 (patch)
tree8ff546a65226e934d2b975ead545bb8bae54affc /sound
parent3b9b1490e098f4847a215d2be6a66fbb891bfc7a (diff)
parent7d25f7ca110e3e1433d3e6b53f4937fdabe42aa7 (diff)
downloadlinux-0969db0d8d15caee41cd817154670c38d9ed7f61.tar.gz
Merge remote-tracking branch 'asoc/for-5.12' into asoc-linus
Diffstat (limited to 'sound')
-rw-r--r--sound/core/pcm_dmaengine.c2
-rw-r--r--sound/soc/Kconfig20
-rw-r--r--sound/soc/Makefile8
-rw-r--r--sound/soc/adi/axi-i2s.c2
-rw-r--r--sound/soc/amd/acp3x-rt5682-max9836.c4
-rw-r--r--sound/soc/atmel/atmel-i2s.c2
-rw-r--r--sound/soc/atmel/atmel-pcm-pdc.c78
-rw-r--r--sound/soc/atmel/mchp-i2s-mcc.c4
-rw-r--r--sound/soc/au1x/i2sc.c2
-rw-r--r--sound/soc/bcm/bcm2835-i2s.c4
-rw-r--r--sound/soc/bcm/bcm63xx-i2s-whistler.c2
-rw-r--r--sound/soc/bcm/cygnus-pcm.c107
-rw-r--r--sound/soc/cirrus/ep93xx-i2s.c2
-rw-r--r--sound/soc/codecs/Kconfig31
-rw-r--r--sound/soc/codecs/Makefile10
-rw-r--r--sound/soc/codecs/ab8500-codec.c4
-rw-r--r--sound/soc/codecs/adau1372.c2
-rw-r--r--sound/soc/codecs/adau1373.c6
-rw-r--r--sound/soc/codecs/adau1701.c2
-rw-r--r--sound/soc/codecs/adau17x1.c3
-rw-r--r--sound/soc/codecs/ak4554.c2
-rw-r--r--sound/soc/codecs/ak4613.c2
-rw-r--r--sound/soc/codecs/ak4641.c4
-rw-r--r--sound/soc/codecs/ak4642.c2
-rw-r--r--sound/soc/codecs/alc5632.c2
-rw-r--r--sound/soc/codecs/cpcap.c127
-rw-r--r--sound/soc/codecs/cros_ec_codec.c12
-rw-r--r--sound/soc/codecs/cs35l32.c2
-rw-r--r--sound/soc/codecs/cs35l33.c2
-rw-r--r--sound/soc/codecs/cs35l34.c2
-rw-r--r--sound/soc/codecs/cs35l35.c2
-rw-r--r--sound/soc/codecs/cs35l36.c2
-rw-r--r--sound/soc/codecs/cs4234.c2
-rw-r--r--sound/soc/codecs/cs4271.c2
-rw-r--r--sound/soc/codecs/cs42l56.c3
-rw-r--r--sound/soc/codecs/cs42l73.c6
-rw-r--r--sound/soc/codecs/cs43130.c6
-rw-r--r--sound/soc/codecs/cs4341.c2
-rw-r--r--sound/soc/codecs/cs4349.c2
-rw-r--r--sound/soc/codecs/cs47l15.c12
-rw-r--r--sound/soc/codecs/cs47l24.c12
-rw-r--r--sound/soc/codecs/cs47l35.c12
-rw-r--r--sound/soc/codecs/cs47l85.c16
-rw-r--r--sound/soc/codecs/cs47l90.c16
-rw-r--r--sound/soc/codecs/cs47l92.c12
-rw-r--r--sound/soc/codecs/cs53l30.c2
-rw-r--r--sound/soc/codecs/cx2072x.c2
-rw-r--r--sound/soc/codecs/da7210.c2
-rw-r--r--sound/soc/codecs/da7213.c2
-rw-r--r--sound/soc/codecs/da7218.c8
-rw-r--r--sound/soc/codecs/da7219.c4
-rw-r--r--sound/soc/codecs/da9055.c2
-rw-r--r--sound/soc/codecs/es8316.c5
-rw-r--r--sound/soc/codecs/es8328.c5
-rw-r--r--sound/soc/codecs/hdmi-codec.c4
-rw-r--r--sound/soc/codecs/inno_rk3036.c2
-rw-r--r--sound/soc/codecs/jz4740.c2
-rw-r--r--sound/soc/codecs/jz4760.c889
-rw-r--r--sound/soc/codecs/lm49453.c2
-rw-r--r--sound/soc/codecs/lochnagar-sc.c12
-rw-r--r--sound/soc/codecs/lpass-rx-macro.c3599
-rw-r--r--sound/soc/codecs/lpass-tx-macro.c1862
-rw-r--r--sound/soc/codecs/lpass-wsa-macro.c43
-rw-r--r--sound/soc/codecs/max98373-sdw.c4
-rw-r--r--sound/soc/codecs/max9860.c2
-rw-r--r--sound/soc/codecs/max9867.c2
-rw-r--r--sound/soc/codecs/mc13783.c2
-rw-r--r--sound/soc/codecs/ml26124.c2
-rw-r--r--sound/soc/codecs/mt6359.c18
-rw-r--r--sound/soc/codecs/mt6660.c4
-rw-r--r--sound/soc/codecs/nau8810.c2
-rw-r--r--sound/soc/codecs/nau8822.c2
-rw-r--r--sound/soc/codecs/rt1015.c122
-rw-r--r--sound/soc/codecs/rt1015.h5
-rw-r--r--sound/soc/codecs/rt1308-sdw.c2
-rw-r--r--sound/soc/codecs/rt274.c2
-rw-r--r--sound/soc/codecs/rt286.c4
-rw-r--r--sound/soc/codecs/rt298.c4
-rw-r--r--sound/soc/codecs/rt5645.c78
-rw-r--r--sound/soc/codecs/rt5670.c4
-rw-r--r--sound/soc/codecs/rt5682-sdw.c21
-rw-r--r--sound/soc/codecs/rt5682.c10
-rw-r--r--sound/soc/codecs/rt5682.h2
-rw-r--r--sound/soc/codecs/rt700-sdw.c2
-rw-r--r--sound/soc/codecs/rt711-sdw.c2
-rw-r--r--sound/soc/codecs/rt715-sdw.c2
-rw-r--r--sound/soc/codecs/sgtl5000.c2
-rw-r--r--sound/soc/codecs/sirf-audio-codec.c575
-rw-r--r--sound/soc/codecs/ssm2602.c4
-rw-r--r--sound/soc/codecs/tas2764.c2
-rw-r--r--sound/soc/codecs/tas2770.c2
-rw-r--r--sound/soc/codecs/tlv320adcx140.c2
-rw-r--r--sound/soc/codecs/tlv320aic31xx.c4
-rw-r--r--sound/soc/codecs/tlv320aic32x4.c2
-rw-r--r--sound/soc/codecs/tlv320aic3x.c2
-rw-r--r--sound/soc/codecs/tscs42xx.c4
-rw-r--r--sound/soc/codecs/tscs454.c12
-rw-r--r--sound/soc/codecs/wm5102.c12
-rw-r--r--sound/soc/codecs/wm5110.c12
-rw-r--r--sound/soc/codecs/wm8510.c2
-rw-r--r--sound/soc/codecs/wm8731.c2
-rw-r--r--sound/soc/codecs/wm8770.c2
-rw-r--r--sound/soc/codecs/wm8804.c2
-rw-r--r--sound/soc/codecs/wm8903.c2
-rw-r--r--sound/soc/codecs/wm8904.c2
-rw-r--r--sound/soc/codecs/wm8940.c2
-rw-r--r--sound/soc/codecs/wm8960.c2
-rw-r--r--sound/soc/codecs/wm8962.c2
-rw-r--r--sound/soc/codecs/wm8974.c2
-rw-r--r--sound/soc/codecs/wm8978.c2
-rw-r--r--sound/soc/codecs/wm8983.c2
-rw-r--r--sound/soc/codecs/wm8985.c2
-rw-r--r--sound/soc/codecs/wm8988.c2
-rw-r--r--sound/soc/codecs/wm8993.c2
-rw-r--r--sound/soc/codecs/wm8994.c4
-rw-r--r--sound/soc/codecs/wm8997.c8
-rw-r--r--sound/soc/codecs/wm8998.c12
-rw-r--r--sound/soc/codecs/wm9713.c2
-rw-r--r--sound/soc/codecs/wm_adsp.c108
-rw-r--r--sound/soc/codecs/wmfw.h6
-rw-r--r--sound/soc/codecs/zl38060.c4
-rw-r--r--sound/soc/codecs/zx_aud96p22.c401
-rw-r--r--sound/soc/fsl/Kconfig1
-rw-r--r--sound/soc/fsl/fsl_asrc.c5
-rw-r--r--sound/soc/fsl/fsl_easrc.c2
-rw-r--r--sound/soc/fsl/fsl_esai.c13
-rw-r--r--sound/soc/fsl/fsl_micfil.c9
-rw-r--r--sound/soc/fsl/fsl_sai.c8
-rw-r--r--sound/soc/fsl/fsl_spdif.c14
-rw-r--r--sound/soc/fsl/fsl_ssi.c12
-rw-r--r--sound/soc/fsl/fsl_xcvr.c7
-rw-r--r--sound/soc/generic/audio-graph-card.c17
-rw-r--r--sound/soc/generic/simple-card-utils.c13
-rw-r--r--sound/soc/intel/Kconfig2
-rw-r--r--sound/soc/intel/boards/Kconfig12
-rw-r--r--sound/soc/intel/boards/Makefile2
-rw-r--r--sound/soc/intel/boards/bytcht_es8316.c3
-rw-r--r--sound/soc/intel/boards/bytcr_rt5640.c89
-rw-r--r--sound/soc/intel/boards/bytcr_rt5651.c13
-rw-r--r--sound/soc/intel/boards/bytcr_wm5102.c465
-rw-r--r--sound/soc/intel/boards/cht_bsw_nau8824.c15
-rw-r--r--sound/soc/intel/boards/sof_maxim_common.c5
-rw-r--r--sound/soc/intel/boards/sof_rt5682.c7
-rw-r--r--sound/soc/intel/boards/sof_sdw.c134
-rw-r--r--sound/soc/intel/catpt/pcm.c14
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-adl-match.c1
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-bxt-match.c3
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-byt-match.c19
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-cfl-match.c3
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-cht-match.c3
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-cml-match.c3
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-cnl-match.c3
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-ehl-match.c5
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-glk-match.c3
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-hsw-bdw-match.c3
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-icl-match.c3
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-jsl-match.c3
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-kbl-match.c3
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-skl-match.c3
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-tgl-match.c25
-rw-r--r--sound/soc/intel/common/soc-intel-quirks.h25
-rw-r--r--sound/soc/intel/keembay/kmb_platform.c230
-rw-r--r--sound/soc/intel/keembay/kmb_platform.h10
-rw-r--r--sound/soc/intel/skylake/skl.c8
-rw-r--r--sound/soc/jz4740/jz4740-i2s.c2
-rw-r--r--sound/soc/kirkwood/kirkwood-dma.c79
-rw-r--r--sound/soc/mediatek/Kconfig2
-rw-r--r--sound/soc/mediatek/mt2701/mt2701-afe-pcm.c10
-rw-r--r--sound/soc/mediatek/mt6797/mt6797-dai-pcm.c8
-rw-r--r--sound/soc/mediatek/mt8173/mt8173-afe-pcm.c2
-rw-r--r--sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c6
-rw-r--r--sound/soc/mediatek/mt8183/mt8183-dai-pcm.c8
-rw-r--r--sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c47
-rw-r--r--sound/soc/mediatek/mt8192/mt8192-afe-pcm.c4
-rw-r--r--sound/soc/mediatek/mt8192/mt8192-dai-pcm.c8
-rw-r--r--sound/soc/mediatek/mt8192/mt8192-dai-tdm.c2
-rw-r--r--sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c84
-rw-r--r--sound/soc/meson/aiu-fifo-i2s.c1
-rw-r--r--sound/soc/meson/aiu-fifo-spdif.c1
-rw-r--r--sound/soc/meson/aiu-fifo.c18
-rw-r--r--sound/soc/pxa/pxa2xx-i2s.c2
-rw-r--r--sound/soc/qcom/lpass-cpu.c17
-rw-r--r--sound/soc/qcom/qdsp6/q6asm-dai.c21
-rw-r--r--sound/soc/qcom/qdsp6/q6asm.c2
-rw-r--r--sound/soc/qcom/qdsp6/q6routing.c18
-rw-r--r--sound/soc/rockchip/rockchip_i2s.c4
-rw-r--r--sound/soc/rockchip/rockchip_pdm.c2
-rw-r--r--sound/soc/samsung/i2s.c2
-rw-r--r--sound/soc/samsung/pcm.c2
-rw-r--r--sound/soc/sh/rcar/core.c4
-rw-r--r--sound/soc/sirf/Kconfig21
-rw-r--r--sound/soc/sirf/Makefile8
-rw-r--r--sound/soc/sirf/sirf-audio-port.c86
-rw-r--r--sound/soc/sirf/sirf-audio.c160
-rw-r--r--sound/soc/sirf/sirf-usp.c435
-rw-r--r--sound/soc/sirf/sirf-usp.h292
-rw-r--r--sound/soc/soc-component.c54
-rw-r--r--sound/soc/soc-dapm.c13
-rw-r--r--sound/soc/soc-pcm.c465
-rw-r--r--sound/soc/soc-topology-test.c843
-rw-r--r--sound/soc/soc-topology.c30
-rw-r--r--sound/soc/sof/core.c19
-rw-r--r--sound/soc/sof/intel/hda-compress.c4
-rw-r--r--sound/soc/sof/intel/hda-dsp.c20
-rw-r--r--sound/soc/sof/intel/hda-loader.c17
-rw-r--r--sound/soc/sof/intel/hda-pcm.c18
-rw-r--r--sound/soc/sof/intel/hda-stream.c38
-rw-r--r--sound/soc/sof/intel/hda-trace.c8
-rw-r--r--sound/soc/sof/intel/hda.c272
-rw-r--r--sound/soc/sof/intel/hda.h7
-rw-r--r--sound/soc/sof/intel/tgl.c3
-rw-r--r--sound/soc/sof/ipc.c4
-rw-r--r--sound/soc/sof/loader.c6
-rw-r--r--sound/soc/sof/ops.h43
-rw-r--r--sound/soc/sof/pm.c1
-rw-r--r--sound/soc/sof/sof-pci-dev.c15
-rw-r--r--sound/soc/sof/sof-priv.h8
-rw-r--r--sound/soc/sof/topology.c10
-rw-r--r--sound/soc/sprd/sprd-mcdt.c10
-rw-r--r--sound/soc/stm/stm32_i2s.c310
-rw-r--r--sound/soc/sunxi/sun4i-i2s.c2
-rw-r--r--sound/soc/sunxi/sun8i-codec.c12
-rw-r--r--sound/soc/tegra/Kconfig42
-rw-r--r--sound/soc/tegra/Makefile2
-rw-r--r--sound/soc/tegra/tegra186_dspk.c2
-rw-r--r--sound/soc/tegra/tegra20_i2s.c2
-rw-r--r--sound/soc/tegra/tegra210_dmic.c2
-rw-r--r--sound/soc/tegra/tegra210_i2s.c2
-rw-r--r--sound/soc/tegra/tegra30_ahub.c64
-rw-r--r--sound/soc/tegra/tegra30_ahub.h5
-rw-r--r--sound/soc/tegra/tegra30_i2s.c2
-rw-r--r--sound/soc/tegra/tegra_audio_graph_card.c252
-rw-r--r--sound/soc/tegra/tegra_pcm.c6
-rw-r--r--sound/soc/ti/davinci-mcasp.c2
-rw-r--r--sound/soc/txx9/Kconfig30
-rw-r--r--sound/soc/txx9/Makefile12
-rw-r--r--sound/soc/txx9/txx9aclc-ac97.c230
-rw-r--r--sound/soc/txx9/txx9aclc-generic.c88
-rw-r--r--sound/soc/txx9/txx9aclc.c422
-rw-r--r--sound/soc/txx9/txx9aclc.h71
-rw-r--r--sound/soc/zte/Kconfig26
-rw-r--r--sound/soc/zte/Makefile4
-rw-r--r--sound/soc/zte/zx-i2s.c452
-rw-r--r--sound/soc/zte/zx-spdif.c363
-rw-r--r--sound/soc/zte/zx-tdm.c458
245 files changed, 10143 insertions, 5718 deletions
diff --git a/sound/core/pcm_dmaengine.c b/sound/core/pcm_dmaengine.c
index 4d0e8fe535a1..1fc2fa077574 100644
--- a/sound/core/pcm_dmaengine.c
+++ b/sound/core/pcm_dmaengine.c
@@ -125,6 +125,8 @@ void snd_dmaengine_pcm_set_config_from_dai_data(
 	}
 
 	slave_config->slave_id = dma_data->slave_id;
+	slave_config->peripheral_config = dma_data->peripheral_config;
+	slave_config->peripheral_size = dma_data->peripheral_size;
 }
 EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_set_config_from_dai_data);
 
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig
index 71a6fe87d1a1..640494f76cbd 100644
--- a/sound/soc/Kconfig
+++ b/sound/soc/Kconfig
@@ -37,6 +37,23 @@ config SND_SOC_COMPRESS
 config SND_SOC_TOPOLOGY
 	bool
 
+config SND_SOC_TOPOLOGY_KUNIT_TESTS
+	tristate "KUnit tests for SoC topology"
+	depends on KUNIT
+	depends on SND_SOC_TOPOLOGY
+	default KUNIT_ALL_TESTS
+	help
+	  If you want to perform tests on ALSA SoC topology support say Y here.
+
+	  This builds a module which can be later manually loaded to run KUNIT
+	  test cases against soc-topology.c API. This should be primarily used
+	  by developers to test their changes to ASoC.
+
+	  Do note that it creates fake playback devices which do not interact
+	  well with userspace. When running tests one may want to disable
+	  userspace applications such as pulseaudio, to prevent unnecessary
+	  problems.
+
 config SND_SOC_ACPI
 	tristate
 
@@ -62,7 +79,6 @@ source "sound/soc/qcom/Kconfig"
 source "sound/soc/rockchip/Kconfig"
 source "sound/soc/samsung/Kconfig"
 source "sound/soc/sh/Kconfig"
-source "sound/soc/sirf/Kconfig"
 source "sound/soc/sof/Kconfig"
 source "sound/soc/spear/Kconfig"
 source "sound/soc/sprd/Kconfig"
@@ -71,12 +87,10 @@ source "sound/soc/stm/Kconfig"
 source "sound/soc/sunxi/Kconfig"
 source "sound/soc/tegra/Kconfig"
 source "sound/soc/ti/Kconfig"
-source "sound/soc/txx9/Kconfig"
 source "sound/soc/uniphier/Kconfig"
 source "sound/soc/ux500/Kconfig"
 source "sound/soc/xilinx/Kconfig"
 source "sound/soc/xtensa/Kconfig"
-source "sound/soc/zte/Kconfig"
 
 # Supported codecs
 source "sound/soc/codecs/Kconfig"
diff --git a/sound/soc/Makefile b/sound/soc/Makefile
index ddbac3a2169f..f56ad996eae8 100644
--- a/sound/soc/Makefile
+++ b/sound/soc/Makefile
@@ -7,6 +7,11 @@ ifneq ($(CONFIG_SND_SOC_TOPOLOGY),)
 snd-soc-core-objs += soc-topology.o
 endif
 
+ifneq ($(CONFIG_SND_SOC_TOPOLOGY_KUNIT_TESTS),)
+# snd-soc-test-objs := soc-topology-test.o
+obj-$(CONFIG_SND_SOC_TOPOLOGY_KUNIT_TESTS) := soc-topology-test.o
+endif
+
 ifneq ($(CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM),)
 snd-soc-core-objs += soc-generic-dmaengine-pcm.o
 endif
@@ -45,7 +50,6 @@ obj-$(CONFIG_SND_SOC)	+= qcom/
 obj-$(CONFIG_SND_SOC)	+= rockchip/
 obj-$(CONFIG_SND_SOC)	+= samsung/
 obj-$(CONFIG_SND_SOC)	+= sh/
-obj-$(CONFIG_SND_SOC)	+= sirf/
 obj-$(CONFIG_SND_SOC)	+= sof/
 obj-$(CONFIG_SND_SOC)	+= spear/
 obj-$(CONFIG_SND_SOC)	+= sprd/
@@ -54,9 +58,7 @@ obj-$(CONFIG_SND_SOC)	+= stm/
 obj-$(CONFIG_SND_SOC)	+= sunxi/
 obj-$(CONFIG_SND_SOC)	+= tegra/
 obj-$(CONFIG_SND_SOC)	+= ti/
-obj-$(CONFIG_SND_SOC)	+= txx9/
 obj-$(CONFIG_SND_SOC)	+= uniphier/
 obj-$(CONFIG_SND_SOC)	+= ux500/
 obj-$(CONFIG_SND_SOC)	+= xilinx/
 obj-$(CONFIG_SND_SOC)	+= xtensa/
-obj-$(CONFIG_SND_SOC)	+= zte/
diff --git a/sound/soc/adi/axi-i2s.c b/sound/soc/adi/axi-i2s.c
index 8c4dc82be0df..aa082131fb90 100644
--- a/sound/soc/adi/axi-i2s.c
+++ b/sound/soc/adi/axi-i2s.c
@@ -156,7 +156,7 @@ static const struct snd_soc_dai_ops axi_i2s_dai_ops = {
 static struct snd_soc_dai_driver axi_i2s_dai = {
 	.probe = axi_i2s_dai_probe,
 	.ops = &axi_i2s_dai_ops,
-	.symmetric_rates = 1,
+	.symmetric_rate = 1,
 };
 
 static const struct snd_soc_component_driver axi_i2s_component = {
diff --git a/sound/soc/amd/acp3x-rt5682-max9836.c b/sound/soc/amd/acp3x-rt5682-max9836.c
index 1a4e8ca0f99c..cea320ad0e1c 100644
--- a/sound/soc/amd/acp3x-rt5682-max9836.c
+++ b/sound/soc/amd/acp3x-rt5682-max9836.c
@@ -140,9 +140,7 @@ static int acp3x_1015_hw_params(struct snd_pcm_substream *substream,
 	for_each_rtd_codec_dais(rtd, i, codec_dai) {
 		if (strcmp(codec_dai->name, "rt1015-aif"))
 			continue;
-		ret = snd_soc_dai_set_bclk_ratio(codec_dai, 64);
-		if (ret < 0)
-			return ret;
+
 		ret = snd_soc_dai_set_pll(codec_dai, 0, RT1015_PLL_S_BCLK,
 						64 * srate, 256 * srate);
 		if (ret < 0)
diff --git a/sound/soc/atmel/atmel-i2s.c b/sound/soc/atmel/atmel-i2s.c
index 232300dda548..7c6187e41f2b 100644
--- a/sound/soc/atmel/atmel-i2s.c
+++ b/sound/soc/atmel/atmel-i2s.c
@@ -541,7 +541,7 @@ static struct snd_soc_dai_driver atmel_i2s_dai = {
 		.formats = ATMEL_I2S_FORMATS,
 	},
 	.ops = &atmel_i2s_dai_ops,
-	.symmetric_rates = 1,
+	.symmetric_rate = 1,
 };
 
 static const struct snd_soc_component_driver atmel_i2s_component = {
diff --git a/sound/soc/atmel/atmel-pcm-pdc.c b/sound/soc/atmel/atmel-pcm-pdc.c
index 704f700013d3..3e7ea2021b46 100644
--- a/sound/soc/atmel/atmel-pcm-pdc.c
+++ b/sound/soc/atmel/atmel-pcm-pdc.c
@@ -34,86 +34,21 @@
 #include "atmel-pcm.h"
 
 
-static int atmel_pcm_preallocate_dma_buffer(struct snd_pcm *pcm,
-	int stream)
-{
-	struct snd_pcm_substream *substream = pcm->streams[stream].substream;
-	struct snd_dma_buffer *buf = &substream->dma_buffer;
-	size_t size = ATMEL_SSC_DMABUF_SIZE;
-
-	buf->dev.type = SNDRV_DMA_TYPE_DEV;
-	buf->dev.dev = pcm->card->dev;
-	buf->private_data = NULL;
-	buf->area = dma_alloc_coherent(pcm->card->dev, size,
-			&buf->addr, GFP_KERNEL);
-	pr_debug("atmel-pcm: alloc dma buffer: area=%p, addr=%p, size=%zu\n",
-			(void *)buf->area, (void *)(long)buf->addr, size);
-
-	if (!buf->area)
-		return -ENOMEM;
-
-	buf->bytes = size;
-	return 0;
-}
-
-static int atmel_pcm_mmap(struct snd_soc_component *component,
-			  struct snd_pcm_substream *substream,
-			  struct vm_area_struct *vma)
-{
-	return remap_pfn_range(vma, vma->vm_start,
-		       substream->dma_buffer.addr >> PAGE_SHIFT,
-		       vma->vm_end - vma->vm_start, vma->vm_page_prot);
-}
-
 static int atmel_pcm_new(struct snd_soc_component *component,
 			 struct snd_soc_pcm_runtime *rtd)
 {
 	struct snd_card *card = rtd->card->snd_card;
-	struct snd_pcm *pcm = rtd->pcm;
 	int ret;
 
 	ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
 	if (ret)
 		return ret;
 
-	if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
-		pr_debug("atmel-pcm: allocating PCM playback DMA buffer\n");
-		ret = atmel_pcm_preallocate_dma_buffer(pcm,
-			SNDRV_PCM_STREAM_PLAYBACK);
-		if (ret)
-			goto out;
-	}
+	snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV,
+				       card->dev, ATMEL_SSC_DMABUF_SIZE,
+				       ATMEL_SSC_DMABUF_SIZE);
 
-	if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
-		pr_debug("atmel-pcm: allocating PCM capture DMA buffer\n");
-		ret = atmel_pcm_preallocate_dma_buffer(pcm,
-			SNDRV_PCM_STREAM_CAPTURE);
-		if (ret)
-			goto out;
-	}
- out:
-	return ret;
-}
-
-static void atmel_pcm_free(struct snd_soc_component *component,
-			   struct snd_pcm *pcm)
-{
-	struct snd_pcm_substream *substream;
-	struct snd_dma_buffer *buf;
-	int stream;
-
-	for (stream = 0; stream < 2; stream++) {
-		substream = pcm->streams[stream].substream;
-		if (!substream)
-			continue;
-
-		buf = &substream->dma_buffer;
-		if (!buf->area)
-			continue;
-		dma_free_coherent(pcm->card->dev, buf->bytes,
-				  buf->area, buf->addr);
-		buf->area = NULL;
-	}
+	return 0;
 }
 
 /*--------------------------------------------------------------------------*\
@@ -210,9 +145,6 @@ static int atmel_pcm_hw_params(struct snd_soc_component *component,
 	/* this may get called several times by oss emulation
 	 * with different params */
 
-	snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
-	runtime->dma_bytes = params_buffer_bytes(params);
-
 	prtd->params = snd_soc_dai_get_dma_data(asoc_rtd_to_cpu(rtd, 0), substream);
 	prtd->params->dma_intr_handler = atmel_pcm_dma_irq;
 
@@ -384,9 +316,7 @@ static const struct snd_soc_component_driver atmel_soc_platform = {
 	.prepare	= atmel_pcm_prepare,
 	.trigger	= atmel_pcm_trigger,
 	.pointer	= atmel_pcm_pointer,
-	.mmap		= atmel_pcm_mmap,
 	.pcm_construct	= atmel_pcm_new,
-	.pcm_destruct	= atmel_pcm_free,
 };
 
 int atmel_pcm_pdc_platform_register(struct device *dev)
diff --git a/sound/soc/atmel/mchp-i2s-mcc.c b/sound/soc/atmel/mchp-i2s-mcc.c
index 04acc18f2d72..6d5ae18f8b38 100644
--- a/sound/soc/atmel/mchp-i2s-mcc.c
+++ b/sound/soc/atmel/mchp-i2s-mcc.c
@@ -859,8 +859,8 @@ static struct snd_soc_dai_driver mchp_i2s_mcc_dai = {
 		.formats = MCHP_I2SMCC_FORMATS,
 	},
 	.ops = &mchp_i2s_mcc_dai_ops,
-	.symmetric_rates = 1,
-	.symmetric_samplebits = 1,
+	.symmetric_rate = 1,
+	.symmetric_sample_bits = 1,
 	.symmetric_channels = 1,
 };
 
diff --git a/sound/soc/au1x/i2sc.c b/sound/soc/au1x/i2sc.c
index 7fd08fafa490..65bd39f5032d 100644
--- a/sound/soc/au1x/i2sc.c
+++ b/sound/soc/au1x/i2sc.c
@@ -210,7 +210,7 @@ static const struct snd_soc_dai_ops au1xi2s_dai_ops = {
 };
 
 static struct snd_soc_dai_driver au1xi2s_dai_driver = {
-	.symmetric_rates	= 1,
+	.symmetric_rate		= 1,
 	.playback = {
 		.rates		= AU1XI2SC_RATES,
 		.formats	= AU1XI2SC_FMTS,
diff --git a/sound/soc/bcm/bcm2835-i2s.c b/sound/soc/bcm/bcm2835-i2s.c
index c2f7631e8705..3d668f449bc1 100644
--- a/sound/soc/bcm/bcm2835-i2s.c
+++ b/sound/soc/bcm/bcm2835-i2s.c
@@ -783,8 +783,8 @@ static struct snd_soc_dai_driver bcm2835_i2s_dai = {
 				| SNDRV_PCM_FMTBIT_S32_LE
 		},
 	.ops = &bcm2835_i2s_dai_ops,
-	.symmetric_rates = 1,
-	.symmetric_samplebits = 1,
+	.symmetric_rate = 1,
+	.symmetric_sample_bits = 1,
 };
 
 static bool bcm2835_i2s_volatile_reg(struct device *dev, unsigned int reg)
diff --git a/sound/soc/bcm/bcm63xx-i2s-whistler.c b/sound/soc/bcm/bcm63xx-i2s-whistler.c
index 246a57ac6679..527caf430715 100644
--- a/sound/soc/bcm/bcm63xx-i2s-whistler.c
+++ b/sound/soc/bcm/bcm63xx-i2s-whistler.c
@@ -212,7 +212,7 @@ static struct snd_soc_dai_driver bcm63xx_i2s_dai = {
 		.formats = SNDRV_PCM_FMTBIT_S32_LE,
 	},
 	.ops = &bcm63xx_i2s_dai_ops,
-	.symmetric_rates = 1,
+	.symmetric_rate = 1,
 	.symmetric_channels = 1,
 };
 
diff --git a/sound/soc/bcm/cygnus-pcm.c b/sound/soc/bcm/cygnus-pcm.c
index 7ad07239f99c..56b71b965624 100644
--- a/sound/soc/bcm/cygnus-pcm.c
+++ b/sound/soc/bcm/cygnus-pcm.c
@@ -636,36 +636,6 @@ static int cygnus_pcm_close(struct snd_soc_component *component,
 	return 0;
 }
 
-static int cygnus_pcm_hw_params(struct snd_soc_component *component,
-				struct snd_pcm_substream *substream,
-				struct snd_pcm_hw_params *params)
-{
-	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
-	struct snd_pcm_runtime *runtime = substream->runtime;
-	struct cygnus_aio_port *aio;
-
-	aio = cygnus_dai_get_dma_data(substream);
-	dev_dbg(asoc_rtd_to_cpu(rtd, 0)->dev, "%s  port %d\n", __func__, aio->portnum);
-
-	snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
-	runtime->dma_bytes = params_buffer_bytes(params);
-
-	return 0;
-}
-
-static int cygnus_pcm_hw_free(struct snd_soc_component *component,
-			      struct snd_pcm_substream *substream)
-{
-	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
-	struct cygnus_aio_port *aio;
-
-	aio = cygnus_dai_get_dma_data(substream);
-	dev_dbg(asoc_rtd_to_cpu(rtd, 0)->dev, "%s  port %d\n", __func__, aio->portnum);
-
-	snd_pcm_set_runtime_buffer(substream, NULL);
-	return 0;
-}
-
 static int cygnus_pcm_prepare(struct snd_soc_component *component,
 			      struct snd_pcm_substream *substream)
 {
@@ -730,87 +700,19 @@ static snd_pcm_uframes_t cygnus_pcm_pointer(struct snd_soc_component *component,
 	return bytes_to_frames(substream->runtime, res);
 }
 
-static int cygnus_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
-{
-	struct snd_pcm_substream *substream = pcm->streams[stream].substream;
-	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
-	struct snd_dma_buffer *buf = &substream->dma_buffer;
-	size_t size;
-
-	size = cygnus_pcm_hw.buffer_bytes_max;
-
-	buf->dev.type = SNDRV_DMA_TYPE_DEV;
-	buf->dev.dev = pcm->card->dev;
-	buf->private_data = NULL;
-	buf->area = dma_alloc_coherent(pcm->card->dev, size,
-			&buf->addr, GFP_KERNEL);
-
-	dev_dbg(asoc_rtd_to_cpu(rtd, 0)->dev, "%s: size 0x%zx @ %pK\n",
-				__func__, size, buf->area);
-
-	if (!buf->area) {
-		dev_err(asoc_rtd_to_cpu(rtd, 0)->dev, "%s: dma_alloc failed\n", __func__);
-		return -ENOMEM;
-	}
-	buf->bytes = size;
-
-	return 0;
-}
-
-static void cygnus_dma_free_dma_buffers(struct snd_soc_component *component,
-					struct snd_pcm *pcm)
-{
-	struct snd_pcm_substream *substream;
-	struct snd_dma_buffer *buf;
-
-	substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
-	if (substream) {
-		buf = &substream->dma_buffer;
-		if (buf->area) {
-			dma_free_coherent(pcm->card->dev, buf->bytes,
-				buf->area, buf->addr);
-			buf->area = NULL;
-		}
-	}
-
-	substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
-	if (substream) {
-		buf = &substream->dma_buffer;
-		if (buf->area) {
-			dma_free_coherent(pcm->card->dev, buf->bytes,
-				buf->area, buf->addr);
-			buf->area = NULL;
-		}
-	}
-}
-
 static int cygnus_dma_new(struct snd_soc_component *component,
 			  struct snd_soc_pcm_runtime *rtd)
 {
+	size_t size = cygnus_pcm_hw.buffer_bytes_max;
 	struct snd_card *card = rtd->card->snd_card;
-	struct snd_pcm *pcm = rtd->pcm;
-	int ret;
 
 	if (!card->dev->dma_mask)
 		card->dev->dma_mask = &cygnus_dma_dmamask;
 	if (!card->dev->coherent_dma_mask)
 		card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
 
-	if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
-		ret = cygnus_pcm_preallocate_dma_buffer(pcm,
-				SNDRV_PCM_STREAM_PLAYBACK);
-		if (ret)
-			return ret;
-	}
-
-	if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
-		ret = cygnus_pcm_preallocate_dma_buffer(pcm,
-				SNDRV_PCM_STREAM_CAPTURE);
-		if (ret) {
-			cygnus_dma_free_dma_buffers(component, pcm);
-			return ret;
-		}
-	}
+	snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV,
+				       card->dev, size, size);
 
 	return 0;
 }
@@ -818,13 +720,10 @@ static int cygnus_dma_new(struct snd_soc_component *component,
 static struct snd_soc_component_driver cygnus_soc_platform = {
 	.open		= cygnus_pcm_open,
 	.close		= cygnus_pcm_close,
-	.hw_params	= cygnus_pcm_hw_params,
-	.hw_free	= cygnus_pcm_hw_free,
 	.prepare	= cygnus_pcm_prepare,
 	.trigger	= cygnus_pcm_trigger,
 	.pointer	= cygnus_pcm_pointer,
 	.pcm_construct	= cygnus_dma_new,
-	.pcm_destruct	= cygnus_dma_free_dma_buffers,
 };
 
 int cygnus_soc_platform_register(struct device *dev,
diff --git a/sound/soc/cirrus/ep93xx-i2s.c b/sound/soc/cirrus/ep93xx-i2s.c
index 371708b17c09..0d26550d0df8 100644
--- a/sound/soc/cirrus/ep93xx-i2s.c
+++ b/sound/soc/cirrus/ep93xx-i2s.c
@@ -404,7 +404,7 @@ static const struct snd_soc_dai_ops ep93xx_i2s_dai_ops = {
 #define EP93XX_I2S_FORMATS (SNDRV_PCM_FMTBIT_S32_LE)
 
 static struct snd_soc_dai_driver ep93xx_i2s_dai = {
-	.symmetric_rates= 1,
+	.symmetric_rate	= 1,
 	.probe		= ep93xx_i2s_dai_probe,
 	.playback	= {
 		.channels_min	= 2,
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 9bf6bfdaf11e..e4cf14e66a51 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -104,6 +104,7 @@ config SND_SOC_ALL_CODECS
 	imply SND_SOC_ISABELLE
 	imply SND_SOC_JZ4740_CODEC
 	imply SND_SOC_JZ4725B_CODEC
+	imply SND_SOC_JZ4760_CODEC
 	imply SND_SOC_JZ4770_CODEC
 	imply SND_SOC_LM4857
 	imply SND_SOC_LM49453
@@ -227,6 +228,8 @@ config SND_SOC_ALL_CODECS
 	imply SND_SOC_UDA1380
 	imply SND_SOC_WCD9335
 	imply SND_SOC_WCD934X
+	imply SND_SOC_LPASS_RX_MACRO
+	imply SND_SOC_LPASS_TX_MACRO
 	imply SND_SOC_WL1273
 	imply SND_SOC_WM0010
 	imply SND_SOC_WM1250_EV1
@@ -712,7 +715,7 @@ config SND_SOC_CX2072X
 	  Enable support for Conexant CX20721 and CX20723 codec chips.
 
 config SND_SOC_JZ4740_CODEC
-	depends on MIPS || COMPILE_TEST
+	depends on MACH_INGENIC || COMPILE_TEST
 	depends on OF
 	select REGMAP_MMIO
 	tristate "Ingenic JZ4740 internal CODEC"
@@ -724,7 +727,7 @@ config SND_SOC_JZ4740_CODEC
 	  will be called snd-soc-jz4740-codec.
 
 config SND_SOC_JZ4725B_CODEC
-	depends on MIPS || COMPILE_TEST
+	depends on MACH_INGENIC || COMPILE_TEST
 	depends on OF
 	select REGMAP
 	tristate "Ingenic JZ4725B internal CODEC"
@@ -735,8 +738,20 @@ config SND_SOC_JZ4725B_CODEC
 	  This driver can also be built as a module. If so, the module
 	  will be called snd-soc-jz4725b-codec.
 
+config SND_SOC_JZ4760_CODEC
+        depends on MACH_INGENIC || COMPILE_TEST
+        depends on OF
+        select REGMAP
+        tristate "Ingenic JZ4760 internal CODEC"
+        help
+          Enable support for the internal CODEC found in the JZ4760 SoC
+          from Ingenic.
+
+          This driver can also be built as a module. If so, the module
+          will be called snd-soc-jz4760-codec.
+
 config SND_SOC_JZ4770_CODEC
-	depends on MIPS || COMPILE_TEST
+	depends on MACH_INGENIC || COMPILE_TEST
 	depends on OF
 	select REGMAP
 	tristate "Ingenic JZ4770 internal CODEC"
@@ -1162,7 +1177,7 @@ config SND_SOC_RT5651
 	depends on I2C
 
 config SND_SOC_RT5659
-	tristate
+	tristate "Realtek RT5658/RT5659 Codec"
 	depends on I2C
 
 config SND_SOC_RT5660
@@ -1820,4 +1835,12 @@ config SND_SOC_LPASS_VA_MACRO
 	depends on COMMON_CLK
 	tristate "Qualcomm VA Macro in LPASS(Low Power Audio SubSystem)"
 
+config SND_SOC_LPASS_RX_MACRO
+	depends on COMMON_CLK
+	tristate "Qualcomm RX Macro in LPASS(Low Power Audio SubSystem)"
+
+config SND_SOC_LPASS_TX_MACRO
+	depends on COMMON_CLK
+	tristate "Qualcomm TX Macro in LPASS(Low Power Audio SubSystem)"
+
 endmenu
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index d277f0366e09..81357dc62ea0 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -101,11 +101,14 @@ snd-soc-inno-rk3036-objs := inno_rk3036.o
 snd-soc-isabelle-objs := isabelle.o
 snd-soc-jz4740-codec-objs := jz4740.o
 snd-soc-jz4725b-codec-objs := jz4725b.o
+snd-soc-jz4760-codec-objs := jz4760.o
 snd-soc-jz4770-codec-objs := jz4770.o
 snd-soc-l3-objs := l3.o
 snd-soc-lm4857-objs := lm4857.o
 snd-soc-lm49453-objs := lm49453.o
 snd-soc-lochnagar-sc-objs := lochnagar-sc.o
+snd-soc-lpass-rx-macro-objs := lpass-rx-macro.o
+snd-soc-lpass-tx-macro-objs := lpass-tx-macro.o
 snd-soc-lpass-wsa-macro-objs := lpass-wsa-macro.o
 snd-soc-lpass-va-macro-objs := lpass-va-macro.o
 snd-soc-madera-objs := madera.o
@@ -201,7 +204,6 @@ snd-soc-sigmadsp-objs := sigmadsp.o
 snd-soc-sigmadsp-i2c-objs := sigmadsp-i2c.o
 snd-soc-sigmadsp-regmap-objs := sigmadsp-regmap.o
 snd-soc-si476x-objs := si476x.o
-snd-soc-sirf-audio-codec-objs := sirf-audio-codec.o
 snd-soc-spdif-tx-objs := spdif_transmitter.o
 snd-soc-spdif-rx-objs := spdif_receiver.o
 snd-soc-ssm2305-objs := ssm2305.o
@@ -302,7 +304,6 @@ snd-soc-wm9713-objs := wm9713.o
 snd-soc-wm-hubs-objs := wm_hubs.o
 snd-soc-wsa881x-objs := wsa881x.o
 snd-soc-zl38060-objs := zl38060.o
-snd-soc-zx-aud96p22-objs := zx_aud96p22.o
 # Amp
 snd-soc-max9877-objs := max9877.o
 snd-soc-max98504-objs := max98504.o
@@ -418,6 +419,7 @@ obj-$(CONFIG_SND_SOC_INNO_RK3036)	+= snd-soc-inno-rk3036.o
 obj-$(CONFIG_SND_SOC_ISABELLE)	+= snd-soc-isabelle.o
 obj-$(CONFIG_SND_SOC_JZ4740_CODEC)	+= snd-soc-jz4740-codec.o
 obj-$(CONFIG_SND_SOC_JZ4725B_CODEC)	+= snd-soc-jz4725b-codec.o
+obj-$(CONFIG_SND_SOC_JZ4760_CODEC)      += snd-soc-jz4760-codec.o
 obj-$(CONFIG_SND_SOC_JZ4770_CODEC)	+= snd-soc-jz4770-codec.o
 obj-$(CONFIG_SND_SOC_L3)	+= snd-soc-l3.o
 obj-$(CONFIG_SND_SOC_LM4857)	+= snd-soc-lm4857.o
@@ -516,7 +518,6 @@ obj-$(CONFIG_SND_SOC_SIGMADSP_I2C)	+= snd-soc-sigmadsp-i2c.o
 obj-$(CONFIG_SND_SOC_SIGMADSP_REGMAP)	+= snd-soc-sigmadsp-regmap.o
 obj-$(CONFIG_SND_SOC_SI476X)	+= snd-soc-si476x.o
 obj-$(CONFIG_SND_SOC_SPDIF)	+= snd-soc-spdif-rx.o snd-soc-spdif-tx.o
-obj-$(CONFIG_SND_SOC_SIRF_AUDIO_CODEC) += sirf-audio-codec.o
 obj-$(CONFIG_SND_SOC_SSM2305)	+= snd-soc-ssm2305.o
 obj-$(CONFIG_SND_SOC_SSM2518)	+= snd-soc-ssm2518.o
 obj-$(CONFIG_SND_SOC_SSM2602)	+= snd-soc-ssm2602.o
@@ -618,7 +619,6 @@ obj-$(CONFIG_SND_SOC_WM_ADSP)	+= snd-soc-wm-adsp.o
 obj-$(CONFIG_SND_SOC_WM_HUBS)	+= snd-soc-wm-hubs.o
 obj-$(CONFIG_SND_SOC_WSA881X)	+= snd-soc-wsa881x.o
 obj-$(CONFIG_SND_SOC_ZL38060)	+= snd-soc-zl38060.o
-obj-$(CONFIG_SND_SOC_ZX_AUD96P22) += snd-soc-zx-aud96p22.o
 
 # Amp
 obj-$(CONFIG_SND_SOC_MAX9877)	+= snd-soc-max9877.o
@@ -627,6 +627,8 @@ obj-$(CONFIG_SND_SOC_SIMPLE_AMPLIFIER)	+= snd-soc-simple-amplifier.o
 obj-$(CONFIG_SND_SOC_TPA6130A2)	+= snd-soc-tpa6130a2.o
 obj-$(CONFIG_SND_SOC_LPASS_WSA_MACRO)	+= snd-soc-lpass-wsa-macro.o
 obj-$(CONFIG_SND_SOC_LPASS_VA_MACRO)	+= snd-soc-lpass-va-macro.o
+obj-$(CONFIG_SND_SOC_LPASS_RX_MACRO)	+= snd-soc-lpass-rx-macro.o
+obj-$(CONFIG_SND_SOC_LPASS_TX_MACRO)	+= snd-soc-lpass-tx-macro.o
 
 # Mux
 obj-$(CONFIG_SND_SOC_SIMPLE_MUX)	+= snd-soc-simple-mux.o
diff --git a/sound/soc/codecs/ab8500-codec.c b/sound/soc/codecs/ab8500-codec.c
index 31a8c4162d20..c95f007cede1 100644
--- a/sound/soc/codecs/ab8500-codec.c
+++ b/sound/soc/codecs/ab8500-codec.c
@@ -2384,7 +2384,7 @@ static struct snd_soc_dai_driver ab8500_codec_dai[] = {
 			.formats = AB8500_SUPPORTED_FMT,
 		},
 		.ops = &ab8500_codec_ops,
-		.symmetric_rates = 1
+		.symmetric_rate = 1
 	},
 	{
 		.name = "ab8500-codec-dai.1",
@@ -2397,7 +2397,7 @@ static struct snd_soc_dai_driver ab8500_codec_dai[] = {
 			.formats = AB8500_SUPPORTED_FMT,
 		},
 		.ops = &ab8500_codec_ops,
-		.symmetric_rates = 1
+		.symmetric_rate = 1
 	}
 };
 
diff --git a/sound/soc/codecs/adau1372.c b/sound/soc/codecs/adau1372.c
index 5ccbf1b6bcf5..6811a8b3866d 100644
--- a/sound/soc/codecs/adau1372.c
+++ b/sound/soc/codecs/adau1372.c
@@ -890,7 +890,7 @@ static struct snd_soc_dai_driver adau1372_dai_driver = {
 		.sig_bits = 24,
 	},
 	.ops = &adau1372_dai_ops,
-	.symmetric_rates = 1,
+	.symmetric_rate = 1,
 };
 
 static int adau1372_setup_pll(struct adau1372 *adau1372, unsigned int rate)
diff --git a/sound/soc/codecs/adau1373.c b/sound/soc/codecs/adau1373.c
index e71fde001b46..9887aa6f0be5 100644
--- a/sound/soc/codecs/adau1373.c
+++ b/sound/soc/codecs/adau1373.c
@@ -1205,7 +1205,7 @@ static struct snd_soc_dai_driver adau1373_dai_driver[] = {
 			.formats = ADAU1373_FORMATS,
 		},
 		.ops = &adau1373_dai_ops,
-		.symmetric_rates = 1,
+		.symmetric_rate = 1,
 	},
 	{
 		.id = 1,
@@ -1225,7 +1225,7 @@ static struct snd_soc_dai_driver adau1373_dai_driver[] = {
 			.formats = ADAU1373_FORMATS,
 		},
 		.ops = &adau1373_dai_ops,
-		.symmetric_rates = 1,
+		.symmetric_rate = 1,
 	},
 	{
 		.id = 2,
@@ -1245,7 +1245,7 @@ static struct snd_soc_dai_driver adau1373_dai_driver[] = {
 			.formats = ADAU1373_FORMATS,
 		},
 		.ops = &adau1373_dai_ops,
-		.symmetric_rates = 1,
+		.symmetric_rate = 1,
 	},
 };
 
diff --git a/sound/soc/codecs/adau1701.c b/sound/soc/codecs/adau1701.c
index 68130eaa64a4..5ce74697564a 100644
--- a/sound/soc/codecs/adau1701.c
+++ b/sound/soc/codecs/adau1701.c
@@ -653,7 +653,7 @@ static struct snd_soc_dai_driver adau1701_dai = {
 		.formats = ADAU1701_FORMATS,
 	},
 	.ops = &adau1701_dai_ops,
-	.symmetric_rates = 1,
+	.symmetric_rate = 1,
 };
 
 #ifdef CONFIG_OF
diff --git a/sound/soc/codecs/adau17x1.c b/sound/soc/codecs/adau17x1.c
index 30e072c80ac1..546ee8178038 100644
--- a/sound/soc/codecs/adau17x1.c
+++ b/sound/soc/codecs/adau17x1.c
@@ -1095,8 +1095,7 @@ void adau17x1_remove(struct device *dev)
 {
 	struct adau *adau = dev_get_drvdata(dev);
 
-	if (adau->mclk)
-		clk_disable_unprepare(adau->mclk);
+	clk_disable_unprepare(adau->mclk);
 }
 EXPORT_SYMBOL_GPL(adau17x1_remove);
 
diff --git a/sound/soc/codecs/ak4554.c b/sound/soc/codecs/ak4554.c
index 2fa83a1a84cf..8e60e2b56ad6 100644
--- a/sound/soc/codecs/ak4554.c
+++ b/sound/soc/codecs/ak4554.c
@@ -56,7 +56,7 @@ static struct snd_soc_dai_driver ak4554_dai = {
 		.rates = SNDRV_PCM_RATE_8000_48000,
 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
 	},
-	.symmetric_rates = 1,
+	.symmetric_rate = 1,
 };
 
 static const struct snd_soc_component_driver soc_component_dev_ak4554 = {
diff --git a/sound/soc/codecs/ak4613.c b/sound/soc/codecs/ak4613.c
index 8d663e8d64c4..fe208cfdd3ba 100644
--- a/sound/soc/codecs/ak4613.c
+++ b/sound/soc/codecs/ak4613.c
@@ -575,7 +575,7 @@ static struct snd_soc_dai_driver ak4613_dai = {
 		.formats	= AK4613_PCM_FMTBIT,
 	},
 	.ops = &ak4613_dai_ops,
-	.symmetric_rates = 1,
+	.symmetric_rate = 1,
 };
 
 static int ak4613_suspend(struct snd_soc_component *component)
diff --git a/sound/soc/codecs/ak4641.c b/sound/soc/codecs/ak4641.c
index 77004cd7caa3..04aef0e72aa5 100644
--- a/sound/soc/codecs/ak4641.c
+++ b/sound/soc/codecs/ak4641.c
@@ -499,7 +499,7 @@ static struct snd_soc_dai_driver ak4641_dai[] = {
 		.formats = AK4641_FORMATS,
 	},
 	.ops = &ak4641_i2s_dai_ops,
-	.symmetric_rates = 1,
+	.symmetric_rate = 1,
 },
 {
 	.name = "ak4641-voice",
@@ -519,7 +519,7 @@ static struct snd_soc_dai_driver ak4641_dai[] = {
 		.formats = AK4641_FORMATS,
 	},
 	.ops = &ak4641_pcm_dai_ops,
-	.symmetric_rates = 1,
+	.symmetric_rate = 1,
 },
 };
 
diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c
index 353237025514..c49c58eeb476 100644
--- a/sound/soc/codecs/ak4642.c
+++ b/sound/soc/codecs/ak4642.c
@@ -516,7 +516,7 @@ static struct snd_soc_dai_driver ak4642_dai = {
 		.rates = SNDRV_PCM_RATE_8000_48000,
 		.formats = SNDRV_PCM_FMTBIT_S16_LE },
 	.ops = &ak4642_dai_ops,
-	.symmetric_rates = 1,
+	.symmetric_rate = 1,
 };
 
 static int ak4642_suspend(struct snd_soc_component *component)
diff --git a/sound/soc/codecs/alc5632.c b/sound/soc/codecs/alc5632.c
index bde5ded67754..79813882a955 100644
--- a/sound/soc/codecs/alc5632.c
+++ b/sound/soc/codecs/alc5632.c
@@ -1032,7 +1032,7 @@ static struct snd_soc_dai_driver alc5632_dai = {
 		.formats = ALC5632_FORMATS,},
 
 	.ops = &alc5632_dai_ops,
-	.symmetric_rates = 1,
+	.symmetric_rate = 1,
 };
 
 #ifdef CONFIG_PM
diff --git a/sound/soc/codecs/cpcap.c b/sound/soc/codecs/cpcap.c
index c0425e3707d9..05bbacd0d174 100644
--- a/sound/soc/codecs/cpcap.c
+++ b/sound/soc/codecs/cpcap.c
@@ -16,6 +16,14 @@
 #include <sound/soc.h>
 #include <sound/tlv.h>
 
+/* Register 512 CPCAP_REG_VAUDIOC --- Audio Regulator and Bias Voltage */
+#define CPCAP_BIT_AUDIO_LOW_PWR           6
+#define CPCAP_BIT_AUD_LOWPWR_SPEED        5
+#define CPCAP_BIT_VAUDIOPRISTBY           4
+#define CPCAP_BIT_VAUDIO_MODE1            2
+#define CPCAP_BIT_VAUDIO_MODE0            1
+#define CPCAP_BIT_V_AUDIO_EN              0
+
 /* Register 513 CPCAP_REG_CC     --- CODEC */
 #define CPCAP_BIT_CDC_CLK2                15
 #define CPCAP_BIT_CDC_CLK1                14
@@ -221,6 +229,7 @@ struct cpcap_reg_info {
 };
 
 static const struct cpcap_reg_info cpcap_default_regs[] = {
+	{ CPCAP_REG_VAUDIOC, 0x003F, 0x0000 },
 	{ CPCAP_REG_CC, 0xFFFF, 0x0000 },
 	{ CPCAP_REG_CC, 0xFFFF, 0x0000 },
 	{ CPCAP_REG_CDI, 0xBFFF, 0x0000 },
@@ -1371,8 +1380,121 @@ static int cpcap_voice_set_dai_fmt(struct snd_soc_dai *codec_dai,
 	return 0;
 }
 
-static int cpcap_voice_set_mute(struct snd_soc_dai *dai,
-				int mute, int direction)
+
+/*
+ * Configure codec for voice call if requested.
+ *
+ * We can configure most with snd_soc_dai_set_sysclk(), snd_soc_dai_set_fmt()
+ * and snd_soc_dai_set_tdm_slot(). This function configures the rest of the
+ * cpcap related hardware as CPU is not involved in the voice call.
+ */
+static int cpcap_voice_call(struct cpcap_audio *cpcap, struct snd_soc_dai *dai,
+			    bool voice_call)
+{
+	int mask, err;
+
+	/* Modem to codec VAUDIO_MODE1 */
+	mask = BIT(CPCAP_BIT_VAUDIO_MODE1);
+	err = regmap_update_bits(cpcap->regmap, CPCAP_REG_VAUDIOC,
+				 mask, voice_call ? mask : 0);
+	if (err)
+		return err;
+
+	/* Clear MIC1_MUX for call */
+	mask = BIT(CPCAP_BIT_MIC1_MUX);
+	err = regmap_update_bits(cpcap->regmap, CPCAP_REG_TXI,
+				 mask, voice_call ? 0 : mask);
+	if (err)
+		return err;
+
+	/* Set MIC2_MUX for call */
+	mask = BIT(CPCAP_BIT_MB_ON1L) | BIT(CPCAP_BIT_MB_ON1R) |
+		BIT(CPCAP_BIT_MIC2_MUX) | BIT(CPCAP_BIT_MIC2_PGA_EN);
+	err = regmap_update_bits(cpcap->regmap, CPCAP_REG_TXI,
+				 mask, voice_call ? mask : 0);
+	if (err)
+		return err;
+
+	/* Enable LDSP for call */
+	mask = BIT(CPCAP_BIT_A2_LDSP_L_EN) | BIT(CPCAP_BIT_A2_LDSP_R_EN);
+	err = regmap_update_bits(cpcap->regmap, CPCAP_REG_RXOA,
+				 mask, voice_call ? mask : 0);
+	if (err)
+		return err;
+
+	/* Enable CPCAP_BIT_PGA_CDC_EN for call */
+	mask = BIT(CPCAP_BIT_PGA_CDC_EN);
+	err = regmap_update_bits(cpcap->regmap, CPCAP_REG_RXCOA,
+				 mask, voice_call ? mask : 0);
+	if (err)
+		return err;
+
+	/* Unmute voice for call */
+	if (dai) {
+		err = snd_soc_dai_digital_mute(dai, !voice_call,
+					       SNDRV_PCM_STREAM_PLAYBACK);
+		if (err)
+			return err;
+	}
+
+	/* Set modem to codec mic CDC and HPF for call */
+	mask = BIT(CPCAP_BIT_MIC2_CDC_EN) | BIT(CPCAP_BIT_CDC_EN_RX) |
+	       BIT(CPCAP_BIT_AUDOHPF_1) | BIT(CPCAP_BIT_AUDOHPF_0) |
+	       BIT(CPCAP_BIT_AUDIHPF_1) | BIT(CPCAP_BIT_AUDIHPF_0);
+	err = regmap_update_bits(cpcap->regmap, CPCAP_REG_CC,
+				 mask, voice_call ? mask : 0);
+	if (err)
+		return err;
+
+	/* Enable modem to codec CDC for call*/
+	mask = BIT(CPCAP_BIT_CDC_CLK_EN);
+	err = regmap_update_bits(cpcap->regmap, CPCAP_REG_CDI,
+				 mask, voice_call ? mask : 0);
+
+	return err;
+}
+
+static int cpcap_voice_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 cpcap_audio *cpcap = snd_soc_component_get_drvdata(component);
+	int err, ts_mask, mask;
+	bool voice_call;
+
+	/*
+	 * Primitive test for voice call, probably needs more checks
+	 * later on for 16-bit calls detected, Bluetooth headset etc.
+	 */
+	if (tx_mask == 0 && rx_mask == 1 && slot_width == 8)
+		voice_call = true;
+	else
+		voice_call = false;
+
+	ts_mask = 0x7 << CPCAP_BIT_MIC2_TIMESLOT0;
+	ts_mask |= 0x7 << CPCAP_BIT_MIC1_RX_TIMESLOT0;
+
+	mask = (tx_mask & 0x7) << CPCAP_BIT_MIC2_TIMESLOT0;
+	mask |= (rx_mask & 0x7) << CPCAP_BIT_MIC1_RX_TIMESLOT0;
+
+	err = regmap_update_bits(cpcap->regmap, CPCAP_REG_CDI,
+				 ts_mask, mask);
+	if (err)
+		return err;
+
+	err = cpcap_set_samprate(cpcap, CPCAP_DAI_VOICE, slot_width * 1000);
+	if (err)
+		return err;
+
+	err = cpcap_voice_call(cpcap, dai, voice_call);
+	if (err)
+		return err;
+
+	return 0;
+}
+
+static int cpcap_voice_set_mute(struct snd_soc_dai *dai, int mute, int direction)
 {
 	struct snd_soc_component *component = dai->component;
 	struct cpcap_audio *cpcap = snd_soc_component_get_drvdata(component);
@@ -1393,6 +1515,7 @@ static const struct snd_soc_dai_ops cpcap_dai_voice_ops = {
 	.hw_params	= cpcap_voice_hw_params,
 	.set_sysclk	= cpcap_voice_set_dai_sysclk,
 	.set_fmt	= cpcap_voice_set_dai_fmt,
+	.set_tdm_slot	= cpcap_voice_set_tdm_slot,
 	.mute_stream	= cpcap_voice_set_mute,
 	.no_capture_mute = 1,
 };
diff --git a/sound/soc/codecs/cros_ec_codec.c b/sound/soc/codecs/cros_ec_codec.c
index f33a2a9654e7..c4772f82485a 100644
--- a/sound/soc/codecs/cros_ec_codec.c
+++ b/sound/soc/codecs/cros_ec_codec.c
@@ -1011,6 +1011,18 @@ static int cros_ec_codec_platform_probe(struct platform_device *pdev)
 	}
 	priv->ec_capabilities = r.capabilities;
 
+	/* Reset EC codec i2s rx. */
+	p.cmd = EC_CODEC_I2S_RX_RESET;
+	ret = send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC_I2S_RX,
+				   (uint8_t *)&p, sizeof(p), NULL, 0);
+	if (ret == -ENOPROTOOPT) {
+		dev_info(dev,
+			 "Missing reset command. Please update EC firmware.\n");
+	} else if (ret) {
+		dev_err(dev, "failed to EC_CODEC_I2S_RESET: %d\n", ret);
+		return ret;
+	}
+
 	platform_set_drvdata(pdev, priv);
 
 	ret = devm_snd_soc_register_component(dev, &i2s_rx_component_driver,
diff --git a/sound/soc/codecs/cs35l32.c b/sound/soc/codecs/cs35l32.c
index 3a644a35c464..f4067230ac42 100644
--- a/sound/soc/codecs/cs35l32.c
+++ b/sound/soc/codecs/cs35l32.c
@@ -194,7 +194,7 @@ static struct snd_soc_dai_driver cs35l32_dai[] = {
 			.formats = CS35L32_FORMATS,
 		},
 		.ops = &cs35l32_ops,
-		.symmetric_rates = 1,
+		.symmetric_rate = 1,
 	}
 };
 
diff --git a/sound/soc/codecs/cs35l33.c b/sound/soc/codecs/cs35l33.c
index 6042194d95d3..7ad7b733af9b 100644
--- a/sound/soc/codecs/cs35l33.c
+++ b/sound/soc/codecs/cs35l33.c
@@ -691,7 +691,7 @@ static struct snd_soc_dai_driver cs35l33_dai = {
 			.formats = CS35L33_FORMATS,
 		},
 		.ops = &cs35l33_ops,
-		.symmetric_rates = 1,
+		.symmetric_rate = 1,
 };
 
 static int cs35l33_set_hg_data(struct snd_soc_component *component,
diff --git a/sound/soc/codecs/cs35l34.c b/sound/soc/codecs/cs35l34.c
index b792c006e530..110ee2d06358 100644
--- a/sound/soc/codecs/cs35l34.c
+++ b/sound/soc/codecs/cs35l34.c
@@ -666,7 +666,7 @@ static struct snd_soc_dai_driver cs35l34_dai = {
 			.formats = CS35L34_FORMATS,
 		},
 		.ops = &cs35l34_ops,
-		.symmetric_rates = 1,
+		.symmetric_rate = 1,
 };
 
 static int cs35l34_boost_inductor(struct cs35l34_private *cs35l34,
diff --git a/sound/soc/codecs/cs35l35.c b/sound/soc/codecs/cs35l35.c
index e330427a4314..55d529aa0011 100644
--- a/sound/soc/codecs/cs35l35.c
+++ b/sound/soc/codecs/cs35l35.c
@@ -692,7 +692,7 @@ static struct snd_soc_dai_driver cs35l35_dai[] = {
 			.formats = CS35L35_FORMATS,
 		},
 		.ops = &cs35l35_ops,
-		.symmetric_rates = 1,
+		.symmetric_rate = 1,
 	},
 	{
 		.name = "cs35l35-pdm",
diff --git a/sound/soc/codecs/cs35l36.c b/sound/soc/codecs/cs35l36.c
index e9b5f76f27a8..4451ca9f4916 100644
--- a/sound/soc/codecs/cs35l36.c
+++ b/sound/soc/codecs/cs35l36.c
@@ -995,7 +995,7 @@ static struct snd_soc_dai_driver cs35l36_dai[] = {
 			.formats = CS35L36_TX_FORMATS,
 		},
 		.ops = &cs35l36_ops,
-		.symmetric_rates = 1,
+		.symmetric_rate = 1,
 	},
 };
 
diff --git a/sound/soc/codecs/cs4234.c b/sound/soc/codecs/cs4234.c
index 2ea83233c3f1..20126cc675b1 100644
--- a/sound/soc/codecs/cs4234.c
+++ b/sound/soc/codecs/cs4234.c
@@ -585,7 +585,7 @@ static struct snd_soc_dai_driver cs4234_dai[] = {
 			.formats = CS4234_FORMATS,
 		},
 		.ops = &cs4234_dai_ops,
-		.symmetric_rates = 1,
+		.symmetric_rate = 1,
 	},
 };
 
diff --git a/sound/soc/codecs/cs4271.c b/sound/soc/codecs/cs4271.c
index d43762ae8f3d..7663f89ac6a2 100644
--- a/sound/soc/codecs/cs4271.c
+++ b/sound/soc/codecs/cs4271.c
@@ -481,7 +481,7 @@ static struct snd_soc_dai_driver cs4271_dai = {
 		.formats	= CS4271_PCM_FORMATS,
 	},
 	.ops = &cs4271_dai_ops,
-	.symmetric_rates = 1,
+	.symmetric_rate = 1,
 };
 
 static int cs4271_reset(struct snd_soc_component *component)
diff --git a/sound/soc/codecs/cs42l56.c b/sound/soc/codecs/cs42l56.c
index bb9599cc832b..c44a5cdb796e 100644
--- a/sound/soc/codecs/cs42l56.c
+++ b/sound/soc/codecs/cs42l56.c
@@ -1250,6 +1250,7 @@ static int cs42l56_i2c_probe(struct i2c_client *i2c_client,
 		dev_err(&i2c_client->dev,
 			"CS42L56 Device ID (%X). Expected %X\n",
 			devid, CS42L56_DEVID);
+		ret = -EINVAL;
 		goto err_enable;
 	}
 	alpha_rev = reg & CS42L56_AREV_MASK;
@@ -1307,7 +1308,7 @@ static int cs42l56_i2c_probe(struct i2c_client *i2c_client,
 	ret =  devm_snd_soc_register_component(&i2c_client->dev,
 			&soc_component_dev_cs42l56, &cs42l56_dai, 1);
 	if (ret < 0)
-		return ret;
+		goto err_enable;
 
 	return 0;
 
diff --git a/sound/soc/codecs/cs42l73.c b/sound/soc/codecs/cs42l73.c
index 988ca7e19821..c3f974ec78e5 100644
--- a/sound/soc/codecs/cs42l73.c
+++ b/sound/soc/codecs/cs42l73.c
@@ -1181,7 +1181,7 @@ static struct snd_soc_dai_driver cs42l73_dai[] = {
 			.formats = CS42L73_FORMATS,
 		},
 		.ops = &cs42l73_ops,
-		.symmetric_rates = 1,
+		.symmetric_rate = 1,
 	 },
 	{
 		.name = "cs42l73-asp",
@@ -1201,7 +1201,7 @@ static struct snd_soc_dai_driver cs42l73_dai[] = {
 			.formats = CS42L73_FORMATS,
 		},
 		.ops = &cs42l73_ops,
-		.symmetric_rates = 1,
+		.symmetric_rate = 1,
 	 },
 	{
 		.name = "cs42l73-vsp",
@@ -1221,7 +1221,7 @@ static struct snd_soc_dai_driver cs42l73_dai[] = {
 			.formats = CS42L73_FORMATS,
 		},
 		.ops = &cs42l73_ops,
-		.symmetric_rates = 1,
+		.symmetric_rate = 1,
 	 }
 };
 
diff --git a/sound/soc/codecs/cs43130.c b/sound/soc/codecs/cs43130.c
index 7fb34422a2a4..80bc7c10ed75 100644
--- a/sound/soc/codecs/cs43130.c
+++ b/sound/soc/codecs/cs43130.c
@@ -1581,7 +1581,7 @@ static struct snd_soc_dai_driver cs43130_dai[] = {
 			.formats = CS43130_PCM_FORMATS,
 		},
 		.ops = &cs43130_pcm_ops,
-		.symmetric_rates = 1,
+		.symmetric_rate = 1,
 	},
 	{
 		.name = "cs43130-asp-dop",
@@ -1594,7 +1594,7 @@ static struct snd_soc_dai_driver cs43130_dai[] = {
 			.formats = CS43130_DOP_FORMATS,
 		},
 		.ops = &cs43130_dop_ops,
-		.symmetric_rates = 1,
+		.symmetric_rate = 1,
 	},
 	{
 		.name = "cs43130-xsp-dop",
@@ -1607,7 +1607,7 @@ static struct snd_soc_dai_driver cs43130_dai[] = {
 			.formats = CS43130_DOP_FORMATS,
 		},
 		.ops = &cs43130_dop_ops,
-		.symmetric_rates = 1,
+		.symmetric_rate = 1,
 	},
 	{
 		.name = "cs43130-xsp-dsd",
diff --git a/sound/soc/codecs/cs4341.c b/sound/soc/codecs/cs4341.c
index f566604de78c..7d3e54d8eef3 100644
--- a/sound/soc/codecs/cs4341.c
+++ b/sound/soc/codecs/cs4341.c
@@ -189,7 +189,7 @@ static struct snd_soc_dai_driver cs4341_dai = {
 				  SNDRV_PCM_FMTBIT_S24_LE,
 	},
 	.ops			= &cs4341_dai_ops,
-	.symmetric_rates	= 1,
+	.symmetric_rate		= 1,
 };
 
 static const struct snd_soc_component_driver soc_component_cs4341 = {
diff --git a/sound/soc/codecs/cs4349.c b/sound/soc/codecs/cs4349.c
index fd5526319779..786c69a8ec4a 100644
--- a/sound/soc/codecs/cs4349.c
+++ b/sound/soc/codecs/cs4349.c
@@ -250,7 +250,7 @@ static struct snd_soc_dai_driver cs4349_dai = {
 		.formats	= CS4349_PCM_FORMATS,
 	},
 	.ops = &cs4349_dai_ops,
-	.symmetric_rates = 1,
+	.symmetric_rate = 1,
 };
 
 static const struct snd_soc_component_driver soc_component_dev_cs4349 = {
diff --git a/sound/soc/codecs/cs47l15.c b/sound/soc/codecs/cs47l15.c
index 254f9d96e766..1ee83160b83f 100644
--- a/sound/soc/codecs/cs47l15.c
+++ b/sound/soc/codecs/cs47l15.c
@@ -1160,8 +1160,8 @@ static struct snd_soc_dai_driver cs47l15_dai[] = {
 			.formats = MADERA_FORMATS,
 		 },
 		.ops = &madera_dai_ops,
-		.symmetric_rates = 1,
-		.symmetric_samplebits = 1,
+		.symmetric_rate = 1,
+		.symmetric_sample_bits = 1,
 	},
 	{
 		.name = "cs47l15-aif2",
@@ -1182,8 +1182,8 @@ static struct snd_soc_dai_driver cs47l15_dai[] = {
 			.formats = MADERA_FORMATS,
 		 },
 		.ops = &madera_dai_ops,
-		.symmetric_rates = 1,
-		.symmetric_samplebits = 1,
+		.symmetric_rate = 1,
+		.symmetric_sample_bits = 1,
 	},
 	{
 		.name = "cs47l15-aif3",
@@ -1204,8 +1204,8 @@ static struct snd_soc_dai_driver cs47l15_dai[] = {
 			.formats = MADERA_FORMATS,
 		 },
 		.ops = &madera_dai_ops,
-		.symmetric_rates = 1,
-		.symmetric_samplebits = 1,
+		.symmetric_rate = 1,
+		.symmetric_sample_bits = 1,
 	},
 	{
 		.name = "cs47l15-cpu-trace",
diff --git a/sound/soc/codecs/cs47l24.c b/sound/soc/codecs/cs47l24.c
index f6d173d0120e..eaabbb56a173 100644
--- a/sound/soc/codecs/cs47l24.c
+++ b/sound/soc/codecs/cs47l24.c
@@ -977,8 +977,8 @@ static struct snd_soc_dai_driver cs47l24_dai[] = {
 			 .formats = CS47L24_FORMATS,
 		 },
 		.ops = &arizona_dai_ops,
-		.symmetric_rates = 1,
-		.symmetric_samplebits = 1,
+		.symmetric_rate = 1,
+		.symmetric_sample_bits = 1,
 	},
 	{
 		.name = "cs47l24-aif2",
@@ -999,8 +999,8 @@ static struct snd_soc_dai_driver cs47l24_dai[] = {
 			 .formats = CS47L24_FORMATS,
 		 },
 		.ops = &arizona_dai_ops,
-		.symmetric_rates = 1,
-		.symmetric_samplebits = 1,
+		.symmetric_rate = 1,
+		.symmetric_sample_bits = 1,
 	},
 	{
 		.name = "cs47l24-aif3",
@@ -1021,8 +1021,8 @@ static struct snd_soc_dai_driver cs47l24_dai[] = {
 			 .formats = CS47L24_FORMATS,
 		 },
 		.ops = &arizona_dai_ops,
-		.symmetric_rates = 1,
-		.symmetric_samplebits = 1,
+		.symmetric_rate = 1,
+		.symmetric_sample_bits = 1,
 	},
 	{
 		.name = "cs47l24-cpu-voicectrl",
diff --git a/sound/soc/codecs/cs47l35.c b/sound/soc/codecs/cs47l35.c
index e967609da8a3..3f04a2a74521 100644
--- a/sound/soc/codecs/cs47l35.c
+++ b/sound/soc/codecs/cs47l35.c
@@ -1368,8 +1368,8 @@ static struct snd_soc_dai_driver cs47l35_dai[] = {
 			.formats = MADERA_FORMATS,
 		 },
 		.ops = &madera_dai_ops,
-		.symmetric_rates = 1,
-		.symmetric_samplebits = 1,
+		.symmetric_rate = 1,
+		.symmetric_sample_bits = 1,
 	},
 	{
 		.name = "cs47l35-aif2",
@@ -1390,8 +1390,8 @@ static struct snd_soc_dai_driver cs47l35_dai[] = {
 			.formats = MADERA_FORMATS,
 		 },
 		.ops = &madera_dai_ops,
-		.symmetric_rates = 1,
-		.symmetric_samplebits = 1,
+		.symmetric_rate = 1,
+		.symmetric_sample_bits = 1,
 	},
 	{
 		.name = "cs47l35-aif3",
@@ -1412,8 +1412,8 @@ static struct snd_soc_dai_driver cs47l35_dai[] = {
 			.formats = MADERA_FORMATS,
 		 },
 		.ops = &madera_dai_ops,
-		.symmetric_rates = 1,
-		.symmetric_samplebits = 1,
+		.symmetric_rate = 1,
+		.symmetric_sample_bits = 1,
 	},
 	{
 		.name = "cs47l35-slim1",
diff --git a/sound/soc/codecs/cs47l85.c b/sound/soc/codecs/cs47l85.c
index 47b16466b6c1..748a180870bc 100644
--- a/sound/soc/codecs/cs47l85.c
+++ b/sound/soc/codecs/cs47l85.c
@@ -2269,8 +2269,8 @@ static struct snd_soc_dai_driver cs47l85_dai[] = {
 			.formats = MADERA_FORMATS,
 		 },
 		.ops = &madera_dai_ops,
-		.symmetric_rates = 1,
-		.symmetric_samplebits = 1,
+		.symmetric_rate = 1,
+		.symmetric_sample_bits = 1,
 	},
 	{
 		.name = "cs47l85-aif2",
@@ -2291,8 +2291,8 @@ static struct snd_soc_dai_driver cs47l85_dai[] = {
 			.formats = MADERA_FORMATS,
 		 },
 		.ops = &madera_dai_ops,
-		.symmetric_rates = 1,
-		.symmetric_samplebits = 1,
+		.symmetric_rate = 1,
+		.symmetric_sample_bits = 1,
 	},
 	{
 		.name = "cs47l85-aif3",
@@ -2313,8 +2313,8 @@ static struct snd_soc_dai_driver cs47l85_dai[] = {
 			.formats = MADERA_FORMATS,
 		 },
 		.ops = &madera_dai_ops,
-		.symmetric_rates = 1,
-		.symmetric_samplebits = 1,
+		.symmetric_rate = 1,
+		.symmetric_sample_bits = 1,
 	},
 	{
 		.name = "cs47l85-aif4",
@@ -2335,8 +2335,8 @@ static struct snd_soc_dai_driver cs47l85_dai[] = {
 			.formats = MADERA_FORMATS,
 		 },
 		.ops = &madera_dai_ops,
-		.symmetric_rates = 1,
-		.symmetric_samplebits = 1,
+		.symmetric_rate = 1,
+		.symmetric_sample_bits = 1,
 	},
 	{
 		.name = "cs47l85-slim1",
diff --git a/sound/soc/codecs/cs47l90.c b/sound/soc/codecs/cs47l90.c
index 8838dd557321..d2911c014b86 100644
--- a/sound/soc/codecs/cs47l90.c
+++ b/sound/soc/codecs/cs47l90.c
@@ -2188,8 +2188,8 @@ static struct snd_soc_dai_driver cs47l90_dai[] = {
 			.formats = MADERA_FORMATS,
 		 },
 		.ops = &madera_dai_ops,
-		.symmetric_rates = 1,
-		.symmetric_samplebits = 1,
+		.symmetric_rate = 1,
+		.symmetric_sample_bits = 1,
 	},
 	{
 		.name = "cs47l90-aif2",
@@ -2210,8 +2210,8 @@ static struct snd_soc_dai_driver cs47l90_dai[] = {
 			.formats = MADERA_FORMATS,
 		 },
 		.ops = &madera_dai_ops,
-		.symmetric_rates = 1,
-		.symmetric_samplebits = 1,
+		.symmetric_rate = 1,
+		.symmetric_sample_bits = 1,
 	},
 	{
 		.name = "cs47l90-aif3",
@@ -2232,8 +2232,8 @@ static struct snd_soc_dai_driver cs47l90_dai[] = {
 			.formats = MADERA_FORMATS,
 		 },
 		.ops = &madera_dai_ops,
-		.symmetric_rates = 1,
-		.symmetric_samplebits = 1,
+		.symmetric_rate = 1,
+		.symmetric_sample_bits = 1,
 	},
 	{
 		.name = "cs47l90-aif4",
@@ -2254,8 +2254,8 @@ static struct snd_soc_dai_driver cs47l90_dai[] = {
 			.formats = MADERA_FORMATS,
 		 },
 		.ops = &madera_dai_ops,
-		.symmetric_rates = 1,
-		.symmetric_samplebits = 1,
+		.symmetric_rate = 1,
+		.symmetric_sample_bits = 1,
 	},
 	{
 		.name = "cs47l90-slim1",
diff --git a/sound/soc/codecs/cs47l92.c b/sound/soc/codecs/cs47l92.c
index 52dc29942ec2..1a0280416d92 100644
--- a/sound/soc/codecs/cs47l92.c
+++ b/sound/soc/codecs/cs47l92.c
@@ -1704,8 +1704,8 @@ static struct snd_soc_dai_driver cs47l92_dai[] = {
 			.formats = MADERA_FORMATS,
 		 },
 		.ops = &madera_dai_ops,
-		.symmetric_rates = 1,
-		.symmetric_samplebits = 1,
+		.symmetric_rate = 1,
+		.symmetric_sample_bits = 1,
 	},
 	{
 		.name = "cs47l92-aif2",
@@ -1726,8 +1726,8 @@ static struct snd_soc_dai_driver cs47l92_dai[] = {
 			.formats = MADERA_FORMATS,
 		 },
 		.ops = &madera_dai_ops,
-		.symmetric_rates = 1,
-		.symmetric_samplebits = 1,
+		.symmetric_rate = 1,
+		.symmetric_sample_bits = 1,
 	},
 	{
 		.name = "cs47l92-aif3",
@@ -1748,8 +1748,8 @@ static struct snd_soc_dai_driver cs47l92_dai[] = {
 			.formats = MADERA_FORMATS,
 		 },
 		.ops = &madera_dai_ops,
-		.symmetric_rates = 1,
-		.symmetric_samplebits = 1,
+		.symmetric_rate = 1,
+		.symmetric_sample_bits = 1,
 	},
 	{
 		.name = "cs47l92-slim1",
diff --git a/sound/soc/codecs/cs53l30.c b/sound/soc/codecs/cs53l30.c
index ed22361b35c1..3d67cbf9eaaa 100644
--- a/sound/soc/codecs/cs53l30.c
+++ b/sound/soc/codecs/cs53l30.c
@@ -869,7 +869,7 @@ static struct snd_soc_dai_driver cs53l30_dai = {
 		.formats = CS53L30_FORMATS,
 	},
 	.ops = &cs53l30_ops,
-	.symmetric_rates = 1,
+	.symmetric_rate = 1,
 };
 
 static int cs53l30_component_probe(struct snd_soc_component *component)
diff --git a/sound/soc/codecs/cx2072x.c b/sound/soc/codecs/cx2072x.c
index 2f10991a8bdb..8ab22815c2c9 100644
--- a/sound/soc/codecs/cx2072x.c
+++ b/sound/soc/codecs/cx2072x.c
@@ -1572,7 +1572,7 @@ static struct snd_soc_dai_driver soc_codec_cx2072x_dai[] = {
 			.formats = CX2072X_FORMATS,
 		},
 		.ops = &cx2072x_dai_ops,
-		.symmetric_rates = 1,
+		.symmetric_rate = 1,
 	},
 	{ /* plabayck only, return echo reference to Conexant DSP chip */
 		.name = "cx2072x-dsp",
diff --git a/sound/soc/codecs/da7210.c b/sound/soc/codecs/da7210.c
index 3d05c37f676e..8af344b2fdbf 100644
--- a/sound/soc/codecs/da7210.c
+++ b/sound/soc/codecs/da7210.c
@@ -1059,7 +1059,7 @@ static struct snd_soc_dai_driver da7210_dai = {
 		.formats = DA7210_FORMATS,
 	},
 	.ops = &da7210_dai_ops,
-	.symmetric_rates = 1,
+	.symmetric_rate = 1,
 };
 
 static int da7210_probe(struct snd_soc_component *component)
diff --git a/sound/soc/codecs/da7213.c b/sound/soc/codecs/da7213.c
index 72402467adcc..3ab89387b4e6 100644
--- a/sound/soc/codecs/da7213.c
+++ b/sound/soc/codecs/da7213.c
@@ -1551,7 +1551,7 @@ static struct snd_soc_dai_driver da7213_dai = {
 		.formats = DA7213_FORMATS,
 	},
 	.ops = &da7213_dai_ops,
-	.symmetric_rates = 1,
+	.symmetric_rate = 1,
 };
 
 static int da7213_set_auto_pll(struct snd_soc_component *component, bool enable)
diff --git a/sound/soc/codecs/da7218.c b/sound/soc/codecs/da7218.c
index 2bfafbe9e3dc..ea426d986d4c 100644
--- a/sound/soc/codecs/da7218.c
+++ b/sound/soc/codecs/da7218.c
@@ -2194,9 +2194,9 @@ static struct snd_soc_dai_driver da7218_dai = {
 		.formats = DA7218_FORMATS,
 	},
 	.ops = &da7218_dai_ops,
-	.symmetric_rates = 1,
+	.symmetric_rate = 1,
 	.symmetric_channels = 1,
-	.symmetric_samplebits = 1,
+	.symmetric_sample_bits = 1,
 };
 
 
@@ -2278,14 +2278,12 @@ static irqreturn_t da7218_irq_thread(int irq, void *data)
  * DT
  */
 
-#ifdef CONFIG_OF
 static const struct of_device_id da7218_of_match[] = {
 	{ .compatible = "dlg,da7217", .data = (void *) DA7217_DEV_ID },
 	{ .compatible = "dlg,da7218", .data = (void *) DA7218_DEV_ID },
 	{ }
 };
 MODULE_DEVICE_TABLE(of, da7218_of_match);
-#endif
 
 static inline int da7218_of_get_id(struct device *dev)
 {
@@ -3311,7 +3309,7 @@ MODULE_DEVICE_TABLE(i2c, da7218_i2c_id);
 static struct i2c_driver da7218_i2c_driver = {
 	.driver = {
 		.name = "da7218",
-		.of_match_table = of_match_ptr(da7218_of_match),
+		.of_match_table = da7218_of_match,
 	},
 	.probe		= da7218_i2c_probe,
 	.id_table	= da7218_i2c_id,
diff --git a/sound/soc/codecs/da7219.c b/sound/soc/codecs/da7219.c
index e9b45daec0ca..13009d08b09a 100644
--- a/sound/soc/codecs/da7219.c
+++ b/sound/soc/codecs/da7219.c
@@ -1692,9 +1692,9 @@ static struct snd_soc_dai_driver da7219_dai = {
 		.formats = DA7219_FORMATS,
 	},
 	.ops = &da7219_dai_ops,
-	.symmetric_rates = 1,
+	.symmetric_rate = 1,
 	.symmetric_channels = 1,
-	.symmetric_samplebits = 1,
+	.symmetric_sample_bits = 1,
 };
 
 
diff --git a/sound/soc/codecs/da9055.c b/sound/soc/codecs/da9055.c
index aed92f615b02..a9676b261129 100644
--- a/sound/soc/codecs/da9055.c
+++ b/sound/soc/codecs/da9055.c
@@ -1347,7 +1347,7 @@ static struct snd_soc_dai_driver da9055_dai = {
 		.formats = DA9055_FORMATS,
 	},
 	.ops = &da9055_dai_ops,
-	.symmetric_rates = 1,
+	.symmetric_rate = 1,
 };
 
 static int da9055_set_bias_level(struct snd_soc_component *component,
diff --git a/sound/soc/codecs/es8316.c b/sound/soc/codecs/es8316.c
index f9ec5cf82599..d632055370e0 100644
--- a/sound/soc/codecs/es8316.c
+++ b/sound/soc/codecs/es8316.c
@@ -543,7 +543,7 @@ static struct snd_soc_dai_driver es8316_dai = {
 		.formats = ES8316_FORMATS,
 	},
 	.ops = &es8316_ops,
-	.symmetric_rates = 1,
+	.symmetric_rate = 1,
 };
 
 static void es8316_enable_micbias_for_mic_gnd_short_detect(
@@ -681,6 +681,9 @@ static void es8316_disable_jack_detect(struct snd_soc_component *component)
 {
 	struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component);
 
+	if (!es8316->jack)
+		return; /* Already disabled (or never enabled) */
+
 	disable_irq(es8316->irq);
 
 	mutex_lock(&es8316->lock);
diff --git a/sound/soc/codecs/es8328.c b/sound/soc/codecs/es8328.c
index 7e26231a596a..9632afc2d4d6 100644
--- a/sound/soc/codecs/es8328.c
+++ b/sound/soc/codecs/es8328.c
@@ -715,7 +715,7 @@ static struct snd_soc_dai_driver es8328_dai = {
 		.formats = ES8328_FORMATS,
 	},
 	.ops = &es8328_dai_ops,
-	.symmetric_rates = 1,
+	.symmetric_rate = 1,
 };
 
 static int es8328_suspend(struct snd_soc_component *component)
@@ -809,8 +809,7 @@ static void es8328_remove(struct snd_soc_component *component)
 
 	es8328 = snd_soc_component_get_drvdata(component);
 
-	if (es8328->clk)
-		clk_disable_unprepare(es8328->clk);
+	clk_disable_unprepare(es8328->clk);
 
 	regulator_bulk_disable(ARRAY_SIZE(es8328->supplies),
 			       es8328->supplies);
diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c
index 0f3ac22f2cf8..422539f933de 100644
--- a/sound/soc/codecs/hdmi-codec.c
+++ b/sound/soc/codecs/hdmi-codec.c
@@ -489,6 +489,7 @@ static int hdmi_codec_hw_params(struct snd_pcm_substream *substream,
 	hp.sample_rate = params_rate(params);
 	hp.channels = params_channels(params);
 
+	cf->bit_fmt = params_format(params);
 	return hcp->hcd.ops->hw_params(dai->dev->parent, hcp->hcd.data,
 				       cf, &hp);
 }
@@ -617,7 +618,8 @@ static const struct snd_soc_dai_ops hdmi_codec_spdif_dai_ops = {
 			 SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S20_3BE |\
 			 SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE |\
 			 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE |\
-			 SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE)
+			 SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE |\
+			 SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE)
 
 static int hdmi_codec_pcm_new(struct snd_soc_pcm_runtime *rtd,
 			      struct snd_soc_dai *dai)
diff --git a/sound/soc/codecs/inno_rk3036.c b/sound/soc/codecs/inno_rk3036.c
index 4dbce24c5f76..e05c4f27486e 100644
--- a/sound/soc/codecs/inno_rk3036.c
+++ b/sound/soc/codecs/inno_rk3036.c
@@ -325,7 +325,7 @@ static struct snd_soc_dai_driver rk3036_codec_dai_driver[] = {
 			.formats = RK3036_CODEC_FMTS,
 		},
 		.ops = &rk3036_codec_dai_ops,
-		.symmetric_rates = 1,
+		.symmetric_rate = 1,
 	},
 };
 
diff --git a/sound/soc/codecs/jz4740.c b/sound/soc/codecs/jz4740.c
index 5e58bfee2b49..081485f784e9 100644
--- a/sound/soc/codecs/jz4740.c
+++ b/sound/soc/codecs/jz4740.c
@@ -214,7 +214,7 @@ static struct snd_soc_dai_driver jz4740_codec_dai = {
 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8,
 	},
 	.ops = &jz4740_codec_dai_ops,
-	.symmetric_rates = 1,
+	.symmetric_rate = 1,
 };
 
 static void jz4740_codec_wakeup(struct regmap *regmap)
diff --git a/sound/soc/codecs/jz4760.c b/sound/soc/codecs/jz4760.c
new file mode 100644
index 000000000000..e8f28ccc145a
--- /dev/null
+++ b/sound/soc/codecs/jz4760.c
@@ -0,0 +1,889 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Ingenic JZ4760 CODEC driver
+//
+// Copyright (C) 2021, Christophe Branchereau <cbranchereau@gmail.com>
+// Copyright (C) 2021, Paul Cercueil <paul@crapouillou.net>
+
+#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/iopoll.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/time64.h>
+
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dai.h>
+#include <sound/soc-dapm.h>
+#include <sound/tlv.h>
+
+#define ICDC_RGADW_OFFSET		0x00
+#define ICDC_RGDATA_OFFSET		0x04
+
+/* ICDC internal register access control register(RGADW) */
+#define ICDC_RGADW_RGWR			BIT(16)
+#define	ICDC_RGADW_RGADDR_MASK		GENMASK(14, 8)
+#define	ICDC_RGADW_RGDIN_MASK		GENMASK(7, 0)
+
+/* ICDC internal register data output register (RGDATA)*/
+#define ICDC_RGDATA_IRQ			BIT(8)
+#define ICDC_RGDATA_RGDOUT_MASK		GENMASK(7, 0)
+
+/* Internal register space, accessed through regmap */
+enum {
+	JZ4760_CODEC_REG_SR,
+	JZ4760_CODEC_REG_AICR,
+	JZ4760_CODEC_REG_CR1,
+	JZ4760_CODEC_REG_CR2,
+	JZ4760_CODEC_REG_CR3,
+	JZ4760_CODEC_REG_CR4,
+	JZ4760_CODEC_REG_CCR1,
+	JZ4760_CODEC_REG_CCR2,
+	JZ4760_CODEC_REG_PMR1,
+	JZ4760_CODEC_REG_PMR2,
+	JZ4760_CODEC_REG_ICR,
+	JZ4760_CODEC_REG_IFR,
+	JZ4760_CODEC_REG_GCR1,
+	JZ4760_CODEC_REG_GCR2,
+	JZ4760_CODEC_REG_GCR3,
+	JZ4760_CODEC_REG_GCR4,
+	JZ4760_CODEC_REG_GCR5,
+	JZ4760_CODEC_REG_GCR6,
+	JZ4760_CODEC_REG_GCR7,
+	JZ4760_CODEC_REG_GCR8,
+	JZ4760_CODEC_REG_GCR9,
+	JZ4760_CODEC_REG_AGC1,
+	JZ4760_CODEC_REG_AGC2,
+	JZ4760_CODEC_REG_AGC3,
+	JZ4760_CODEC_REG_AGC4,
+	JZ4760_CODEC_REG_AGC5,
+	JZ4760_CODEC_REG_MIX1,
+	JZ4760_CODEC_REG_MIX2,
+};
+
+#define REG_AICR_DAC_ADWL_MASK		GENMASK(7, 6)
+#define REG_AICR_DAC_SERIAL		BIT(3)
+#define REG_AICR_DAC_I2S		BIT(1)
+
+#define REG_AICR_ADC_ADWL_MASK		GENMASK(5, 4)
+
+#define REG_AICR_ADC_SERIAL		BIT(2)
+#define REG_AICR_ADC_I2S		BIT(0)
+
+#define REG_CR1_HP_LOAD			BIT(7)
+#define REG_CR1_HP_MUTE			BIT(5)
+#define REG_CR1_LO_MUTE_OFFSET		4
+#define REG_CR1_BTL_MUTE_OFFSET		3
+#define REG_CR1_OUTSEL_OFFSET		0
+#define REG_CR1_OUTSEL_MASK		GENMASK(1, REG_CR1_OUTSEL_OFFSET)
+
+#define REG_CR2_DAC_MONO		BIT(7)
+#define REG_CR2_DAC_MUTE		BIT(5)
+#define REG_CR2_DAC_NOMAD		BIT(1)
+#define REG_CR2_DAC_RIGHT_ONLY		BIT(0)
+
+#define REG_CR3_ADC_INSEL_OFFSET	2
+#define REG_CR3_ADC_INSEL_MASK		GENMASK(3, REG_CR3_ADC_INSEL_OFFSET)
+#define REG_CR3_MICSTEREO_OFFSET	1
+#define REG_CR3_MICDIFF_OFFSET		0
+
+#define REG_CR4_ADC_HPF_OFFSET		7
+#define REG_CR4_ADC_RIGHT_ONLY		BIT(0)
+
+#define REG_CCR1_CRYSTAL_MASK		GENMASK(3, 0)
+
+#define REG_CCR2_DAC_FREQ_MASK		GENMASK(7, 4)
+#define REG_CCR2_ADC_FREQ_MASK		GENMASK(3, 0)
+
+#define REG_PMR1_SB			BIT(7)
+#define REG_PMR1_SB_SLEEP		BIT(6)
+#define REG_PMR1_SB_AIP_OFFSET		5
+#define REG_PMR1_SB_LINE_OFFSET		4
+#define REG_PMR1_SB_MIC1_OFFSET		3
+#define REG_PMR1_SB_MIC2_OFFSET		2
+#define REG_PMR1_SB_BYPASS_OFFSET	1
+#define REG_PMR1_SB_MICBIAS_OFFSET	0
+
+#define REG_PMR2_SB_ADC_OFFSET		4
+#define REG_PMR2_SB_HP_OFFSET		3
+#define REG_PMR2_SB_BTL_OFFSET		2
+#define REG_PMR2_SB_LOUT_OFFSET		1
+#define REG_PMR2_SB_DAC_OFFSET		0
+
+#define REG_ICR_INT_FORM_MASK		GENMASK(7, 6)
+#define REG_ICR_ALL_MASK		GENMASK(5, 0)
+#define REG_ICR_JACK_MASK		BIT(5)
+#define REG_ICR_SCMC_MASK		BIT(4)
+#define REG_ICR_RUP_MASK		BIT(3)
+#define REG_ICR_RDO_MASK		BIT(2)
+#define REG_ICR_GUP_MASK		BIT(1)
+#define REG_ICR_GDO_MASK		BIT(0)
+
+#define REG_IFR_ALL_MASK		GENMASK(5, 0)
+#define REG_IFR_JACK			BIT(6)
+#define REG_IFR_JACK_EVENT		BIT(5)
+#define REG_IFR_SCMC			BIT(4)
+#define REG_IFR_RUP			BIT(3)
+#define REG_IFR_RDO			BIT(2)
+#define REG_IFR_GUP			BIT(1)
+#define REG_IFR_GDO			BIT(0)
+
+#define REG_GCR_GAIN_OFFSET		0
+#define REG_GCR_GAIN_MAX		0x1f
+
+#define REG_GCR_RL			BIT(7)
+
+#define REG_GCR_GIM1_MASK		GENMASK(5, 3)
+#define REG_GCR_GIM2_MASK		GENMASK(2, 0)
+#define REG_GCR_GIM_GAIN_MAX		7
+
+#define REG_AGC1_EN			BIT(7)
+#define REG_AGC1_TARGET_MASK		GENMASK(5, 2)
+
+#define REG_AGC2_NG_THR_MASK		GENMASK(6, 4)
+#define REG_AGC2_HOLD_MASK		GENMASK(3, 0)
+
+#define REG_AGC3_ATK_MASK		GENMASK(7, 4)
+#define REG_AGC3_DCY_MASK		GENMASK(3, 0)
+
+#define REG_AGC4_AGC_MAX_MASK		GENMASK(4, 0)
+
+#define REG_AGC5_AGC_MIN_MASK		GENMASK(4, 0)
+
+#define REG_MIX1_MIX_REC_MASK		GENMASK(7, 6)
+#define REG_MIX1_GIMIX_MASK		GENMASK(4, 0)
+
+#define REG_MIX2_DAC_MIX_MASK		GENMASK(7, 6)
+#define REG_MIX2_GOMIX_MASK		GENMASK(4, 0)
+
+/* codec private data */
+struct jz_codec {
+	struct device *dev;
+	struct regmap *regmap;
+	void __iomem *base;
+	struct clk *clk;
+};
+
+static int jz4760_codec_set_bias_level(struct snd_soc_component *codec,
+				       enum snd_soc_bias_level level)
+{
+	struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
+	struct regmap *regmap = jz_codec->regmap;
+
+	switch (level) {
+	case SND_SOC_BIAS_PREPARE:
+		/* Reset all interrupt flags. */
+		regmap_write(regmap, JZ4760_CODEC_REG_IFR, REG_IFR_ALL_MASK);
+
+		regmap_clear_bits(regmap, JZ4760_CODEC_REG_PMR1, REG_PMR1_SB);
+		msleep(250);
+		regmap_clear_bits(regmap, JZ4760_CODEC_REG_PMR1, REG_PMR1_SB_SLEEP);
+		msleep(400);
+		break;
+	case SND_SOC_BIAS_STANDBY:
+		regmap_set_bits(regmap, JZ4760_CODEC_REG_PMR1, REG_PMR1_SB_SLEEP);
+		regmap_set_bits(regmap, JZ4760_CODEC_REG_PMR1, REG_PMR1_SB);
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static int jz4760_codec_startup(struct snd_pcm_substream *substream,
+				struct snd_soc_dai *dai)
+{
+	struct snd_soc_component *codec = dai->component;
+	struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(codec);
+	int ret;
+
+	/*
+	 * SYSCLK output from the codec to the AIC is required to keep the
+	 * DMA transfer going during playback when all audible outputs have
+	 * been disabled.
+	 */
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		ret = snd_soc_dapm_force_enable_pin(dapm, "SYSCLK");
+	return 0;
+}
+
+static void jz4760_codec_shutdown(struct snd_pcm_substream *substream,
+				  struct snd_soc_dai *dai)
+{
+	struct snd_soc_component *codec = dai->component;
+	struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(codec);
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		snd_soc_dapm_disable_pin(dapm, "SYSCLK");
+}
+
+
+static int jz4760_codec_pcm_trigger(struct snd_pcm_substream *substream,
+				    int cmd, struct snd_soc_dai *dai)
+{
+	struct snd_soc_component *codec = dai->component;
+	int ret = 0;
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+	case SNDRV_PCM_TRIGGER_RESUME:
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
+			snd_soc_component_force_bias_level(codec, SND_SOC_BIAS_ON);
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+		/* do nothing */
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static int jz4760_codec_mute_stream(struct snd_soc_dai *dai, int mute, int direction)
+{
+	struct snd_soc_component *codec = dai->component;
+	struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
+	unsigned int gain_bit = mute ? REG_IFR_GDO : REG_IFR_GUP;
+	unsigned int val, reg;
+	int change, err;
+
+	change = snd_soc_component_update_bits(codec, JZ4760_CODEC_REG_CR2,
+					       REG_CR2_DAC_MUTE,
+					       mute ? REG_CR2_DAC_MUTE : 0);
+	if (change == 1) {
+		regmap_read(jz_codec->regmap, JZ4760_CODEC_REG_PMR2, &val);
+
+		if (val & BIT(REG_PMR2_SB_DAC_OFFSET))
+			return 1;
+
+		err = regmap_read_poll_timeout(jz_codec->regmap,
+					       JZ4760_CODEC_REG_IFR,
+					       val, val & gain_bit,
+					       1000, 1 * USEC_PER_SEC);
+		if (err) {
+			dev_err(jz_codec->dev,
+				"Timeout while setting digital mute: %d", err);
+			return err;
+		}
+
+		/* clear GUP/GDO flag */
+		regmap_write(jz_codec->regmap, JZ4760_CODEC_REG_IFR, gain_bit);
+	}
+
+	regmap_read(jz_codec->regmap, JZ4760_CODEC_REG_CR2, &reg);
+
+	return 0;
+}
+
+/* unit: 0.01dB */
+static const DECLARE_TLV_DB_MINMAX_MUTE(dac_tlv, -3100, 100);
+static const DECLARE_TLV_DB_SCALE(adc_tlv, 0, 100, 0);
+static const DECLARE_TLV_DB_MINMAX(out_tlv, -2500, 100);
+static const DECLARE_TLV_DB_SCALE(linein_tlv, -2500, 100, 0);
+
+/* Unconditional controls. */
+static const struct snd_kcontrol_new jz4760_codec_snd_controls[] = {
+	/* record gain control */
+	SOC_DOUBLE_R_TLV("PCM Capture Volume",
+			 JZ4760_CODEC_REG_GCR9, JZ4760_CODEC_REG_GCR8,
+			 REG_GCR_GAIN_OFFSET, REG_GCR_GAIN_MAX, 0, adc_tlv),
+
+	SOC_DOUBLE_R_TLV("Line In Bypass Playback Volume",
+			 JZ4760_CODEC_REG_GCR4, JZ4760_CODEC_REG_GCR3,
+			 REG_GCR_GAIN_OFFSET, REG_GCR_GAIN_MAX, 1, linein_tlv),
+
+	SOC_SINGLE("High-Pass Filter Capture Switch",
+		   JZ4760_CODEC_REG_CR4,
+		   REG_CR4_ADC_HPF_OFFSET, 1, 0),
+};
+
+static const struct snd_kcontrol_new jz4760_codec_pcm_playback_controls[] = {
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Volume",
+		.info = snd_soc_info_volsw,
+		.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ
+			| SNDRV_CTL_ELEM_ACCESS_READWRITE,
+		.tlv.p = dac_tlv,
+		.get = snd_soc_dapm_get_volsw,
+		.put = snd_soc_dapm_put_volsw,
+		.private_value = SOC_DOUBLE_R_VALUE(JZ4760_CODEC_REG_GCR6,
+						    JZ4760_CODEC_REG_GCR5,
+						    REG_GCR_GAIN_OFFSET,
+						    REG_GCR_GAIN_MAX, 1),
+	},
+};
+
+static const struct snd_kcontrol_new jz4760_codec_hp_playback_controls[] = {
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Volume",
+		.info = snd_soc_info_volsw,
+		.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ
+			| SNDRV_CTL_ELEM_ACCESS_READWRITE,
+		.tlv.p = out_tlv,
+		.get = snd_soc_dapm_get_volsw,
+		.put = snd_soc_dapm_put_volsw,
+		.private_value = SOC_DOUBLE_R_VALUE(JZ4760_CODEC_REG_GCR2,
+						    JZ4760_CODEC_REG_GCR1,
+						    REG_GCR_GAIN_OFFSET,
+						    REG_GCR_GAIN_MAX, 1),
+	},
+};
+
+static int hpout_event(struct snd_soc_dapm_widget *w,
+		       struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_component *codec = snd_soc_dapm_to_component(w->dapm);
+	struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
+	unsigned int val;
+	int err;
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		/* unmute HP */
+		regmap_clear_bits(jz_codec->regmap, JZ4760_CODEC_REG_CR1,
+				  REG_CR1_HP_MUTE);
+		break;
+
+	case SND_SOC_DAPM_POST_PMU:
+		/* wait for ramp-up complete (RUP) */
+		err = regmap_read_poll_timeout(jz_codec->regmap,
+					       JZ4760_CODEC_REG_IFR,
+					       val, val & REG_IFR_RUP,
+					       1000, 1 * USEC_PER_SEC);
+		if (err) {
+			dev_err(jz_codec->dev, "RUP timeout: %d", err);
+			return err;
+		}
+
+		/* clear RUP flag */
+		regmap_set_bits(jz_codec->regmap, JZ4760_CODEC_REG_IFR,
+				REG_IFR_RUP);
+
+		break;
+
+	case SND_SOC_DAPM_POST_PMD:
+		/* mute HP */
+		regmap_set_bits(jz_codec->regmap, JZ4760_CODEC_REG_CR1,
+				REG_CR1_HP_MUTE);
+
+		err = regmap_read_poll_timeout(jz_codec->regmap,
+					       JZ4760_CODEC_REG_IFR,
+					       val, val & REG_IFR_RDO,
+					       1000, 1 * USEC_PER_SEC);
+		if (err) {
+			dev_err(jz_codec->dev, "RDO timeout: %d", err);
+			return err;
+		}
+
+		/* clear RDO flag */
+		regmap_set_bits(jz_codec->regmap, JZ4760_CODEC_REG_IFR,
+				REG_IFR_RDO);
+
+		break;
+	}
+
+	return 0;
+}
+
+static const char * const jz4760_codec_hp_texts[] = {
+	"PCM", "Line In", "Mic 1", "Mic 2"
+};
+
+static const unsigned int jz4760_codec_hp_values[] = { 3, 2, 0, 1 };
+
+static SOC_VALUE_ENUM_SINGLE_DECL(jz4760_codec_hp_enum,
+				  JZ4760_CODEC_REG_CR1,
+				  REG_CR1_OUTSEL_OFFSET,
+				  REG_CR1_OUTSEL_MASK >> REG_CR1_OUTSEL_OFFSET,
+				  jz4760_codec_hp_texts,
+				  jz4760_codec_hp_values);
+static const struct snd_kcontrol_new jz4760_codec_hp_source =
+			SOC_DAPM_ENUM("Route", jz4760_codec_hp_enum);
+
+static const char * const jz4760_codec_cap_texts[] = {
+	"Line In", "Mic 1", "Mic 2"
+};
+
+static const unsigned int jz4760_codec_cap_values[] = { 2, 0, 1 };
+
+static SOC_VALUE_ENUM_SINGLE_DECL(jz4760_codec_cap_enum,
+				  JZ4760_CODEC_REG_CR3,
+				  REG_CR3_ADC_INSEL_OFFSET,
+				  REG_CR3_ADC_INSEL_MASK >> REG_CR3_ADC_INSEL_OFFSET,
+				  jz4760_codec_cap_texts,
+				  jz4760_codec_cap_values);
+static const struct snd_kcontrol_new jz4760_codec_cap_source =
+			SOC_DAPM_ENUM("Route", jz4760_codec_cap_enum);
+
+static const struct snd_kcontrol_new jz4760_codec_mic_controls[] = {
+	SOC_DAPM_SINGLE("Stereo Capture Switch", JZ4760_CODEC_REG_CR3,
+			REG_CR3_MICSTEREO_OFFSET, 1, 0),
+};
+
+static const struct snd_kcontrol_new jz4760_codec_line_out_switch =
+	SOC_DAPM_SINGLE("Switch", JZ4760_CODEC_REG_CR1,
+			REG_CR1_LO_MUTE_OFFSET, 0, 0);
+static const struct snd_kcontrol_new jz4760_codec_btl_out_switch =
+	SOC_DAPM_SINGLE("Switch", JZ4760_CODEC_REG_CR1,
+			REG_CR1_BTL_MUTE_OFFSET, 0, 0);
+
+static const struct snd_soc_dapm_widget jz4760_codec_dapm_widgets[] = {
+	SND_SOC_DAPM_PGA_E("HP Out", JZ4760_CODEC_REG_PMR2,
+			   REG_PMR2_SB_HP_OFFSET, 1, NULL, 0, hpout_event,
+			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+			   SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_SWITCH("Line Out", JZ4760_CODEC_REG_PMR2,
+			    REG_PMR2_SB_LOUT_OFFSET, 1,
+			    &jz4760_codec_line_out_switch),
+
+	SND_SOC_DAPM_SWITCH("BTL Out", JZ4760_CODEC_REG_PMR2,
+			    REG_PMR2_SB_BTL_OFFSET, 1,
+			    &jz4760_codec_btl_out_switch),
+
+	SND_SOC_DAPM_PGA("Line In", JZ4760_CODEC_REG_PMR1,
+			 REG_PMR1_SB_LINE_OFFSET, 1, NULL, 0),
+
+	SND_SOC_DAPM_MUX("Headphones Source", SND_SOC_NOPM, 0, 0,
+			 &jz4760_codec_hp_source),
+
+	SND_SOC_DAPM_MUX("Capture Source", SND_SOC_NOPM, 0, 0,
+			 &jz4760_codec_cap_source),
+
+	SND_SOC_DAPM_PGA("Mic 1", JZ4760_CODEC_REG_PMR1,
+			 REG_PMR1_SB_MIC1_OFFSET, 1, NULL, 0),
+
+	SND_SOC_DAPM_PGA("Mic 2", JZ4760_CODEC_REG_PMR1,
+			 REG_PMR1_SB_MIC2_OFFSET, 1, NULL, 0),
+
+	SND_SOC_DAPM_PGA("Mic Diff", JZ4760_CODEC_REG_CR3,
+			 REG_CR3_MICDIFF_OFFSET, 0, NULL, 0),
+
+	SND_SOC_DAPM_MIXER("Mic", SND_SOC_NOPM, 0, 0,
+			   jz4760_codec_mic_controls,
+			   ARRAY_SIZE(jz4760_codec_mic_controls)),
+
+	SND_SOC_DAPM_PGA("Line In Bypass", JZ4760_CODEC_REG_PMR1,
+			 REG_PMR1_SB_BYPASS_OFFSET, 1, NULL, 0),
+
+	SND_SOC_DAPM_ADC("ADC", "Capture", JZ4760_CODEC_REG_PMR2,
+			 REG_PMR2_SB_ADC_OFFSET, 1),
+
+	SND_SOC_DAPM_DAC("DAC", "Playback", JZ4760_CODEC_REG_PMR2,
+			 REG_PMR2_SB_DAC_OFFSET, 1),
+
+	SND_SOC_DAPM_MIXER("PCM Playback", SND_SOC_NOPM, 0, 0,
+			   jz4760_codec_pcm_playback_controls,
+			   ARRAY_SIZE(jz4760_codec_pcm_playback_controls)),
+
+	SND_SOC_DAPM_MIXER("Headphones Playback", SND_SOC_NOPM, 0, 0,
+			   jz4760_codec_hp_playback_controls,
+			   ARRAY_SIZE(jz4760_codec_hp_playback_controls)),
+
+	SND_SOC_DAPM_SUPPLY("MICBIAS", JZ4760_CODEC_REG_PMR1,
+			    REG_PMR1_SB_MICBIAS_OFFSET, 1, NULL, 0),
+
+	SND_SOC_DAPM_INPUT("MIC1P"),
+	SND_SOC_DAPM_INPUT("MIC1N"),
+	SND_SOC_DAPM_INPUT("MIC2P"),
+	SND_SOC_DAPM_INPUT("MIC2N"),
+
+	SND_SOC_DAPM_INPUT("LLINEIN"),
+	SND_SOC_DAPM_INPUT("RLINEIN"),
+
+	SND_SOC_DAPM_OUTPUT("LHPOUT"),
+	SND_SOC_DAPM_OUTPUT("RHPOUT"),
+
+	SND_SOC_DAPM_OUTPUT("LOUT"),
+	SND_SOC_DAPM_OUTPUT("ROUT"),
+
+	SND_SOC_DAPM_OUTPUT("BTLP"),
+	SND_SOC_DAPM_OUTPUT("BTLN"),
+
+	SND_SOC_DAPM_OUTPUT("SYSCLK"),
+};
+
+/* Unconditional routes. */
+static const struct snd_soc_dapm_route jz4760_codec_dapm_routes[] = {
+	{ "Mic 1", NULL, "MIC1P" },
+	{ "Mic Diff", NULL, "MIC1N" },
+	{ "Mic 1", NULL, "Mic Diff" },
+	{ "Mic 2", NULL, "MIC2P" },
+	{ "Mic Diff", NULL, "MIC2N" },
+	{ "Mic 2", NULL, "Mic Diff" },
+
+	{ "Line In", NULL, "LLINEIN" },
+	{ "Line In", NULL, "RLINEIN" },
+
+	{ "Mic", "Stereo Capture Switch", "Mic 1" },
+	{ "Mic", "Stereo Capture Switch", "Mic 2" },
+	{ "Headphones Source", "Mic 1", "Mic" },
+	{ "Headphones Source", "Mic 2", "Mic" },
+	{ "Capture Source", "Mic 1", "Mic" },
+	{ "Capture Source", "Mic 2", "Mic" },
+
+	{ "Capture Source", "Line In", "Line In" },
+	{ "Capture Source", "Mic 1", "Mic 1" },
+	{ "Capture Source", "Mic 2", "Mic 2" },
+	{ "ADC", NULL, "Capture Source" },
+
+	{ "Line In Bypass", NULL, "Line In" },
+
+	{ "Headphones Source", "Mic 1", "Mic 1" },
+	{ "Headphones Source", "Mic 2", "Mic 2" },
+	{ "Headphones Source", "Line In", "Line In Bypass" },
+	{ "Headphones Source", "PCM", "Headphones Playback" },
+	{ "HP Out", NULL, "Headphones Source" },
+
+	{ "LHPOUT", NULL, "HP Out" },
+	{ "RHPOUT", NULL, "HP Out" },
+	{ "Line Out", "Switch", "HP Out" },
+
+	{ "LOUT", NULL, "Line Out" },
+	{ "ROUT", NULL, "Line Out" },
+	{ "BTL Out", "Switch", "Line Out" },
+
+	{ "BTLP", NULL, "BTL Out"},
+	{ "BTLN", NULL, "BTL Out"},
+
+	{ "PCM Playback", "Volume", "DAC" },
+	{ "Headphones Playback", "Volume", "PCM Playback" },
+
+	{ "SYSCLK", NULL, "DAC" },
+};
+
+static void jz4760_codec_codec_init_regs(struct snd_soc_component *codec)
+{
+	struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
+	struct regmap *regmap = jz_codec->regmap;
+
+	/* Collect updates for later sending. */
+	regcache_cache_only(regmap, true);
+
+	/* default Amp output to PCM */
+	regmap_set_bits(regmap, JZ4760_CODEC_REG_CR1, REG_CR1_OUTSEL_MASK);
+
+	/* Disable stereo mic */
+	regmap_clear_bits(regmap, JZ4760_CODEC_REG_CR3,
+			  BIT(REG_CR3_MICSTEREO_OFFSET));
+
+	/* Set mic 1 as default source for ADC */
+	regmap_clear_bits(regmap, JZ4760_CODEC_REG_CR3,
+			  REG_CR3_ADC_INSEL_MASK);
+
+	/* ADC/DAC: serial + i2s */
+	regmap_set_bits(regmap, JZ4760_CODEC_REG_AICR,
+			REG_AICR_ADC_SERIAL | REG_AICR_ADC_I2S |
+			REG_AICR_DAC_SERIAL | REG_AICR_DAC_I2S);
+
+	/* The generated IRQ is a high level */
+	regmap_clear_bits(regmap, JZ4760_CODEC_REG_ICR, REG_ICR_INT_FORM_MASK);
+	regmap_update_bits(regmap, JZ4760_CODEC_REG_ICR, REG_ICR_ALL_MASK,
+			   REG_ICR_JACK_MASK | REG_ICR_RUP_MASK |
+			   REG_ICR_RDO_MASK  | REG_ICR_GUP_MASK |
+			   REG_ICR_GDO_MASK);
+
+	/* 12M oscillator */
+	regmap_clear_bits(regmap, JZ4760_CODEC_REG_CCR1, REG_CCR1_CRYSTAL_MASK);
+
+	/* 0: 16ohm/220uF, 1: 10kohm/1uF */
+	regmap_clear_bits(regmap, JZ4760_CODEC_REG_CR1, REG_CR1_HP_LOAD);
+
+	/* default to NOMAD */
+	regmap_set_bits(jz_codec->regmap, JZ4760_CODEC_REG_CR2,
+			REG_CR2_DAC_NOMAD);
+
+	/* disable automatic gain */
+	regmap_clear_bits(regmap, JZ4760_CODEC_REG_AGC1, REG_AGC1_EN);
+
+	/* Independent L/R DAC gain control */
+	regmap_clear_bits(regmap, JZ4760_CODEC_REG_GCR5,
+			  REG_GCR_RL);
+
+	/* Send collected updates. */
+	regcache_cache_only(regmap, false);
+	regcache_sync(regmap);
+}
+
+static int jz4760_codec_codec_probe(struct snd_soc_component *codec)
+{
+	struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
+
+	clk_prepare_enable(jz_codec->clk);
+
+	jz4760_codec_codec_init_regs(codec);
+
+	return 0;
+}
+
+static void jz4760_codec_codec_remove(struct snd_soc_component *codec)
+{
+	struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
+
+	clk_disable_unprepare(jz_codec->clk);
+}
+
+static const struct snd_soc_component_driver jz4760_codec_soc_codec_dev = {
+	.probe			= jz4760_codec_codec_probe,
+	.remove			= jz4760_codec_codec_remove,
+	.set_bias_level		= jz4760_codec_set_bias_level,
+	.controls		= jz4760_codec_snd_controls,
+	.num_controls		= ARRAY_SIZE(jz4760_codec_snd_controls),
+	.dapm_widgets		= jz4760_codec_dapm_widgets,
+	.num_dapm_widgets	= ARRAY_SIZE(jz4760_codec_dapm_widgets),
+	.dapm_routes		= jz4760_codec_dapm_routes,
+	.num_dapm_routes	= ARRAY_SIZE(jz4760_codec_dapm_routes),
+	.suspend_bias_off	= 1,
+	.use_pmdown_time	= 1,
+};
+
+static const unsigned int jz4760_codec_sample_rates[] = {
+	96000, 48000, 44100, 32000,
+	24000, 22050, 16000, 12000,
+	11025, 9600, 8000,
+};
+
+static int jz4760_codec_hw_params(struct snd_pcm_substream *substream,
+				  struct snd_pcm_hw_params *params,
+				  struct snd_soc_dai *dai)
+{
+	struct jz_codec *codec = snd_soc_component_get_drvdata(dai->component);
+	unsigned int rate, bit_width;
+
+	switch (params_format(params)) {
+	case SNDRV_PCM_FORMAT_S16_LE:
+		bit_width = 0;
+		break;
+	case SNDRV_PCM_FORMAT_S18_3LE:
+		bit_width = 1;
+		break;
+	case SNDRV_PCM_FORMAT_S20_3LE:
+		bit_width = 2;
+		break;
+	case SNDRV_PCM_FORMAT_S24_3LE:
+		bit_width = 3;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	for (rate = 0; rate < ARRAY_SIZE(jz4760_codec_sample_rates); rate++) {
+		if (jz4760_codec_sample_rates[rate] == params_rate(params))
+			break;
+	}
+
+	if (rate == ARRAY_SIZE(jz4760_codec_sample_rates))
+		return -EINVAL;
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		regmap_update_bits(codec->regmap, JZ4760_CODEC_REG_AICR,
+				   REG_AICR_DAC_ADWL_MASK,
+				   FIELD_PREP(REG_AICR_DAC_ADWL_MASK, bit_width));
+		regmap_update_bits(codec->regmap, JZ4760_CODEC_REG_CCR2,
+				   REG_CCR2_DAC_FREQ_MASK,
+				   FIELD_PREP(REG_CCR2_DAC_FREQ_MASK, rate));
+	} else {
+		regmap_update_bits(codec->regmap, JZ4760_CODEC_REG_AICR,
+				   REG_AICR_ADC_ADWL_MASK,
+				   FIELD_PREP(REG_AICR_ADC_ADWL_MASK, bit_width));
+		regmap_update_bits(codec->regmap, JZ4760_CODEC_REG_CCR2,
+				   REG_CCR2_ADC_FREQ_MASK,
+				   FIELD_PREP(REG_CCR2_ADC_FREQ_MASK, rate));
+	}
+
+	return 0;
+}
+
+static const struct snd_soc_dai_ops jz4760_codec_dai_ops = {
+	.startup	= jz4760_codec_startup,
+	.shutdown	= jz4760_codec_shutdown,
+	.hw_params	= jz4760_codec_hw_params,
+	.trigger	= jz4760_codec_pcm_trigger,
+	.mute_stream	= jz4760_codec_mute_stream,
+	.no_capture_mute = 1,
+};
+
+#define JZ_CODEC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE  | \
+			  SNDRV_PCM_FMTBIT_S18_3LE | \
+			  SNDRV_PCM_FMTBIT_S20_3LE | \
+			  SNDRV_PCM_FMTBIT_S24_3LE)
+
+static struct snd_soc_dai_driver jz4760_codec_dai = {
+	.name = "jz4760-hifi",
+	.playback = {
+		.stream_name = "Playback",
+		.channels_min = 2,
+		.channels_max = 2,
+		.rates = SNDRV_PCM_RATE_8000_96000,
+		.formats = JZ_CODEC_FORMATS,
+	},
+	.capture = {
+		.stream_name = "Capture",
+		.channels_min = 2,
+		.channels_max = 2,
+		.rates = SNDRV_PCM_RATE_8000_96000,
+		.formats = JZ_CODEC_FORMATS,
+	},
+	.ops = &jz4760_codec_dai_ops,
+};
+
+static bool jz4760_codec_volatile(struct device *dev, unsigned int reg)
+{
+	return reg == JZ4760_CODEC_REG_SR || reg == JZ4760_CODEC_REG_IFR;
+}
+
+static bool jz4760_codec_writeable(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case JZ4760_CODEC_REG_SR:
+		return false;
+	default:
+		return true;
+	}
+}
+
+static int jz4760_codec_io_wait(struct jz_codec *codec)
+{
+	u32 reg;
+
+	return readl_poll_timeout(codec->base + ICDC_RGADW_OFFSET, reg,
+				  !(reg & ICDC_RGADW_RGWR),
+				  1000, 1 * USEC_PER_SEC);
+}
+
+static int jz4760_codec_reg_read(void *context, unsigned int reg,
+				 unsigned int *val)
+{
+	struct jz_codec *codec = context;
+	unsigned int i;
+	u32 tmp;
+	int ret;
+
+	ret = jz4760_codec_io_wait(codec);
+	if (ret)
+		return ret;
+
+	tmp = readl(codec->base + ICDC_RGADW_OFFSET);
+	tmp &= ~ICDC_RGADW_RGADDR_MASK;
+	tmp |= FIELD_PREP(ICDC_RGADW_RGADDR_MASK, reg);
+	writel(tmp, codec->base + ICDC_RGADW_OFFSET);
+
+	/* wait 6+ cycles */
+	for (i = 0; i < 6; i++)
+		*val = readl(codec->base + ICDC_RGDATA_OFFSET) &
+			ICDC_RGDATA_RGDOUT_MASK;
+
+	return 0;
+}
+
+static int jz4760_codec_reg_write(void *context, unsigned int reg,
+				  unsigned int val)
+{
+	struct jz_codec *codec = context;
+	int ret;
+
+	ret = jz4760_codec_io_wait(codec);
+	if (ret)
+		return ret;
+
+	writel(ICDC_RGADW_RGWR | FIELD_PREP(ICDC_RGADW_RGADDR_MASK, reg) | val,
+	       codec->base + ICDC_RGADW_OFFSET);
+
+	ret = jz4760_codec_io_wait(codec);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static const u8 jz4760_codec_reg_defaults[] = {
+	0x00, 0xFC, 0x1B, 0x20, 0x00, 0x80, 0x00, 0x00,
+	0xFF, 0x1F, 0x3F, 0x00, 0x06, 0x06, 0x06, 0x06,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x07, 0x44,
+	0x1F, 0x00, 0x00, 0x00
+};
+
+static struct regmap_config jz4760_codec_regmap_config = {
+	.reg_bits = 7,
+	.val_bits = 8,
+
+	.max_register = JZ4760_CODEC_REG_MIX2,
+	.volatile_reg = jz4760_codec_volatile,
+	.writeable_reg = jz4760_codec_writeable,
+
+	.reg_read = jz4760_codec_reg_read,
+	.reg_write = jz4760_codec_reg_write,
+
+	.reg_defaults_raw = jz4760_codec_reg_defaults,
+	.num_reg_defaults_raw = ARRAY_SIZE(jz4760_codec_reg_defaults),
+	.cache_type = REGCACHE_FLAT,
+};
+
+static int jz4760_codec_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct jz_codec *codec;
+	int ret;
+
+	codec = devm_kzalloc(dev, sizeof(*codec), GFP_KERNEL);
+	if (!codec)
+		return -ENOMEM;
+
+	codec->dev = dev;
+
+	codec->base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(codec->base)) {
+		ret = PTR_ERR(codec->base);
+		dev_err(dev, "Failed to ioremap mmio memory: %d\n", ret);
+		return ret;
+	}
+
+	codec->regmap = devm_regmap_init(dev, NULL, codec,
+					&jz4760_codec_regmap_config);
+	if (IS_ERR(codec->regmap))
+		return PTR_ERR(codec->regmap);
+
+	codec->clk = devm_clk_get(dev, "aic");
+	if (IS_ERR(codec->clk))
+		return PTR_ERR(codec->clk);
+
+	platform_set_drvdata(pdev, codec);
+
+	ret = devm_snd_soc_register_component(dev, &jz4760_codec_soc_codec_dev,
+					      &jz4760_codec_dai, 1);
+	if (ret) {
+		dev_err(dev, "Failed to register codec: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static const struct of_device_id jz4760_codec_of_matches[] = {
+	{ .compatible = "ingenic,jz4760-codec", },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, jz4760_codec_of_matches);
+
+static struct platform_driver jz4760_codec_driver = {
+	.probe			= jz4760_codec_probe,
+	.driver			= {
+		.name		= "jz4760-codec",
+		.of_match_table = jz4760_codec_of_matches,
+	},
+};
+module_platform_driver(jz4760_codec_driver);
+
+MODULE_DESCRIPTION("JZ4760 SoC internal codec driver");
+MODULE_AUTHOR("Christophe Branchereau <cbranchereau@gmail.com>");
+MODULE_AUTHOR("Paul Cercueil <paul@crapouillou.net>");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/lm49453.c b/sound/soc/codecs/lm49453.c
index 06ab61f6f719..eb3dd0bd80d9 100644
--- a/sound/soc/codecs/lm49453.c
+++ b/sound/soc/codecs/lm49453.c
@@ -1343,7 +1343,7 @@ static struct snd_soc_dai_driver lm49453_dai[] = {
 			.formats = LM49453_FORMATS,
 		},
 		.ops = &lm49453_headset_dai_ops,
-		.symmetric_rates = 1,
+		.symmetric_rate = 1,
 	},
 	{
 		.name = "LM49453 Speaker",
diff --git a/sound/soc/codecs/lochnagar-sc.c b/sound/soc/codecs/lochnagar-sc.c
index 3209b39e46af..54426a90bc0b 100644
--- a/sound/soc/codecs/lochnagar-sc.c
+++ b/sound/soc/codecs/lochnagar-sc.c
@@ -166,8 +166,8 @@ static struct snd_soc_dai_driver lochnagar_sc_dai[] = {
 			.formats = SNDRV_PCM_FMTBIT_S32_LE,
 		},
 		.ops = &lochnagar_sc_line_ops,
-		.symmetric_rates = true,
-		.symmetric_samplebits = true,
+		.symmetric_rate = true,
+		.symmetric_sample_bits = true,
 	},
 	{
 		.name = "lochnagar-usb1",
@@ -186,8 +186,8 @@ static struct snd_soc_dai_driver lochnagar_sc_dai[] = {
 			.formats = SNDRV_PCM_FMTBIT_S32_LE,
 		},
 		.ops = &lochnagar_sc_usb_ops,
-		.symmetric_rates = true,
-		.symmetric_samplebits = true,
+		.symmetric_rate = true,
+		.symmetric_sample_bits = true,
 	},
 	{
 		.name = "lochnagar-usb2",
@@ -206,8 +206,8 @@ static struct snd_soc_dai_driver lochnagar_sc_dai[] = {
 			.formats = SNDRV_PCM_FMTBIT_S32_LE,
 		},
 		.ops = &lochnagar_sc_usb_ops,
-		.symmetric_rates = true,
-		.symmetric_samplebits = true,
+		.symmetric_rate = true,
+		.symmetric_sample_bits = true,
 	},
 };
 
diff --git a/sound/soc/codecs/lpass-rx-macro.c b/sound/soc/codecs/lpass-rx-macro.c
new file mode 100644
index 000000000000..c9c21d22c2c4
--- /dev/null
+++ b/sound/soc/codecs/lpass-rx-macro.c
@@ -0,0 +1,3599 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <sound/soc.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc-dapm.h>
+#include <sound/tlv.h>
+#include <linux/of_clk.h>
+#include <linux/clk-provider.h>
+
+#define CDC_RX_TOP_TOP_CFG0		(0x0000)
+#define CDC_RX_TOP_SWR_CTRL		(0x0008)
+#define CDC_RX_TOP_DEBUG		(0x000C)
+#define CDC_RX_TOP_DEBUG_BUS		(0x0010)
+#define CDC_RX_TOP_DEBUG_EN0		(0x0014)
+#define CDC_RX_TOP_DEBUG_EN1		(0x0018)
+#define CDC_RX_TOP_DEBUG_EN2		(0x001C)
+#define CDC_RX_TOP_HPHL_COMP_WR_LSB	(0x0020)
+#define CDC_RX_TOP_HPHL_COMP_WR_MSB	(0x0024)
+#define CDC_RX_TOP_HPHL_COMP_LUT	(0x0028)
+#define CDC_RX_TOP_HPH_LUT_BYPASS_MASK	BIT(7)
+#define CDC_RX_TOP_HPHL_COMP_RD_LSB	(0x002C)
+#define CDC_RX_TOP_HPHL_COMP_RD_MSB	(0x0030)
+#define CDC_RX_TOP_HPHR_COMP_WR_LSB	(0x0034)
+#define CDC_RX_TOP_HPHR_COMP_WR_MSB	(0x0038)
+#define CDC_RX_TOP_HPHR_COMP_LUT	(0x003C)
+#define CDC_RX_TOP_HPHR_COMP_RD_LSB	(0x0040)
+#define CDC_RX_TOP_HPHR_COMP_RD_MSB	(0x0044)
+#define CDC_RX_TOP_DSD0_DEBUG_CFG0	(0x0070)
+#define CDC_RX_TOP_DSD0_DEBUG_CFG1	(0x0074)
+#define CDC_RX_TOP_DSD0_DEBUG_CFG2	(0x0078)
+#define CDC_RX_TOP_DSD0_DEBUG_CFG3	(0x007C)
+#define CDC_RX_TOP_DSD1_DEBUG_CFG0	(0x0080)
+#define CDC_RX_TOP_DSD1_DEBUG_CFG1	(0x0084)
+#define CDC_RX_TOP_DSD1_DEBUG_CFG2	(0x0088)
+#define CDC_RX_TOP_DSD1_DEBUG_CFG3	(0x008C)
+#define CDC_RX_TOP_RX_I2S_CTL		(0x0090)
+#define CDC_RX_TOP_TX_I2S2_CTL		(0x0094)
+#define CDC_RX_TOP_I2S_CLK		(0x0098)
+#define CDC_RX_TOP_I2S_RESET		(0x009C)
+#define CDC_RX_TOP_I2S_MUX		(0x00A0)
+#define CDC_RX_CLK_RST_CTRL_MCLK_CONTROL	(0x0100)
+#define CDC_RX_CLK_MCLK_EN_MASK		BIT(0)
+#define CDC_RX_CLK_MCLK_ENABLE		BIT(0)
+#define CDC_RX_CLK_MCLK2_EN_MASK	BIT(1)
+#define CDC_RX_CLK_MCLK2_ENABLE		BIT(1)
+#define CDC_RX_CLK_RST_CTRL_FS_CNT_CONTROL	(0x0104)
+#define CDC_RX_FS_MCLK_CNT_EN_MASK	BIT(0)
+#define CDC_RX_FS_MCLK_CNT_ENABLE	BIT(0)
+#define CDC_RX_FS_MCLK_CNT_CLR_MASK	BIT(1)
+#define CDC_RX_FS_MCLK_CNT_CLR		BIT(1)
+#define CDC_RX_CLK_RST_CTRL_SWR_CONTROL	(0x0108)
+#define CDC_RX_SWR_CLK_EN_MASK		BIT(0)
+#define CDC_RX_SWR_RESET_MASK		BIT(1)
+#define CDC_RX_SWR_RESET		BIT(1)
+#define CDC_RX_CLK_RST_CTRL_DSD_CONTROL	(0x010C)
+#define CDC_RX_CLK_RST_CTRL_ASRC_SHARE_CONTROL	(0x0110)
+#define CDC_RX_SOFTCLIP_CRC		(0x0140)
+#define CDC_RX_SOFTCLIP_CLK_EN_MASK	BIT(0)
+#define CDC_RX_SOFTCLIP_SOFTCLIP_CTRL	(0x0144)
+#define CDC_RX_SOFTCLIP_EN_MASK		BIT(0)
+#define CDC_RX_INP_MUX_RX_INT0_CFG0	(0x0180)
+#define CDC_RX_INTX_1_MIX_INP0_SEL_MASK	GENMASK(3, 0)
+#define CDC_RX_INTX_1_MIX_INP1_SEL_MASK	GENMASK(7, 4)
+#define CDC_RX_INP_MUX_RX_INT0_CFG1	(0x0184)
+#define CDC_RX_INTX_2_SEL_MASK		GENMASK(3, 0)
+#define CDC_RX_INTX_1_MIX_INP2_SEL_MASK	GENMASK(7, 4)
+#define CDC_RX_INP_MUX_RX_INT1_CFG0	(0x0188)
+#define CDC_RX_INP_MUX_RX_INT1_CFG1	(0x018C)
+#define CDC_RX_INP_MUX_RX_INT2_CFG0	(0x0190)
+#define CDC_RX_INP_MUX_RX_INT2_CFG1	(0x0194)
+#define CDC_RX_INP_MUX_RX_MIX_CFG4	(0x0198)
+#define CDC_RX_INP_MUX_RX_MIX_CFG5	(0x019C)
+#define CDC_RX_INP_MUX_SIDETONE_SRC_CFG0	(0x01A0)
+#define CDC_RX_CLSH_CRC			(0x0200)
+#define CDC_RX_CLSH_CLK_EN_MASK		BIT(0)
+#define CDC_RX_CLSH_DLY_CTRL		(0x0204)
+#define CDC_RX_CLSH_DECAY_CTRL		(0x0208)
+#define CDC_RX_CLSH_DECAY_RATE_MASK	GENMASK(2, 0)
+#define CDC_RX_CLSH_HPH_V_PA		(0x020C)
+#define CDC_RX_CLSH_HPH_V_PA_MIN_MASK	GENMASK(5, 0)
+#define CDC_RX_CLSH_EAR_V_PA		(0x0210)
+#define CDC_RX_CLSH_HPH_V_HD		(0x0214)
+#define CDC_RX_CLSH_EAR_V_HD		(0x0218)
+#define CDC_RX_CLSH_K1_MSB		(0x021C)
+#define CDC_RX_CLSH_K1_MSB_COEFF_MASK	GENMASK(3, 0)
+#define CDC_RX_CLSH_K1_LSB		(0x0220)
+#define CDC_RX_CLSH_K2_MSB		(0x0224)
+#define CDC_RX_CLSH_K2_LSB		(0x0228)
+#define CDC_RX_CLSH_IDLE_CTRL		(0x022C)
+#define CDC_RX_CLSH_IDLE_HPH		(0x0230)
+#define CDC_RX_CLSH_IDLE_EAR		(0x0234)
+#define CDC_RX_CLSH_TEST0		(0x0238)
+#define CDC_RX_CLSH_TEST1		(0x023C)
+#define CDC_RX_CLSH_OVR_VREF		(0x0240)
+#define CDC_RX_CLSH_CLSG_CTL		(0x0244)
+#define CDC_RX_CLSH_CLSG_CFG1		(0x0248)
+#define CDC_RX_CLSH_CLSG_CFG2		(0x024C)
+#define CDC_RX_BCL_VBAT_PATH_CTL	(0x0280)
+#define CDC_RX_BCL_VBAT_CFG		(0x0284)
+#define CDC_RX_BCL_VBAT_ADC_CAL1	(0x0288)
+#define CDC_RX_BCL_VBAT_ADC_CAL2	(0x028C)
+#define CDC_RX_BCL_VBAT_ADC_CAL3	(0x0290)
+#define CDC_RX_BCL_VBAT_PK_EST1		(0x0294)
+#define CDC_RX_BCL_VBAT_PK_EST2		(0x0298)
+#define CDC_RX_BCL_VBAT_PK_EST3		(0x029C)
+#define CDC_RX_BCL_VBAT_RF_PROC1	(0x02A0)
+#define CDC_RX_BCL_VBAT_RF_PROC2	(0x02A4)
+#define CDC_RX_BCL_VBAT_TAC1		(0x02A8)
+#define CDC_RX_BCL_VBAT_TAC2		(0x02AC)
+#define CDC_RX_BCL_VBAT_TAC3		(0x02B0)
+#define CDC_RX_BCL_VBAT_TAC4		(0x02B4)
+#define CDC_RX_BCL_VBAT_GAIN_UPD1	(0x02B8)
+#define CDC_RX_BCL_VBAT_GAIN_UPD2	(0x02BC)
+#define CDC_RX_BCL_VBAT_GAIN_UPD3	(0x02C0)
+#define CDC_RX_BCL_VBAT_GAIN_UPD4	(0x02C4)
+#define CDC_RX_BCL_VBAT_GAIN_UPD5	(0x02C8)
+#define CDC_RX_BCL_VBAT_DEBUG1		(0x02CC)
+#define CDC_RX_BCL_VBAT_GAIN_UPD_MON	(0x02D0)
+#define CDC_RX_BCL_VBAT_GAIN_MON_VAL	(0x02D4)
+#define CDC_RX_BCL_VBAT_BAN		(0x02D8)
+#define CDC_RX_BCL_VBAT_BCL_GAIN_UPD1	(0x02DC)
+#define CDC_RX_BCL_VBAT_BCL_GAIN_UPD2	(0x02E0)
+#define CDC_RX_BCL_VBAT_BCL_GAIN_UPD3	(0x02E4)
+#define CDC_RX_BCL_VBAT_BCL_GAIN_UPD4	(0x02E8)
+#define CDC_RX_BCL_VBAT_BCL_GAIN_UPD5	(0x02EC)
+#define CDC_RX_BCL_VBAT_BCL_GAIN_UPD6	(0x02F0)
+#define CDC_RX_BCL_VBAT_BCL_GAIN_UPD7	(0x02F4)
+#define CDC_RX_BCL_VBAT_BCL_GAIN_UPD8	(0x02F8)
+#define CDC_RX_BCL_VBAT_BCL_GAIN_UPD9	(0x02FC)
+#define CDC_RX_BCL_VBAT_ATTN1		(0x0300)
+#define CDC_RX_BCL_VBAT_ATTN2		(0x0304)
+#define CDC_RX_BCL_VBAT_ATTN3		(0x0308)
+#define CDC_RX_BCL_VBAT_DECODE_CTL1	(0x030C)
+#define CDC_RX_BCL_VBAT_DECODE_CTL2	(0x0310)
+#define CDC_RX_BCL_VBAT_DECODE_CFG1	(0x0314)
+#define CDC_RX_BCL_VBAT_DECODE_CFG2	(0x0318)
+#define CDC_RX_BCL_VBAT_DECODE_CFG3	(0x031C)
+#define CDC_RX_BCL_VBAT_DECODE_CFG4	(0x0320)
+#define CDC_RX_BCL_VBAT_DECODE_ST	(0x0324)
+#define CDC_RX_INTR_CTRL_CFG		(0x0340)
+#define CDC_RX_INTR_CTRL_CLR_COMMIT	(0x0344)
+#define CDC_RX_INTR_CTRL_PIN1_MASK0	(0x0360)
+#define CDC_RX_INTR_CTRL_PIN1_STATUS0	(0x0368)
+#define CDC_RX_INTR_CTRL_PIN1_CLEAR0	(0x0370)
+#define CDC_RX_INTR_CTRL_PIN2_MASK0	(0x0380)
+#define CDC_RX_INTR_CTRL_PIN2_STATUS0	(0x0388)
+#define CDC_RX_INTR_CTRL_PIN2_CLEAR0	(0x0390)
+#define CDC_RX_INTR_CTRL_LEVEL0		(0x03C0)
+#define CDC_RX_INTR_CTRL_BYPASS0	(0x03C8)
+#define CDC_RX_INTR_CTRL_SET0		(0x03D0)
+#define CDC_RX_RXn_RX_PATH_CTL(n)	(0x0400 + 0x80 * n)
+#define CDC_RX_RX0_RX_PATH_CTL		(0x0400)
+#define CDC_RX_PATH_RESET_EN_MASK	BIT(6)
+#define CDC_RX_PATH_CLK_EN_MASK		BIT(5)
+#define CDC_RX_PATH_CLK_ENABLE		BIT(5)
+#define CDC_RX_PATH_PGA_MUTE_MASK	BIT(4)
+#define CDC_RX_PATH_PGA_MUTE_ENABLE	BIT(4)
+#define CDC_RX_PATH_PCM_RATE_MASK	GENMASK(3, 0)
+#define CDC_RX_RXn_RX_PATH_CFG0(n)	(0x0404 + 0x80 * n)
+#define CDC_RX_RXn_COMP_EN_MASK		BIT(1)
+#define CDC_RX_RX0_RX_PATH_CFG0		(0x0404)
+#define CDC_RX_RXn_CLSH_EN_MASK		BIT(6)
+#define CDC_RX_DLY_ZN_EN_MASK		BIT(3)
+#define CDC_RX_DLY_ZN_ENABLE		BIT(3)
+#define CDC_RX_RXn_HD2_EN_MASK		BIT(2)
+#define CDC_RX_RXn_RX_PATH_CFG1(n)	(0x0408 + 0x80 * n)
+#define CDC_RX_RXn_SIDETONE_EN_MASK	BIT(4)
+#define CDC_RX_RX0_RX_PATH_CFG1		(0x0408)
+#define CDC_RX_RX0_HPH_L_EAR_SEL_MASK	BIT(1)
+#define CDC_RX_RXn_RX_PATH_CFG2(n)	(0x040C + 0x80 * n)
+#define CDC_RX_RXn_HPF_CUT_FREQ_MASK	GENMASK(1, 0)
+#define CDC_RX_RX0_RX_PATH_CFG2		(0x040C)
+#define CDC_RX_RXn_RX_PATH_CFG3(n)	(0x0410 + 0x80 * n)
+#define CDC_RX_RX0_RX_PATH_CFG3		(0x0410)
+#define CDC_RX_DC_COEFF_SEL_MASK	GENMASK(1, 0)
+#define CDC_RX_DC_COEFF_SEL_TWO		0x2
+#define CDC_RX_RXn_RX_VOL_CTL(n)	(0x0414 + 0x80 * n)
+#define CDC_RX_RX0_RX_VOL_CTL		(0x0414)
+#define CDC_RX_RXn_RX_PATH_MIX_CTL(n)	(0x0418 + 0x80 * n)
+#define CDC_RX_RXn_MIX_PCM_RATE_MASK	GENMASK(3, 0)
+#define CDC_RX_RXn_MIX_RESET_MASK	BIT(6)
+#define CDC_RX_RXn_MIX_RESET		BIT(6)
+#define CDC_RX_RXn_MIX_CLK_EN_MASK	BIT(5)
+#define CDC_RX_RX0_RX_PATH_MIX_CTL	(0x0418)
+#define CDC_RX_RX0_RX_PATH_MIX_CFG	(0x041C)
+#define CDC_RX_RXn_RX_VOL_MIX_CTL(n)	(0x0420 + 0x80 * n)
+#define CDC_RX_RX0_RX_VOL_MIX_CTL	(0x0420)
+#define CDC_RX_RX0_RX_PATH_SEC1		(0x0424)
+#define CDC_RX_RX0_RX_PATH_SEC2		(0x0428)
+#define CDC_RX_RX0_RX_PATH_SEC3		(0x042C)
+#define CDC_RX_RX0_RX_PATH_SEC4		(0x0430)
+#define CDC_RX_RX0_RX_PATH_SEC7		(0x0434)
+#define CDC_RX_DSM_OUT_DELAY_SEL_MASK	GENMASK(2, 0)
+#define CDC_RX_DSM_OUT_DELAY_TWO_SAMPLE	0x2
+#define CDC_RX_RX0_RX_PATH_MIX_SEC0	(0x0438)
+#define CDC_RX_RX0_RX_PATH_MIX_SEC1	(0x043C)
+#define CDC_RX_RXn_RX_PATH_DSM_CTL(n)	(0x0440 + 0x80 * n)
+#define CDC_RX_RXn_DSM_CLK_EN_MASK	BIT(0)
+#define CDC_RX_RX0_RX_PATH_DSM_CTL	(0x0440)
+#define CDC_RX_RX0_RX_PATH_DSM_DATA1	(0x0444)
+#define CDC_RX_RX0_RX_PATH_DSM_DATA2	(0x0448)
+#define CDC_RX_RX0_RX_PATH_DSM_DATA3	(0x044C)
+#define CDC_RX_RX0_RX_PATH_DSM_DATA4	(0x0450)
+#define CDC_RX_RX0_RX_PATH_DSM_DATA5	(0x0454)
+#define CDC_RX_RX0_RX_PATH_DSM_DATA6	(0x0458)
+#define CDC_RX_RX1_RX_PATH_CTL		(0x0480)
+#define CDC_RX_RX1_RX_PATH_CFG0		(0x0484)
+#define CDC_RX_RX1_RX_PATH_CFG1		(0x0488)
+#define CDC_RX_RX1_RX_PATH_CFG2		(0x048C)
+#define CDC_RX_RX1_RX_PATH_CFG3		(0x0490)
+#define CDC_RX_RX1_RX_VOL_CTL		(0x0494)
+#define CDC_RX_RX1_RX_PATH_MIX_CTL	(0x0498)
+#define CDC_RX_RX1_RX_PATH_MIX_CFG	(0x049C)
+#define CDC_RX_RX1_RX_VOL_MIX_CTL	(0x04A0)
+#define CDC_RX_RX1_RX_PATH_SEC1		(0x04A4)
+#define CDC_RX_RX1_RX_PATH_SEC2		(0x04A8)
+#define CDC_RX_RX1_RX_PATH_SEC3		(0x04AC)
+#define CDC_RX_RXn_HD2_ALPHA_MASK	GENMASK(5, 2)
+#define CDC_RX_RX1_RX_PATH_SEC4		(0x04B0)
+#define CDC_RX_RX1_RX_PATH_SEC7		(0x04B4)
+#define CDC_RX_RX1_RX_PATH_MIX_SEC0	(0x04B8)
+#define CDC_RX_RX1_RX_PATH_MIX_SEC1	(0x04BC)
+#define CDC_RX_RX1_RX_PATH_DSM_CTL	(0x04C0)
+#define CDC_RX_RX1_RX_PATH_DSM_DATA1	(0x04C4)
+#define CDC_RX_RX1_RX_PATH_DSM_DATA2	(0x04C8)
+#define CDC_RX_RX1_RX_PATH_DSM_DATA3	(0x04CC)
+#define CDC_RX_RX1_RX_PATH_DSM_DATA4	(0x04D0)
+#define CDC_RX_RX1_RX_PATH_DSM_DATA5	(0x04D4)
+#define CDC_RX_RX1_RX_PATH_DSM_DATA6	(0x04D8)
+#define CDC_RX_RX2_RX_PATH_CTL		(0x0500)
+#define CDC_RX_RX2_RX_PATH_CFG0		(0x0504)
+#define CDC_RX_RX2_CLSH_EN_MASK		BIT(4)
+#define CDC_RX_RX2_DLY_Z_EN_MASK	BIT(3)
+#define CDC_RX_RX2_RX_PATH_CFG1		(0x0508)
+#define CDC_RX_RX2_RX_PATH_CFG2		(0x050C)
+#define CDC_RX_RX2_RX_PATH_CFG3		(0x0510)
+#define CDC_RX_RX2_RX_VOL_CTL		(0x0514)
+#define CDC_RX_RX2_RX_PATH_MIX_CTL	(0x0518)
+#define CDC_RX_RX2_RX_PATH_MIX_CFG	(0x051C)
+#define CDC_RX_RX2_RX_VOL_MIX_CTL	(0x0520)
+#define CDC_RX_RX2_RX_PATH_SEC0		(0x0524)
+#define CDC_RX_RX2_RX_PATH_SEC1		(0x0528)
+#define CDC_RX_RX2_RX_PATH_SEC2		(0x052C)
+#define CDC_RX_RX2_RX_PATH_SEC3		(0x0530)
+#define CDC_RX_RX2_RX_PATH_SEC4		(0x0534)
+#define CDC_RX_RX2_RX_PATH_SEC5		(0x0538)
+#define CDC_RX_RX2_RX_PATH_SEC6		(0x053C)
+#define CDC_RX_RX2_RX_PATH_SEC7		(0x0540)
+#define CDC_RX_RX2_RX_PATH_MIX_SEC0	(0x0544)
+#define CDC_RX_RX2_RX_PATH_MIX_SEC1	(0x0548)
+#define CDC_RX_RX2_RX_PATH_DSM_CTL	(0x054C)
+#define CDC_RX_IDLE_DETECT_PATH_CTL	(0x0780)
+#define CDC_RX_IDLE_DETECT_CFG0		(0x0784)
+#define CDC_RX_IDLE_DETECT_CFG1		(0x0788)
+#define CDC_RX_IDLE_DETECT_CFG2		(0x078C)
+#define CDC_RX_IDLE_DETECT_CFG3		(0x0790)
+#define CDC_RX_COMPANDERn_CTL0(n)	(0x0800 + 0x40 * n)
+#define CDC_RX_COMPANDERn_CLK_EN_MASK	BIT(0)
+#define CDC_RX_COMPANDERn_SOFT_RST_MASK	BIT(1)
+#define CDC_RX_COMPANDERn_HALT_MASK	BIT(2)
+#define CDC_RX_COMPANDER0_CTL0		(0x0800)
+#define CDC_RX_COMPANDER0_CTL1		(0x0804)
+#define CDC_RX_COMPANDER0_CTL2		(0x0808)
+#define CDC_RX_COMPANDER0_CTL3		(0x080C)
+#define CDC_RX_COMPANDER0_CTL4		(0x0810)
+#define CDC_RX_COMPANDER0_CTL5		(0x0814)
+#define CDC_RX_COMPANDER0_CTL6		(0x0818)
+#define CDC_RX_COMPANDER0_CTL7		(0x081C)
+#define CDC_RX_COMPANDER1_CTL0		(0x0840)
+#define CDC_RX_COMPANDER1_CTL1		(0x0844)
+#define CDC_RX_COMPANDER1_CTL2		(0x0848)
+#define CDC_RX_COMPANDER1_CTL3		(0x084C)
+#define CDC_RX_COMPANDER1_CTL4		(0x0850)
+#define CDC_RX_COMPANDER1_CTL5		(0x0854)
+#define CDC_RX_COMPANDER1_CTL6		(0x0858)
+#define CDC_RX_COMPANDER1_CTL7		(0x085C)
+#define CDC_RX_COMPANDER1_HPH_LOW_PWR_MODE_MASK	BIT(5)
+#define CDC_RX_SIDETONE_IIR0_IIR_PATH_CTL	(0x0A00)
+#define CDC_RX_SIDETONE_IIR0_IIR_GAIN_B1_CTL	(0x0A04)
+#define CDC_RX_SIDETONE_IIR0_IIR_GAIN_B2_CTL	(0x0A08)
+#define CDC_RX_SIDETONE_IIR0_IIR_GAIN_B3_CTL	(0x0A0C)
+#define CDC_RX_SIDETONE_IIR0_IIR_GAIN_B4_CTL	(0x0A10)
+#define CDC_RX_SIDETONE_IIR0_IIR_GAIN_B5_CTL	(0x0A14)
+#define CDC_RX_SIDETONE_IIR0_IIR_GAIN_B6_CTL	(0x0A18)
+#define CDC_RX_SIDETONE_IIR0_IIR_GAIN_B7_CTL	(0x0A1C)
+#define CDC_RX_SIDETONE_IIR0_IIR_GAIN_B8_CTL	(0x0A20)
+#define CDC_RX_SIDETONE_IIR0_IIR_CTL		(0x0A24)
+#define CDC_RX_SIDETONE_IIR0_IIR_GAIN_TIMER_CTL	(0x0A28)
+#define CDC_RX_SIDETONE_IIR0_IIR_COEF_B1_CTL	(0x0A2C)
+#define CDC_RX_SIDETONE_IIR0_IIR_COEF_B2_CTL	(0x0A30)
+#define CDC_RX_SIDETONE_IIR1_IIR_PATH_CTL	(0x0A80)
+#define CDC_RX_SIDETONE_IIR1_IIR_GAIN_B1_CTL	(0x0A84)
+#define CDC_RX_SIDETONE_IIR1_IIR_GAIN_B2_CTL	(0x0A88)
+#define CDC_RX_SIDETONE_IIR1_IIR_GAIN_B3_CTL	(0x0A8C)
+#define CDC_RX_SIDETONE_IIR1_IIR_GAIN_B4_CTL	(0x0A90)
+#define CDC_RX_SIDETONE_IIR1_IIR_GAIN_B5_CTL	(0x0A94)
+#define CDC_RX_SIDETONE_IIR1_IIR_GAIN_B6_CTL	(0x0A98)
+#define CDC_RX_SIDETONE_IIR1_IIR_GAIN_B7_CTL	(0x0A9C)
+#define CDC_RX_SIDETONE_IIR1_IIR_GAIN_B8_CTL	(0x0AA0)
+#define CDC_RX_SIDETONE_IIR1_IIR_CTL		(0x0AA4)
+#define CDC_RX_SIDETONE_IIR1_IIR_GAIN_TIMER_CTL	(0x0AA8)
+#define CDC_RX_SIDETONE_IIR1_IIR_COEF_B1_CTL	(0x0AAC)
+#define CDC_RX_SIDETONE_IIR1_IIR_COEF_B2_CTL	(0x0AB0)
+#define CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG0	(0x0B00)
+#define CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG1	(0x0B04)
+#define CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG2	(0x0B08)
+#define CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG3	(0x0B0C)
+#define CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG0	(0x0B10)
+#define CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG1	(0x0B14)
+#define CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG2	(0x0B18)
+#define CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG3	(0x0B1C)
+#define CDC_RX_SIDETONE_SRC0_ST_SRC_PATH_CTL	(0x0B40)
+#define CDC_RX_SIDETONE_SRC0_ST_SRC_PATH_CFG1	(0x0B44)
+#define CDC_RX_SIDETONE_SRC1_ST_SRC_PATH_CTL	(0x0B50)
+#define CDC_RX_SIDETONE_SRC1_ST_SRC_PATH_CFG1	(0x0B54)
+#define CDC_RX_EC_REF_HQ0_EC_REF_HQ_PATH_CTL	(0x0C00)
+#define CDC_RX_EC_REF_HQ0_EC_REF_HQ_CFG0	(0x0C04)
+#define CDC_RX_EC_REF_HQ1_EC_REF_HQ_PATH_CTL	(0x0C40)
+#define CDC_RX_EC_REF_HQ1_EC_REF_HQ_CFG0	(0x0C44)
+#define CDC_RX_EC_REF_HQ2_EC_REF_HQ_PATH_CTL	(0x0C80)
+#define CDC_RX_EC_REF_HQ2_EC_REF_HQ_CFG0	(0x0C84)
+#define CDC_RX_EC_ASRC0_CLK_RST_CTL		(0x0D00)
+#define CDC_RX_EC_ASRC0_CTL0			(0x0D04)
+#define CDC_RX_EC_ASRC0_CTL1			(0x0D08)
+#define CDC_RX_EC_ASRC0_FIFO_CTL		(0x0D0C)
+#define CDC_RX_EC_ASRC0_STATUS_FMIN_CNTR_LSB	(0x0D10)
+#define CDC_RX_EC_ASRC0_STATUS_FMIN_CNTR_MSB	(0x0D14)
+#define CDC_RX_EC_ASRC0_STATUS_FMAX_CNTR_LSB	(0x0D18)
+#define CDC_RX_EC_ASRC0_STATUS_FMAX_CNTR_MSB	(0x0D1C)
+#define CDC_RX_EC_ASRC0_STATUS_FIFO		(0x0D20)
+#define CDC_RX_EC_ASRC1_CLK_RST_CTL		(0x0D40)
+#define CDC_RX_EC_ASRC1_CTL0			(0x0D44)
+#define CDC_RX_EC_ASRC1_CTL1			(0x0D48)
+#define CDC_RX_EC_ASRC1_FIFO_CTL		(0x0D4C)
+#define CDC_RX_EC_ASRC1_STATUS_FMIN_CNTR_LSB	(0x0D50)
+#define CDC_RX_EC_ASRC1_STATUS_FMIN_CNTR_MSB	(0x0D54)
+#define CDC_RX_EC_ASRC1_STATUS_FMAX_CNTR_LSB	(0x0D58)
+#define CDC_RX_EC_ASRC1_STATUS_FMAX_CNTR_MSB	(0x0D5C)
+#define CDC_RX_EC_ASRC1_STATUS_FIFO		(0x0D60)
+#define CDC_RX_EC_ASRC2_CLK_RST_CTL		(0x0D80)
+#define CDC_RX_EC_ASRC2_CTL0			(0x0D84)
+#define CDC_RX_EC_ASRC2_CTL1			(0x0D88)
+#define CDC_RX_EC_ASRC2_FIFO_CTL		(0x0D8C)
+#define CDC_RX_EC_ASRC2_STATUS_FMIN_CNTR_LSB	(0x0D90)
+#define CDC_RX_EC_ASRC2_STATUS_FMIN_CNTR_MSB	(0x0D94)
+#define CDC_RX_EC_ASRC2_STATUS_FMAX_CNTR_LSB	(0x0D98)
+#define CDC_RX_EC_ASRC2_STATUS_FMAX_CNTR_MSB	(0x0D9C)
+#define CDC_RX_EC_ASRC2_STATUS_FIFO		(0x0DA0)
+#define CDC_RX_DSD0_PATH_CTL			(0x0F00)
+#define CDC_RX_DSD0_CFG0			(0x0F04)
+#define CDC_RX_DSD0_CFG1			(0x0F08)
+#define CDC_RX_DSD0_CFG2			(0x0F0C)
+#define CDC_RX_DSD1_PATH_CTL			(0x0F80)
+#define CDC_RX_DSD1_CFG0			(0x0F84)
+#define CDC_RX_DSD1_CFG1			(0x0F88)
+#define CDC_RX_DSD1_CFG2			(0x0F8C)
+#define RX_MAX_OFFSET				(0x0F8C)
+
+#define MCLK_FREQ		9600000
+
+#define RX_MACRO_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
+			SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 |\
+			SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000 |\
+			SNDRV_PCM_RATE_384000)
+/* Fractional Rates */
+#define RX_MACRO_FRAC_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_88200 |\
+				SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800)
+
+#define RX_MACRO_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
+		SNDRV_PCM_FMTBIT_S24_LE |\
+		SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE)
+
+#define RX_MACRO_ECHO_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
+			SNDRV_PCM_RATE_48000)
+#define RX_MACRO_ECHO_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
+		SNDRV_PCM_FMTBIT_S24_LE |\
+		SNDRV_PCM_FMTBIT_S24_3LE)
+
+#define RX_MACRO_MAX_DMA_CH_PER_PORT 2
+
+#define RX_MACRO_EC_MIX_TX0_MASK 0xf0
+#define RX_MACRO_EC_MIX_TX1_MASK 0x0f
+#define RX_MACRO_EC_MIX_TX2_MASK 0x0f
+
+#define COMP_MAX_COEFF 25
+#define RX_NUM_CLKS_MAX	5
+
+struct comp_coeff_val {
+	u8 lsb;
+	u8 msb;
+};
+
+enum {
+	HPH_ULP,
+	HPH_LOHIFI,
+	HPH_MODE_MAX,
+};
+
+static const struct comp_coeff_val comp_coeff_table[HPH_MODE_MAX][COMP_MAX_COEFF] = {
+	{
+		{0x40, 0x00},
+		{0x4C, 0x00},
+		{0x5A, 0x00},
+		{0x6B, 0x00},
+		{0x7F, 0x00},
+		{0x97, 0x00},
+		{0xB3, 0x00},
+		{0xD5, 0x00},
+		{0xFD, 0x00},
+		{0x2D, 0x01},
+		{0x66, 0x01},
+		{0xA7, 0x01},
+		{0xF8, 0x01},
+		{0x57, 0x02},
+		{0xC7, 0x02},
+		{0x4B, 0x03},
+		{0xE9, 0x03},
+		{0xA3, 0x04},
+		{0x7D, 0x05},
+		{0x90, 0x06},
+		{0xD1, 0x07},
+		{0x49, 0x09},
+		{0x00, 0x0B},
+		{0x01, 0x0D},
+		{0x59, 0x0F},
+	},
+	{
+		{0x40, 0x00},
+		{0x4C, 0x00},
+		{0x5A, 0x00},
+		{0x6B, 0x00},
+		{0x80, 0x00},
+		{0x98, 0x00},
+		{0xB4, 0x00},
+		{0xD5, 0x00},
+		{0xFE, 0x00},
+		{0x2E, 0x01},
+		{0x66, 0x01},
+		{0xA9, 0x01},
+		{0xF8, 0x01},
+		{0x56, 0x02},
+		{0xC4, 0x02},
+		{0x4F, 0x03},
+		{0xF0, 0x03},
+		{0xAE, 0x04},
+		{0x8B, 0x05},
+		{0x8E, 0x06},
+		{0xBC, 0x07},
+		{0x56, 0x09},
+		{0x0F, 0x0B},
+		{0x13, 0x0D},
+		{0x6F, 0x0F},
+	},
+};
+
+struct rx_macro_reg_mask_val {
+	u16 reg;
+	u8 mask;
+	u8 val;
+};
+
+enum {
+	INTERP_HPHL,
+	INTERP_HPHR,
+	INTERP_AUX,
+	INTERP_MAX
+};
+
+enum {
+	RX_MACRO_RX0,
+	RX_MACRO_RX1,
+	RX_MACRO_RX2,
+	RX_MACRO_RX3,
+	RX_MACRO_RX4,
+	RX_MACRO_RX5,
+	RX_MACRO_PORTS_MAX
+};
+
+enum {
+	RX_MACRO_COMP1, /* HPH_L */
+	RX_MACRO_COMP2, /* HPH_R */
+	RX_MACRO_COMP_MAX
+};
+
+enum {
+	RX_MACRO_EC0_MUX = 0,
+	RX_MACRO_EC1_MUX,
+	RX_MACRO_EC2_MUX,
+	RX_MACRO_EC_MUX_MAX,
+};
+
+enum {
+	INTn_1_INP_SEL_ZERO = 0,
+	INTn_1_INP_SEL_DEC0,
+	INTn_1_INP_SEL_DEC1,
+	INTn_1_INP_SEL_IIR0,
+	INTn_1_INP_SEL_IIR1,
+	INTn_1_INP_SEL_RX0,
+	INTn_1_INP_SEL_RX1,
+	INTn_1_INP_SEL_RX2,
+	INTn_1_INP_SEL_RX3,
+	INTn_1_INP_SEL_RX4,
+	INTn_1_INP_SEL_RX5,
+};
+
+enum {
+	INTn_2_INP_SEL_ZERO = 0,
+	INTn_2_INP_SEL_RX0,
+	INTn_2_INP_SEL_RX1,
+	INTn_2_INP_SEL_RX2,
+	INTn_2_INP_SEL_RX3,
+	INTn_2_INP_SEL_RX4,
+	INTn_2_INP_SEL_RX5,
+};
+
+enum {
+	INTERP_MAIN_PATH,
+	INTERP_MIX_PATH,
+};
+
+/* Codec supports 2 IIR filters */
+enum {
+	IIR0 = 0,
+	IIR1,
+	IIR_MAX,
+};
+
+/* Each IIR has 5 Filter Stages */
+enum {
+	BAND1 = 0,
+	BAND2,
+	BAND3,
+	BAND4,
+	BAND5,
+	BAND_MAX,
+};
+
+#define RX_MACRO_IIR_FILTER_SIZE	(sizeof(u32) * BAND_MAX)
+
+#define RX_MACRO_IIR_FILTER_CTL(xname, iidx, bidx) \
+{ \
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
+	.info = rx_macro_iir_filter_info, \
+	.get = rx_macro_get_iir_band_audio_mixer, \
+	.put = rx_macro_put_iir_band_audio_mixer, \
+	.private_value = (unsigned long)&(struct wcd_iir_filter_ctl) { \
+		.iir_idx = iidx, \
+		.band_idx = bidx, \
+		.bytes_ext = {.max = RX_MACRO_IIR_FILTER_SIZE, }, \
+	} \
+}
+
+struct interp_sample_rate {
+	int sample_rate;
+	int rate_val;
+};
+
+static struct interp_sample_rate sr_val_tbl[] = {
+	{8000, 0x0}, {16000, 0x1}, {32000, 0x3}, {48000, 0x4}, {96000, 0x5},
+	{192000, 0x6}, {384000, 0x7}, {44100, 0x9}, {88200, 0xA},
+	{176400, 0xB}, {352800, 0xC},
+};
+
+enum {
+	RX_MACRO_AIF_INVALID = 0,
+	RX_MACRO_AIF1_PB,
+	RX_MACRO_AIF2_PB,
+	RX_MACRO_AIF3_PB,
+	RX_MACRO_AIF4_PB,
+	RX_MACRO_AIF_ECHO,
+	RX_MACRO_MAX_DAIS,
+};
+
+enum {
+	RX_MACRO_AIF1_CAP = 0,
+	RX_MACRO_AIF2_CAP,
+	RX_MACRO_AIF3_CAP,
+	RX_MACRO_MAX_AIF_CAP_DAIS
+};
+
+struct rx_macro {
+	struct device *dev;
+	int comp_enabled[RX_MACRO_COMP_MAX];
+	/* Main path clock users count */
+	int main_clk_users[INTERP_MAX];
+	int rx_port_value[RX_MACRO_PORTS_MAX];
+	u16 prim_int_users[INTERP_MAX];
+	int rx_mclk_users;
+	bool reset_swr;
+	int clsh_users;
+	int rx_mclk_cnt;
+	bool is_ear_mode_on;
+	bool hph_pwr_mode;
+	bool hph_hd2_mode;
+	struct snd_soc_component *component;
+	unsigned long active_ch_mask[RX_MACRO_MAX_DAIS];
+	unsigned long active_ch_cnt[RX_MACRO_MAX_DAIS];
+	u16 bit_width[RX_MACRO_MAX_DAIS];
+	int is_softclip_on;
+	int is_aux_hpf_on;
+	int softclip_clk_users;
+
+	struct regmap *regmap;
+	struct clk_bulk_data clks[RX_NUM_CLKS_MAX];
+	struct clk_hw hw;
+};
+#define to_rx_macro(_hw) container_of(_hw, struct rx_macro, hw)
+
+struct wcd_iir_filter_ctl {
+	unsigned int iir_idx;
+	unsigned int band_idx;
+	struct soc_bytes_ext bytes_ext;
+};
+
+static const DECLARE_TLV_DB_SCALE(digital_gain, -8400, 100, -8400);
+
+static const char * const rx_int_mix_mux_text[] = {
+	"ZERO", "RX0", "RX1", "RX2", "RX3", "RX4", "RX5"
+};
+
+static const char * const rx_prim_mix_text[] = {
+	"ZERO", "DEC0", "DEC1", "IIR0", "IIR1", "RX0", "RX1", "RX2",
+	"RX3", "RX4", "RX5"
+};
+
+static const char * const rx_sidetone_mix_text[] = {
+	"ZERO", "SRC0", "SRC1", "SRC_SUM"
+};
+
+static const char * const iir_inp_mux_text[] = {
+	"ZERO", "DEC0", "DEC1", "DEC2", "DEC3",
+	"RX0", "RX1", "RX2", "RX3", "RX4", "RX5"
+};
+
+static const char * const rx_int_dem_inp_mux_text[] = {
+	"NORMAL_DSM_OUT", "CLSH_DSM_OUT",
+};
+
+static const char * const rx_int0_1_interp_mux_text[] = {
+	"ZERO", "RX INT0_1 MIX1",
+};
+
+static const char * const rx_int1_1_interp_mux_text[] = {
+	"ZERO", "RX INT1_1 MIX1",
+};
+
+static const char * const rx_int2_1_interp_mux_text[] = {
+	"ZERO", "RX INT2_1 MIX1",
+};
+
+static const char * const rx_int0_2_interp_mux_text[] = {
+	"ZERO", "RX INT0_2 MUX",
+};
+
+static const char * const rx_int1_2_interp_mux_text[] = {
+	"ZERO", "RX INT1_2 MUX",
+};
+
+static const char * const rx_int2_2_interp_mux_text[] = {
+	"ZERO", "RX INT2_2 MUX",
+};
+
+static const char *const rx_macro_mux_text[] = {
+	"ZERO", "AIF1_PB", "AIF2_PB", "AIF3_PB", "AIF4_PB"
+};
+
+static const char *const rx_macro_hph_pwr_mode_text[] = {
+	"ULP", "LOHIFI"
+};
+
+static const char * const rx_echo_mux_text[] = {
+	"ZERO", "RX_MIX0", "RX_MIX1", "RX_MIX2"
+};
+
+static const struct soc_enum rx_macro_hph_pwr_mode_enum =
+		SOC_ENUM_SINGLE_EXT(2, rx_macro_hph_pwr_mode_text);
+static const struct soc_enum rx_mix_tx2_mux_enum =
+		SOC_ENUM_SINGLE(CDC_RX_INP_MUX_RX_MIX_CFG5, 0, 4, rx_echo_mux_text);
+static const struct soc_enum rx_mix_tx1_mux_enum =
+		SOC_ENUM_SINGLE(CDC_RX_INP_MUX_RX_MIX_CFG4, 0, 4, rx_echo_mux_text);
+static const struct soc_enum rx_mix_tx0_mux_enum =
+		SOC_ENUM_SINGLE(CDC_RX_INP_MUX_RX_MIX_CFG4, 4, 4, rx_echo_mux_text);
+
+static SOC_ENUM_SINGLE_DECL(rx_int0_2_enum, CDC_RX_INP_MUX_RX_INT0_CFG1, 0,
+			    rx_int_mix_mux_text);
+static SOC_ENUM_SINGLE_DECL(rx_int1_2_enum, CDC_RX_INP_MUX_RX_INT1_CFG1, 0,
+			    rx_int_mix_mux_text);
+static SOC_ENUM_SINGLE_DECL(rx_int2_2_enum, CDC_RX_INP_MUX_RX_INT2_CFG1, 0,
+			    rx_int_mix_mux_text);
+
+static SOC_ENUM_SINGLE_DECL(rx_int0_1_mix_inp0_enum, CDC_RX_INP_MUX_RX_INT0_CFG0, 0,
+			    rx_prim_mix_text);
+static SOC_ENUM_SINGLE_DECL(rx_int0_1_mix_inp1_enum, CDC_RX_INP_MUX_RX_INT0_CFG0, 4,
+			    rx_prim_mix_text);
+static SOC_ENUM_SINGLE_DECL(rx_int0_1_mix_inp2_enum, CDC_RX_INP_MUX_RX_INT0_CFG1, 4,
+			    rx_prim_mix_text);
+static SOC_ENUM_SINGLE_DECL(rx_int1_1_mix_inp0_enum, CDC_RX_INP_MUX_RX_INT1_CFG0, 0,
+			    rx_prim_mix_text);
+static SOC_ENUM_SINGLE_DECL(rx_int1_1_mix_inp1_enum, CDC_RX_INP_MUX_RX_INT1_CFG0, 4,
+			    rx_prim_mix_text);
+static SOC_ENUM_SINGLE_DECL(rx_int1_1_mix_inp2_enum, CDC_RX_INP_MUX_RX_INT1_CFG1, 4,
+			    rx_prim_mix_text);
+static SOC_ENUM_SINGLE_DECL(rx_int2_1_mix_inp0_enum, CDC_RX_INP_MUX_RX_INT2_CFG0, 0,
+			    rx_prim_mix_text);
+static SOC_ENUM_SINGLE_DECL(rx_int2_1_mix_inp1_enum, CDC_RX_INP_MUX_RX_INT2_CFG0, 4,
+			    rx_prim_mix_text);
+static SOC_ENUM_SINGLE_DECL(rx_int2_1_mix_inp2_enum, CDC_RX_INP_MUX_RX_INT2_CFG1, 4,
+			    rx_prim_mix_text);
+
+static SOC_ENUM_SINGLE_DECL(rx_int0_mix2_inp_enum, CDC_RX_INP_MUX_SIDETONE_SRC_CFG0, 2,
+			    rx_sidetone_mix_text);
+static SOC_ENUM_SINGLE_DECL(rx_int1_mix2_inp_enum, CDC_RX_INP_MUX_SIDETONE_SRC_CFG0, 4,
+			    rx_sidetone_mix_text);
+static SOC_ENUM_SINGLE_DECL(rx_int2_mix2_inp_enum, CDC_RX_INP_MUX_SIDETONE_SRC_CFG0, 6,
+			    rx_sidetone_mix_text);
+static SOC_ENUM_SINGLE_DECL(iir0_inp0_enum, CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG0, 0,
+			    iir_inp_mux_text);
+static SOC_ENUM_SINGLE_DECL(iir0_inp1_enum, CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG1, 0,
+			    iir_inp_mux_text);
+static SOC_ENUM_SINGLE_DECL(iir0_inp2_enum, CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG2, 0,
+			    iir_inp_mux_text);
+static SOC_ENUM_SINGLE_DECL(iir0_inp3_enum, CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG3, 0,
+			    iir_inp_mux_text);
+static SOC_ENUM_SINGLE_DECL(iir1_inp0_enum, CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG0, 0,
+			    iir_inp_mux_text);
+static SOC_ENUM_SINGLE_DECL(iir1_inp1_enum, CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG1, 0,
+			    iir_inp_mux_text);
+static SOC_ENUM_SINGLE_DECL(iir1_inp2_enum, CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG2, 0,
+			    iir_inp_mux_text);
+static SOC_ENUM_SINGLE_DECL(iir1_inp3_enum, CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG3, 0,
+			    iir_inp_mux_text);
+
+static SOC_ENUM_SINGLE_DECL(rx_int0_1_interp_enum, SND_SOC_NOPM, 0,
+			    rx_int0_1_interp_mux_text);
+static SOC_ENUM_SINGLE_DECL(rx_int1_1_interp_enum, SND_SOC_NOPM, 0,
+			    rx_int1_1_interp_mux_text);
+static SOC_ENUM_SINGLE_DECL(rx_int2_1_interp_enum, SND_SOC_NOPM, 0,
+			    rx_int2_1_interp_mux_text);
+static SOC_ENUM_SINGLE_DECL(rx_int0_2_interp_enum, SND_SOC_NOPM, 0,
+			    rx_int0_2_interp_mux_text);
+static SOC_ENUM_SINGLE_DECL(rx_int1_2_interp_enum, SND_SOC_NOPM, 0,
+			    rx_int1_2_interp_mux_text);
+static SOC_ENUM_SINGLE_DECL(rx_int2_2_interp_enum, SND_SOC_NOPM, 0,
+			    rx_int2_2_interp_mux_text);
+static SOC_ENUM_SINGLE_DECL(rx_int0_dem_inp_enum, CDC_RX_RX0_RX_PATH_CFG1, 0,
+			    rx_int_dem_inp_mux_text);
+static SOC_ENUM_SINGLE_DECL(rx_int1_dem_inp_enum, CDC_RX_RX1_RX_PATH_CFG1, 0,
+			    rx_int_dem_inp_mux_text);
+
+static SOC_ENUM_SINGLE_DECL(rx_macro_rx0_enum, SND_SOC_NOPM, 0, rx_macro_mux_text);
+static SOC_ENUM_SINGLE_DECL(rx_macro_rx1_enum, SND_SOC_NOPM, 0, rx_macro_mux_text);
+static SOC_ENUM_SINGLE_DECL(rx_macro_rx2_enum, SND_SOC_NOPM, 0, rx_macro_mux_text);
+static SOC_ENUM_SINGLE_DECL(rx_macro_rx3_enum, SND_SOC_NOPM, 0, rx_macro_mux_text);
+static SOC_ENUM_SINGLE_DECL(rx_macro_rx4_enum, SND_SOC_NOPM, 0, rx_macro_mux_text);
+static SOC_ENUM_SINGLE_DECL(rx_macro_rx5_enum, SND_SOC_NOPM, 0, rx_macro_mux_text);
+
+static const struct snd_kcontrol_new rx_mix_tx1_mux =
+		SOC_DAPM_ENUM("RX MIX TX1_MUX Mux", rx_mix_tx1_mux_enum);
+static const struct snd_kcontrol_new rx_mix_tx2_mux = 
+		SOC_DAPM_ENUM("RX MIX TX2_MUX Mux", rx_mix_tx2_mux_enum);
+static const struct snd_kcontrol_new rx_int0_2_mux =
+		SOC_DAPM_ENUM("rx_int0_2", rx_int0_2_enum);
+static const struct snd_kcontrol_new rx_int1_2_mux =
+		SOC_DAPM_ENUM("rx_int1_2", rx_int1_2_enum);
+static const struct snd_kcontrol_new rx_int2_2_mux =
+		SOC_DAPM_ENUM("rx_int2_2", rx_int2_2_enum);
+static const struct snd_kcontrol_new rx_int0_1_mix_inp0_mux =
+		SOC_DAPM_ENUM("rx_int0_1_mix_inp0", rx_int0_1_mix_inp0_enum);
+static const struct snd_kcontrol_new rx_int0_1_mix_inp1_mux =
+		SOC_DAPM_ENUM("rx_int0_1_mix_inp1", rx_int0_1_mix_inp1_enum);
+static const struct snd_kcontrol_new rx_int0_1_mix_inp2_mux =
+		SOC_DAPM_ENUM("rx_int0_1_mix_inp2", rx_int0_1_mix_inp2_enum);
+static const struct snd_kcontrol_new rx_int1_1_mix_inp0_mux =
+		SOC_DAPM_ENUM("rx_int1_1_mix_inp0", rx_int1_1_mix_inp0_enum);
+static const struct snd_kcontrol_new rx_int1_1_mix_inp1_mux =
+		SOC_DAPM_ENUM("rx_int1_1_mix_inp1", rx_int1_1_mix_inp1_enum);
+static const struct snd_kcontrol_new rx_int1_1_mix_inp2_mux =
+		SOC_DAPM_ENUM("rx_int1_1_mix_inp2", rx_int1_1_mix_inp2_enum);
+static const struct snd_kcontrol_new rx_int2_1_mix_inp0_mux =
+		SOC_DAPM_ENUM("rx_int2_1_mix_inp0", rx_int2_1_mix_inp0_enum);
+static const struct snd_kcontrol_new rx_int2_1_mix_inp1_mux =
+		SOC_DAPM_ENUM("rx_int2_1_mix_inp1", rx_int2_1_mix_inp1_enum);
+static const struct snd_kcontrol_new rx_int2_1_mix_inp2_mux =
+		SOC_DAPM_ENUM("rx_int2_1_mix_inp2", rx_int2_1_mix_inp2_enum);
+static const struct snd_kcontrol_new rx_int0_mix2_inp_mux =
+		SOC_DAPM_ENUM("rx_int0_mix2_inp", rx_int0_mix2_inp_enum);
+static const struct snd_kcontrol_new rx_int1_mix2_inp_mux =
+		SOC_DAPM_ENUM("rx_int1_mix2_inp", rx_int1_mix2_inp_enum);
+static const struct snd_kcontrol_new rx_int2_mix2_inp_mux =
+		SOC_DAPM_ENUM("rx_int2_mix2_inp", rx_int2_mix2_inp_enum);
+static const struct snd_kcontrol_new iir0_inp0_mux =
+		SOC_DAPM_ENUM("iir0_inp0", iir0_inp0_enum);
+static const struct snd_kcontrol_new iir0_inp1_mux =
+		SOC_DAPM_ENUM("iir0_inp1", iir0_inp1_enum);
+static const struct snd_kcontrol_new iir0_inp2_mux =
+		SOC_DAPM_ENUM("iir0_inp2", iir0_inp2_enum);
+static const struct snd_kcontrol_new iir0_inp3_mux =
+		SOC_DAPM_ENUM("iir0_inp3", iir0_inp3_enum);
+static const struct snd_kcontrol_new iir1_inp0_mux =
+		SOC_DAPM_ENUM("iir1_inp0", iir1_inp0_enum);
+static const struct snd_kcontrol_new iir1_inp1_mux =
+		SOC_DAPM_ENUM("iir1_inp1", iir1_inp1_enum);
+static const struct snd_kcontrol_new iir1_inp2_mux =
+		SOC_DAPM_ENUM("iir1_inp2", iir1_inp2_enum);
+static const struct snd_kcontrol_new iir1_inp3_mux =
+		SOC_DAPM_ENUM("iir1_inp3", iir1_inp3_enum);
+static const struct snd_kcontrol_new rx_int0_1_interp_mux =
+		SOC_DAPM_ENUM("rx_int0_1_interp", rx_int0_1_interp_enum);
+static const struct snd_kcontrol_new rx_int1_1_interp_mux =
+		SOC_DAPM_ENUM("rx_int1_1_interp", rx_int1_1_interp_enum);
+static const struct snd_kcontrol_new rx_int2_1_interp_mux =
+		SOC_DAPM_ENUM("rx_int2_1_interp", rx_int2_1_interp_enum);
+static const struct snd_kcontrol_new rx_int0_2_interp_mux =
+		SOC_DAPM_ENUM("rx_int0_2_interp", rx_int0_2_interp_enum);
+static const struct snd_kcontrol_new rx_int1_2_interp_mux =
+		SOC_DAPM_ENUM("rx_int1_2_interp", rx_int1_2_interp_enum);
+static const struct snd_kcontrol_new rx_int2_2_interp_mux =
+		SOC_DAPM_ENUM("rx_int2_2_interp", rx_int2_2_interp_enum);
+static const struct snd_kcontrol_new rx_mix_tx0_mux =
+		SOC_DAPM_ENUM("RX MIX TX0_MUX Mux", rx_mix_tx0_mux_enum);
+
+static const struct reg_default rx_defaults[] = {
+	/* RX Macro */
+	{ CDC_RX_TOP_TOP_CFG0, 0x00 },
+	{ CDC_RX_TOP_SWR_CTRL, 0x00 },
+	{ CDC_RX_TOP_DEBUG, 0x00 },
+	{ CDC_RX_TOP_DEBUG_BUS, 0x00 },
+	{ CDC_RX_TOP_DEBUG_EN0, 0x00 },
+	{ CDC_RX_TOP_DEBUG_EN1, 0x00 },
+	{ CDC_RX_TOP_DEBUG_EN2, 0x00 },
+	{ CDC_RX_TOP_HPHL_COMP_WR_LSB, 0x00 },
+	{ CDC_RX_TOP_HPHL_COMP_WR_MSB, 0x00 },
+	{ CDC_RX_TOP_HPHL_COMP_LUT, 0x00 },
+	{ CDC_RX_TOP_HPHL_COMP_RD_LSB, 0x00 },
+	{ CDC_RX_TOP_HPHL_COMP_RD_MSB, 0x00 },
+	{ CDC_RX_TOP_HPHR_COMP_WR_LSB, 0x00 },
+	{ CDC_RX_TOP_HPHR_COMP_WR_MSB, 0x00 },
+	{ CDC_RX_TOP_HPHR_COMP_LUT, 0x00 },
+	{ CDC_RX_TOP_HPHR_COMP_RD_LSB, 0x00 },
+	{ CDC_RX_TOP_HPHR_COMP_RD_MSB, 0x00 },
+	{ CDC_RX_TOP_DSD0_DEBUG_CFG0, 0x11 },
+	{ CDC_RX_TOP_DSD0_DEBUG_CFG1, 0x20 },
+	{ CDC_RX_TOP_DSD0_DEBUG_CFG2, 0x00 },
+	{ CDC_RX_TOP_DSD0_DEBUG_CFG3, 0x00 },
+	{ CDC_RX_TOP_DSD1_DEBUG_CFG0, 0x11 },
+	{ CDC_RX_TOP_DSD1_DEBUG_CFG1, 0x20 },
+	{ CDC_RX_TOP_DSD1_DEBUG_CFG2, 0x00 },
+	{ CDC_RX_TOP_DSD1_DEBUG_CFG3, 0x00 },
+	{ CDC_RX_TOP_RX_I2S_CTL, 0x0C },
+	{ CDC_RX_TOP_TX_I2S2_CTL, 0x0C },
+	{ CDC_RX_TOP_I2S_CLK, 0x0C },
+	{ CDC_RX_TOP_I2S_RESET, 0x00 },
+	{ CDC_RX_TOP_I2S_MUX, 0x00 },
+	{ CDC_RX_CLK_RST_CTRL_MCLK_CONTROL, 0x00 },
+	{ CDC_RX_CLK_RST_CTRL_FS_CNT_CONTROL, 0x00 },
+	{ CDC_RX_CLK_RST_CTRL_SWR_CONTROL, 0x00 },
+	{ CDC_RX_CLK_RST_CTRL_DSD_CONTROL, 0x00 },
+	{ CDC_RX_CLK_RST_CTRL_ASRC_SHARE_CONTROL, 0x08 },
+	{ CDC_RX_SOFTCLIP_CRC, 0x00 },
+	{ CDC_RX_SOFTCLIP_SOFTCLIP_CTRL, 0x38 },
+	{ CDC_RX_INP_MUX_RX_INT0_CFG0, 0x00 },
+	{ CDC_RX_INP_MUX_RX_INT0_CFG1, 0x00 },
+	{ CDC_RX_INP_MUX_RX_INT1_CFG0, 0x00 },
+	{ CDC_RX_INP_MUX_RX_INT1_CFG1, 0x00 },
+	{ CDC_RX_INP_MUX_RX_INT2_CFG0, 0x00 },
+	{ CDC_RX_INP_MUX_RX_INT2_CFG1, 0x00 },
+	{ CDC_RX_INP_MUX_RX_MIX_CFG4, 0x00 },
+	{ CDC_RX_INP_MUX_RX_MIX_CFG5, 0x00 },
+	{ CDC_RX_INP_MUX_SIDETONE_SRC_CFG0, 0x00 },
+	{ CDC_RX_CLSH_CRC, 0x00 },
+	{ CDC_RX_CLSH_DLY_CTRL, 0x03 },
+	{ CDC_RX_CLSH_DECAY_CTRL, 0x02 },
+	{ CDC_RX_CLSH_HPH_V_PA, 0x1C },
+	{ CDC_RX_CLSH_EAR_V_PA, 0x39 },
+	{ CDC_RX_CLSH_HPH_V_HD, 0x0C },
+	{ CDC_RX_CLSH_EAR_V_HD, 0x0C },
+	{ CDC_RX_CLSH_K1_MSB, 0x01 },
+	{ CDC_RX_CLSH_K1_LSB, 0x00 },
+	{ CDC_RX_CLSH_K2_MSB, 0x00 },
+	{ CDC_RX_CLSH_K2_LSB, 0x80 },
+	{ CDC_RX_CLSH_IDLE_CTRL, 0x00 },
+	{ CDC_RX_CLSH_IDLE_HPH, 0x00 },
+	{ CDC_RX_CLSH_IDLE_EAR, 0x00 },
+	{ CDC_RX_CLSH_TEST0, 0x07 },
+	{ CDC_RX_CLSH_TEST1, 0x00 },
+	{ CDC_RX_CLSH_OVR_VREF, 0x00 },
+	{ CDC_RX_CLSH_CLSG_CTL, 0x02 },
+	{ CDC_RX_CLSH_CLSG_CFG1, 0x9A },
+	{ CDC_RX_CLSH_CLSG_CFG2, 0x10 },
+	{ CDC_RX_BCL_VBAT_PATH_CTL, 0x00 },
+	{ CDC_RX_BCL_VBAT_CFG, 0x10 },
+	{ CDC_RX_BCL_VBAT_ADC_CAL1, 0x00 },
+	{ CDC_RX_BCL_VBAT_ADC_CAL2, 0x00 },
+	{ CDC_RX_BCL_VBAT_ADC_CAL3, 0x04 },
+	{ CDC_RX_BCL_VBAT_PK_EST1, 0xE0 },
+	{ CDC_RX_BCL_VBAT_PK_EST2, 0x01 },
+	{ CDC_RX_BCL_VBAT_PK_EST3, 0x40 },
+	{ CDC_RX_BCL_VBAT_RF_PROC1, 0x2A },
+	{ CDC_RX_BCL_VBAT_RF_PROC1, 0x00 },
+	{ CDC_RX_BCL_VBAT_TAC1, 0x00 },
+	{ CDC_RX_BCL_VBAT_TAC2, 0x18 },
+	{ CDC_RX_BCL_VBAT_TAC3, 0x18 },
+	{ CDC_RX_BCL_VBAT_TAC4, 0x03 },
+	{ CDC_RX_BCL_VBAT_GAIN_UPD1, 0x01 },
+	{ CDC_RX_BCL_VBAT_GAIN_UPD2, 0x00 },
+	{ CDC_RX_BCL_VBAT_GAIN_UPD3, 0x00 },
+	{ CDC_RX_BCL_VBAT_GAIN_UPD4, 0x64 },
+	{ CDC_RX_BCL_VBAT_GAIN_UPD5, 0x01 },
+	{ CDC_RX_BCL_VBAT_DEBUG1, 0x00 },
+	{ CDC_RX_BCL_VBAT_GAIN_UPD_MON, 0x00 },
+	{ CDC_RX_BCL_VBAT_GAIN_MON_VAL, 0x00 },
+	{ CDC_RX_BCL_VBAT_BAN, 0x0C },
+	{ CDC_RX_BCL_VBAT_BCL_GAIN_UPD1, 0x00 },
+	{ CDC_RX_BCL_VBAT_BCL_GAIN_UPD2, 0x77 },
+	{ CDC_RX_BCL_VBAT_BCL_GAIN_UPD3, 0x01 },
+	{ CDC_RX_BCL_VBAT_BCL_GAIN_UPD4, 0x00 },
+	{ CDC_RX_BCL_VBAT_BCL_GAIN_UPD5, 0x4B },
+	{ CDC_RX_BCL_VBAT_BCL_GAIN_UPD6, 0x00 },
+	{ CDC_RX_BCL_VBAT_BCL_GAIN_UPD7, 0x01 },
+	{ CDC_RX_BCL_VBAT_BCL_GAIN_UPD8, 0x00 },
+	{ CDC_RX_BCL_VBAT_BCL_GAIN_UPD9, 0x00 },
+	{ CDC_RX_BCL_VBAT_ATTN1, 0x04 },
+	{ CDC_RX_BCL_VBAT_ATTN2, 0x08 },
+	{ CDC_RX_BCL_VBAT_ATTN3, 0x0C },
+	{ CDC_RX_BCL_VBAT_DECODE_CTL1, 0xE0 },
+	{ CDC_RX_BCL_VBAT_DECODE_CTL2, 0x00 },
+	{ CDC_RX_BCL_VBAT_DECODE_CFG1, 0x00 },
+	{ CDC_RX_BCL_VBAT_DECODE_CFG2, 0x00 },
+	{ CDC_RX_BCL_VBAT_DECODE_CFG3, 0x00 },
+	{ CDC_RX_BCL_VBAT_DECODE_CFG4, 0x00 },
+	{ CDC_RX_BCL_VBAT_DECODE_ST, 0x00 },
+	{ CDC_RX_INTR_CTRL_CFG, 0x00 },
+	{ CDC_RX_INTR_CTRL_CLR_COMMIT, 0x00 },
+	{ CDC_RX_INTR_CTRL_PIN1_MASK0, 0xFF },
+	{ CDC_RX_INTR_CTRL_PIN1_STATUS0, 0x00 },
+	{ CDC_RX_INTR_CTRL_PIN1_CLEAR0, 0x00 },
+	{ CDC_RX_INTR_CTRL_PIN2_MASK0, 0xFF },
+	{ CDC_RX_INTR_CTRL_PIN2_STATUS0, 0x00 },
+	{ CDC_RX_INTR_CTRL_PIN2_CLEAR0, 0x00 },
+	{ CDC_RX_INTR_CTRL_LEVEL0, 0x00 },
+	{ CDC_RX_INTR_CTRL_BYPASS0, 0x00 },
+	{ CDC_RX_INTR_CTRL_SET0, 0x00 },
+	{ CDC_RX_RX0_RX_PATH_CTL, 0x04 },
+	{ CDC_RX_RX0_RX_PATH_CFG0, 0x00 },
+	{ CDC_RX_RX0_RX_PATH_CFG1, 0x64 },
+	{ CDC_RX_RX0_RX_PATH_CFG2, 0x8F },
+	{ CDC_RX_RX0_RX_PATH_CFG3, 0x00 },
+	{ CDC_RX_RX0_RX_VOL_CTL, 0x00 },
+	{ CDC_RX_RX0_RX_PATH_MIX_CTL, 0x04 },
+	{ CDC_RX_RX0_RX_PATH_MIX_CFG, 0x7E },
+	{ CDC_RX_RX0_RX_VOL_MIX_CTL, 0x00 },
+	{ CDC_RX_RX0_RX_PATH_SEC1, 0x08 },
+	{ CDC_RX_RX0_RX_PATH_SEC2, 0x00 },
+	{ CDC_RX_RX0_RX_PATH_SEC3, 0x00 },
+	{ CDC_RX_RX0_RX_PATH_SEC4, 0x00 },
+	{ CDC_RX_RX0_RX_PATH_SEC7, 0x00 },
+	{ CDC_RX_RX0_RX_PATH_MIX_SEC0, 0x08 },
+	{ CDC_RX_RX0_RX_PATH_MIX_SEC1, 0x00 },
+	{ CDC_RX_RX0_RX_PATH_DSM_CTL, 0x08 },
+	{ CDC_RX_RX0_RX_PATH_DSM_DATA1, 0x00 },
+	{ CDC_RX_RX0_RX_PATH_DSM_DATA2, 0x00 },
+	{ CDC_RX_RX0_RX_PATH_DSM_DATA3, 0x00 },
+	{ CDC_RX_RX0_RX_PATH_DSM_DATA4, 0x55 },
+	{ CDC_RX_RX0_RX_PATH_DSM_DATA5, 0x55 },
+	{ CDC_RX_RX0_RX_PATH_DSM_DATA6, 0x55 },
+	{ CDC_RX_RX1_RX_PATH_CTL, 0x04 },
+	{ CDC_RX_RX1_RX_PATH_CFG0, 0x00 },
+	{ CDC_RX_RX1_RX_PATH_CFG1, 0x64 },
+	{ CDC_RX_RX1_RX_PATH_CFG2, 0x8F },
+	{ CDC_RX_RX1_RX_PATH_CFG3, 0x00 },
+	{ CDC_RX_RX1_RX_VOL_CTL, 0x00 },
+	{ CDC_RX_RX1_RX_PATH_MIX_CTL, 0x04 },
+	{ CDC_RX_RX1_RX_PATH_MIX_CFG, 0x7E },
+	{ CDC_RX_RX1_RX_VOL_MIX_CTL, 0x00 },
+	{ CDC_RX_RX1_RX_PATH_SEC1, 0x08 },
+	{ CDC_RX_RX1_RX_PATH_SEC2, 0x00 },
+	{ CDC_RX_RX1_RX_PATH_SEC3, 0x00 },
+	{ CDC_RX_RX1_RX_PATH_SEC4, 0x00 },
+	{ CDC_RX_RX1_RX_PATH_SEC7, 0x00 },
+	{ CDC_RX_RX1_RX_PATH_MIX_SEC0, 0x08 },
+	{ CDC_RX_RX1_RX_PATH_MIX_SEC1, 0x00 },
+	{ CDC_RX_RX1_RX_PATH_DSM_CTL, 0x08 },
+	{ CDC_RX_RX1_RX_PATH_DSM_DATA1, 0x00 },
+	{ CDC_RX_RX1_RX_PATH_DSM_DATA2, 0x00 },
+	{ CDC_RX_RX1_RX_PATH_DSM_DATA3, 0x00 },
+	{ CDC_RX_RX1_RX_PATH_DSM_DATA4, 0x55 },
+	{ CDC_RX_RX1_RX_PATH_DSM_DATA5, 0x55 },
+	{ CDC_RX_RX1_RX_PATH_DSM_DATA6, 0x55 },
+	{ CDC_RX_RX2_RX_PATH_CTL, 0x04 },
+	{ CDC_RX_RX2_RX_PATH_CFG0, 0x00 },
+	{ CDC_RX_RX2_RX_PATH_CFG1, 0x64 },
+	{ CDC_RX_RX2_RX_PATH_CFG2, 0x8F },
+	{ CDC_RX_RX2_RX_PATH_CFG3, 0x00 },
+	{ CDC_RX_RX2_RX_VOL_CTL, 0x00 },
+	{ CDC_RX_RX2_RX_PATH_MIX_CTL, 0x04 },
+	{ CDC_RX_RX2_RX_PATH_MIX_CFG, 0x7E },
+	{ CDC_RX_RX2_RX_VOL_MIX_CTL, 0x00 },
+	{ CDC_RX_RX2_RX_PATH_SEC0, 0x04 },
+	{ CDC_RX_RX2_RX_PATH_SEC1, 0x08 },
+	{ CDC_RX_RX2_RX_PATH_SEC2, 0x00 },
+	{ CDC_RX_RX2_RX_PATH_SEC3, 0x00 },
+	{ CDC_RX_RX2_RX_PATH_SEC4, 0x00 },
+	{ CDC_RX_RX2_RX_PATH_SEC5, 0x00 },
+	{ CDC_RX_RX2_RX_PATH_SEC6, 0x00 },
+	{ CDC_RX_RX2_RX_PATH_SEC7, 0x00 },
+	{ CDC_RX_RX2_RX_PATH_MIX_SEC0, 0x08 },
+	{ CDC_RX_RX2_RX_PATH_MIX_SEC1, 0x00 },
+	{ CDC_RX_RX2_RX_PATH_DSM_CTL, 0x00 },
+	{ CDC_RX_IDLE_DETECT_PATH_CTL, 0x00 },
+	{ CDC_RX_IDLE_DETECT_CFG0, 0x07 },
+	{ CDC_RX_IDLE_DETECT_CFG1, 0x3C },
+	{ CDC_RX_IDLE_DETECT_CFG2, 0x00 },
+	{ CDC_RX_IDLE_DETECT_CFG3, 0x00 },
+	{ CDC_RX_COMPANDER0_CTL0, 0x60 },
+	{ CDC_RX_COMPANDER0_CTL1, 0xDB },
+	{ CDC_RX_COMPANDER0_CTL2, 0xFF },
+	{ CDC_RX_COMPANDER0_CTL3, 0x35 },
+	{ CDC_RX_COMPANDER0_CTL4, 0xFF },
+	{ CDC_RX_COMPANDER0_CTL5, 0x00 },
+	{ CDC_RX_COMPANDER0_CTL6, 0x01 },
+	{ CDC_RX_COMPANDER0_CTL7, 0x28 },
+	{ CDC_RX_COMPANDER1_CTL0, 0x60 },
+	{ CDC_RX_COMPANDER1_CTL1, 0xDB },
+	{ CDC_RX_COMPANDER1_CTL2, 0xFF },
+	{ CDC_RX_COMPANDER1_CTL3, 0x35 },
+	{ CDC_RX_COMPANDER1_CTL4, 0xFF },
+	{ CDC_RX_COMPANDER1_CTL5, 0x00 },
+	{ CDC_RX_COMPANDER1_CTL6, 0x01 },
+	{ CDC_RX_COMPANDER1_CTL7, 0x28 },
+	{ CDC_RX_SIDETONE_IIR0_IIR_PATH_CTL, 0x00 },
+	{ CDC_RX_SIDETONE_IIR0_IIR_GAIN_B1_CTL, 0x00 },
+	{ CDC_RX_SIDETONE_IIR0_IIR_GAIN_B2_CTL, 0x00 },
+	{ CDC_RX_SIDETONE_IIR0_IIR_GAIN_B3_CTL, 0x00 },
+	{ CDC_RX_SIDETONE_IIR0_IIR_GAIN_B4_CTL, 0x00 },
+	{ CDC_RX_SIDETONE_IIR0_IIR_GAIN_B5_CTL, 0x00 },
+	{ CDC_RX_SIDETONE_IIR0_IIR_GAIN_B6_CTL, 0x00 },
+	{ CDC_RX_SIDETONE_IIR0_IIR_GAIN_B7_CTL, 0x00 },
+	{ CDC_RX_SIDETONE_IIR0_IIR_GAIN_B8_CTL, 0x00 },
+	{ CDC_RX_SIDETONE_IIR0_IIR_CTL, 0x40 },
+	{ CDC_RX_SIDETONE_IIR0_IIR_GAIN_TIMER_CTL, 0x00 },
+	{ CDC_RX_SIDETONE_IIR0_IIR_COEF_B1_CTL, 0x00 },
+	{ CDC_RX_SIDETONE_IIR0_IIR_COEF_B2_CTL, 0x00 },
+	{ CDC_RX_SIDETONE_IIR1_IIR_PATH_CTL, 0x00 },
+	{ CDC_RX_SIDETONE_IIR1_IIR_GAIN_B1_CTL, 0x00 },
+	{ CDC_RX_SIDETONE_IIR1_IIR_GAIN_B2_CTL, 0x00 },
+	{ CDC_RX_SIDETONE_IIR1_IIR_GAIN_B3_CTL, 0x00 },
+	{ CDC_RX_SIDETONE_IIR1_IIR_GAIN_B4_CTL, 0x00 },
+	{ CDC_RX_SIDETONE_IIR1_IIR_GAIN_B5_CTL, 0x00 },
+	{ CDC_RX_SIDETONE_IIR1_IIR_GAIN_B6_CTL, 0x00 },
+	{ CDC_RX_SIDETONE_IIR1_IIR_GAIN_B7_CTL, 0x00 },
+	{ CDC_RX_SIDETONE_IIR1_IIR_GAIN_B8_CTL, 0x00 },
+	{ CDC_RX_SIDETONE_IIR1_IIR_CTL, 0x40 },
+	{ CDC_RX_SIDETONE_IIR1_IIR_GAIN_TIMER_CTL, 0x00 },
+	{ CDC_RX_SIDETONE_IIR1_IIR_COEF_B1_CTL, 0x00 },
+	{ CDC_RX_SIDETONE_IIR1_IIR_COEF_B2_CTL, 0x00 },
+	{ CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG0, 0x00 },
+	{ CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG1, 0x00 },
+	{ CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG2, 0x00 },
+	{ CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG3, 0x00 },
+	{ CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG0, 0x00 },
+	{ CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG1, 0x00 },
+	{ CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG2, 0x00 },
+	{ CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG3, 0x00 },
+	{ CDC_RX_SIDETONE_SRC0_ST_SRC_PATH_CTL, 0x04 },
+	{ CDC_RX_SIDETONE_SRC0_ST_SRC_PATH_CFG1, 0x00 },
+	{ CDC_RX_SIDETONE_SRC1_ST_SRC_PATH_CTL, 0x04 },
+	{ CDC_RX_SIDETONE_SRC1_ST_SRC_PATH_CFG1, 0x00 },
+	{ CDC_RX_EC_REF_HQ0_EC_REF_HQ_PATH_CTL, 0x00 },
+	{ CDC_RX_EC_REF_HQ0_EC_REF_HQ_CFG0, 0x01 },
+	{ CDC_RX_EC_REF_HQ1_EC_REF_HQ_PATH_CTL, 0x00 },
+	{ CDC_RX_EC_REF_HQ1_EC_REF_HQ_CFG0, 0x01 },
+	{ CDC_RX_EC_REF_HQ2_EC_REF_HQ_PATH_CTL, 0x00 },
+	{ CDC_RX_EC_REF_HQ2_EC_REF_HQ_CFG0, 0x01 },
+	{ CDC_RX_EC_ASRC0_CLK_RST_CTL, 0x00 },
+	{ CDC_RX_EC_ASRC0_CTL0, 0x00 },
+	{ CDC_RX_EC_ASRC0_CTL1, 0x00 },
+	{ CDC_RX_EC_ASRC0_FIFO_CTL, 0xA8 },
+	{ CDC_RX_EC_ASRC0_STATUS_FMIN_CNTR_LSB, 0x00 },
+	{ CDC_RX_EC_ASRC0_STATUS_FMIN_CNTR_MSB, 0x00 },
+	{ CDC_RX_EC_ASRC0_STATUS_FMAX_CNTR_LSB, 0x00 },
+	{ CDC_RX_EC_ASRC0_STATUS_FMAX_CNTR_MSB, 0x00 },
+	{ CDC_RX_EC_ASRC0_STATUS_FIFO, 0x00 },
+	{ CDC_RX_EC_ASRC1_CLK_RST_CTL, 0x00 },
+	{ CDC_RX_EC_ASRC1_CTL0, 0x00 },
+	{ CDC_RX_EC_ASRC1_CTL1, 0x00 },
+	{ CDC_RX_EC_ASRC1_FIFO_CTL, 0xA8 },
+	{ CDC_RX_EC_ASRC1_STATUS_FMIN_CNTR_LSB, 0x00 },
+	{ CDC_RX_EC_ASRC1_STATUS_FMIN_CNTR_MSB, 0x00 },
+	{ CDC_RX_EC_ASRC1_STATUS_FMAX_CNTR_LSB, 0x00 },
+	{ CDC_RX_EC_ASRC1_STATUS_FMAX_CNTR_MSB, 0x00 },
+	{ CDC_RX_EC_ASRC1_STATUS_FIFO, 0x00 },
+	{ CDC_RX_EC_ASRC2_CLK_RST_CTL, 0x00 },
+	{ CDC_RX_EC_ASRC2_CTL0, 0x00 },
+	{ CDC_RX_EC_ASRC2_CTL1, 0x00 },
+	{ CDC_RX_EC_ASRC2_FIFO_CTL, 0xA8 },
+	{ CDC_RX_EC_ASRC2_STATUS_FMIN_CNTR_LSB, 0x00 },
+	{ CDC_RX_EC_ASRC2_STATUS_FMIN_CNTR_MSB, 0x00 },
+	{ CDC_RX_EC_ASRC2_STATUS_FMAX_CNTR_LSB, 0x00 },
+	{ CDC_RX_EC_ASRC2_STATUS_FMAX_CNTR_MSB, 0x00 },
+	{ CDC_RX_EC_ASRC2_STATUS_FIFO, 0x00 },
+	{ CDC_RX_DSD0_PATH_CTL, 0x00 },
+	{ CDC_RX_DSD0_CFG0, 0x00 },
+	{ CDC_RX_DSD0_CFG1, 0x62 },
+	{ CDC_RX_DSD0_CFG2, 0x96 },
+	{ CDC_RX_DSD1_PATH_CTL, 0x00 },
+	{ CDC_RX_DSD1_CFG0, 0x00 },
+	{ CDC_RX_DSD1_CFG1, 0x62 },
+	{ CDC_RX_DSD1_CFG2, 0x96 },
+};
+
+static bool rx_is_wronly_register(struct device *dev,
+					unsigned int reg)
+{
+	switch (reg) {
+	case CDC_RX_BCL_VBAT_GAIN_UPD_MON:
+	case CDC_RX_INTR_CTRL_CLR_COMMIT:
+	case CDC_RX_INTR_CTRL_PIN1_CLEAR0:
+	case CDC_RX_INTR_CTRL_PIN2_CLEAR0:
+		return true;
+	}
+
+	return false;
+}
+
+static bool rx_is_volatile_register(struct device *dev, unsigned int reg)
+{
+	/* Update volatile list for rx/tx macros */
+	switch (reg) {
+	case CDC_RX_TOP_HPHL_COMP_RD_LSB:
+	case CDC_RX_TOP_HPHL_COMP_WR_LSB:
+	case CDC_RX_TOP_HPHL_COMP_RD_MSB:
+	case CDC_RX_TOP_HPHL_COMP_WR_MSB:
+	case CDC_RX_TOP_HPHR_COMP_RD_LSB:
+	case CDC_RX_TOP_HPHR_COMP_WR_LSB:
+	case CDC_RX_TOP_HPHR_COMP_RD_MSB:
+	case CDC_RX_TOP_HPHR_COMP_WR_MSB:
+	case CDC_RX_TOP_DSD0_DEBUG_CFG2:
+	case CDC_RX_TOP_DSD1_DEBUG_CFG2:
+	case CDC_RX_BCL_VBAT_GAIN_MON_VAL:
+	case CDC_RX_BCL_VBAT_DECODE_ST:
+	case CDC_RX_INTR_CTRL_PIN1_STATUS0:
+	case CDC_RX_INTR_CTRL_PIN2_STATUS0:
+	case CDC_RX_COMPANDER0_CTL6:
+	case CDC_RX_COMPANDER1_CTL6:
+	case CDC_RX_EC_ASRC0_STATUS_FMIN_CNTR_LSB:
+	case CDC_RX_EC_ASRC0_STATUS_FMIN_CNTR_MSB:
+	case CDC_RX_EC_ASRC0_STATUS_FMAX_CNTR_LSB:
+	case CDC_RX_EC_ASRC0_STATUS_FMAX_CNTR_MSB:
+	case CDC_RX_EC_ASRC0_STATUS_FIFO:
+	case CDC_RX_EC_ASRC1_STATUS_FMIN_CNTR_LSB:
+	case CDC_RX_EC_ASRC1_STATUS_FMIN_CNTR_MSB:
+	case CDC_RX_EC_ASRC1_STATUS_FMAX_CNTR_LSB:
+	case CDC_RX_EC_ASRC1_STATUS_FMAX_CNTR_MSB:
+	case CDC_RX_EC_ASRC1_STATUS_FIFO:
+	case CDC_RX_EC_ASRC2_STATUS_FMIN_CNTR_LSB:
+	case CDC_RX_EC_ASRC2_STATUS_FMIN_CNTR_MSB:
+	case CDC_RX_EC_ASRC2_STATUS_FMAX_CNTR_LSB:
+	case CDC_RX_EC_ASRC2_STATUS_FMAX_CNTR_MSB:
+	case CDC_RX_EC_ASRC2_STATUS_FIFO:
+		return true;
+	}
+	return false;
+}
+
+static bool rx_is_rw_register(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case CDC_RX_TOP_TOP_CFG0:
+	case CDC_RX_TOP_SWR_CTRL:
+	case CDC_RX_TOP_DEBUG:
+	case CDC_RX_TOP_DEBUG_BUS:
+	case CDC_RX_TOP_DEBUG_EN0:
+	case CDC_RX_TOP_DEBUG_EN1:
+	case CDC_RX_TOP_DEBUG_EN2:
+	case CDC_RX_TOP_HPHL_COMP_WR_LSB:
+	case CDC_RX_TOP_HPHL_COMP_WR_MSB:
+	case CDC_RX_TOP_HPHL_COMP_LUT:
+	case CDC_RX_TOP_HPHR_COMP_WR_LSB:
+	case CDC_RX_TOP_HPHR_COMP_WR_MSB:
+	case CDC_RX_TOP_HPHR_COMP_LUT:
+	case CDC_RX_TOP_DSD0_DEBUG_CFG0:
+	case CDC_RX_TOP_DSD0_DEBUG_CFG1:
+	case CDC_RX_TOP_DSD0_DEBUG_CFG3:
+	case CDC_RX_TOP_DSD1_DEBUG_CFG0:
+	case CDC_RX_TOP_DSD1_DEBUG_CFG1:
+	case CDC_RX_TOP_DSD1_DEBUG_CFG3:
+	case CDC_RX_TOP_RX_I2S_CTL:
+	case CDC_RX_TOP_TX_I2S2_CTL:
+	case CDC_RX_TOP_I2S_CLK:
+	case CDC_RX_TOP_I2S_RESET:
+	case CDC_RX_TOP_I2S_MUX:
+	case CDC_RX_CLK_RST_CTRL_MCLK_CONTROL:
+	case CDC_RX_CLK_RST_CTRL_FS_CNT_CONTROL:
+	case CDC_RX_CLK_RST_CTRL_SWR_CONTROL:
+	case CDC_RX_CLK_RST_CTRL_DSD_CONTROL:
+	case CDC_RX_CLK_RST_CTRL_ASRC_SHARE_CONTROL:
+	case CDC_RX_SOFTCLIP_CRC:
+	case CDC_RX_SOFTCLIP_SOFTCLIP_CTRL:
+	case CDC_RX_INP_MUX_RX_INT0_CFG0:
+	case CDC_RX_INP_MUX_RX_INT0_CFG1:
+	case CDC_RX_INP_MUX_RX_INT1_CFG0:
+	case CDC_RX_INP_MUX_RX_INT1_CFG1:
+	case CDC_RX_INP_MUX_RX_INT2_CFG0:
+	case CDC_RX_INP_MUX_RX_INT2_CFG1:
+	case CDC_RX_INP_MUX_RX_MIX_CFG4:
+	case CDC_RX_INP_MUX_RX_MIX_CFG5:
+	case CDC_RX_INP_MUX_SIDETONE_SRC_CFG0:
+	case CDC_RX_CLSH_CRC:
+	case CDC_RX_CLSH_DLY_CTRL:
+	case CDC_RX_CLSH_DECAY_CTRL:
+	case CDC_RX_CLSH_HPH_V_PA:
+	case CDC_RX_CLSH_EAR_V_PA:
+	case CDC_RX_CLSH_HPH_V_HD:
+	case CDC_RX_CLSH_EAR_V_HD:
+	case CDC_RX_CLSH_K1_MSB:
+	case CDC_RX_CLSH_K1_LSB:
+	case CDC_RX_CLSH_K2_MSB:
+	case CDC_RX_CLSH_K2_LSB:
+	case CDC_RX_CLSH_IDLE_CTRL:
+	case CDC_RX_CLSH_IDLE_HPH:
+	case CDC_RX_CLSH_IDLE_EAR:
+	case CDC_RX_CLSH_TEST0:
+	case CDC_RX_CLSH_TEST1:
+	case CDC_RX_CLSH_OVR_VREF:
+	case CDC_RX_CLSH_CLSG_CTL:
+	case CDC_RX_CLSH_CLSG_CFG1:
+	case CDC_RX_CLSH_CLSG_CFG2:
+	case CDC_RX_BCL_VBAT_PATH_CTL:
+	case CDC_RX_BCL_VBAT_CFG:
+	case CDC_RX_BCL_VBAT_ADC_CAL1:
+	case CDC_RX_BCL_VBAT_ADC_CAL2:
+	case CDC_RX_BCL_VBAT_ADC_CAL3:
+	case CDC_RX_BCL_VBAT_PK_EST1:
+	case CDC_RX_BCL_VBAT_PK_EST2:
+	case CDC_RX_BCL_VBAT_PK_EST3:
+	case CDC_RX_BCL_VBAT_RF_PROC1:
+	case CDC_RX_BCL_VBAT_RF_PROC2:
+	case CDC_RX_BCL_VBAT_TAC1:
+	case CDC_RX_BCL_VBAT_TAC2:
+	case CDC_RX_BCL_VBAT_TAC3:
+	case CDC_RX_BCL_VBAT_TAC4:
+	case CDC_RX_BCL_VBAT_GAIN_UPD1:
+	case CDC_RX_BCL_VBAT_GAIN_UPD2:
+	case CDC_RX_BCL_VBAT_GAIN_UPD3:
+	case CDC_RX_BCL_VBAT_GAIN_UPD4:
+	case CDC_RX_BCL_VBAT_GAIN_UPD5:
+	case CDC_RX_BCL_VBAT_DEBUG1:
+	case CDC_RX_BCL_VBAT_BAN:
+	case CDC_RX_BCL_VBAT_BCL_GAIN_UPD1:
+	case CDC_RX_BCL_VBAT_BCL_GAIN_UPD2:
+	case CDC_RX_BCL_VBAT_BCL_GAIN_UPD3:
+	case CDC_RX_BCL_VBAT_BCL_GAIN_UPD4:
+	case CDC_RX_BCL_VBAT_BCL_GAIN_UPD5:
+	case CDC_RX_BCL_VBAT_BCL_GAIN_UPD6:
+	case CDC_RX_BCL_VBAT_BCL_GAIN_UPD7:
+	case CDC_RX_BCL_VBAT_BCL_GAIN_UPD8:
+	case CDC_RX_BCL_VBAT_BCL_GAIN_UPD9:
+	case CDC_RX_BCL_VBAT_ATTN1:
+	case CDC_RX_BCL_VBAT_ATTN2:
+	case CDC_RX_BCL_VBAT_ATTN3:
+	case CDC_RX_BCL_VBAT_DECODE_CTL1:
+	case CDC_RX_BCL_VBAT_DECODE_CTL2:
+	case CDC_RX_BCL_VBAT_DECODE_CFG1:
+	case CDC_RX_BCL_VBAT_DECODE_CFG2:
+	case CDC_RX_BCL_VBAT_DECODE_CFG3:
+	case CDC_RX_BCL_VBAT_DECODE_CFG4:
+	case CDC_RX_INTR_CTRL_CFG:
+	case CDC_RX_INTR_CTRL_PIN1_MASK0:
+	case CDC_RX_INTR_CTRL_PIN2_MASK0:
+	case CDC_RX_INTR_CTRL_LEVEL0:
+	case CDC_RX_INTR_CTRL_BYPASS0:
+	case CDC_RX_INTR_CTRL_SET0:
+	case CDC_RX_RX0_RX_PATH_CTL:
+	case CDC_RX_RX0_RX_PATH_CFG0:
+	case CDC_RX_RX0_RX_PATH_CFG1:
+	case CDC_RX_RX0_RX_PATH_CFG2:
+	case CDC_RX_RX0_RX_PATH_CFG3:
+	case CDC_RX_RX0_RX_VOL_CTL:
+	case CDC_RX_RX0_RX_PATH_MIX_CTL:
+	case CDC_RX_RX0_RX_PATH_MIX_CFG:
+	case CDC_RX_RX0_RX_VOL_MIX_CTL:
+	case CDC_RX_RX0_RX_PATH_SEC1:
+	case CDC_RX_RX0_RX_PATH_SEC2:
+	case CDC_RX_RX0_RX_PATH_SEC3:
+	case CDC_RX_RX0_RX_PATH_SEC4:
+	case CDC_RX_RX0_RX_PATH_SEC7:
+	case CDC_RX_RX0_RX_PATH_MIX_SEC0:
+	case CDC_RX_RX0_RX_PATH_MIX_SEC1:
+	case CDC_RX_RX0_RX_PATH_DSM_CTL:
+	case CDC_RX_RX0_RX_PATH_DSM_DATA1:
+	case CDC_RX_RX0_RX_PATH_DSM_DATA2:
+	case CDC_RX_RX0_RX_PATH_DSM_DATA3:
+	case CDC_RX_RX0_RX_PATH_DSM_DATA4:
+	case CDC_RX_RX0_RX_PATH_DSM_DATA5:
+	case CDC_RX_RX0_RX_PATH_DSM_DATA6:
+	case CDC_RX_RX1_RX_PATH_CTL:
+	case CDC_RX_RX1_RX_PATH_CFG0:
+	case CDC_RX_RX1_RX_PATH_CFG1:
+	case CDC_RX_RX1_RX_PATH_CFG2:
+	case CDC_RX_RX1_RX_PATH_CFG3:
+	case CDC_RX_RX1_RX_VOL_CTL:
+	case CDC_RX_RX1_RX_PATH_MIX_CTL:
+	case CDC_RX_RX1_RX_PATH_MIX_CFG:
+	case CDC_RX_RX1_RX_VOL_MIX_CTL:
+	case CDC_RX_RX1_RX_PATH_SEC1:
+	case CDC_RX_RX1_RX_PATH_SEC2:
+	case CDC_RX_RX1_RX_PATH_SEC3:
+	case CDC_RX_RX1_RX_PATH_SEC4:
+	case CDC_RX_RX1_RX_PATH_SEC7:
+	case CDC_RX_RX1_RX_PATH_MIX_SEC0:
+	case CDC_RX_RX1_RX_PATH_MIX_SEC1:
+	case CDC_RX_RX1_RX_PATH_DSM_CTL:
+	case CDC_RX_RX1_RX_PATH_DSM_DATA1:
+	case CDC_RX_RX1_RX_PATH_DSM_DATA2:
+	case CDC_RX_RX1_RX_PATH_DSM_DATA3:
+	case CDC_RX_RX1_RX_PATH_DSM_DATA4:
+	case CDC_RX_RX1_RX_PATH_DSM_DATA5:
+	case CDC_RX_RX1_RX_PATH_DSM_DATA6:
+	case CDC_RX_RX2_RX_PATH_CTL:
+	case CDC_RX_RX2_RX_PATH_CFG0:
+	case CDC_RX_RX2_RX_PATH_CFG1:
+	case CDC_RX_RX2_RX_PATH_CFG2:
+	case CDC_RX_RX2_RX_PATH_CFG3:
+	case CDC_RX_RX2_RX_VOL_CTL:
+	case CDC_RX_RX2_RX_PATH_MIX_CTL:
+	case CDC_RX_RX2_RX_PATH_MIX_CFG:
+	case CDC_RX_RX2_RX_VOL_MIX_CTL:
+	case CDC_RX_RX2_RX_PATH_SEC0:
+	case CDC_RX_RX2_RX_PATH_SEC1:
+	case CDC_RX_RX2_RX_PATH_SEC2:
+	case CDC_RX_RX2_RX_PATH_SEC3:
+	case CDC_RX_RX2_RX_PATH_SEC4:
+	case CDC_RX_RX2_RX_PATH_SEC5:
+	case CDC_RX_RX2_RX_PATH_SEC6:
+	case CDC_RX_RX2_RX_PATH_SEC7:
+	case CDC_RX_RX2_RX_PATH_MIX_SEC0:
+	case CDC_RX_RX2_RX_PATH_MIX_SEC1:
+	case CDC_RX_RX2_RX_PATH_DSM_CTL:
+	case CDC_RX_IDLE_DETECT_PATH_CTL:
+	case CDC_RX_IDLE_DETECT_CFG0:
+	case CDC_RX_IDLE_DETECT_CFG1:
+	case CDC_RX_IDLE_DETECT_CFG2:
+	case CDC_RX_IDLE_DETECT_CFG3:
+	case CDC_RX_COMPANDER0_CTL0:
+	case CDC_RX_COMPANDER0_CTL1:
+	case CDC_RX_COMPANDER0_CTL2:
+	case CDC_RX_COMPANDER0_CTL3:
+	case CDC_RX_COMPANDER0_CTL4:
+	case CDC_RX_COMPANDER0_CTL5:
+	case CDC_RX_COMPANDER0_CTL7:
+	case CDC_RX_COMPANDER1_CTL0:
+	case CDC_RX_COMPANDER1_CTL1:
+	case CDC_RX_COMPANDER1_CTL2:
+	case CDC_RX_COMPANDER1_CTL3:
+	case CDC_RX_COMPANDER1_CTL4:
+	case CDC_RX_COMPANDER1_CTL5:
+	case CDC_RX_COMPANDER1_CTL7:
+	case CDC_RX_SIDETONE_IIR0_IIR_PATH_CTL:
+	case CDC_RX_SIDETONE_IIR0_IIR_GAIN_B1_CTL:
+	case CDC_RX_SIDETONE_IIR0_IIR_GAIN_B2_CTL:
+	case CDC_RX_SIDETONE_IIR0_IIR_GAIN_B3_CTL:
+	case CDC_RX_SIDETONE_IIR0_IIR_GAIN_B4_CTL:
+	case CDC_RX_SIDETONE_IIR0_IIR_GAIN_B5_CTL:
+	case CDC_RX_SIDETONE_IIR0_IIR_GAIN_B6_CTL:
+	case CDC_RX_SIDETONE_IIR0_IIR_GAIN_B7_CTL:
+	case CDC_RX_SIDETONE_IIR0_IIR_GAIN_B8_CTL:
+	case CDC_RX_SIDETONE_IIR0_IIR_CTL:
+	case CDC_RX_SIDETONE_IIR0_IIR_GAIN_TIMER_CTL:
+	case CDC_RX_SIDETONE_IIR0_IIR_COEF_B1_CTL:
+	case CDC_RX_SIDETONE_IIR0_IIR_COEF_B2_CTL:
+	case CDC_RX_SIDETONE_IIR1_IIR_PATH_CTL:
+	case CDC_RX_SIDETONE_IIR1_IIR_GAIN_B1_CTL:
+	case CDC_RX_SIDETONE_IIR1_IIR_GAIN_B2_CTL:
+	case CDC_RX_SIDETONE_IIR1_IIR_GAIN_B3_CTL:
+	case CDC_RX_SIDETONE_IIR1_IIR_GAIN_B4_CTL:
+	case CDC_RX_SIDETONE_IIR1_IIR_GAIN_B5_CTL:
+	case CDC_RX_SIDETONE_IIR1_IIR_GAIN_B6_CTL:
+	case CDC_RX_SIDETONE_IIR1_IIR_GAIN_B7_CTL:
+	case CDC_RX_SIDETONE_IIR1_IIR_GAIN_B8_CTL:
+	case CDC_RX_SIDETONE_IIR1_IIR_CTL:
+	case CDC_RX_SIDETONE_IIR1_IIR_GAIN_TIMER_CTL:
+	case CDC_RX_SIDETONE_IIR1_IIR_COEF_B1_CTL:
+	case CDC_RX_SIDETONE_IIR1_IIR_COEF_B2_CTL:
+	case CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG0:
+	case CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG1:
+	case CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG2:
+	case CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG3:
+	case CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG0:
+	case CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG1:
+	case CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG2:
+	case CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG3:
+	case CDC_RX_SIDETONE_SRC0_ST_SRC_PATH_CTL:
+	case CDC_RX_SIDETONE_SRC0_ST_SRC_PATH_CFG1:
+	case CDC_RX_SIDETONE_SRC1_ST_SRC_PATH_CTL:
+	case CDC_RX_SIDETONE_SRC1_ST_SRC_PATH_CFG1:
+	case CDC_RX_EC_REF_HQ0_EC_REF_HQ_PATH_CTL:
+	case CDC_RX_EC_REF_HQ0_EC_REF_HQ_CFG0:
+	case CDC_RX_EC_REF_HQ1_EC_REF_HQ_PATH_CTL:
+	case CDC_RX_EC_REF_HQ1_EC_REF_HQ_CFG0:
+	case CDC_RX_EC_REF_HQ2_EC_REF_HQ_PATH_CTL:
+	case CDC_RX_EC_REF_HQ2_EC_REF_HQ_CFG0:
+	case CDC_RX_EC_ASRC0_CLK_RST_CTL:
+	case CDC_RX_EC_ASRC0_CTL0:
+	case CDC_RX_EC_ASRC0_CTL1:
+	case CDC_RX_EC_ASRC0_FIFO_CTL:
+	case CDC_RX_EC_ASRC1_CLK_RST_CTL:
+	case CDC_RX_EC_ASRC1_CTL0:
+	case CDC_RX_EC_ASRC1_CTL1:
+	case CDC_RX_EC_ASRC1_FIFO_CTL:
+	case CDC_RX_EC_ASRC2_CLK_RST_CTL:
+	case CDC_RX_EC_ASRC2_CTL0:
+	case CDC_RX_EC_ASRC2_CTL1:
+	case CDC_RX_EC_ASRC2_FIFO_CTL:
+	case CDC_RX_DSD0_PATH_CTL:
+	case CDC_RX_DSD0_CFG0:
+	case CDC_RX_DSD0_CFG1:
+	case CDC_RX_DSD0_CFG2:
+	case CDC_RX_DSD1_PATH_CTL:
+	case CDC_RX_DSD1_CFG0:
+	case CDC_RX_DSD1_CFG1:
+	case CDC_RX_DSD1_CFG2:
+		return true;
+	}
+
+	return false;
+}
+
+static bool rx_is_writeable_register(struct device *dev, unsigned int reg)
+{
+	bool ret;
+
+	ret = rx_is_rw_register(dev, reg);
+	if (!ret)
+		return rx_is_wronly_register(dev, reg);
+
+	return ret;
+}
+
+static bool rx_is_readable_register(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case CDC_RX_TOP_HPHL_COMP_RD_LSB:
+	case CDC_RX_TOP_HPHL_COMP_RD_MSB:
+	case CDC_RX_TOP_HPHR_COMP_RD_LSB:
+	case CDC_RX_TOP_HPHR_COMP_RD_MSB:
+	case CDC_RX_TOP_DSD0_DEBUG_CFG2:
+	case CDC_RX_TOP_DSD1_DEBUG_CFG2:
+	case CDC_RX_BCL_VBAT_GAIN_MON_VAL:
+	case CDC_RX_BCL_VBAT_DECODE_ST:
+	case CDC_RX_INTR_CTRL_PIN1_STATUS0:
+	case CDC_RX_INTR_CTRL_PIN2_STATUS0:
+	case CDC_RX_COMPANDER0_CTL6:
+	case CDC_RX_COMPANDER1_CTL6:
+	case CDC_RX_EC_ASRC0_STATUS_FMIN_CNTR_LSB:
+	case CDC_RX_EC_ASRC0_STATUS_FMIN_CNTR_MSB:
+	case CDC_RX_EC_ASRC0_STATUS_FMAX_CNTR_LSB:
+	case CDC_RX_EC_ASRC0_STATUS_FMAX_CNTR_MSB:
+	case CDC_RX_EC_ASRC0_STATUS_FIFO:
+	case CDC_RX_EC_ASRC1_STATUS_FMIN_CNTR_LSB:
+	case CDC_RX_EC_ASRC1_STATUS_FMIN_CNTR_MSB:
+	case CDC_RX_EC_ASRC1_STATUS_FMAX_CNTR_LSB:
+	case CDC_RX_EC_ASRC1_STATUS_FMAX_CNTR_MSB:
+	case CDC_RX_EC_ASRC1_STATUS_FIFO:
+	case CDC_RX_EC_ASRC2_STATUS_FMIN_CNTR_LSB:
+	case CDC_RX_EC_ASRC2_STATUS_FMIN_CNTR_MSB:
+	case CDC_RX_EC_ASRC2_STATUS_FMAX_CNTR_LSB:
+	case CDC_RX_EC_ASRC2_STATUS_FMAX_CNTR_MSB:
+	case CDC_RX_EC_ASRC2_STATUS_FIFO:
+		return true;
+	}
+
+	return rx_is_rw_register(dev, reg);
+}
+
+static const struct regmap_config rx_regmap_config = {
+	.name = "rx_macro",
+	.reg_bits = 16,
+	.val_bits = 32, /* 8 but with 32 bit read/write */
+	.reg_stride = 4,
+	.cache_type = REGCACHE_FLAT,
+	.reg_defaults = rx_defaults,
+	.num_reg_defaults = ARRAY_SIZE(rx_defaults),
+	.max_register = RX_MAX_OFFSET,
+	.writeable_reg = rx_is_writeable_register,
+	.volatile_reg = rx_is_volatile_register,
+	.readable_reg = rx_is_readable_register,
+};
+
+static int rx_macro_int_dem_inp_mux_put(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_dapm_widget *widget = snd_soc_dapm_kcontrol_widget(kcontrol);
+	struct snd_soc_component *component = snd_soc_dapm_to_component(widget->dapm);
+	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+	unsigned short look_ahead_dly_reg;
+	unsigned int val;
+
+	val = ucontrol->value.enumerated.item[0];
+
+	if (e->reg == CDC_RX_RX0_RX_PATH_CFG1)
+		look_ahead_dly_reg = CDC_RX_RX0_RX_PATH_CFG0;
+	else if (e->reg == CDC_RX_RX1_RX_PATH_CFG1)
+		look_ahead_dly_reg = CDC_RX_RX1_RX_PATH_CFG0;
+
+	/* Set Look Ahead Delay */
+	if (val)
+		snd_soc_component_update_bits(component, look_ahead_dly_reg,
+					      CDC_RX_DLY_ZN_EN_MASK,
+					      CDC_RX_DLY_ZN_ENABLE);
+	else
+		snd_soc_component_update_bits(component, look_ahead_dly_reg,
+					      CDC_RX_DLY_ZN_EN_MASK, 0);
+	/* Set DEM INP Select */
+	return snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
+}
+
+static const struct snd_kcontrol_new rx_int0_dem_inp_mux =
+		SOC_DAPM_ENUM_EXT("rx_int0_dem_inp", rx_int0_dem_inp_enum,
+		  snd_soc_dapm_get_enum_double, rx_macro_int_dem_inp_mux_put);
+static const struct snd_kcontrol_new rx_int1_dem_inp_mux =
+		SOC_DAPM_ENUM_EXT("rx_int1_dem_inp", rx_int1_dem_inp_enum,
+		  snd_soc_dapm_get_enum_double, rx_macro_int_dem_inp_mux_put);
+
+static int rx_macro_set_prim_interpolator_rate(struct snd_soc_dai *dai,
+					       int rate_reg_val, u32 sample_rate)
+{
+
+	u8 int_1_mix1_inp;
+	u32 j, port;
+	u16 int_mux_cfg0, int_mux_cfg1;
+	u16 int_fs_reg;
+	u8 inp0_sel, inp1_sel, inp2_sel;
+	struct snd_soc_component *component = dai->component;
+	struct rx_macro *rx = snd_soc_component_get_drvdata(component);
+
+	for_each_set_bit(port, &rx->active_ch_mask[dai->id], RX_MACRO_PORTS_MAX) {
+		int_1_mix1_inp = port;
+		int_mux_cfg0 = CDC_RX_INP_MUX_RX_INT0_CFG0;
+		/*
+		 * Loop through all interpolator MUX inputs and find out
+		 * to which interpolator input, the rx port
+		 * is connected
+		 */
+		for (j = 0; j < INTERP_MAX; j++) {
+			int_mux_cfg1 = int_mux_cfg0 + 4;
+
+			inp0_sel = snd_soc_component_read_field(component, int_mux_cfg0,
+								CDC_RX_INTX_1_MIX_INP0_SEL_MASK);
+			inp1_sel = snd_soc_component_read_field(component, int_mux_cfg0,
+								CDC_RX_INTX_1_MIX_INP1_SEL_MASK);
+			inp2_sel = snd_soc_component_read_field(component, int_mux_cfg1,
+								CDC_RX_INTX_1_MIX_INP2_SEL_MASK);
+
+			if ((inp0_sel == int_1_mix1_inp + INTn_1_INP_SEL_RX0) ||
+			    (inp1_sel == int_1_mix1_inp + INTn_1_INP_SEL_RX0) ||
+			    (inp2_sel == int_1_mix1_inp + INTn_1_INP_SEL_RX0)) {
+				int_fs_reg = CDC_RX_RXn_RX_PATH_CTL(j);
+				/* sample_rate is in Hz */
+				snd_soc_component_update_bits(component, int_fs_reg,
+							      CDC_RX_PATH_PCM_RATE_MASK,
+							      rate_reg_val);
+			}
+			int_mux_cfg0 += 8;
+		}
+	}
+
+	return 0;
+}
+
+static int rx_macro_set_mix_interpolator_rate(struct snd_soc_dai *dai,
+					      int rate_reg_val, u32 sample_rate)
+{
+
+	u8 int_2_inp;
+	u32 j, port;
+	u16 int_mux_cfg1, int_fs_reg;
+	u8 int_mux_cfg1_val;
+	struct snd_soc_component *component = dai->component;
+	struct rx_macro *rx = snd_soc_component_get_drvdata(component);
+
+	for_each_set_bit(port, &rx->active_ch_mask[dai->id], RX_MACRO_PORTS_MAX) {
+		int_2_inp = port;
+
+		int_mux_cfg1 = CDC_RX_INP_MUX_RX_INT0_CFG1;
+		for (j = 0; j < INTERP_MAX; j++) {
+			int_mux_cfg1_val = snd_soc_component_read_field(component, int_mux_cfg1,
+									CDC_RX_INTX_2_SEL_MASK);
+
+			if (int_mux_cfg1_val == int_2_inp + INTn_2_INP_SEL_RX0) {
+				int_fs_reg = CDC_RX_RXn_RX_PATH_MIX_CTL(j);
+				snd_soc_component_update_bits(component, int_fs_reg,
+							      CDC_RX_RXn_MIX_PCM_RATE_MASK,
+							      rate_reg_val);
+			}
+			int_mux_cfg1 += 8;
+		}
+	}
+	return 0;
+}
+
+static int rx_macro_set_interpolator_rate(struct snd_soc_dai *dai,
+					  u32 sample_rate)
+{
+	int rate_val = 0;
+	int i, ret;
+
+	for (i = 0; i < ARRAY_SIZE(sr_val_tbl); i++)
+		if (sample_rate == sr_val_tbl[i].sample_rate)
+			rate_val = sr_val_tbl[i].rate_val;
+
+	ret = rx_macro_set_prim_interpolator_rate(dai, rate_val, sample_rate);
+	if (ret)
+		return ret;
+
+	ret = rx_macro_set_mix_interpolator_rate(dai, rate_val, sample_rate);
+	if (ret)
+		return ret;
+
+	return ret;
+}
+
+static int rx_macro_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 rx_macro *rx = snd_soc_component_get_drvdata(component);
+	int ret;
+
+	switch (substream->stream) {
+	case SNDRV_PCM_STREAM_PLAYBACK:
+		ret = rx_macro_set_interpolator_rate(dai, params_rate(params));
+		if (ret) {
+			dev_err(component->dev, "%s: cannot set sample rate: %u\n",
+				__func__, params_rate(params));
+			return ret;
+		}
+		rx->bit_width[dai->id] = params_width(params);
+		break;
+	default:
+		break;
+	}
+	return 0;
+}
+
+static int rx_macro_get_channel_map(struct snd_soc_dai *dai,
+				    unsigned int *tx_num, unsigned int *tx_slot,
+				    unsigned int *rx_num, unsigned int *rx_slot)
+{
+	struct snd_soc_component *component = dai->component;
+	struct rx_macro *rx = snd_soc_component_get_drvdata(component);
+	u16 val, mask = 0, cnt = 0, temp;
+
+	switch (dai->id) {
+	case RX_MACRO_AIF1_PB:
+	case RX_MACRO_AIF2_PB:
+	case RX_MACRO_AIF3_PB:
+	case RX_MACRO_AIF4_PB:
+		for_each_set_bit(temp, &rx->active_ch_mask[dai->id],
+			 RX_MACRO_PORTS_MAX) {
+			mask |= (1 << temp);
+			if (++cnt == RX_MACRO_MAX_DMA_CH_PER_PORT)
+				break;
+		}
+		/*
+		 * CDC_DMA_RX_0 port drives RX0/RX1 -- ch_mask 0x1/0x2/0x3
+		 * CDC_DMA_RX_1 port drives RX2/RX3 -- ch_mask 0x1/0x2/0x3
+		 * CDC_DMA_RX_2 port drives RX4     -- ch_mask 0x1
+		 * CDC_DMA_RX_3 port drives RX5     -- ch_mask 0x1
+		 * AIFn can pair to any CDC_DMA_RX_n port.
+		 * In general, below convention is used::
+		 * CDC_DMA_RX_0(AIF1)/CDC_DMA_RX_1(AIF2)/
+		 * CDC_DMA_RX_2(AIF3)/CDC_DMA_RX_3(AIF4)
+		 */
+		if (mask & 0x0C)
+			mask = mask >> 2;
+		if ((mask & 0x10) || (mask & 0x20))
+			mask = 0x1;
+		*rx_slot = mask;
+		*rx_num = rx->active_ch_cnt[dai->id];
+		break;
+	case RX_MACRO_AIF_ECHO:
+		val = snd_soc_component_read(component,	CDC_RX_INP_MUX_RX_MIX_CFG4);
+		if (val & RX_MACRO_EC_MIX_TX0_MASK) {
+			mask |= 0x1;
+			cnt++;
+		}
+		if (val & RX_MACRO_EC_MIX_TX1_MASK) {
+			mask |= 0x2;
+			cnt++;
+		}
+		val = snd_soc_component_read(component,
+			CDC_RX_INP_MUX_RX_MIX_CFG5);
+		if (val & RX_MACRO_EC_MIX_TX2_MASK) {
+			mask |= 0x4;
+			cnt++;
+		}
+		*tx_slot = mask;
+		*tx_num = cnt;
+		break;
+	default:
+		dev_err(component->dev, "%s: Invalid AIF\n", __func__);
+		break;
+	}
+	return 0;
+}
+
+static int rx_macro_digital_mute(struct snd_soc_dai *dai, int mute, int stream)
+{
+	struct snd_soc_component *component = dai->component;
+	uint16_t j, reg, mix_reg, dsm_reg;
+	u16 int_mux_cfg0, int_mux_cfg1;
+	u8 int_mux_cfg0_val, int_mux_cfg1_val;
+
+	switch (dai->id) {
+	case RX_MACRO_AIF1_PB:
+	case RX_MACRO_AIF2_PB:
+	case RX_MACRO_AIF3_PB:
+	case RX_MACRO_AIF4_PB:
+	for (j = 0; j < INTERP_MAX; j++) {
+		reg = CDC_RX_RXn_RX_PATH_CTL(j);
+		mix_reg = CDC_RX_RXn_RX_PATH_MIX_CTL(j);
+		dsm_reg = CDC_RX_RXn_RX_PATH_DSM_CTL(j);
+
+		if (mute) {
+			snd_soc_component_update_bits(component, reg,
+						      CDC_RX_PATH_PGA_MUTE_MASK,
+						      CDC_RX_PATH_PGA_MUTE_ENABLE);
+			snd_soc_component_update_bits(component, mix_reg,
+						      CDC_RX_PATH_PGA_MUTE_MASK,
+						      CDC_RX_PATH_PGA_MUTE_ENABLE);
+		} else {
+			snd_soc_component_update_bits(component, reg,
+						      CDC_RX_PATH_PGA_MUTE_MASK, 0x0);
+			snd_soc_component_update_bits(component, mix_reg,
+						      CDC_RX_PATH_PGA_MUTE_MASK, 0x0);
+		}
+
+		if (j == INTERP_AUX)
+			dsm_reg = CDC_RX_RX2_RX_PATH_DSM_CTL;
+
+		int_mux_cfg0 = CDC_RX_INP_MUX_RX_INT0_CFG0 + j * 8;
+		int_mux_cfg1 = int_mux_cfg0 + 4;
+		int_mux_cfg0_val = snd_soc_component_read(component, int_mux_cfg0);
+		int_mux_cfg1_val = snd_soc_component_read(component, int_mux_cfg1);
+
+		if (snd_soc_component_read(component, dsm_reg) & 0x01) {
+			if (int_mux_cfg0_val || (int_mux_cfg1_val & 0xF0))
+				snd_soc_component_update_bits(component, reg, 0x20, 0x20);
+			if (int_mux_cfg1_val & 0x0F) {
+				snd_soc_component_update_bits(component, reg, 0x20, 0x20);
+				snd_soc_component_update_bits(component, mix_reg, 0x20, 0x20);
+			}
+		}
+	}
+		break;
+	default:
+		break;
+	}
+	return 0;
+}
+
+static struct snd_soc_dai_ops rx_macro_dai_ops = {
+	.hw_params = rx_macro_hw_params,
+	.get_channel_map = rx_macro_get_channel_map,
+	.mute_stream = rx_macro_digital_mute,
+};
+
+static struct snd_soc_dai_driver rx_macro_dai[] = {
+	{
+		.name = "rx_macro_rx1",
+		.id = RX_MACRO_AIF1_PB,
+		.playback = {
+			.stream_name = "RX_MACRO_AIF1 Playback",
+			.rates = RX_MACRO_RATES | RX_MACRO_FRAC_RATES,
+			.formats = RX_MACRO_FORMATS,
+			.rate_max = 384000,
+			.rate_min = 8000,
+			.channels_min = 1,
+			.channels_max = 2,
+		},
+		.ops = &rx_macro_dai_ops,
+	},
+	{
+		.name = "rx_macro_rx2",
+		.id = RX_MACRO_AIF2_PB,
+		.playback = {
+			.stream_name = "RX_MACRO_AIF2 Playback",
+			.rates = RX_MACRO_RATES | RX_MACRO_FRAC_RATES,
+			.formats = RX_MACRO_FORMATS,
+			.rate_max = 384000,
+			.rate_min = 8000,
+			.channels_min = 1,
+			.channels_max = 2,
+		},
+		.ops = &rx_macro_dai_ops,
+	},
+	{
+		.name = "rx_macro_rx3",
+		.id = RX_MACRO_AIF3_PB,
+		.playback = {
+			.stream_name = "RX_MACRO_AIF3 Playback",
+			.rates = RX_MACRO_RATES | RX_MACRO_FRAC_RATES,
+			.formats = RX_MACRO_FORMATS,
+			.rate_max = 384000,
+			.rate_min = 8000,
+			.channels_min = 1,
+			.channels_max = 2,
+		},
+		.ops = &rx_macro_dai_ops,
+	},
+	{
+		.name = "rx_macro_rx4",
+		.id = RX_MACRO_AIF4_PB,
+		.playback = {
+			.stream_name = "RX_MACRO_AIF4 Playback",
+			.rates = RX_MACRO_RATES | RX_MACRO_FRAC_RATES,
+			.formats = RX_MACRO_FORMATS,
+			.rate_max = 384000,
+			.rate_min = 8000,
+			.channels_min = 1,
+			.channels_max = 2,
+		},
+		.ops = &rx_macro_dai_ops,
+	},
+	{
+		.name = "rx_macro_echo",
+		.id = RX_MACRO_AIF_ECHO,
+		.capture = {
+			.stream_name = "RX_AIF_ECHO Capture",
+			.rates = RX_MACRO_ECHO_RATES,
+			.formats = RX_MACRO_ECHO_FORMATS,
+			.rate_max = 48000,
+			.rate_min = 8000,
+			.channels_min = 1,
+			.channels_max = 3,
+		},
+		.ops = &rx_macro_dai_ops,
+	},
+};
+
+static void rx_macro_mclk_enable(struct rx_macro *rx, bool mclk_enable)
+{
+	struct regmap *regmap = rx->regmap;
+
+	if (mclk_enable) {
+		if (rx->rx_mclk_users == 0) {
+			regmap_update_bits(regmap, CDC_RX_CLK_RST_CTRL_MCLK_CONTROL,
+					   CDC_RX_CLK_MCLK_EN_MASK |
+					   CDC_RX_CLK_MCLK2_EN_MASK,
+					   CDC_RX_CLK_MCLK_ENABLE |
+					   CDC_RX_CLK_MCLK2_ENABLE);
+			regmap_update_bits(regmap, CDC_RX_CLK_RST_CTRL_FS_CNT_CONTROL,
+					   CDC_RX_FS_MCLK_CNT_CLR_MASK, 0x00);
+			regmap_update_bits(regmap, CDC_RX_CLK_RST_CTRL_FS_CNT_CONTROL,
+					   CDC_RX_FS_MCLK_CNT_EN_MASK,
+					   CDC_RX_FS_MCLK_CNT_ENABLE);
+			regcache_mark_dirty(regmap);
+			regcache_sync(regmap);
+		}
+		rx->rx_mclk_users++;
+	} else {
+		if (rx->rx_mclk_users <= 0) {
+			dev_err(rx->dev, "%s: clock already disabled\n", __func__);
+			rx->rx_mclk_users = 0;
+			return;
+		}
+		rx->rx_mclk_users--;
+		if (rx->rx_mclk_users == 0) {
+			regmap_update_bits(regmap, CDC_RX_CLK_RST_CTRL_FS_CNT_CONTROL,
+					   CDC_RX_FS_MCLK_CNT_EN_MASK, 0x0);
+			regmap_update_bits(regmap, CDC_RX_CLK_RST_CTRL_FS_CNT_CONTROL,
+					   CDC_RX_FS_MCLK_CNT_CLR_MASK,
+					   CDC_RX_FS_MCLK_CNT_CLR);
+			regmap_update_bits(regmap, CDC_RX_CLK_RST_CTRL_MCLK_CONTROL,
+					   CDC_RX_CLK_MCLK_EN_MASK |
+					   CDC_RX_CLK_MCLK2_EN_MASK, 0x0);
+		}
+	}
+}
+
+static int rx_macro_mclk_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 rx_macro *rx = snd_soc_component_get_drvdata(component);
+	int ret = 0;
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		rx_macro_mclk_enable(rx, true);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		rx_macro_mclk_enable(rx, false);
+		break;
+	default:
+		dev_err(component->dev, "%s: invalid DAPM event %d\n", __func__, event);
+		ret = -EINVAL;
+	}
+	return ret;
+}
+
+static bool rx_macro_adie_lb(struct snd_soc_component *component,
+			     int interp_idx)
+{
+	u16 int_mux_cfg0, int_mux_cfg1;
+	u8 int_n_inp0, int_n_inp1, int_n_inp2;
+
+	int_mux_cfg0 = CDC_RX_INP_MUX_RX_INT0_CFG0 + interp_idx * 8;
+	int_mux_cfg1 = int_mux_cfg0 + 4;
+
+	int_n_inp0 = snd_soc_component_read_field(component, int_mux_cfg0,
+						  CDC_RX_INTX_1_MIX_INP0_SEL_MASK);
+	int_n_inp1 = snd_soc_component_read_field(component, int_mux_cfg0,
+						  CDC_RX_INTX_1_MIX_INP1_SEL_MASK);
+	int_n_inp2 = snd_soc_component_read_field(component, int_mux_cfg1,
+						  CDC_RX_INTX_1_MIX_INP2_SEL_MASK);
+
+	if (int_n_inp0 == INTn_1_INP_SEL_DEC0 ||
+		int_n_inp0 == INTn_1_INP_SEL_DEC1 ||
+		int_n_inp0 == INTn_1_INP_SEL_IIR0 ||
+		int_n_inp0 == INTn_1_INP_SEL_IIR1)
+		return true;
+
+	if (int_n_inp1 == INTn_1_INP_SEL_DEC0 ||
+		int_n_inp1 == INTn_1_INP_SEL_DEC1 ||
+		int_n_inp1 == INTn_1_INP_SEL_IIR0 ||
+		int_n_inp1 == INTn_1_INP_SEL_IIR1)
+		return true;
+
+	if (int_n_inp2 == INTn_1_INP_SEL_DEC0 ||
+		int_n_inp2 == INTn_1_INP_SEL_DEC1 ||
+		int_n_inp2 == INTn_1_INP_SEL_IIR0 ||
+		int_n_inp2 == INTn_1_INP_SEL_IIR1)
+		return true;
+
+	return false;
+}
+
+static int rx_macro_enable_interp_clk(struct snd_soc_component *component,
+				      int event, int interp_idx);
+static int rx_macro_enable_main_path(struct snd_soc_dapm_widget *w,
+					struct snd_kcontrol *kcontrol,
+					int event)
+{
+	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
+	u16 gain_reg, reg;
+
+	reg = CDC_RX_RXn_RX_PATH_CTL(w->shift);
+	gain_reg = CDC_RX_RXn_RX_VOL_CTL(w->shift);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		rx_macro_enable_interp_clk(component, event, w->shift);
+		if (rx_macro_adie_lb(component, w->shift))
+			snd_soc_component_update_bits(component, reg,
+						      CDC_RX_PATH_CLK_EN_MASK,
+						      CDC_RX_PATH_CLK_ENABLE);
+		break;
+	case SND_SOC_DAPM_POST_PMU:
+		snd_soc_component_write(component, gain_reg,
+			snd_soc_component_read(component, gain_reg));
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		rx_macro_enable_interp_clk(component, event, w->shift);
+		break;
+	}
+
+	return 0;
+}
+
+static int rx_macro_config_compander(struct snd_soc_component *component,
+				struct rx_macro *rx,
+				int comp, int event)
+{
+	u8 pcm_rate, val;
+
+	/* AUX does not have compander */
+	if (comp == INTERP_AUX)
+		return 0;
+
+	pcm_rate = snd_soc_component_read(component, CDC_RX_RXn_RX_PATH_CTL(comp)) & 0x0F;
+	if (pcm_rate < 0x06)
+		val = 0x03;
+	else if (pcm_rate < 0x08)
+		val = 0x01;
+	else if (pcm_rate < 0x0B)
+		val = 0x02;
+	else
+		val = 0x00;
+
+	if (SND_SOC_DAPM_EVENT_ON(event))
+		snd_soc_component_update_bits(component, CDC_RX_RXn_RX_PATH_CFG3(comp),
+					      CDC_RX_DC_COEFF_SEL_MASK, val);
+
+	if (SND_SOC_DAPM_EVENT_OFF(event))
+		snd_soc_component_update_bits(component, CDC_RX_RXn_RX_PATH_CFG3(comp),
+					      CDC_RX_DC_COEFF_SEL_MASK, 0x3);
+	if (!rx->comp_enabled[comp])
+		return 0;
+
+	if (SND_SOC_DAPM_EVENT_ON(event)) {
+		/* Enable Compander Clock */
+		snd_soc_component_write_field(component, CDC_RX_COMPANDERn_CTL0(comp),
+					      CDC_RX_COMPANDERn_CLK_EN_MASK, 0x1);
+		snd_soc_component_write_field(component, CDC_RX_COMPANDERn_CTL0(comp),
+					      CDC_RX_COMPANDERn_SOFT_RST_MASK, 0x1);
+		snd_soc_component_write_field(component, CDC_RX_COMPANDERn_CTL0(comp),
+					      CDC_RX_COMPANDERn_SOFT_RST_MASK, 0x0);
+		snd_soc_component_write_field(component, CDC_RX_RXn_RX_PATH_CFG0(comp),
+					      CDC_RX_RXn_COMP_EN_MASK, 0x1);
+	}
+
+	if (SND_SOC_DAPM_EVENT_OFF(event)) {
+		snd_soc_component_write_field(component, CDC_RX_COMPANDERn_CTL0(comp),
+					      CDC_RX_COMPANDERn_HALT_MASK, 0x1);
+		snd_soc_component_write_field(component, CDC_RX_RXn_RX_PATH_CFG0(comp),
+					      CDC_RX_RXn_COMP_EN_MASK, 0x0);
+		snd_soc_component_write_field(component, CDC_RX_COMPANDERn_CTL0(comp),
+					      CDC_RX_COMPANDERn_CLK_EN_MASK, 0x0);
+		snd_soc_component_write_field(component, CDC_RX_COMPANDERn_CTL0(comp),
+					      CDC_RX_COMPANDERn_HALT_MASK, 0x0);
+	}
+
+	return 0;
+}
+
+static int rx_macro_load_compander_coeff(struct snd_soc_component *component,
+					 struct rx_macro *rx,
+					 int comp, int event)
+{
+	u16 comp_coeff_lsb_reg, comp_coeff_msb_reg;
+	int i;
+	int hph_pwr_mode = HPH_LOHIFI;
+
+	if (!rx->comp_enabled[comp])
+		return 0;
+
+	if (comp == INTERP_HPHL) {
+		comp_coeff_lsb_reg = CDC_RX_TOP_HPHL_COMP_WR_LSB;
+		comp_coeff_msb_reg = CDC_RX_TOP_HPHL_COMP_WR_MSB;
+	} else if (comp == INTERP_HPHR) {
+		comp_coeff_lsb_reg = CDC_RX_TOP_HPHR_COMP_WR_LSB;
+		comp_coeff_msb_reg = CDC_RX_TOP_HPHR_COMP_WR_MSB;
+	} else {
+		/* compander coefficients are loaded only for hph path */
+		return 0;
+	}
+
+	hph_pwr_mode = rx->hph_pwr_mode;
+
+	if (SND_SOC_DAPM_EVENT_ON(event)) {
+		/* Load Compander Coeff */
+		for (i = 0; i < COMP_MAX_COEFF; i++) {
+			snd_soc_component_write(component, comp_coeff_lsb_reg,
+					comp_coeff_table[hph_pwr_mode][i].lsb);
+			snd_soc_component_write(component, comp_coeff_msb_reg,
+					comp_coeff_table[hph_pwr_mode][i].msb);
+		}
+	}
+
+	return 0;
+}
+
+static void rx_macro_enable_softclip_clk(struct snd_soc_component *component,
+					 struct rx_macro *rx, bool enable)
+{
+	if (enable) {
+		if (rx->softclip_clk_users == 0)
+			snd_soc_component_write_field(component, CDC_RX_SOFTCLIP_CRC,
+						      CDC_RX_SOFTCLIP_CLK_EN_MASK, 1);
+		rx->softclip_clk_users++;
+	} else {
+		rx->softclip_clk_users--;
+		if (rx->softclip_clk_users == 0)
+			snd_soc_component_write_field(component, CDC_RX_SOFTCLIP_CRC,
+						      CDC_RX_SOFTCLIP_CLK_EN_MASK, 0);
+	}
+}
+
+static int rx_macro_config_softclip(struct snd_soc_component *component,
+				    struct rx_macro *rx, int event)
+{
+
+	if (!rx->is_softclip_on)
+		return 0;
+
+	if (SND_SOC_DAPM_EVENT_ON(event)) {
+		/* Enable Softclip clock */
+		rx_macro_enable_softclip_clk(component, rx, true);
+		/* Enable Softclip control */
+		snd_soc_component_write_field(component, CDC_RX_SOFTCLIP_SOFTCLIP_CTRL,
+					     CDC_RX_SOFTCLIP_EN_MASK, 0x01);
+	}
+
+	if (SND_SOC_DAPM_EVENT_OFF(event)) {
+		snd_soc_component_write_field(component, CDC_RX_SOFTCLIP_SOFTCLIP_CTRL,
+					     CDC_RX_SOFTCLIP_EN_MASK, 0x0);
+		rx_macro_enable_softclip_clk(component, rx, false);
+	}
+
+	return 0;
+}
+
+static int rx_macro_config_aux_hpf(struct snd_soc_component *component,
+				   struct rx_macro *rx, int event)
+{
+	if (SND_SOC_DAPM_EVENT_ON(event)) {
+		/* Update Aux HPF control */
+		if (!rx->is_aux_hpf_on)
+			snd_soc_component_update_bits(component,
+				CDC_RX_RX2_RX_PATH_CFG1, 0x04, 0x00);
+	}
+
+	if (SND_SOC_DAPM_EVENT_OFF(event)) {
+		/* Reset to default (HPF=ON) */
+		snd_soc_component_update_bits(component,
+			CDC_RX_RX2_RX_PATH_CFG1, 0x04, 0x04);
+	}
+
+	return 0;
+}
+
+static inline void rx_macro_enable_clsh_block(struct rx_macro *rx, bool enable)
+{
+	if ((enable && ++rx->clsh_users == 1) || (!enable && --rx->clsh_users == 0))
+		snd_soc_component_update_bits(rx->component, CDC_RX_CLSH_CRC,
+					     CDC_RX_CLSH_CLK_EN_MASK, enable);
+	if (rx->clsh_users < 0)
+		rx->clsh_users = 0;
+}
+
+static int rx_macro_config_classh(struct snd_soc_component *component,
+				struct rx_macro *rx,
+				int interp_n, int event)
+{
+	if (SND_SOC_DAPM_EVENT_OFF(event)) {
+		rx_macro_enable_clsh_block(rx, false);
+		return 0;
+	}
+
+	if (!SND_SOC_DAPM_EVENT_ON(event))
+		return 0;
+
+	rx_macro_enable_clsh_block(rx, true);
+	if (interp_n == INTERP_HPHL ||
+		interp_n == INTERP_HPHR) {
+		/*
+		 * These K1 values depend on the Headphone Impedance
+		 * For now it is assumed to be 16 ohm
+		 */
+		snd_soc_component_write(component, CDC_RX_CLSH_K1_LSB, 0xc0);
+		snd_soc_component_write_field(component, CDC_RX_CLSH_K1_MSB,
+					      CDC_RX_CLSH_K1_MSB_COEFF_MASK, 0);
+	}
+	switch (interp_n) {
+	case INTERP_HPHL:
+		if (rx->is_ear_mode_on)
+			snd_soc_component_update_bits(component,
+				CDC_RX_CLSH_HPH_V_PA,
+				CDC_RX_CLSH_HPH_V_PA_MIN_MASK, 0x39);
+		else
+			snd_soc_component_update_bits(component,
+				CDC_RX_CLSH_HPH_V_PA,
+				CDC_RX_CLSH_HPH_V_PA_MIN_MASK, 0x1c);
+		snd_soc_component_update_bits(component,
+				CDC_RX_CLSH_DECAY_CTRL,
+				CDC_RX_CLSH_DECAY_RATE_MASK, 0x0);
+		snd_soc_component_write_field(component,
+				CDC_RX_RX0_RX_PATH_CFG0,
+				CDC_RX_RXn_CLSH_EN_MASK, 0x1);
+		break;
+	case INTERP_HPHR:
+		if (rx->is_ear_mode_on)
+			snd_soc_component_update_bits(component,
+				CDC_RX_CLSH_HPH_V_PA,
+				CDC_RX_CLSH_HPH_V_PA_MIN_MASK, 0x39);
+		else
+			snd_soc_component_update_bits(component,
+				CDC_RX_CLSH_HPH_V_PA,
+				CDC_RX_CLSH_HPH_V_PA_MIN_MASK, 0x1c);
+		snd_soc_component_update_bits(component,
+				CDC_RX_CLSH_DECAY_CTRL,
+				CDC_RX_CLSH_DECAY_RATE_MASK, 0x0);
+		snd_soc_component_update_bits(component,
+				CDC_RX_RX1_RX_PATH_CFG0,
+				CDC_RX_RXn_CLSH_EN_MASK, 0x1);
+		break;
+	case INTERP_AUX:
+		snd_soc_component_update_bits(component,
+				CDC_RX_RX2_RX_PATH_CFG0,
+				CDC_RX_RX2_DLY_Z_EN_MASK, 1);
+		snd_soc_component_write_field(component,
+				CDC_RX_RX2_RX_PATH_CFG0,
+				CDC_RX_RX2_CLSH_EN_MASK, 1);
+		break;
+	}
+
+	return 0;
+}
+
+static void rx_macro_hd2_control(struct snd_soc_component *component,
+				 u16 interp_idx, int event)
+{
+	u16 hd2_scale_reg, hd2_enable_reg;
+
+	switch (interp_idx) {
+	case INTERP_HPHL:
+		hd2_scale_reg = CDC_RX_RX0_RX_PATH_SEC3;
+		hd2_enable_reg = CDC_RX_RX0_RX_PATH_CFG0;
+		break;
+	case INTERP_HPHR:
+		hd2_scale_reg = CDC_RX_RX1_RX_PATH_SEC3;
+		hd2_enable_reg = CDC_RX_RX1_RX_PATH_CFG0;
+		break;
+	}
+
+	if (hd2_enable_reg && SND_SOC_DAPM_EVENT_ON(event)) {
+		snd_soc_component_update_bits(component, hd2_scale_reg,
+				CDC_RX_RXn_HD2_ALPHA_MASK, 0x14);
+		snd_soc_component_write_field(component, hd2_enable_reg,
+					      CDC_RX_RXn_HD2_EN_MASK, 1);
+	}
+
+	if (hd2_enable_reg && SND_SOC_DAPM_EVENT_OFF(event)) {
+		snd_soc_component_write_field(component, hd2_enable_reg,
+					      CDC_RX_RXn_HD2_EN_MASK, 0);
+		snd_soc_component_update_bits(component, hd2_scale_reg,
+				CDC_RX_RXn_HD2_ALPHA_MASK, 0x0);
+	}
+}
+
+static int rx_macro_get_compander(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+	int comp = ((struct soc_mixer_control *) kcontrol->private_value)->shift;
+	struct rx_macro *rx = snd_soc_component_get_drvdata(component);
+
+	ucontrol->value.integer.value[0] = rx->comp_enabled[comp];
+	return 0;
+}
+
+static int rx_macro_set_compander(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
+	int comp = ((struct soc_mixer_control *)  kcontrol->private_value)->shift;
+	int value = ucontrol->value.integer.value[0];
+	struct rx_macro *rx = snd_soc_component_get_drvdata(component);
+
+	rx->comp_enabled[comp] = value;
+
+	return 0;
+}
+
+static int rx_macro_mux_get(struct snd_kcontrol *kcontrol,
+			  struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_dapm_widget *widget = snd_soc_dapm_kcontrol_widget(kcontrol);
+	struct snd_soc_component *component = snd_soc_dapm_to_component(widget->dapm);
+	struct rx_macro *rx = snd_soc_component_get_drvdata(component);
+
+	ucontrol->value.integer.value[0] =
+			rx->rx_port_value[widget->shift];
+	return 0;
+}
+
+static int rx_macro_mux_put(struct snd_kcontrol *kcontrol,
+			    struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_dapm_widget *widget = snd_soc_dapm_kcontrol_widget(kcontrol);
+	struct snd_soc_component *component = snd_soc_dapm_to_component(widget->dapm);
+	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+	struct snd_soc_dapm_update *update = NULL;
+	u32 rx_port_value = ucontrol->value.integer.value[0];
+	u32 aif_rst;
+	struct rx_macro *rx = snd_soc_component_get_drvdata(component);
+
+	aif_rst = rx->rx_port_value[widget->shift];
+	if (!rx_port_value) {
+		if (aif_rst == 0) {
+			dev_err(component->dev, "%s:AIF reset already\n", __func__);
+			return 0;
+		}
+		if (aif_rst > RX_MACRO_AIF4_PB) {
+			dev_err(component->dev, "%s: Invalid AIF reset\n", __func__);
+			return 0;
+		}
+	}
+	rx->rx_port_value[widget->shift] = rx_port_value;
+
+	switch (rx_port_value) {
+	case 0:
+		if (rx->active_ch_cnt[aif_rst]) {
+			clear_bit(widget->shift,
+				&rx->active_ch_mask[aif_rst]);
+			rx->active_ch_cnt[aif_rst]--;
+		}
+		break;
+	case 1:
+	case 2:
+	case 3:
+	case 4:
+		set_bit(widget->shift,
+			&rx->active_ch_mask[rx_port_value]);
+		rx->active_ch_cnt[rx_port_value]++;
+		break;
+	default:
+		dev_err(component->dev,
+			"%s:Invalid AIF_ID for RX_MACRO MUX %d\n",
+			__func__, rx_port_value);
+		goto err;
+	}
+
+	snd_soc_dapm_mux_update_power(widget->dapm, kcontrol,
+					rx_port_value, e, update);
+	return 0;
+err:
+	return -EINVAL;
+}
+
+static const struct snd_kcontrol_new rx_macro_rx0_mux =
+		SOC_DAPM_ENUM_EXT("rx_macro_rx0", rx_macro_rx0_enum,
+		  rx_macro_mux_get, rx_macro_mux_put);
+static const struct snd_kcontrol_new rx_macro_rx1_mux =
+		SOC_DAPM_ENUM_EXT("rx_macro_rx1", rx_macro_rx1_enum,
+		  rx_macro_mux_get, rx_macro_mux_put);
+static const struct snd_kcontrol_new rx_macro_rx2_mux =
+		SOC_DAPM_ENUM_EXT("rx_macro_rx2", rx_macro_rx2_enum,
+		  rx_macro_mux_get, rx_macro_mux_put);
+static const struct snd_kcontrol_new rx_macro_rx3_mux =
+		SOC_DAPM_ENUM_EXT("rx_macro_rx3", rx_macro_rx3_enum,
+		  rx_macro_mux_get, rx_macro_mux_put);
+static const struct snd_kcontrol_new rx_macro_rx4_mux =
+		SOC_DAPM_ENUM_EXT("rx_macro_rx4", rx_macro_rx4_enum,
+		  rx_macro_mux_get, rx_macro_mux_put);
+static const struct snd_kcontrol_new rx_macro_rx5_mux =
+		SOC_DAPM_ENUM_EXT("rx_macro_rx5", rx_macro_rx5_enum,
+		  rx_macro_mux_get, rx_macro_mux_put);
+
+static int rx_macro_get_ear_mode(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
+	struct rx_macro *rx = snd_soc_component_get_drvdata(component);
+
+	ucontrol->value.integer.value[0] = rx->is_ear_mode_on;
+	return 0;
+}
+
+static int rx_macro_put_ear_mode(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
+	struct rx_macro *rx = snd_soc_component_get_drvdata(component);
+
+	rx->is_ear_mode_on = (!ucontrol->value.integer.value[0] ? false : true);
+	return 0;
+}
+
+static int rx_macro_get_hph_hd2_mode(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
+	struct rx_macro *rx = snd_soc_component_get_drvdata(component);
+
+	ucontrol->value.integer.value[0] = rx->hph_hd2_mode;
+	return 0;
+}
+
+static int rx_macro_put_hph_hd2_mode(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
+	struct rx_macro *rx = snd_soc_component_get_drvdata(component);
+
+	rx->hph_hd2_mode = ucontrol->value.integer.value[0];
+	return 0;
+}
+
+static int rx_macro_get_hph_pwr_mode(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
+	struct rx_macro *rx = snd_soc_component_get_drvdata(component);
+
+	ucontrol->value.integer.value[0] = rx->hph_pwr_mode;
+	return 0;
+}
+
+static int rx_macro_put_hph_pwr_mode(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
+	struct rx_macro *rx = snd_soc_component_get_drvdata(component);
+
+	rx->hph_pwr_mode = ucontrol->value.integer.value[0];
+	return 0;
+}
+
+static int rx_macro_soft_clip_enable_get(struct snd_kcontrol *kcontrol,
+					  struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
+	struct rx_macro *rx = snd_soc_component_get_drvdata(component);
+
+	ucontrol->value.integer.value[0] = rx->is_softclip_on;
+
+	return 0;
+}
+
+static int rx_macro_soft_clip_enable_put(struct snd_kcontrol *kcontrol,
+					  struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
+	struct rx_macro *rx = snd_soc_component_get_drvdata(component);
+
+	rx->is_softclip_on = ucontrol->value.integer.value[0];
+
+	return 0;
+}
+
+static int rx_macro_aux_hpf_mode_get(struct snd_kcontrol *kcontrol,
+					  struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
+	struct rx_macro *rx = snd_soc_component_get_drvdata(component);
+
+	ucontrol->value.integer.value[0] = rx->is_aux_hpf_on;
+
+	return 0;
+}
+
+static int rx_macro_aux_hpf_mode_put(struct snd_kcontrol *kcontrol,
+					  struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
+	struct rx_macro *rx = snd_soc_component_get_drvdata(component);
+
+	rx->is_aux_hpf_on = ucontrol->value.integer.value[0];
+
+	return 0;
+}
+
+static int rx_macro_hphdelay_lutbypass(struct snd_soc_component *component,
+					struct rx_macro *rx,
+					u16 interp_idx, int event)
+{
+	u16 hph_lut_bypass_reg;
+	u16 hph_comp_ctrl7;
+
+	switch (interp_idx) {
+	case INTERP_HPHL:
+		hph_lut_bypass_reg = CDC_RX_TOP_HPHL_COMP_LUT;
+		hph_comp_ctrl7 = CDC_RX_COMPANDER0_CTL7;
+		break;
+	case INTERP_HPHR:
+		hph_lut_bypass_reg = CDC_RX_TOP_HPHR_COMP_LUT;
+		hph_comp_ctrl7 = CDC_RX_COMPANDER1_CTL7;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (hph_lut_bypass_reg && SND_SOC_DAPM_EVENT_ON(event)) {
+		if (interp_idx == INTERP_HPHL) {
+			if (rx->is_ear_mode_on)
+				snd_soc_component_write_field(component,
+					CDC_RX_RX0_RX_PATH_CFG1,
+					CDC_RX_RX0_HPH_L_EAR_SEL_MASK, 0x1);
+			else
+				snd_soc_component_write_field(component,
+					hph_lut_bypass_reg,
+					CDC_RX_TOP_HPH_LUT_BYPASS_MASK, 1);
+		} else {
+			snd_soc_component_write_field(component, hph_lut_bypass_reg,
+					CDC_RX_TOP_HPH_LUT_BYPASS_MASK, 1);
+		}
+		if (rx->hph_pwr_mode)
+			snd_soc_component_write_field(component, hph_comp_ctrl7,
+					CDC_RX_COMPANDER1_HPH_LOW_PWR_MODE_MASK, 0x0);
+	}
+
+	if (hph_lut_bypass_reg && SND_SOC_DAPM_EVENT_OFF(event)) {
+		snd_soc_component_write_field(component,
+					CDC_RX_RX0_RX_PATH_CFG1,
+					CDC_RX_RX0_HPH_L_EAR_SEL_MASK, 0x0);
+		snd_soc_component_update_bits(component, hph_lut_bypass_reg,
+					CDC_RX_TOP_HPH_LUT_BYPASS_MASK, 0);
+		snd_soc_component_write_field(component, hph_comp_ctrl7,
+					CDC_RX_COMPANDER1_HPH_LOW_PWR_MODE_MASK, 0x1);
+	}
+
+	return 0;
+}
+
+static int rx_macro_enable_interp_clk(struct snd_soc_component *component,
+				      int event, int interp_idx)
+{
+	u16 main_reg, dsm_reg, rx_cfg2_reg;
+	struct rx_macro *rx = snd_soc_component_get_drvdata(component);
+
+	main_reg = CDC_RX_RXn_RX_PATH_CTL(interp_idx);
+	dsm_reg = CDC_RX_RXn_RX_PATH_DSM_CTL(interp_idx);
+	if (interp_idx == INTERP_AUX)
+		dsm_reg = CDC_RX_RX2_RX_PATH_DSM_CTL;
+	rx_cfg2_reg = CDC_RX_RXn_RX_PATH_CFG2(interp_idx);
+
+	if (SND_SOC_DAPM_EVENT_ON(event)) {
+		if (rx->main_clk_users[interp_idx] == 0) {
+			/* Main path PGA mute enable */
+			snd_soc_component_write_field(component, main_reg,
+						      CDC_RX_PATH_PGA_MUTE_MASK, 0x1);
+			snd_soc_component_write_field(component, dsm_reg,
+						      CDC_RX_RXn_DSM_CLK_EN_MASK, 0x1);
+			snd_soc_component_update_bits(component, rx_cfg2_reg,
+					CDC_RX_RXn_HPF_CUT_FREQ_MASK, 0x03);
+			rx_macro_load_compander_coeff(component, rx, interp_idx, event);
+			if (rx->hph_hd2_mode)
+				rx_macro_hd2_control(component, interp_idx, event);
+			rx_macro_hphdelay_lutbypass(component, rx, interp_idx, event);
+			rx_macro_config_compander(component, rx, interp_idx, event);
+			if (interp_idx == INTERP_AUX) {
+				rx_macro_config_softclip(component, rx,	event);
+				rx_macro_config_aux_hpf(component, rx, event);
+			}
+			rx_macro_config_classh(component, rx, interp_idx, event);
+		}
+		rx->main_clk_users[interp_idx]++;
+	}
+
+	if (SND_SOC_DAPM_EVENT_OFF(event)) {
+		rx->main_clk_users[interp_idx]--;
+		if (rx->main_clk_users[interp_idx] <= 0) {
+			rx->main_clk_users[interp_idx] = 0;
+			/* Main path PGA mute enable */
+			snd_soc_component_write_field(component, main_reg,
+						      CDC_RX_PATH_PGA_MUTE_MASK, 0x1);
+			/* Clk Disable */
+			snd_soc_component_write_field(component, dsm_reg,
+						      CDC_RX_RXn_DSM_CLK_EN_MASK, 0);
+			snd_soc_component_write_field(component, main_reg,
+						      CDC_RX_PATH_CLK_EN_MASK, 0);
+			/* Reset enable and disable */
+			snd_soc_component_write_field(component, main_reg,
+						      CDC_RX_PATH_RESET_EN_MASK, 1);
+			snd_soc_component_write_field(component, main_reg,
+						      CDC_RX_PATH_RESET_EN_MASK, 0);
+			/* Reset rate to 48K*/
+			snd_soc_component_update_bits(component, main_reg,
+						      CDC_RX_PATH_PCM_RATE_MASK,
+						      0x04);
+			snd_soc_component_update_bits(component, rx_cfg2_reg,
+						      CDC_RX_RXn_HPF_CUT_FREQ_MASK, 0x00);
+			rx_macro_config_classh(component, rx, interp_idx, event);
+			rx_macro_config_compander(component, rx, interp_idx, event);
+			if (interp_idx ==  INTERP_AUX) {
+				rx_macro_config_softclip(component, rx,	event);
+				rx_macro_config_aux_hpf(component, rx, event);
+			}
+			rx_macro_hphdelay_lutbypass(component, rx, interp_idx, event);
+			if (rx->hph_hd2_mode)
+				rx_macro_hd2_control(component, interp_idx, event);
+		}
+	}
+
+	return rx->main_clk_users[interp_idx];
+}
+
+static int rx_macro_enable_mix_path(struct snd_soc_dapm_widget *w,
+				    struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
+	u16 gain_reg, mix_reg;
+
+	gain_reg = CDC_RX_RXn_RX_VOL_MIX_CTL(w->shift);
+	mix_reg = CDC_RX_RXn_RX_PATH_MIX_CTL(w->shift);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		rx_macro_enable_interp_clk(component, event, w->shift);
+		break;
+	case SND_SOC_DAPM_POST_PMU:
+		snd_soc_component_write(component, gain_reg,
+					snd_soc_component_read(component, gain_reg));
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		/* Clk Disable */
+		snd_soc_component_update_bits(component, mix_reg,
+					      CDC_RX_RXn_MIX_CLK_EN_MASK, 0x00);
+		rx_macro_enable_interp_clk(component, event, w->shift);
+		/* Reset enable and disable */
+		snd_soc_component_update_bits(component, mix_reg,
+					      CDC_RX_RXn_MIX_RESET_MASK,
+					      CDC_RX_RXn_MIX_RESET);
+		snd_soc_component_update_bits(component, mix_reg,
+					      CDC_RX_RXn_MIX_RESET_MASK, 0x00);
+		break;
+	}
+
+	return 0;
+}
+
+static int rx_macro_enable_rx_path_clk(struct snd_soc_dapm_widget *w,
+				       struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		rx_macro_enable_interp_clk(component, event, w->shift);
+		snd_soc_component_write_field(component, CDC_RX_RXn_RX_PATH_CFG1(w->shift),
+					      CDC_RX_RXn_SIDETONE_EN_MASK, 1);
+		snd_soc_component_write_field(component, CDC_RX_RXn_RX_PATH_CTL(w->shift),
+					      CDC_RX_PATH_CLK_EN_MASK, 1);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		snd_soc_component_write_field(component, CDC_RX_RXn_RX_PATH_CFG1(w->shift),
+					      CDC_RX_RXn_SIDETONE_EN_MASK, 0);
+		rx_macro_enable_interp_clk(component, event, w->shift);
+		break;
+	default:
+		break;
+	};
+	return 0;
+}
+
+static int rx_macro_set_iir_gain(struct snd_soc_dapm_widget *w,
+				 struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
+
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMU: /* fall through */
+	case SND_SOC_DAPM_PRE_PMD:
+		if (strnstr(w->name, "IIR0", sizeof("IIR0"))) {
+			snd_soc_component_write(component,
+				CDC_RX_SIDETONE_IIR0_IIR_GAIN_B1_CTL,
+			snd_soc_component_read(component,
+				CDC_RX_SIDETONE_IIR0_IIR_GAIN_B1_CTL));
+			snd_soc_component_write(component,
+				CDC_RX_SIDETONE_IIR0_IIR_GAIN_B2_CTL,
+			snd_soc_component_read(component,
+				CDC_RX_SIDETONE_IIR0_IIR_GAIN_B2_CTL));
+			snd_soc_component_write(component,
+				CDC_RX_SIDETONE_IIR0_IIR_GAIN_B3_CTL,
+			snd_soc_component_read(component,
+				CDC_RX_SIDETONE_IIR0_IIR_GAIN_B3_CTL));
+			snd_soc_component_write(component,
+				CDC_RX_SIDETONE_IIR0_IIR_GAIN_B4_CTL,
+			snd_soc_component_read(component,
+				CDC_RX_SIDETONE_IIR0_IIR_GAIN_B4_CTL));
+		} else {
+			snd_soc_component_write(component,
+				CDC_RX_SIDETONE_IIR1_IIR_GAIN_B1_CTL,
+			snd_soc_component_read(component,
+				CDC_RX_SIDETONE_IIR1_IIR_GAIN_B1_CTL));
+			snd_soc_component_write(component,
+				CDC_RX_SIDETONE_IIR1_IIR_GAIN_B2_CTL,
+			snd_soc_component_read(component,
+				CDC_RX_SIDETONE_IIR1_IIR_GAIN_B2_CTL));
+			snd_soc_component_write(component,
+				CDC_RX_SIDETONE_IIR1_IIR_GAIN_B3_CTL,
+			snd_soc_component_read(component,
+				CDC_RX_SIDETONE_IIR1_IIR_GAIN_B3_CTL));
+			snd_soc_component_write(component,
+				CDC_RX_SIDETONE_IIR1_IIR_GAIN_B4_CTL,
+			snd_soc_component_read(component,
+				CDC_RX_SIDETONE_IIR1_IIR_GAIN_B4_CTL));
+		}
+		break;
+	}
+	return 0;
+}
+
+static uint32_t get_iir_band_coeff(struct snd_soc_component *component,
+				   int iir_idx, int band_idx, int coeff_idx)
+{
+	u32 value;
+	int reg, b2_reg;
+
+	/* Address does not automatically update if reading */
+	reg = CDC_RX_SIDETONE_IIR0_IIR_COEF_B1_CTL + 16 * iir_idx;
+	b2_reg = CDC_RX_SIDETONE_IIR0_IIR_COEF_B2_CTL + 16 * iir_idx;
+
+	snd_soc_component_write(component, reg,
+				((band_idx * BAND_MAX + coeff_idx) *
+				 sizeof(uint32_t)) & 0x7F);
+
+	value = snd_soc_component_read(component, b2_reg);
+	snd_soc_component_write(component, reg,
+				((band_idx * BAND_MAX + coeff_idx)
+				 * sizeof(uint32_t) + 1) & 0x7F);
+
+	value |= (snd_soc_component_read(component, b2_reg) << 8);
+	snd_soc_component_write(component, reg,
+				((band_idx * BAND_MAX + coeff_idx)
+				 * sizeof(uint32_t) + 2) & 0x7F);
+
+	value |= (snd_soc_component_read(component, b2_reg) << 16);
+	snd_soc_component_write(component, reg,
+		((band_idx * BAND_MAX + coeff_idx)
+		* sizeof(uint32_t) + 3) & 0x7F);
+
+	/* Mask bits top 2 bits since they are reserved */
+	value |= (snd_soc_component_read(component, b2_reg) << 24);
+	return value;
+}
+
+static void set_iir_band_coeff(struct snd_soc_component *component,
+			       int iir_idx, int band_idx, uint32_t value)
+{
+	int reg = CDC_RX_SIDETONE_IIR0_IIR_COEF_B2_CTL + 16 * iir_idx;
+
+	snd_soc_component_write(component, reg, (value & 0xFF));
+	snd_soc_component_write(component, reg, (value >> 8) & 0xFF);
+	snd_soc_component_write(component, reg, (value >> 16) & 0xFF);
+	/* Mask top 2 bits, 7-8 are reserved */
+	snd_soc_component_write(component, reg, (value >> 24) & 0x3F);
+}
+
+static int rx_macro_put_iir_band_audio_mixer(
+					struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct wcd_iir_filter_ctl *ctl =
+			(struct wcd_iir_filter_ctl *)kcontrol->private_value;
+	struct soc_bytes_ext *params = &ctl->bytes_ext;
+	int iir_idx = ctl->iir_idx;
+	int band_idx = ctl->band_idx;
+	u32 coeff[BAND_MAX];
+	int reg = CDC_RX_SIDETONE_IIR0_IIR_COEF_B1_CTL + 16 * iir_idx;
+
+	memcpy(&coeff[0], ucontrol->value.bytes.data, params->max);
+
+	/* Mask top bit it is reserved */
+	/* Updates addr automatically for each B2 write */
+	snd_soc_component_write(component, reg, (band_idx * BAND_MAX *
+						 sizeof(uint32_t)) & 0x7F);
+
+	set_iir_band_coeff(component, iir_idx, band_idx, coeff[0]);
+	set_iir_band_coeff(component, iir_idx, band_idx, coeff[1]);
+	set_iir_band_coeff(component, iir_idx, band_idx, coeff[2]);
+	set_iir_band_coeff(component, iir_idx, band_idx, coeff[3]);
+	set_iir_band_coeff(component, iir_idx, band_idx, coeff[4]);
+
+	return 0;
+}
+
+static int rx_macro_get_iir_band_audio_mixer(struct snd_kcontrol *kcontrol,
+				    struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct wcd_iir_filter_ctl *ctl =
+			(struct wcd_iir_filter_ctl *)kcontrol->private_value;
+	struct soc_bytes_ext *params = &ctl->bytes_ext;
+	int iir_idx = ctl->iir_idx;
+	int band_idx = ctl->band_idx;
+	u32 coeff[BAND_MAX];
+
+	coeff[0] = get_iir_band_coeff(component, iir_idx, band_idx, 0);
+	coeff[1] = get_iir_band_coeff(component, iir_idx, band_idx, 1);
+	coeff[2] = get_iir_band_coeff(component, iir_idx, band_idx, 2);
+	coeff[3] = get_iir_band_coeff(component, iir_idx, band_idx, 3);
+	coeff[4] = get_iir_band_coeff(component, iir_idx, band_idx, 4);
+
+	memcpy(ucontrol->value.bytes.data, &coeff[0], params->max);
+
+	return 0;
+}
+
+static int rx_macro_iir_filter_info(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_info *ucontrol)
+{
+	struct wcd_iir_filter_ctl *ctl =
+		(struct wcd_iir_filter_ctl *)kcontrol->private_value;
+	struct soc_bytes_ext *params = &ctl->bytes_ext;
+
+	ucontrol->type = SNDRV_CTL_ELEM_TYPE_BYTES;
+	ucontrol->count = params->max;
+
+	return 0;
+}
+
+static const struct snd_kcontrol_new rx_macro_snd_controls[] = {
+	SOC_SINGLE_S8_TLV("RX_RX0 Digital Volume", CDC_RX_RX0_RX_VOL_CTL,
+			  -84, 40, digital_gain),
+	SOC_SINGLE_S8_TLV("RX_RX1 Digital Volume", CDC_RX_RX1_RX_VOL_CTL,
+			  -84, 40, digital_gain),
+	SOC_SINGLE_S8_TLV("RX_RX2 Digital Volume", CDC_RX_RX2_RX_VOL_CTL,
+			  -84, 40, digital_gain),
+	SOC_SINGLE_S8_TLV("RX_RX0 Mix Digital Volume", CDC_RX_RX0_RX_VOL_MIX_CTL,
+			  -84, 40, digital_gain),
+	SOC_SINGLE_S8_TLV("RX_RX1 Mix Digital Volume", CDC_RX_RX1_RX_VOL_MIX_CTL,
+			  -84, 40, digital_gain),
+	SOC_SINGLE_S8_TLV("RX_RX2 Mix Digital Volume", CDC_RX_RX2_RX_VOL_MIX_CTL,
+			  -84, 40, digital_gain),
+
+	SOC_SINGLE_EXT("RX_COMP1 Switch", SND_SOC_NOPM, RX_MACRO_COMP1, 1, 0,
+		rx_macro_get_compander, rx_macro_set_compander),
+	SOC_SINGLE_EXT("RX_COMP2 Switch", SND_SOC_NOPM, RX_MACRO_COMP2, 1, 0,
+		rx_macro_get_compander, rx_macro_set_compander),
+
+	SOC_SINGLE_EXT("RX_EAR Mode Switch", SND_SOC_NOPM, 0, 1, 0,
+		rx_macro_get_ear_mode, rx_macro_put_ear_mode),
+
+	SOC_SINGLE_EXT("RX_HPH HD2 Mode Switch", SND_SOC_NOPM, 0, 1, 0,
+		rx_macro_get_hph_hd2_mode, rx_macro_put_hph_hd2_mode),
+
+	SOC_ENUM_EXT("RX_HPH PWR Mode", rx_macro_hph_pwr_mode_enum,
+		rx_macro_get_hph_pwr_mode, rx_macro_put_hph_pwr_mode),
+
+	SOC_SINGLE_EXT("RX_Softclip Switch", SND_SOC_NOPM, 0, 1, 0,
+		     rx_macro_soft_clip_enable_get,
+		     rx_macro_soft_clip_enable_put),
+	SOC_SINGLE_EXT("AUX_HPF Switch", SND_SOC_NOPM, 0, 1, 0,
+			rx_macro_aux_hpf_mode_get,
+			rx_macro_aux_hpf_mode_put),
+
+	SOC_SINGLE_S8_TLV("IIR0 INP0 Volume",
+		CDC_RX_SIDETONE_IIR0_IIR_GAIN_B1_CTL, -84, 40,
+		digital_gain),
+	SOC_SINGLE_S8_TLV("IIR0 INP1 Volume",
+		CDC_RX_SIDETONE_IIR0_IIR_GAIN_B2_CTL, -84, 40,
+		digital_gain),
+	SOC_SINGLE_S8_TLV("IIR0 INP2 Volume",
+		CDC_RX_SIDETONE_IIR0_IIR_GAIN_B3_CTL, -84, 40,
+		digital_gain),
+	SOC_SINGLE_S8_TLV("IIR0 INP3 Volume",
+		CDC_RX_SIDETONE_IIR0_IIR_GAIN_B4_CTL, -84, 40,
+		digital_gain),
+	SOC_SINGLE_S8_TLV("IIR1 INP0 Volume",
+		CDC_RX_SIDETONE_IIR1_IIR_GAIN_B1_CTL, -84, 40,
+		digital_gain),
+	SOC_SINGLE_S8_TLV("IIR1 INP1 Volume",
+		CDC_RX_SIDETONE_IIR1_IIR_GAIN_B2_CTL, -84, 40,
+		digital_gain),
+	SOC_SINGLE_S8_TLV("IIR1 INP2 Volume",
+		CDC_RX_SIDETONE_IIR1_IIR_GAIN_B3_CTL, -84, 40,
+		digital_gain),
+	SOC_SINGLE_S8_TLV("IIR1 INP3 Volume",
+		CDC_RX_SIDETONE_IIR1_IIR_GAIN_B4_CTL, -84, 40,
+		digital_gain),
+
+	SOC_SINGLE("IIR1 Band1 Switch", CDC_RX_SIDETONE_IIR0_IIR_CTL,
+		   0, 1, 0),
+	SOC_SINGLE("IIR1 Band2 Switch", CDC_RX_SIDETONE_IIR0_IIR_CTL,
+		   1, 1, 0),
+	SOC_SINGLE("IIR1 Band3 Switch", CDC_RX_SIDETONE_IIR0_IIR_CTL,
+		   2, 1, 0),
+	SOC_SINGLE("IIR1 Band4 Switch", CDC_RX_SIDETONE_IIR0_IIR_CTL,
+		   3, 1, 0),
+	SOC_SINGLE("IIR1 Band5 Switch", CDC_RX_SIDETONE_IIR0_IIR_CTL,
+		   4, 1, 0),
+	SOC_SINGLE("IIR2 Band1 Switch", CDC_RX_SIDETONE_IIR1_IIR_CTL,
+		   0, 1, 0),
+	SOC_SINGLE("IIR2 Band2 Switch", CDC_RX_SIDETONE_IIR1_IIR_CTL,
+		   1, 1, 0),
+	SOC_SINGLE("IIR2 Band3 Switch", CDC_RX_SIDETONE_IIR1_IIR_CTL,
+		   2, 1, 0),
+	SOC_SINGLE("IIR2 Band4 Switch", CDC_RX_SIDETONE_IIR1_IIR_CTL,
+		   3, 1, 0),
+	SOC_SINGLE("IIR2 Band5 Switch", CDC_RX_SIDETONE_IIR1_IIR_CTL,
+		   4, 1, 0),
+
+	RX_MACRO_IIR_FILTER_CTL("IIR0 Band1", IIR0, BAND1),
+	RX_MACRO_IIR_FILTER_CTL("IIR0 Band2", IIR0, BAND2),
+	RX_MACRO_IIR_FILTER_CTL("IIR0 Band3", IIR0, BAND3),
+	RX_MACRO_IIR_FILTER_CTL("IIR0 Band4", IIR0, BAND4),
+	RX_MACRO_IIR_FILTER_CTL("IIR0 Band5", IIR0, BAND5),
+
+	RX_MACRO_IIR_FILTER_CTL("IIR1 Band1", IIR1, BAND1),
+	RX_MACRO_IIR_FILTER_CTL("IIR1 Band2", IIR1, BAND2),
+	RX_MACRO_IIR_FILTER_CTL("IIR1 Band3", IIR1, BAND3),
+	RX_MACRO_IIR_FILTER_CTL("IIR1 Band4", IIR1, BAND4),
+	RX_MACRO_IIR_FILTER_CTL("IIR1 Band5", IIR1, BAND5),
+
+};
+
+static int rx_macro_enable_echo(struct snd_soc_dapm_widget *w,
+				struct snd_kcontrol *kcontrol,
+				int event)
+{
+	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
+	u16 val, ec_hq_reg;
+	int ec_tx;
+
+	val = snd_soc_component_read(component,
+			CDC_RX_INP_MUX_RX_MIX_CFG4);
+	if (!(strcmp(w->name, "RX MIX TX0 MUX")))
+		ec_tx = ((val & 0xf0) >> 0x4) - 1;
+	else if (!(strcmp(w->name, "RX MIX TX1 MUX")))
+		ec_tx = (val & 0x0f) - 1;
+
+	val = snd_soc_component_read(component,
+			CDC_RX_INP_MUX_RX_MIX_CFG5);
+	if (!(strcmp(w->name, "RX MIX TX2 MUX")))
+		ec_tx = (val & 0x0f) - 1;
+
+	if (ec_tx < 0 || (ec_tx >= RX_MACRO_EC_MUX_MAX)) {
+		dev_err(component->dev, "%s: EC mix control not set correctly\n",
+			__func__);
+		return -EINVAL;
+	}
+	ec_hq_reg = CDC_RX_EC_REF_HQ0_EC_REF_HQ_PATH_CTL +
+			    0x40 * ec_tx;
+	snd_soc_component_update_bits(component, ec_hq_reg, 0x01, 0x01);
+	ec_hq_reg = CDC_RX_EC_REF_HQ0_EC_REF_HQ_CFG0 +
+				0x40 * ec_tx;
+	/* default set to 48k */
+	snd_soc_component_update_bits(component, ec_hq_reg, 0x1E, 0x08);
+
+	return 0;
+}
+
+static const struct snd_soc_dapm_widget rx_macro_dapm_widgets[] = {
+	SND_SOC_DAPM_AIF_IN("RX AIF1 PB", "RX_MACRO_AIF1 Playback", 0,
+		SND_SOC_NOPM, 0, 0),
+
+	SND_SOC_DAPM_AIF_IN("RX AIF2 PB", "RX_MACRO_AIF2 Playback", 0,
+		SND_SOC_NOPM, 0, 0),
+
+	SND_SOC_DAPM_AIF_IN("RX AIF3 PB", "RX_MACRO_AIF3 Playback", 0,
+		SND_SOC_NOPM, 0, 0),
+
+	SND_SOC_DAPM_AIF_IN("RX AIF4 PB", "RX_MACRO_AIF4 Playback", 0,
+		SND_SOC_NOPM, 0, 0),
+
+	SND_SOC_DAPM_AIF_OUT("RX AIF_ECHO", "RX_AIF_ECHO Capture", 0,
+		SND_SOC_NOPM, 0, 0),
+
+	SND_SOC_DAPM_MUX("RX_MACRO RX0 MUX", SND_SOC_NOPM, RX_MACRO_RX0, 0,
+			 &rx_macro_rx0_mux),
+	SND_SOC_DAPM_MUX("RX_MACRO RX1 MUX", SND_SOC_NOPM, RX_MACRO_RX1, 0,
+			 &rx_macro_rx1_mux),
+	SND_SOC_DAPM_MUX("RX_MACRO RX2 MUX", SND_SOC_NOPM, RX_MACRO_RX2, 0,
+			 &rx_macro_rx2_mux),
+	SND_SOC_DAPM_MUX("RX_MACRO RX3 MUX", SND_SOC_NOPM, RX_MACRO_RX3, 0,
+			 &rx_macro_rx3_mux),
+	SND_SOC_DAPM_MUX("RX_MACRO RX4 MUX", SND_SOC_NOPM, RX_MACRO_RX4, 0,
+			 &rx_macro_rx4_mux),
+	SND_SOC_DAPM_MUX("RX_MACRO RX5 MUX", SND_SOC_NOPM, RX_MACRO_RX5, 0,
+			 &rx_macro_rx5_mux),
+
+	SND_SOC_DAPM_MIXER("RX_RX0", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("RX_RX1", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("RX_RX2", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("RX_RX3", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("RX_RX4", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("RX_RX5", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+	SND_SOC_DAPM_MUX("IIR0 INP0 MUX", SND_SOC_NOPM, 0, 0, &iir0_inp0_mux),
+	SND_SOC_DAPM_MUX("IIR0 INP1 MUX", SND_SOC_NOPM, 0, 0, &iir0_inp1_mux),
+	SND_SOC_DAPM_MUX("IIR0 INP2 MUX", SND_SOC_NOPM, 0, 0, &iir0_inp2_mux),
+	SND_SOC_DAPM_MUX("IIR0 INP3 MUX", SND_SOC_NOPM, 0, 0, &iir0_inp3_mux),
+	SND_SOC_DAPM_MUX("IIR1 INP0 MUX", SND_SOC_NOPM, 0, 0, &iir1_inp0_mux),
+	SND_SOC_DAPM_MUX("IIR1 INP1 MUX", SND_SOC_NOPM, 0, 0, &iir1_inp1_mux),
+	SND_SOC_DAPM_MUX("IIR1 INP2 MUX", SND_SOC_NOPM, 0, 0, &iir1_inp2_mux),
+	SND_SOC_DAPM_MUX("IIR1 INP3 MUX", SND_SOC_NOPM, 0, 0, &iir1_inp3_mux),
+
+	SND_SOC_DAPM_MUX_E("RX MIX TX0 MUX", SND_SOC_NOPM,
+			   RX_MACRO_EC0_MUX, 0,
+			   &rx_mix_tx0_mux, rx_macro_enable_echo,
+			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MUX_E("RX MIX TX1 MUX", SND_SOC_NOPM,
+			   RX_MACRO_EC1_MUX, 0,
+			   &rx_mix_tx1_mux, rx_macro_enable_echo,
+			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MUX_E("RX MIX TX2 MUX", SND_SOC_NOPM,
+			   RX_MACRO_EC2_MUX, 0,
+			   &rx_mix_tx2_mux, rx_macro_enable_echo,
+			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MIXER_E("IIR0", CDC_RX_SIDETONE_IIR0_IIR_PATH_CTL,
+		4, 0, NULL, 0, rx_macro_set_iir_gain,
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+	SND_SOC_DAPM_MIXER_E("IIR1", CDC_RX_SIDETONE_IIR1_IIR_PATH_CTL,
+		4, 0, NULL, 0, rx_macro_set_iir_gain,
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+	SND_SOC_DAPM_MIXER("SRC0", CDC_RX_SIDETONE_SRC0_ST_SRC_PATH_CTL,
+		4, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("SRC1", CDC_RX_SIDETONE_SRC1_ST_SRC_PATH_CTL,
+		4, 0, NULL, 0),
+
+	SND_SOC_DAPM_MUX("RX INT0 DEM MUX", SND_SOC_NOPM, 0, 0,
+			 &rx_int0_dem_inp_mux),
+	SND_SOC_DAPM_MUX("RX INT1 DEM MUX", SND_SOC_NOPM, 0, 0,
+			 &rx_int1_dem_inp_mux),
+
+	SND_SOC_DAPM_MUX_E("RX INT0_2 MUX", SND_SOC_NOPM, INTERP_HPHL, 0,
+		&rx_int0_2_mux, rx_macro_enable_mix_path,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MUX_E("RX INT1_2 MUX", SND_SOC_NOPM, INTERP_HPHR, 0,
+		&rx_int1_2_mux, rx_macro_enable_mix_path,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MUX_E("RX INT2_2 MUX", SND_SOC_NOPM, INTERP_AUX, 0,
+		&rx_int2_2_mux, rx_macro_enable_mix_path,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MUX("RX INT0_1 MIX1 INP0", SND_SOC_NOPM, 0, 0, &rx_int0_1_mix_inp0_mux),
+	SND_SOC_DAPM_MUX("RX INT0_1 MIX1 INP1", SND_SOC_NOPM, 0, 0, &rx_int0_1_mix_inp1_mux),
+	SND_SOC_DAPM_MUX("RX INT0_1 MIX1 INP2", SND_SOC_NOPM, 0, 0, &rx_int0_1_mix_inp2_mux),
+	SND_SOC_DAPM_MUX("RX INT1_1 MIX1 INP0", SND_SOC_NOPM, 0, 0, &rx_int1_1_mix_inp0_mux),
+	SND_SOC_DAPM_MUX("RX INT1_1 MIX1 INP1", SND_SOC_NOPM, 0, 0, &rx_int1_1_mix_inp1_mux),
+	SND_SOC_DAPM_MUX("RX INT1_1 MIX1 INP2", SND_SOC_NOPM, 0, 0, &rx_int1_1_mix_inp2_mux),
+	SND_SOC_DAPM_MUX("RX INT2_1 MIX1 INP0", SND_SOC_NOPM, 0, 0, &rx_int2_1_mix_inp0_mux),
+	SND_SOC_DAPM_MUX("RX INT2_1 MIX1 INP1", SND_SOC_NOPM, 0, 0, &rx_int2_1_mix_inp1_mux),
+	SND_SOC_DAPM_MUX("RX INT2_1 MIX1 INP2", SND_SOC_NOPM, 0, 0, &rx_int2_1_mix_inp2_mux),
+
+	SND_SOC_DAPM_MUX_E("RX INT0_1 INTERP", SND_SOC_NOPM, INTERP_HPHL, 0,
+		&rx_int0_1_interp_mux, rx_macro_enable_main_path,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MUX_E("RX INT1_1 INTERP", SND_SOC_NOPM, INTERP_HPHR, 0,
+		&rx_int1_1_interp_mux, rx_macro_enable_main_path,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MUX_E("RX INT2_1 INTERP", SND_SOC_NOPM, INTERP_AUX, 0,
+		&rx_int2_1_interp_mux, rx_macro_enable_main_path,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MUX("RX INT0_2 INTERP", SND_SOC_NOPM, 0, 0,
+			 &rx_int0_2_interp_mux),
+	SND_SOC_DAPM_MUX("RX INT1_2 INTERP", SND_SOC_NOPM, 0, 0,
+			 &rx_int1_2_interp_mux),
+	SND_SOC_DAPM_MUX("RX INT2_2 INTERP", SND_SOC_NOPM, 0, 0,
+			 &rx_int2_2_interp_mux),
+
+	SND_SOC_DAPM_MIXER("RX INT0_1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("RX INT0 SEC MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("RX INT1_1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("RX INT1 SEC MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("RX INT2_1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("RX INT2 SEC MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+	SND_SOC_DAPM_MUX_E("RX INT0 MIX2 INP", SND_SOC_NOPM, INTERP_HPHL,
+		0, &rx_int0_mix2_inp_mux, rx_macro_enable_rx_path_clk,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MUX_E("RX INT1 MIX2 INP", SND_SOC_NOPM, INTERP_HPHR,
+		0, &rx_int1_mix2_inp_mux, rx_macro_enable_rx_path_clk,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MUX_E("RX INT2 MIX2 INP", SND_SOC_NOPM, INTERP_AUX,
+		0, &rx_int2_mix2_inp_mux, rx_macro_enable_rx_path_clk,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MIXER("RX INT0 MIX2", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("RX INT1 MIX2", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("RX INT2 MIX2", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+	SND_SOC_DAPM_OUTPUT("HPHL_OUT"),
+	SND_SOC_DAPM_OUTPUT("HPHR_OUT"),
+	SND_SOC_DAPM_OUTPUT("AUX_OUT"),
+
+	SND_SOC_DAPM_INPUT("RX_TX DEC0_INP"),
+	SND_SOC_DAPM_INPUT("RX_TX DEC1_INP"),
+	SND_SOC_DAPM_INPUT("RX_TX DEC2_INP"),
+	SND_SOC_DAPM_INPUT("RX_TX DEC3_INP"),
+
+	SND_SOC_DAPM_SUPPLY_S("RX_MCLK", 0, SND_SOC_NOPM, 0, 0,
+	rx_macro_mclk_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+};
+
+static const struct snd_soc_dapm_route rx_audio_map[] = {
+	{"RX AIF1 PB", NULL, "RX_MCLK"},
+	{"RX AIF2 PB", NULL, "RX_MCLK"},
+	{"RX AIF3 PB", NULL, "RX_MCLK"},
+	{"RX AIF4 PB", NULL, "RX_MCLK"},
+
+	{"RX_MACRO RX0 MUX", "AIF1_PB", "RX AIF1 PB"},
+	{"RX_MACRO RX1 MUX", "AIF1_PB", "RX AIF1 PB"},
+	{"RX_MACRO RX2 MUX", "AIF1_PB", "RX AIF1 PB"},
+	{"RX_MACRO RX3 MUX", "AIF1_PB", "RX AIF1 PB"},
+	{"RX_MACRO RX4 MUX", "AIF1_PB", "RX AIF1 PB"},
+	{"RX_MACRO RX5 MUX", "AIF1_PB", "RX AIF1 PB"},
+
+	{"RX_MACRO RX0 MUX", "AIF2_PB", "RX AIF2 PB"},
+	{"RX_MACRO RX1 MUX", "AIF2_PB", "RX AIF2 PB"},
+	{"RX_MACRO RX2 MUX", "AIF2_PB", "RX AIF2 PB"},
+	{"RX_MACRO RX3 MUX", "AIF2_PB", "RX AIF2 PB"},
+	{"RX_MACRO RX4 MUX", "AIF2_PB", "RX AIF2 PB"},
+	{"RX_MACRO RX5 MUX", "AIF2_PB", "RX AIF2 PB"},
+
+	{"RX_MACRO RX0 MUX", "AIF3_PB", "RX AIF3 PB"},
+	{"RX_MACRO RX1 MUX", "AIF3_PB", "RX AIF3 PB"},
+	{"RX_MACRO RX2 MUX", "AIF3_PB", "RX AIF3 PB"},
+	{"RX_MACRO RX3 MUX", "AIF3_PB", "RX AIF3 PB"},
+	{"RX_MACRO RX4 MUX", "AIF3_PB", "RX AIF3 PB"},
+	{"RX_MACRO RX5 MUX", "AIF3_PB", "RX AIF3 PB"},
+
+	{"RX_MACRO RX0 MUX", "AIF4_PB", "RX AIF4 PB"},
+	{"RX_MACRO RX1 MUX", "AIF4_PB", "RX AIF4 PB"},
+	{"RX_MACRO RX2 MUX", "AIF4_PB", "RX AIF4 PB"},
+	{"RX_MACRO RX3 MUX", "AIF4_PB", "RX AIF4 PB"},
+	{"RX_MACRO RX4 MUX", "AIF4_PB", "RX AIF4 PB"},
+	{"RX_MACRO RX5 MUX", "AIF4_PB", "RX AIF4 PB"},
+
+	{"RX_RX0", NULL, "RX_MACRO RX0 MUX"},
+	{"RX_RX1", NULL, "RX_MACRO RX1 MUX"},
+	{"RX_RX2", NULL, "RX_MACRO RX2 MUX"},
+	{"RX_RX3", NULL, "RX_MACRO RX3 MUX"},
+	{"RX_RX4", NULL, "RX_MACRO RX4 MUX"},
+	{"RX_RX5", NULL, "RX_MACRO RX5 MUX"},
+
+	{"RX INT0_1 MIX1 INP0", "RX0", "RX_RX0"},
+	{"RX INT0_1 MIX1 INP0", "RX1", "RX_RX1"},
+	{"RX INT0_1 MIX1 INP0", "RX2", "RX_RX2"},
+	{"RX INT0_1 MIX1 INP0", "RX3", "RX_RX3"},
+	{"RX INT0_1 MIX1 INP0", "RX4", "RX_RX4"},
+	{"RX INT0_1 MIX1 INP0", "RX5", "RX_RX5"},
+	{"RX INT0_1 MIX1 INP0", "IIR0", "IIR0"},
+	{"RX INT0_1 MIX1 INP0", "IIR1", "IIR1"},
+	{"RX INT0_1 MIX1 INP0", "DEC0", "RX_TX DEC0_INP"},
+	{"RX INT0_1 MIX1 INP0", "DEC1", "RX_TX DEC1_INP"},
+	{"RX INT0_1 MIX1 INP1", "RX0", "RX_RX0"},
+	{"RX INT0_1 MIX1 INP1", "RX1", "RX_RX1"},
+	{"RX INT0_1 MIX1 INP1", "RX2", "RX_RX2"},
+	{"RX INT0_1 MIX1 INP1", "RX3", "RX_RX3"},
+	{"RX INT0_1 MIX1 INP1", "RX4", "RX_RX4"},
+	{"RX INT0_1 MIX1 INP1", "RX5", "RX_RX5"},
+	{"RX INT0_1 MIX1 INP1", "IIR0", "IIR0"},
+	{"RX INT0_1 MIX1 INP1", "IIR1", "IIR1"},
+	{"RX INT0_1 MIX1 INP1", "DEC0", "RX_TX DEC0_INP"},
+	{"RX INT0_1 MIX1 INP1", "DEC1", "RX_TX DEC1_INP"},
+	{"RX INT0_1 MIX1 INP2", "RX0", "RX_RX0"},
+	{"RX INT0_1 MIX1 INP2", "RX1", "RX_RX1"},
+	{"RX INT0_1 MIX1 INP2", "RX2", "RX_RX2"},
+	{"RX INT0_1 MIX1 INP2", "RX3", "RX_RX3"},
+	{"RX INT0_1 MIX1 INP2", "RX4", "RX_RX4"},
+	{"RX INT0_1 MIX1 INP2", "RX5", "RX_RX5"},
+	{"RX INT0_1 MIX1 INP2", "IIR0", "IIR0"},
+	{"RX INT0_1 MIX1 INP2", "IIR1", "IIR1"},
+	{"RX INT0_1 MIX1 INP2", "DEC0", "RX_TX DEC0_INP"},
+	{"RX INT0_1 MIX1 INP2", "DEC1", "RX_TX DEC1_INP"},
+
+	{"RX INT1_1 MIX1 INP0", "RX0", "RX_RX0"},
+	{"RX INT1_1 MIX1 INP0", "RX1", "RX_RX1"},
+	{"RX INT1_1 MIX1 INP0", "RX2", "RX_RX2"},
+	{"RX INT1_1 MIX1 INP0", "RX3", "RX_RX3"},
+	{"RX INT1_1 MIX1 INP0", "RX4", "RX_RX4"},
+	{"RX INT1_1 MIX1 INP0", "RX5", "RX_RX5"},
+	{"RX INT1_1 MIX1 INP0", "IIR0", "IIR0"},
+	{"RX INT1_1 MIX1 INP0", "IIR1", "IIR1"},
+	{"RX INT1_1 MIX1 INP0", "DEC0", "RX_TX DEC0_INP"},
+	{"RX INT1_1 MIX1 INP0", "DEC1", "RX_TX DEC1_INP"},
+	{"RX INT1_1 MIX1 INP1", "RX0", "RX_RX0"},
+	{"RX INT1_1 MIX1 INP1", "RX1", "RX_RX1"},
+	{"RX INT1_1 MIX1 INP1", "RX2", "RX_RX2"},
+	{"RX INT1_1 MIX1 INP1", "RX3", "RX_RX3"},
+	{"RX INT1_1 MIX1 INP1", "RX4", "RX_RX4"},
+	{"RX INT1_1 MIX1 INP1", "RX5", "RX_RX5"},
+	{"RX INT1_1 MIX1 INP1", "IIR0", "IIR0"},
+	{"RX INT1_1 MIX1 INP1", "IIR1", "IIR1"},
+	{"RX INT1_1 MIX1 INP1", "DEC0", "RX_TX DEC0_INP"},
+	{"RX INT1_1 MIX1 INP1", "DEC1", "RX_TX DEC1_INP"},
+	{"RX INT1_1 MIX1 INP2", "RX0", "RX_RX0"},
+	{"RX INT1_1 MIX1 INP2", "RX1", "RX_RX1"},
+	{"RX INT1_1 MIX1 INP2", "RX2", "RX_RX2"},
+	{"RX INT1_1 MIX1 INP2", "RX3", "RX_RX3"},
+	{"RX INT1_1 MIX1 INP2", "RX4", "RX_RX4"},
+	{"RX INT1_1 MIX1 INP2", "RX5", "RX_RX5"},
+	{"RX INT1_1 MIX1 INP2", "IIR0", "IIR0"},
+	{"RX INT1_1 MIX1 INP2", "IIR1", "IIR1"},
+	{"RX INT1_1 MIX1 INP2", "DEC0", "RX_TX DEC0_INP"},
+	{"RX INT1_1 MIX1 INP2", "DEC1", "RX_TX DEC1_INP"},
+
+	{"RX INT2_1 MIX1 INP0", "RX0", "RX_RX0"},
+	{"RX INT2_1 MIX1 INP0", "RX1", "RX_RX1"},
+	{"RX INT2_1 MIX1 INP0", "RX2", "RX_RX2"},
+	{"RX INT2_1 MIX1 INP0", "RX3", "RX_RX3"},
+	{"RX INT2_1 MIX1 INP0", "RX4", "RX_RX4"},
+	{"RX INT2_1 MIX1 INP0", "RX5", "RX_RX5"},
+	{"RX INT2_1 MIX1 INP0", "IIR0", "IIR0"},
+	{"RX INT2_1 MIX1 INP0", "IIR1", "IIR1"},
+	{"RX INT2_1 MIX1 INP0", "DEC0", "RX_TX DEC0_INP"},
+	{"RX INT2_1 MIX1 INP0", "DEC1", "RX_TX DEC1_INP"},
+	{"RX INT2_1 MIX1 INP1", "RX0", "RX_RX0"},
+	{"RX INT2_1 MIX1 INP1", "RX1", "RX_RX1"},
+	{"RX INT2_1 MIX1 INP1", "RX2", "RX_RX2"},
+	{"RX INT2_1 MIX1 INP1", "RX3", "RX_RX3"},
+	{"RX INT2_1 MIX1 INP1", "RX4", "RX_RX4"},
+	{"RX INT2_1 MIX1 INP1", "RX5", "RX_RX5"},
+	{"RX INT2_1 MIX1 INP1", "IIR0", "IIR0"},
+	{"RX INT2_1 MIX1 INP1", "IIR1", "IIR1"},
+	{"RX INT2_1 MIX1 INP1", "DEC0", "RX_TX DEC0_INP"},
+	{"RX INT2_1 MIX1 INP1", "DEC1", "RX_TX DEC1_INP"},
+	{"RX INT2_1 MIX1 INP2", "RX0", "RX_RX0"},
+	{"RX INT2_1 MIX1 INP2", "RX1", "RX_RX1"},
+	{"RX INT2_1 MIX1 INP2", "RX2", "RX_RX2"},
+	{"RX INT2_1 MIX1 INP2", "RX3", "RX_RX3"},
+	{"RX INT2_1 MIX1 INP2", "RX4", "RX_RX4"},
+	{"RX INT2_1 MIX1 INP2", "RX5", "RX_RX5"},
+	{"RX INT2_1 MIX1 INP2", "IIR0", "IIR0"},
+	{"RX INT2_1 MIX1 INP2", "IIR1", "IIR1"},
+	{"RX INT2_1 MIX1 INP2", "DEC0", "RX_TX DEC0_INP"},
+	{"RX INT2_1 MIX1 INP2", "DEC1", "RX_TX DEC1_INP"},
+
+	{"RX INT0_1 MIX1", NULL, "RX INT0_1 MIX1 INP0"},
+	{"RX INT0_1 MIX1", NULL, "RX INT0_1 MIX1 INP1"},
+	{"RX INT0_1 MIX1", NULL, "RX INT0_1 MIX1 INP2"},
+	{"RX INT1_1 MIX1", NULL, "RX INT1_1 MIX1 INP0"},
+	{"RX INT1_1 MIX1", NULL, "RX INT1_1 MIX1 INP1"},
+	{"RX INT1_1 MIX1", NULL, "RX INT1_1 MIX1 INP2"},
+	{"RX INT2_1 MIX1", NULL, "RX INT2_1 MIX1 INP0"},
+	{"RX INT2_1 MIX1", NULL, "RX INT2_1 MIX1 INP1"},
+	{"RX INT2_1 MIX1", NULL, "RX INT2_1 MIX1 INP2"},
+
+	{"RX MIX TX0 MUX", "RX_MIX0", "RX INT0 SEC MIX"},
+	{"RX MIX TX0 MUX", "RX_MIX1", "RX INT1 SEC MIX"},
+	{"RX MIX TX0 MUX", "RX_MIX2", "RX INT2 SEC MIX"},
+	{"RX MIX TX1 MUX", "RX_MIX0", "RX INT0 SEC MIX"},
+	{"RX MIX TX1 MUX", "RX_MIX1", "RX INT1 SEC MIX"},
+	{"RX MIX TX1 MUX", "RX_MIX2", "RX INT2 SEC MIX"},
+	{"RX MIX TX2 MUX", "RX_MIX0", "RX INT0 SEC MIX"},
+	{"RX MIX TX2 MUX", "RX_MIX1", "RX INT1 SEC MIX"},
+	{"RX MIX TX2 MUX", "RX_MIX2", "RX INT2 SEC MIX"},
+	{"RX AIF_ECHO", NULL, "RX MIX TX0 MUX"},
+	{"RX AIF_ECHO", NULL, "RX MIX TX1 MUX"},
+	{"RX AIF_ECHO", NULL, "RX MIX TX2 MUX"},
+	{"RX AIF_ECHO", NULL, "RX_MCLK"},
+
+	/* Mixing path INT0 */
+	{"RX INT0_2 MUX", "RX0", "RX_RX0"},
+	{"RX INT0_2 MUX", "RX1", "RX_RX1"},
+	{"RX INT0_2 MUX", "RX2", "RX_RX2"},
+	{"RX INT0_2 MUX", "RX3", "RX_RX3"},
+	{"RX INT0_2 MUX", "RX4", "RX_RX4"},
+	{"RX INT0_2 MUX", "RX5", "RX_RX5"},
+	{"RX INT0_2 INTERP", NULL, "RX INT0_2 MUX"},
+	{"RX INT0 SEC MIX", NULL, "RX INT0_2 INTERP"},
+
+	/* Mixing path INT1 */
+	{"RX INT1_2 MUX", "RX0", "RX_RX0"},
+	{"RX INT1_2 MUX", "RX1", "RX_RX1"},
+	{"RX INT1_2 MUX", "RX2", "RX_RX2"},
+	{"RX INT1_2 MUX", "RX3", "RX_RX3"},
+	{"RX INT1_2 MUX", "RX4", "RX_RX4"},
+	{"RX INT1_2 MUX", "RX5", "RX_RX5"},
+	{"RX INT1_2 INTERP", NULL, "RX INT1_2 MUX"},
+	{"RX INT1 SEC MIX", NULL, "RX INT1_2 INTERP"},
+
+	/* Mixing path INT2 */
+	{"RX INT2_2 MUX", "RX0", "RX_RX0"},
+	{"RX INT2_2 MUX", "RX1", "RX_RX1"},
+	{"RX INT2_2 MUX", "RX2", "RX_RX2"},
+	{"RX INT2_2 MUX", "RX3", "RX_RX3"},
+	{"RX INT2_2 MUX", "RX4", "RX_RX4"},
+	{"RX INT2_2 MUX", "RX5", "RX_RX5"},
+	{"RX INT2_2 INTERP", NULL, "RX INT2_2 MUX"},
+	{"RX INT2 SEC MIX", NULL, "RX INT2_2 INTERP"},
+
+	{"RX INT0_1 INTERP", NULL, "RX INT0_1 MIX1"},
+	{"RX INT0 SEC MIX", NULL, "RX INT0_1 INTERP"},
+	{"RX INT0 MIX2", NULL, "RX INT0 SEC MIX"},
+	{"RX INT0 MIX2", NULL, "RX INT0 MIX2 INP"},
+	{"RX INT0 DEM MUX", "CLSH_DSM_OUT", "RX INT0 MIX2"},
+	{"HPHL_OUT", NULL, "RX INT0 DEM MUX"},
+	{"HPHL_OUT", NULL, "RX_MCLK"},
+
+	{"RX INT1_1 INTERP", NULL, "RX INT1_1 MIX1"},
+	{"RX INT1 SEC MIX", NULL, "RX INT1_1 INTERP"},
+	{"RX INT1 MIX2", NULL, "RX INT1 SEC MIX"},
+	{"RX INT1 MIX2", NULL, "RX INT1 MIX2 INP"},
+	{"RX INT1 DEM MUX", "CLSH_DSM_OUT", "RX INT1 MIX2"},
+	{"HPHR_OUT", NULL, "RX INT1 DEM MUX"},
+	{"HPHR_OUT", NULL, "RX_MCLK"},
+
+	{"RX INT2_1 INTERP", NULL, "RX INT2_1 MIX1"},
+
+	{"RX INT2 SEC MIX", NULL, "RX INT2_1 INTERP"},
+	{"RX INT2 MIX2", NULL, "RX INT2 SEC MIX"},
+	{"RX INT2 MIX2", NULL, "RX INT2 MIX2 INP"},
+	{"AUX_OUT", NULL, "RX INT2 MIX2"},
+	{"AUX_OUT", NULL, "RX_MCLK"},
+
+	{"IIR0", NULL, "RX_MCLK"},
+	{"IIR0", NULL, "IIR0 INP0 MUX"},
+	{"IIR0 INP0 MUX", "DEC0", "RX_TX DEC0_INP"},
+	{"IIR0 INP0 MUX", "DEC1", "RX_TX DEC1_INP"},
+	{"IIR0 INP0 MUX", "DEC2", "RX_TX DEC2_INP"},
+	{"IIR0 INP0 MUX", "DEC3", "RX_TX DEC3_INP"},
+	{"IIR0 INP0 MUX", "RX0", "RX_RX0"},
+	{"IIR0 INP0 MUX", "RX1", "RX_RX1"},
+	{"IIR0 INP0 MUX", "RX2", "RX_RX2"},
+	{"IIR0 INP0 MUX", "RX3", "RX_RX3"},
+	{"IIR0 INP0 MUX", "RX4", "RX_RX4"},
+	{"IIR0 INP0 MUX", "RX5", "RX_RX5"},
+	{"IIR0", NULL, "IIR0 INP1 MUX"},
+	{"IIR0 INP1 MUX", "DEC0", "RX_TX DEC0_INP"},
+	{"IIR0 INP1 MUX", "DEC1", "RX_TX DEC1_INP"},
+	{"IIR0 INP1 MUX", "DEC2", "RX_TX DEC2_INP"},
+	{"IIR0 INP1 MUX", "DEC3", "RX_TX DEC3_INP"},
+	{"IIR0 INP1 MUX", "RX0", "RX_RX0"},
+	{"IIR0 INP1 MUX", "RX1", "RX_RX1"},
+	{"IIR0 INP1 MUX", "RX2", "RX_RX2"},
+	{"IIR0 INP1 MUX", "RX3", "RX_RX3"},
+	{"IIR0 INP1 MUX", "RX4", "RX_RX4"},
+	{"IIR0 INP1 MUX", "RX5", "RX_RX5"},
+	{"IIR0", NULL, "IIR0 INP2 MUX"},
+	{"IIR0 INP2 MUX", "DEC0", "RX_TX DEC0_INP"},
+	{"IIR0 INP2 MUX", "DEC1", "RX_TX DEC1_INP"},
+	{"IIR0 INP2 MUX", "DEC2", "RX_TX DEC2_INP"},
+	{"IIR0 INP2 MUX", "DEC3", "RX_TX DEC3_INP"},
+	{"IIR0 INP2 MUX", "RX0", "RX_RX0"},
+	{"IIR0 INP2 MUX", "RX1", "RX_RX1"},
+	{"IIR0 INP2 MUX", "RX2", "RX_RX2"},
+	{"IIR0 INP2 MUX", "RX3", "RX_RX3"},
+	{"IIR0 INP2 MUX", "RX4", "RX_RX4"},
+	{"IIR0 INP2 MUX", "RX5", "RX_RX5"},
+	{"IIR0", NULL, "IIR0 INP3 MUX"},
+	{"IIR0 INP3 MUX", "DEC0", "RX_TX DEC0_INP"},
+	{"IIR0 INP3 MUX", "DEC1", "RX_TX DEC1_INP"},
+	{"IIR0 INP3 MUX", "DEC2", "RX_TX DEC2_INP"},
+	{"IIR0 INP3 MUX", "DEC3", "RX_TX DEC3_INP"},
+	{"IIR0 INP3 MUX", "RX0", "RX_RX0"},
+	{"IIR0 INP3 MUX", "RX1", "RX_RX1"},
+	{"IIR0 INP3 MUX", "RX2", "RX_RX2"},
+	{"IIR0 INP3 MUX", "RX3", "RX_RX3"},
+	{"IIR0 INP3 MUX", "RX4", "RX_RX4"},
+	{"IIR0 INP3 MUX", "RX5", "RX_RX5"},
+
+	{"IIR1", NULL, "RX_MCLK"},
+	{"IIR1", NULL, "IIR1 INP0 MUX"},
+	{"IIR1 INP0 MUX", "DEC0", "RX_TX DEC0_INP"},
+	{"IIR1 INP0 MUX", "DEC1", "RX_TX DEC1_INP"},
+	{"IIR1 INP0 MUX", "DEC2", "RX_TX DEC2_INP"},
+	{"IIR1 INP0 MUX", "DEC3", "RX_TX DEC3_INP"},
+	{"IIR1 INP0 MUX", "RX0", "RX_RX0"},
+	{"IIR1 INP0 MUX", "RX1", "RX_RX1"},
+	{"IIR1 INP0 MUX", "RX2", "RX_RX2"},
+	{"IIR1 INP0 MUX", "RX3", "RX_RX3"},
+	{"IIR1 INP0 MUX", "RX4", "RX_RX4"},
+	{"IIR1 INP0 MUX", "RX5", "RX_RX5"},
+	{"IIR1", NULL, "IIR1 INP1 MUX"},
+	{"IIR1 INP1 MUX", "DEC0", "RX_TX DEC0_INP"},
+	{"IIR1 INP1 MUX", "DEC1", "RX_TX DEC1_INP"},
+	{"IIR1 INP1 MUX", "DEC2", "RX_TX DEC2_INP"},
+	{"IIR1 INP1 MUX", "DEC3", "RX_TX DEC3_INP"},
+	{"IIR1 INP1 MUX", "RX0", "RX_RX0"},
+	{"IIR1 INP1 MUX", "RX1", "RX_RX1"},
+	{"IIR1 INP1 MUX", "RX2", "RX_RX2"},
+	{"IIR1 INP1 MUX", "RX3", "RX_RX3"},
+	{"IIR1 INP1 MUX", "RX4", "RX_RX4"},
+	{"IIR1 INP1 MUX", "RX5", "RX_RX5"},
+	{"IIR1", NULL, "IIR1 INP2 MUX"},
+	{"IIR1 INP2 MUX", "DEC0", "RX_TX DEC0_INP"},
+	{"IIR1 INP2 MUX", "DEC1", "RX_TX DEC1_INP"},
+	{"IIR1 INP2 MUX", "DEC2", "RX_TX DEC2_INP"},
+	{"IIR1 INP2 MUX", "DEC3", "RX_TX DEC3_INP"},
+	{"IIR1 INP2 MUX", "RX0", "RX_RX0"},
+	{"IIR1 INP2 MUX", "RX1", "RX_RX1"},
+	{"IIR1 INP2 MUX", "RX2", "RX_RX2"},
+	{"IIR1 INP2 MUX", "RX3", "RX_RX3"},
+	{"IIR1 INP2 MUX", "RX4", "RX_RX4"},
+	{"IIR1 INP2 MUX", "RX5", "RX_RX5"},
+	{"IIR1", NULL, "IIR1 INP3 MUX"},
+	{"IIR1 INP3 MUX", "DEC0", "RX_TX DEC0_INP"},
+	{"IIR1 INP3 MUX", "DEC1", "RX_TX DEC1_INP"},
+	{"IIR1 INP3 MUX", "DEC2", "RX_TX DEC2_INP"},
+	{"IIR1 INP3 MUX", "DEC3", "RX_TX DEC3_INP"},
+	{"IIR1 INP3 MUX", "RX0", "RX_RX0"},
+	{"IIR1 INP3 MUX", "RX1", "RX_RX1"},
+	{"IIR1 INP3 MUX", "RX2", "RX_RX2"},
+	{"IIR1 INP3 MUX", "RX3", "RX_RX3"},
+	{"IIR1 INP3 MUX", "RX4", "RX_RX4"},
+	{"IIR1 INP3 MUX", "RX5", "RX_RX5"},
+
+	{"SRC0", NULL, "IIR0"},
+	{"SRC1", NULL, "IIR1"},
+	{"RX INT0 MIX2 INP", "SRC0", "SRC0"},
+	{"RX INT0 MIX2 INP", "SRC1", "SRC1"},
+	{"RX INT1 MIX2 INP", "SRC0", "SRC0"},
+	{"RX INT1 MIX2 INP", "SRC1", "SRC1"},
+	{"RX INT2 MIX2 INP", "SRC0", "SRC0"},
+	{"RX INT2 MIX2 INP", "SRC1", "SRC1"},
+};
+
+static int rx_macro_component_probe(struct snd_soc_component *component)
+{
+	struct rx_macro *rx = snd_soc_component_get_drvdata(component);
+
+	snd_soc_component_init_regmap(component, rx->regmap);
+
+	snd_soc_component_update_bits(component, CDC_RX_RX0_RX_PATH_SEC7,
+				      CDC_RX_DSM_OUT_DELAY_SEL_MASK,
+				      CDC_RX_DSM_OUT_DELAY_TWO_SAMPLE);
+	snd_soc_component_update_bits(component, CDC_RX_RX1_RX_PATH_SEC7,
+				      CDC_RX_DSM_OUT_DELAY_SEL_MASK,
+				      CDC_RX_DSM_OUT_DELAY_TWO_SAMPLE);
+	snd_soc_component_update_bits(component, CDC_RX_RX2_RX_PATH_SEC7,
+				      CDC_RX_DSM_OUT_DELAY_SEL_MASK,
+				      CDC_RX_DSM_OUT_DELAY_TWO_SAMPLE);
+	snd_soc_component_update_bits(component, CDC_RX_RX0_RX_PATH_CFG3,
+				      CDC_RX_DC_COEFF_SEL_MASK,
+				      CDC_RX_DC_COEFF_SEL_TWO);
+	snd_soc_component_update_bits(component, CDC_RX_RX1_RX_PATH_CFG3,
+				      CDC_RX_DC_COEFF_SEL_MASK,
+				      CDC_RX_DC_COEFF_SEL_TWO);
+	snd_soc_component_update_bits(component, CDC_RX_RX2_RX_PATH_CFG3,
+				      CDC_RX_DC_COEFF_SEL_MASK,
+				      CDC_RX_DC_COEFF_SEL_TWO);
+
+	rx->component = component;
+
+	return 0;
+}
+
+static int swclk_gate_enable(struct clk_hw *hw)
+{
+	struct rx_macro *rx = to_rx_macro(hw);
+
+	rx_macro_mclk_enable(rx, true);
+	if (rx->reset_swr)
+		regmap_update_bits(rx->regmap, CDC_RX_CLK_RST_CTRL_SWR_CONTROL,
+				   CDC_RX_SWR_RESET_MASK,
+				   CDC_RX_SWR_RESET);
+
+	regmap_update_bits(rx->regmap, CDC_RX_CLK_RST_CTRL_SWR_CONTROL,
+			   CDC_RX_SWR_CLK_EN_MASK, 1);
+
+	if (rx->reset_swr)
+		regmap_update_bits(rx->regmap, CDC_RX_CLK_RST_CTRL_SWR_CONTROL,
+				   CDC_RX_SWR_RESET_MASK, 0);
+	rx->reset_swr = false;
+
+	return 0;
+}
+
+static void swclk_gate_disable(struct clk_hw *hw)
+{
+	struct rx_macro *rx = to_rx_macro(hw);
+
+	regmap_update_bits(rx->regmap, CDC_RX_CLK_RST_CTRL_SWR_CONTROL, 
+			   CDC_RX_SWR_CLK_EN_MASK, 0);
+
+	rx_macro_mclk_enable(rx, false);
+}
+
+static int swclk_gate_is_enabled(struct clk_hw *hw)
+{
+	struct rx_macro *rx = to_rx_macro(hw);
+	int ret, val;
+
+	regmap_read(rx->regmap, CDC_RX_CLK_RST_CTRL_SWR_CONTROL, &val);
+	ret = val & BIT(0);
+
+	return ret;
+}
+
+static unsigned long swclk_recalc_rate(struct clk_hw *hw,
+				       unsigned long parent_rate)
+{
+	return parent_rate / 2;
+}
+
+static const struct clk_ops swclk_gate_ops = {
+	.prepare = swclk_gate_enable,
+	.unprepare = swclk_gate_disable,
+	.is_enabled = swclk_gate_is_enabled,
+	.recalc_rate = swclk_recalc_rate,
+
+};
+
+static struct clk *rx_macro_register_mclk_output(struct rx_macro *rx)
+{
+	struct device *dev = rx->dev;
+	struct device_node *np = dev->of_node;
+	const char *parent_clk_name = NULL;
+	const char *clk_name = "lpass-rx-mclk";
+	struct clk_hw *hw;
+	struct clk_init_data init;
+	int ret;
+
+	parent_clk_name = __clk_get_name(rx->clks[2].clk);
+
+	init.name = clk_name;
+	init.ops = &swclk_gate_ops;
+	init.flags = 0;
+	init.parent_names = &parent_clk_name;
+	init.num_parents = 1;
+	rx->hw.init = &init;
+	hw = &rx->hw;
+	ret = clk_hw_register(rx->dev, hw);
+	if (ret)
+		return ERR_PTR(ret);
+
+	of_clk_add_provider(np, of_clk_src_simple_get, hw->clk);
+
+	return NULL;
+}
+
+static const struct snd_soc_component_driver rx_macro_component_drv = {
+	.name = "RX-MACRO",
+	.probe = rx_macro_component_probe,
+	.controls = rx_macro_snd_controls,
+	.num_controls = ARRAY_SIZE(rx_macro_snd_controls),
+	.dapm_widgets = rx_macro_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(rx_macro_dapm_widgets),
+	.dapm_routes = rx_audio_map,
+	.num_dapm_routes = ARRAY_SIZE(rx_audio_map),
+};
+
+static int rx_macro_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct rx_macro *rx;
+	void __iomem *base;
+	int ret;
+
+	rx = devm_kzalloc(dev, sizeof(*rx), GFP_KERNEL);
+	if (!rx)
+		return -ENOMEM;
+
+	rx->clks[0].id = "macro";
+	rx->clks[1].id = "dcodec";
+	rx->clks[2].id = "mclk";
+	rx->clks[3].id = "npl";
+	rx->clks[4].id = "fsgen";
+
+	ret = devm_clk_bulk_get(dev, RX_NUM_CLKS_MAX, rx->clks);
+	if (ret) {
+		dev_err(dev, "Error getting RX Clocks (%d)\n", ret);
+		return ret;
+	}
+
+	base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+
+	rx->regmap = devm_regmap_init_mmio(dev, base, &rx_regmap_config);
+
+	dev_set_drvdata(dev, rx);
+
+	rx->reset_swr = true;
+	rx->dev = dev;
+
+	/* set MCLK and NPL rates */
+	clk_set_rate(rx->clks[2].clk, MCLK_FREQ);
+	clk_set_rate(rx->clks[3].clk, MCLK_FREQ);
+
+	ret = clk_bulk_prepare_enable(RX_NUM_CLKS_MAX, rx->clks);
+	if (ret)
+		return ret;
+
+	rx_macro_register_mclk_output(rx);
+
+	ret = devm_snd_soc_register_component(dev, &rx_macro_component_drv,
+					      rx_macro_dai,
+					      ARRAY_SIZE(rx_macro_dai));
+	if (ret)
+		clk_bulk_disable_unprepare(RX_NUM_CLKS_MAX, rx->clks);
+
+	return ret;
+}
+
+static int rx_macro_remove(struct platform_device *pdev)
+{
+	struct rx_macro *rx = dev_get_drvdata(&pdev->dev);
+
+	of_clk_del_provider(pdev->dev.of_node);
+	clk_bulk_disable_unprepare(RX_NUM_CLKS_MAX, rx->clks);
+	return 0;
+}
+
+static const struct of_device_id rx_macro_dt_match[] = {
+	{ .compatible = "qcom,sm8250-lpass-rx-macro" },
+	{ }
+};
+
+static struct platform_driver rx_macro_driver = {
+	.driver = {
+		.name = "rx_macro",
+		.owner = THIS_MODULE,
+		.of_match_table = rx_macro_dt_match,
+		.suppress_bind_attrs = true,
+	},
+	.probe = rx_macro_probe,
+	.remove = rx_macro_remove,
+};
+
+module_platform_driver(rx_macro_driver);
+
+MODULE_DESCRIPTION("RX macro driver");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/lpass-tx-macro.c b/sound/soc/codecs/lpass-tx-macro.c
new file mode 100644
index 000000000000..36d7a6442cdb
--- /dev/null
+++ b/sound/soc/codecs/lpass-tx-macro.c
@@ -0,0 +1,1862 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/tlv.h>
+#include <linux/of_clk.h>
+#include <linux/clk-provider.h>
+
+#define CDC_TX_CLK_RST_CTRL_MCLK_CONTROL (0x0000)
+#define CDC_TX_MCLK_EN_MASK		BIT(0)
+#define CDC_TX_MCLK_ENABLE		BIT(0)
+#define CDC_TX_CLK_RST_CTRL_FS_CNT_CONTROL (0x0004)
+#define CDC_TX_FS_CNT_EN_MASK		BIT(0)
+#define CDC_TX_FS_CNT_ENABLE		BIT(0)
+#define CDC_TX_CLK_RST_CTRL_SWR_CONTROL	(0x0008)
+#define CDC_TX_SWR_RESET_MASK		BIT(1)
+#define CDC_TX_SWR_RESET_ENABLE		BIT(1)
+#define CDC_TX_SWR_CLK_EN_MASK		BIT(0)
+#define CDC_TX_SWR_CLK_ENABLE		BIT(0)
+#define CDC_TX_TOP_CSR_TOP_CFG0		(0x0080)
+#define CDC_TX_TOP_CSR_ANC_CFG		(0x0084)
+#define CDC_TX_TOP_CSR_SWR_CTRL		(0x0088)
+#define CDC_TX_TOP_CSR_FREQ_MCLK	(0x0090)
+#define CDC_TX_TOP_CSR_DEBUG_BUS	(0x0094)
+#define CDC_TX_TOP_CSR_DEBUG_EN		(0x0098)
+#define CDC_TX_TOP_CSR_TX_I2S_CTL	(0x00A4)
+#define CDC_TX_TOP_CSR_I2S_CLK		(0x00A8)
+#define CDC_TX_TOP_CSR_I2S_RESET	(0x00AC)
+#define CDC_TX_TOP_CSR_SWR_DMICn_CTL(n)	(0x00C0 + n * 0x4)
+#define CDC_TX_TOP_CSR_SWR_DMIC0_CTL	(0x00C0)
+#define CDC_TX_SWR_DMIC_CLK_SEL_MASK	GENMASK(3, 1)
+#define CDC_TX_TOP_CSR_SWR_DMIC1_CTL	(0x00C4)
+#define CDC_TX_TOP_CSR_SWR_DMIC2_CTL	(0x00C8)
+#define CDC_TX_TOP_CSR_SWR_DMIC3_CTL	(0x00CC)
+#define CDC_TX_TOP_CSR_SWR_AMIC0_CTL	(0x00D0)
+#define CDC_TX_TOP_CSR_SWR_AMIC1_CTL	(0x00D4)
+#define CDC_TX_INP_MUX_ADC_MUXn_CFG0(n)	(0x0100 + 0x8 * n)
+#define CDC_TX_MACRO_SWR_MIC_MUX_SEL_MASK GENMASK(3, 0)
+#define CDC_TX_INP_MUX_ADC_MUX0_CFG0	(0x0100)
+#define CDC_TX_INP_MUX_ADC_MUXn_CFG1(n)	(0x0104 + 0x8 * n)
+#define CDC_TX_INP_MUX_ADC_MUX0_CFG1	(0x0104)
+#define CDC_TX_INP_MUX_ADC_MUX1_CFG0	(0x0108)
+#define CDC_TX_INP_MUX_ADC_MUX1_CFG1	(0x010C)
+#define CDC_TX_INP_MUX_ADC_MUX2_CFG0	(0x0110)
+#define CDC_TX_INP_MUX_ADC_MUX2_CFG1	(0x0114)
+#define CDC_TX_INP_MUX_ADC_MUX3_CFG0	(0x0118)
+#define CDC_TX_INP_MUX_ADC_MUX3_CFG1	(0x011C)
+#define CDC_TX_INP_MUX_ADC_MUX4_CFG0	(0x0120)
+#define CDC_TX_INP_MUX_ADC_MUX4_CFG1	(0x0124)
+#define CDC_TX_INP_MUX_ADC_MUX5_CFG0	(0x0128)
+#define CDC_TX_INP_MUX_ADC_MUX5_CFG1	(0x012C)
+#define CDC_TX_INP_MUX_ADC_MUX6_CFG0	(0x0130)
+#define CDC_TX_INP_MUX_ADC_MUX6_CFG1	(0x0134)
+#define CDC_TX_INP_MUX_ADC_MUX7_CFG0	(0x0138)
+#define CDC_TX_INP_MUX_ADC_MUX7_CFG1	(0x013C)
+#define CDC_TX_ANC0_CLK_RESET_CTL	(0x0200)
+#define CDC_TX_ANC0_MODE_1_CTL		(0x0204)
+#define CDC_TX_ANC0_MODE_2_CTL		(0x0208)
+#define CDC_TX_ANC0_FF_SHIFT		(0x020C)
+#define CDC_TX_ANC0_FB_SHIFT		(0x0210)
+#define CDC_TX_ANC0_LPF_FF_A_CTL	(0x0214)
+#define CDC_TX_ANC0_LPF_FF_B_CTL	(0x0218)
+#define CDC_TX_ANC0_LPF_FB_CTL		(0x021C)
+#define CDC_TX_ANC0_SMLPF_CTL		(0x0220)
+#define CDC_TX_ANC0_DCFLT_SHIFT_CTL	(0x0224)
+#define CDC_TX_ANC0_IIR_ADAPT_CTL	(0x0228)
+#define CDC_TX_ANC0_IIR_COEFF_1_CTL	(0x022C)
+#define CDC_TX_ANC0_IIR_COEFF_2_CTL	(0x0230)
+#define CDC_TX_ANC0_FF_A_GAIN_CTL	(0x0234)
+#define CDC_TX_ANC0_FF_B_GAIN_CTL	(0x0238)
+#define CDC_TX_ANC0_FB_GAIN_CTL		(0x023C)
+#define CDC_TXn_TX_PATH_CTL(n)		(0x0400 + 0x80 * n)
+#define CDC_TXn_PCM_RATE_MASK		GENMASK(3, 0)
+#define CDC_TXn_PGA_MUTE_MASK		BIT(4)
+#define CDC_TXn_CLK_EN_MASK		BIT(5)
+#define CDC_TX0_TX_PATH_CTL		(0x0400)
+#define CDC_TXn_TX_PATH_CFG0(n)		(0x0404 + 0x80 * n)
+#define CDC_TX0_TX_PATH_CFG0		(0x0404)
+#define CDC_TXn_PH_EN_MASK		BIT(0)
+#define CDC_TXn_ADC_MODE_MASK		GENMASK(2, 1)
+#define CDC_TXn_HPF_CUT_FREQ_MASK	GENMASK(6, 5)
+#define CDC_TXn_ADC_DMIC_SEL_MASK	BIT(7)
+#define CDC_TX0_TX_PATH_CFG1		(0x0408)
+#define CDC_TXn_TX_VOL_CTL(n)		(0x040C + 0x80 * n)
+#define CDC_TX0_TX_VOL_CTL		(0x040C)
+#define CDC_TX0_TX_PATH_SEC0		(0x0410)
+#define CDC_TX0_TX_PATH_SEC1		(0x0414)
+#define CDC_TXn_TX_PATH_SEC2(n)		(0x0418 + 0x80 * n)
+#define CDC_TXn_HPF_F_CHANGE_MASK	 BIT(1)
+#define CDC_TXn_HPF_ZERO_GATE_MASK	 BIT(0)
+#define CDC_TX0_TX_PATH_SEC2		(0x0418)
+#define CDC_TX0_TX_PATH_SEC3		(0x041C)
+#define CDC_TX0_TX_PATH_SEC4		(0x0420)
+#define CDC_TX0_TX_PATH_SEC5		(0x0424)
+#define CDC_TX0_TX_PATH_SEC6		(0x0428)
+#define CDC_TX0_TX_PATH_SEC7		(0x042C)
+#define CDC_TX0_MBHC_CTL_EN_MASK	BIT(6)
+#define CDC_TX1_TX_PATH_CTL		(0x0480)
+#define CDC_TX1_TX_PATH_CFG0		(0x0484)
+#define CDC_TX1_TX_PATH_CFG1		(0x0488)
+#define CDC_TX1_TX_VOL_CTL		(0x048C)
+#define CDC_TX1_TX_PATH_SEC0		(0x0490)
+#define CDC_TX1_TX_PATH_SEC1		(0x0494)
+#define CDC_TX1_TX_PATH_SEC2		(0x0498)
+#define CDC_TX1_TX_PATH_SEC3		(0x049C)
+#define CDC_TX1_TX_PATH_SEC4		(0x04A0)
+#define CDC_TX1_TX_PATH_SEC5		(0x04A4)
+#define CDC_TX1_TX_PATH_SEC6		(0x04A8)
+#define CDC_TX2_TX_PATH_CTL		(0x0500)
+#define CDC_TX2_TX_PATH_CFG0		(0x0504)
+#define CDC_TX2_TX_PATH_CFG1		(0x0508)
+#define CDC_TX2_TX_VOL_CTL		(0x050C)
+#define CDC_TX2_TX_PATH_SEC0		(0x0510)
+#define CDC_TX2_TX_PATH_SEC1		(0x0514)
+#define CDC_TX2_TX_PATH_SEC2		(0x0518)
+#define CDC_TX2_TX_PATH_SEC3		(0x051C)
+#define CDC_TX2_TX_PATH_SEC4		(0x0520)
+#define CDC_TX2_TX_PATH_SEC5		(0x0524)
+#define CDC_TX2_TX_PATH_SEC6		(0x0528)
+#define CDC_TX3_TX_PATH_CTL		(0x0580)
+#define CDC_TX3_TX_PATH_CFG0		(0x0584)
+#define CDC_TX3_TX_PATH_CFG1		(0x0588)
+#define CDC_TX3_TX_VOL_CTL		(0x058C)
+#define CDC_TX3_TX_PATH_SEC0		(0x0590)
+#define CDC_TX3_TX_PATH_SEC1		(0x0594)
+#define CDC_TX3_TX_PATH_SEC2		(0x0598)
+#define CDC_TX3_TX_PATH_SEC3		(0x059C)
+#define CDC_TX3_TX_PATH_SEC4		(0x05A0)
+#define CDC_TX3_TX_PATH_SEC5		(0x05A4)
+#define CDC_TX3_TX_PATH_SEC6		(0x05A8)
+#define CDC_TX4_TX_PATH_CTL		(0x0600)
+#define CDC_TX4_TX_PATH_CFG0		(0x0604)
+#define CDC_TX4_TX_PATH_CFG1		(0x0608)
+#define CDC_TX4_TX_VOL_CTL		(0x060C)
+#define CDC_TX4_TX_PATH_SEC0		(0x0610)
+#define CDC_TX4_TX_PATH_SEC1		(0x0614)
+#define CDC_TX4_TX_PATH_SEC2		(0x0618)
+#define CDC_TX4_TX_PATH_SEC3		(0x061C)
+#define CDC_TX4_TX_PATH_SEC4		(0x0620)
+#define CDC_TX4_TX_PATH_SEC5		(0x0624)
+#define CDC_TX4_TX_PATH_SEC6		(0x0628)
+#define CDC_TX5_TX_PATH_CTL		(0x0680)
+#define CDC_TX5_TX_PATH_CFG0		(0x0684)
+#define CDC_TX5_TX_PATH_CFG1		(0x0688)
+#define CDC_TX5_TX_VOL_CTL		(0x068C)
+#define CDC_TX5_TX_PATH_SEC0		(0x0690)
+#define CDC_TX5_TX_PATH_SEC1		(0x0694)
+#define CDC_TX5_TX_PATH_SEC2		(0x0698)
+#define CDC_TX5_TX_PATH_SEC3		(0x069C)
+#define CDC_TX5_TX_PATH_SEC4		(0x06A0)
+#define CDC_TX5_TX_PATH_SEC5		(0x06A4)
+#define CDC_TX5_TX_PATH_SEC6		(0x06A8)
+#define CDC_TX6_TX_PATH_CTL		(0x0700)
+#define CDC_TX6_TX_PATH_CFG0		(0x0704)
+#define CDC_TX6_TX_PATH_CFG1		(0x0708)
+#define CDC_TX6_TX_VOL_CTL		(0x070C)
+#define CDC_TX6_TX_PATH_SEC0		(0x0710)
+#define CDC_TX6_TX_PATH_SEC1		(0x0714)
+#define CDC_TX6_TX_PATH_SEC2		(0x0718)
+#define CDC_TX6_TX_PATH_SEC3		(0x071C)
+#define CDC_TX6_TX_PATH_SEC4		(0x0720)
+#define CDC_TX6_TX_PATH_SEC5		(0x0724)
+#define CDC_TX6_TX_PATH_SEC6		(0x0728)
+#define CDC_TX7_TX_PATH_CTL		(0x0780)
+#define CDC_TX7_TX_PATH_CFG0		(0x0784)
+#define CDC_TX7_TX_PATH_CFG1		(0x0788)
+#define CDC_TX7_TX_VOL_CTL		(0x078C)
+#define CDC_TX7_TX_PATH_SEC0		(0x0790)
+#define CDC_TX7_TX_PATH_SEC1		(0x0794)
+#define CDC_TX7_TX_PATH_SEC2		(0x0798)
+#define CDC_TX7_TX_PATH_SEC3		(0x079C)
+#define CDC_TX7_TX_PATH_SEC4		(0x07A0)
+#define CDC_TX7_TX_PATH_SEC5		(0x07A4)
+#define CDC_TX7_TX_PATH_SEC6		(0x07A8)
+#define TX_MAX_OFFSET			(0x07A8)
+
+#define TX_MACRO_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
+			SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 |\
+			SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000)
+#define TX_MACRO_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
+			SNDRV_PCM_FMTBIT_S24_LE |\
+			SNDRV_PCM_FMTBIT_S24_3LE)
+
+#define  CF_MIN_3DB_4HZ			0x0
+#define  CF_MIN_3DB_75HZ		0x1
+#define  CF_MIN_3DB_150HZ		0x2
+#define	TX_ADC_MAX	5
+#define TX_ADC_TO_DMIC(n) ((n - TX_ADC_MAX)/2)
+#define NUM_DECIMATORS 8
+#define TX_NUM_CLKS_MAX	5
+#define TX_MACRO_DMIC_UNMUTE_DELAY_MS	40
+#define TX_MACRO_AMIC_UNMUTE_DELAY_MS	100
+#define TX_MACRO_DMIC_HPF_DELAY_MS	300
+#define TX_MACRO_AMIC_HPF_DELAY_MS	300
+#define MCLK_FREQ		9600000
+
+enum {
+	TX_MACRO_AIF_INVALID = 0,
+	TX_MACRO_AIF1_CAP,
+	TX_MACRO_AIF2_CAP,
+	TX_MACRO_AIF3_CAP,
+	TX_MACRO_MAX_DAIS
+};
+
+enum {
+	TX_MACRO_DEC0,
+	TX_MACRO_DEC1,
+	TX_MACRO_DEC2,
+	TX_MACRO_DEC3,
+	TX_MACRO_DEC4,
+	TX_MACRO_DEC5,
+	TX_MACRO_DEC6,
+	TX_MACRO_DEC7,
+	TX_MACRO_DEC_MAX,
+};
+
+enum {
+	TX_MACRO_CLK_DIV_2,
+	TX_MACRO_CLK_DIV_3,
+	TX_MACRO_CLK_DIV_4,
+	TX_MACRO_CLK_DIV_6,
+	TX_MACRO_CLK_DIV_8,
+	TX_MACRO_CLK_DIV_16,
+};
+
+enum {
+	MSM_DMIC,
+	SWR_MIC,
+	ANC_FB_TUNE1
+};
+
+struct tx_mute_work {
+	struct tx_macro *tx;
+	u32 decimator;
+	struct delayed_work dwork;
+};
+
+struct hpf_work {
+	struct tx_macro *tx;
+	u8 decimator;
+	u8 hpf_cut_off_freq;
+	struct delayed_work dwork;
+};
+
+struct tx_macro {
+	struct device *dev;
+	struct snd_soc_component *component;
+	struct hpf_work tx_hpf_work[NUM_DECIMATORS];
+	struct tx_mute_work tx_mute_dwork[NUM_DECIMATORS];
+	unsigned long active_ch_mask[TX_MACRO_MAX_DAIS];
+	unsigned long active_ch_cnt[TX_MACRO_MAX_DAIS];
+	unsigned long active_decimator[TX_MACRO_MAX_DAIS];
+	struct regmap *regmap;
+	struct clk_bulk_data clks[TX_NUM_CLKS_MAX];
+	struct clk_hw hw;
+	bool dec_active[NUM_DECIMATORS];
+	bool reset_swr;
+	int tx_mclk_users;
+	u16 dmic_clk_div;
+	bool bcs_enable;
+	int dec_mode[NUM_DECIMATORS];
+	bool bcs_clk_en;
+};
+#define to_tx_macro(_hw) container_of(_hw, struct tx_macro, hw)
+
+static const DECLARE_TLV_DB_SCALE(digital_gain, -8400, 100, -8400);
+
+static const struct reg_default tx_defaults[] = {
+	/* TX Macro */
+	{ CDC_TX_CLK_RST_CTRL_MCLK_CONTROL, 0x00 },
+	{ CDC_TX_CLK_RST_CTRL_FS_CNT_CONTROL, 0x00 },
+	{ CDC_TX_CLK_RST_CTRL_SWR_CONTROL, 0x00},
+	{ CDC_TX_TOP_CSR_TOP_CFG0, 0x00},
+	{ CDC_TX_TOP_CSR_ANC_CFG, 0x00},
+	{ CDC_TX_TOP_CSR_SWR_CTRL, 0x00},
+	{ CDC_TX_TOP_CSR_FREQ_MCLK, 0x00},
+	{ CDC_TX_TOP_CSR_DEBUG_BUS, 0x00},
+	{ CDC_TX_TOP_CSR_DEBUG_EN, 0x00},
+	{ CDC_TX_TOP_CSR_TX_I2S_CTL, 0x0C},
+	{ CDC_TX_TOP_CSR_I2S_CLK, 0x00},
+	{ CDC_TX_TOP_CSR_I2S_RESET, 0x00},
+	{ CDC_TX_TOP_CSR_SWR_DMIC0_CTL, 0x00},
+	{ CDC_TX_TOP_CSR_SWR_DMIC1_CTL, 0x00},
+	{ CDC_TX_TOP_CSR_SWR_DMIC2_CTL, 0x00},
+	{ CDC_TX_TOP_CSR_SWR_DMIC3_CTL, 0x00},
+	{ CDC_TX_TOP_CSR_SWR_AMIC0_CTL, 0x00},
+	{ CDC_TX_TOP_CSR_SWR_AMIC1_CTL, 0x00},
+	{ CDC_TX_INP_MUX_ADC_MUX0_CFG0, 0x00},
+	{ CDC_TX_INP_MUX_ADC_MUX0_CFG1, 0x00},
+	{ CDC_TX_INP_MUX_ADC_MUX1_CFG0, 0x00},
+	{ CDC_TX_INP_MUX_ADC_MUX1_CFG1, 0x00},
+	{ CDC_TX_INP_MUX_ADC_MUX2_CFG0, 0x00},
+	{ CDC_TX_INP_MUX_ADC_MUX2_CFG1, 0x00},
+	{ CDC_TX_INP_MUX_ADC_MUX3_CFG0, 0x00},
+	{ CDC_TX_INP_MUX_ADC_MUX3_CFG1, 0x00},
+	{ CDC_TX_INP_MUX_ADC_MUX4_CFG0, 0x00},
+	{ CDC_TX_INP_MUX_ADC_MUX4_CFG1, 0x00},
+	{ CDC_TX_INP_MUX_ADC_MUX5_CFG0, 0x00},
+	{ CDC_TX_INP_MUX_ADC_MUX5_CFG1, 0x00},
+	{ CDC_TX_INP_MUX_ADC_MUX6_CFG0, 0x00},
+	{ CDC_TX_INP_MUX_ADC_MUX6_CFG1, 0x00},
+	{ CDC_TX_INP_MUX_ADC_MUX7_CFG0, 0x00},
+	{ CDC_TX_INP_MUX_ADC_MUX7_CFG1, 0x00},
+	{ CDC_TX_ANC0_CLK_RESET_CTL, 0x00},
+	{ CDC_TX_ANC0_MODE_1_CTL, 0x00},
+	{ CDC_TX_ANC0_MODE_2_CTL, 0x00},
+	{ CDC_TX_ANC0_FF_SHIFT, 0x00},
+	{ CDC_TX_ANC0_FB_SHIFT, 0x00},
+	{ CDC_TX_ANC0_LPF_FF_A_CTL, 0x00},
+	{ CDC_TX_ANC0_LPF_FF_B_CTL, 0x00},
+	{ CDC_TX_ANC0_LPF_FB_CTL, 0x00},
+	{ CDC_TX_ANC0_SMLPF_CTL, 0x00},
+	{ CDC_TX_ANC0_DCFLT_SHIFT_CTL, 0x00},
+	{ CDC_TX_ANC0_IIR_ADAPT_CTL, 0x00},
+	{ CDC_TX_ANC0_IIR_COEFF_1_CTL, 0x00},
+	{ CDC_TX_ANC0_IIR_COEFF_2_CTL, 0x00},
+	{ CDC_TX_ANC0_FF_A_GAIN_CTL, 0x00},
+	{ CDC_TX_ANC0_FF_B_GAIN_CTL, 0x00},
+	{ CDC_TX_ANC0_FB_GAIN_CTL, 0x00},
+	{ CDC_TX0_TX_PATH_CTL, 0x04},
+	{ CDC_TX0_TX_PATH_CFG0, 0x10},
+	{ CDC_TX0_TX_PATH_CFG1, 0x0B},
+	{ CDC_TX0_TX_VOL_CTL, 0x00},
+	{ CDC_TX0_TX_PATH_SEC0, 0x00},
+	{ CDC_TX0_TX_PATH_SEC1, 0x00},
+	{ CDC_TX0_TX_PATH_SEC2, 0x01},
+	{ CDC_TX0_TX_PATH_SEC3, 0x3C},
+	{ CDC_TX0_TX_PATH_SEC4, 0x20},
+	{ CDC_TX0_TX_PATH_SEC5, 0x00},
+	{ CDC_TX0_TX_PATH_SEC6, 0x00},
+	{ CDC_TX0_TX_PATH_SEC7, 0x25},
+	{ CDC_TX1_TX_PATH_CTL, 0x04},
+	{ CDC_TX1_TX_PATH_CFG0, 0x10},
+	{ CDC_TX1_TX_PATH_CFG1, 0x0B},
+	{ CDC_TX1_TX_VOL_CTL, 0x00},
+	{ CDC_TX1_TX_PATH_SEC0, 0x00},
+	{ CDC_TX1_TX_PATH_SEC1, 0x00},
+	{ CDC_TX1_TX_PATH_SEC2, 0x01},
+	{ CDC_TX1_TX_PATH_SEC3, 0x3C},
+	{ CDC_TX1_TX_PATH_SEC4, 0x20},
+	{ CDC_TX1_TX_PATH_SEC5, 0x00},
+	{ CDC_TX1_TX_PATH_SEC6, 0x00},
+	{ CDC_TX2_TX_PATH_CTL, 0x04},
+	{ CDC_TX2_TX_PATH_CFG0, 0x10},
+	{ CDC_TX2_TX_PATH_CFG1, 0x0B},
+	{ CDC_TX2_TX_VOL_CTL, 0x00},
+	{ CDC_TX2_TX_PATH_SEC0, 0x00},
+	{ CDC_TX2_TX_PATH_SEC1, 0x00},
+	{ CDC_TX2_TX_PATH_SEC2, 0x01},
+	{ CDC_TX2_TX_PATH_SEC3, 0x3C},
+	{ CDC_TX2_TX_PATH_SEC4, 0x20},
+	{ CDC_TX2_TX_PATH_SEC5, 0x00},
+	{ CDC_TX2_TX_PATH_SEC6, 0x00},
+	{ CDC_TX3_TX_PATH_CTL, 0x04},
+	{ CDC_TX3_TX_PATH_CFG0, 0x10},
+	{ CDC_TX3_TX_PATH_CFG1, 0x0B},
+	{ CDC_TX3_TX_VOL_CTL, 0x00},
+	{ CDC_TX3_TX_PATH_SEC0, 0x00},
+	{ CDC_TX3_TX_PATH_SEC1, 0x00},
+	{ CDC_TX3_TX_PATH_SEC2, 0x01},
+	{ CDC_TX3_TX_PATH_SEC3, 0x3C},
+	{ CDC_TX3_TX_PATH_SEC4, 0x20},
+	{ CDC_TX3_TX_PATH_SEC5, 0x00},
+	{ CDC_TX3_TX_PATH_SEC6, 0x00},
+	{ CDC_TX4_TX_PATH_CTL, 0x04},
+	{ CDC_TX4_TX_PATH_CFG0, 0x10},
+	{ CDC_TX4_TX_PATH_CFG1, 0x0B},
+	{ CDC_TX4_TX_VOL_CTL, 0x00},
+	{ CDC_TX4_TX_PATH_SEC0, 0x00},
+	{ CDC_TX4_TX_PATH_SEC1, 0x00},
+	{ CDC_TX4_TX_PATH_SEC2, 0x01},
+	{ CDC_TX4_TX_PATH_SEC3, 0x3C},
+	{ CDC_TX4_TX_PATH_SEC4, 0x20},
+	{ CDC_TX4_TX_PATH_SEC5, 0x00},
+	{ CDC_TX4_TX_PATH_SEC6, 0x00},
+	{ CDC_TX5_TX_PATH_CTL, 0x04},
+	{ CDC_TX5_TX_PATH_CFG0, 0x10},
+	{ CDC_TX5_TX_PATH_CFG1, 0x0B},
+	{ CDC_TX5_TX_VOL_CTL, 0x00},
+	{ CDC_TX5_TX_PATH_SEC0, 0x00},
+	{ CDC_TX5_TX_PATH_SEC1, 0x00},
+	{ CDC_TX5_TX_PATH_SEC2, 0x01},
+	{ CDC_TX5_TX_PATH_SEC3, 0x3C},
+	{ CDC_TX5_TX_PATH_SEC4, 0x20},
+	{ CDC_TX5_TX_PATH_SEC5, 0x00},
+	{ CDC_TX5_TX_PATH_SEC6, 0x00},
+	{ CDC_TX6_TX_PATH_CTL, 0x04},
+	{ CDC_TX6_TX_PATH_CFG0, 0x10},
+	{ CDC_TX6_TX_PATH_CFG1, 0x0B},
+	{ CDC_TX6_TX_VOL_CTL, 0x00},
+	{ CDC_TX6_TX_PATH_SEC0, 0x00},
+	{ CDC_TX6_TX_PATH_SEC1, 0x00},
+	{ CDC_TX6_TX_PATH_SEC2, 0x01},
+	{ CDC_TX6_TX_PATH_SEC3, 0x3C},
+	{ CDC_TX6_TX_PATH_SEC4, 0x20},
+	{ CDC_TX6_TX_PATH_SEC5, 0x00},
+	{ CDC_TX6_TX_PATH_SEC6, 0x00},
+	{ CDC_TX7_TX_PATH_CTL, 0x04},
+	{ CDC_TX7_TX_PATH_CFG0, 0x10},
+	{ CDC_TX7_TX_PATH_CFG1, 0x0B},
+	{ CDC_TX7_TX_VOL_CTL, 0x00},
+	{ CDC_TX7_TX_PATH_SEC0, 0x00},
+	{ CDC_TX7_TX_PATH_SEC1, 0x00},
+	{ CDC_TX7_TX_PATH_SEC2, 0x01},
+	{ CDC_TX7_TX_PATH_SEC3, 0x3C},
+	{ CDC_TX7_TX_PATH_SEC4, 0x20},
+	{ CDC_TX7_TX_PATH_SEC5, 0x00},
+	{ CDC_TX7_TX_PATH_SEC6, 0x00},
+};
+
+static bool tx_is_volatile_register(struct device *dev, unsigned int reg)
+{
+	/* Update volatile list for tx/tx macros */
+	switch (reg) {
+	case CDC_TX_TOP_CSR_SWR_DMIC0_CTL:
+	case CDC_TX_TOP_CSR_SWR_DMIC1_CTL:
+	case CDC_TX_TOP_CSR_SWR_DMIC2_CTL:
+	case CDC_TX_TOP_CSR_SWR_DMIC3_CTL:
+		return true;
+	}
+	return false;
+}
+
+static bool tx_is_rw_register(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case CDC_TX_CLK_RST_CTRL_MCLK_CONTROL:
+	case CDC_TX_CLK_RST_CTRL_FS_CNT_CONTROL:
+	case CDC_TX_CLK_RST_CTRL_SWR_CONTROL:
+	case CDC_TX_TOP_CSR_TOP_CFG0:
+	case CDC_TX_TOP_CSR_ANC_CFG:
+	case CDC_TX_TOP_CSR_SWR_CTRL:
+	case CDC_TX_TOP_CSR_FREQ_MCLK:
+	case CDC_TX_TOP_CSR_DEBUG_BUS:
+	case CDC_TX_TOP_CSR_DEBUG_EN:
+	case CDC_TX_TOP_CSR_TX_I2S_CTL:
+	case CDC_TX_TOP_CSR_I2S_CLK:
+	case CDC_TX_TOP_CSR_I2S_RESET:
+	case CDC_TX_TOP_CSR_SWR_DMIC0_CTL:
+	case CDC_TX_TOP_CSR_SWR_DMIC1_CTL:
+	case CDC_TX_TOP_CSR_SWR_DMIC2_CTL:
+	case CDC_TX_TOP_CSR_SWR_DMIC3_CTL:
+	case CDC_TX_TOP_CSR_SWR_AMIC0_CTL:
+	case CDC_TX_TOP_CSR_SWR_AMIC1_CTL:
+	case CDC_TX_ANC0_CLK_RESET_CTL:
+	case CDC_TX_ANC0_MODE_1_CTL:
+	case CDC_TX_ANC0_MODE_2_CTL:
+	case CDC_TX_ANC0_FF_SHIFT:
+	case CDC_TX_ANC0_FB_SHIFT:
+	case CDC_TX_ANC0_LPF_FF_A_CTL:
+	case CDC_TX_ANC0_LPF_FF_B_CTL:
+	case CDC_TX_ANC0_LPF_FB_CTL:
+	case CDC_TX_ANC0_SMLPF_CTL:
+	case CDC_TX_ANC0_DCFLT_SHIFT_CTL:
+	case CDC_TX_ANC0_IIR_ADAPT_CTL:
+	case CDC_TX_ANC0_IIR_COEFF_1_CTL:
+	case CDC_TX_ANC0_IIR_COEFF_2_CTL:
+	case CDC_TX_ANC0_FF_A_GAIN_CTL:
+	case CDC_TX_ANC0_FF_B_GAIN_CTL:
+	case CDC_TX_ANC0_FB_GAIN_CTL:
+	case CDC_TX_INP_MUX_ADC_MUX0_CFG0:
+	case CDC_TX_INP_MUX_ADC_MUX0_CFG1:
+	case CDC_TX_INP_MUX_ADC_MUX1_CFG0:
+	case CDC_TX_INP_MUX_ADC_MUX1_CFG1:
+	case CDC_TX_INP_MUX_ADC_MUX2_CFG0:
+	case CDC_TX_INP_MUX_ADC_MUX2_CFG1:
+	case CDC_TX_INP_MUX_ADC_MUX3_CFG0:
+	case CDC_TX_INP_MUX_ADC_MUX3_CFG1:
+	case CDC_TX_INP_MUX_ADC_MUX4_CFG0:
+	case CDC_TX_INP_MUX_ADC_MUX4_CFG1:
+	case CDC_TX_INP_MUX_ADC_MUX5_CFG0:
+	case CDC_TX_INP_MUX_ADC_MUX5_CFG1:
+	case CDC_TX_INP_MUX_ADC_MUX6_CFG0:
+	case CDC_TX_INP_MUX_ADC_MUX6_CFG1:
+	case CDC_TX_INP_MUX_ADC_MUX7_CFG0:
+	case CDC_TX_INP_MUX_ADC_MUX7_CFG1:
+	case CDC_TX0_TX_PATH_CTL:
+	case CDC_TX0_TX_PATH_CFG0:
+	case CDC_TX0_TX_PATH_CFG1:
+	case CDC_TX0_TX_VOL_CTL:
+	case CDC_TX0_TX_PATH_SEC0:
+	case CDC_TX0_TX_PATH_SEC1:
+	case CDC_TX0_TX_PATH_SEC2:
+	case CDC_TX0_TX_PATH_SEC3:
+	case CDC_TX0_TX_PATH_SEC4:
+	case CDC_TX0_TX_PATH_SEC5:
+	case CDC_TX0_TX_PATH_SEC6:
+	case CDC_TX0_TX_PATH_SEC7:
+	case CDC_TX1_TX_PATH_CTL:
+	case CDC_TX1_TX_PATH_CFG0:
+	case CDC_TX1_TX_PATH_CFG1:
+	case CDC_TX1_TX_VOL_CTL:
+	case CDC_TX1_TX_PATH_SEC0:
+	case CDC_TX1_TX_PATH_SEC1:
+	case CDC_TX1_TX_PATH_SEC2:
+	case CDC_TX1_TX_PATH_SEC3:
+	case CDC_TX1_TX_PATH_SEC4:
+	case CDC_TX1_TX_PATH_SEC5:
+	case CDC_TX1_TX_PATH_SEC6:
+	case CDC_TX2_TX_PATH_CTL:
+	case CDC_TX2_TX_PATH_CFG0:
+	case CDC_TX2_TX_PATH_CFG1:
+	case CDC_TX2_TX_VOL_CTL:
+	case CDC_TX2_TX_PATH_SEC0:
+	case CDC_TX2_TX_PATH_SEC1:
+	case CDC_TX2_TX_PATH_SEC2:
+	case CDC_TX2_TX_PATH_SEC3:
+	case CDC_TX2_TX_PATH_SEC4:
+	case CDC_TX2_TX_PATH_SEC5:
+	case CDC_TX2_TX_PATH_SEC6:
+	case CDC_TX3_TX_PATH_CTL:
+	case CDC_TX3_TX_PATH_CFG0:
+	case CDC_TX3_TX_PATH_CFG1:
+	case CDC_TX3_TX_VOL_CTL:
+	case CDC_TX3_TX_PATH_SEC0:
+	case CDC_TX3_TX_PATH_SEC1:
+	case CDC_TX3_TX_PATH_SEC2:
+	case CDC_TX3_TX_PATH_SEC3:
+	case CDC_TX3_TX_PATH_SEC4:
+	case CDC_TX3_TX_PATH_SEC5:
+	case CDC_TX3_TX_PATH_SEC6:
+	case CDC_TX4_TX_PATH_CTL:
+	case CDC_TX4_TX_PATH_CFG0:
+	case CDC_TX4_TX_PATH_CFG1:
+	case CDC_TX4_TX_VOL_CTL:
+	case CDC_TX4_TX_PATH_SEC0:
+	case CDC_TX4_TX_PATH_SEC1:
+	case CDC_TX4_TX_PATH_SEC2:
+	case CDC_TX4_TX_PATH_SEC3:
+	case CDC_TX4_TX_PATH_SEC4:
+	case CDC_TX4_TX_PATH_SEC5:
+	case CDC_TX4_TX_PATH_SEC6:
+	case CDC_TX5_TX_PATH_CTL:
+	case CDC_TX5_TX_PATH_CFG0:
+	case CDC_TX5_TX_PATH_CFG1:
+	case CDC_TX5_TX_VOL_CTL:
+	case CDC_TX5_TX_PATH_SEC0:
+	case CDC_TX5_TX_PATH_SEC1:
+	case CDC_TX5_TX_PATH_SEC2:
+	case CDC_TX5_TX_PATH_SEC3:
+	case CDC_TX5_TX_PATH_SEC4:
+	case CDC_TX5_TX_PATH_SEC5:
+	case CDC_TX5_TX_PATH_SEC6:
+	case CDC_TX6_TX_PATH_CTL:
+	case CDC_TX6_TX_PATH_CFG0:
+	case CDC_TX6_TX_PATH_CFG1:
+	case CDC_TX6_TX_VOL_CTL:
+	case CDC_TX6_TX_PATH_SEC0:
+	case CDC_TX6_TX_PATH_SEC1:
+	case CDC_TX6_TX_PATH_SEC2:
+	case CDC_TX6_TX_PATH_SEC3:
+	case CDC_TX6_TX_PATH_SEC4:
+	case CDC_TX6_TX_PATH_SEC5:
+	case CDC_TX6_TX_PATH_SEC6:
+	case CDC_TX7_TX_PATH_CTL:
+	case CDC_TX7_TX_PATH_CFG0:
+	case CDC_TX7_TX_PATH_CFG1:
+	case CDC_TX7_TX_VOL_CTL:
+	case CDC_TX7_TX_PATH_SEC0:
+	case CDC_TX7_TX_PATH_SEC1:
+	case CDC_TX7_TX_PATH_SEC2:
+	case CDC_TX7_TX_PATH_SEC3:
+	case CDC_TX7_TX_PATH_SEC4:
+	case CDC_TX7_TX_PATH_SEC5:
+	case CDC_TX7_TX_PATH_SEC6:
+		return true;
+	}
+
+	return false;
+}
+
+static const struct regmap_config tx_regmap_config = {
+	.name = "tx_macro",
+	.reg_bits = 16,
+	.val_bits = 32,
+	.reg_stride = 4,
+	.cache_type = REGCACHE_FLAT,
+	.max_register = TX_MAX_OFFSET,
+	.reg_defaults = tx_defaults,
+	.num_reg_defaults = ARRAY_SIZE(tx_defaults),
+	.writeable_reg = tx_is_rw_register,
+	.volatile_reg = tx_is_volatile_register,
+	.readable_reg = tx_is_rw_register,
+};
+
+static int tx_macro_mclk_enable(struct tx_macro *tx,
+				bool mclk_enable)
+{
+	struct regmap *regmap = tx->regmap;
+
+	if (mclk_enable) {
+		if (tx->tx_mclk_users == 0) {
+			/* 9.6MHz MCLK, set value 0x00 if other frequency */
+			regmap_update_bits(regmap, CDC_TX_TOP_CSR_FREQ_MCLK, 0x01, 0x01);
+			regmap_update_bits(regmap, CDC_TX_CLK_RST_CTRL_MCLK_CONTROL,
+					   CDC_TX_MCLK_EN_MASK,
+					   CDC_TX_MCLK_ENABLE);
+			regmap_update_bits(regmap, CDC_TX_CLK_RST_CTRL_FS_CNT_CONTROL,
+					   CDC_TX_FS_CNT_EN_MASK,
+					   CDC_TX_FS_CNT_ENABLE);
+			regcache_mark_dirty(regmap);
+			regcache_sync(regmap);
+		}
+		tx->tx_mclk_users++;
+	} else {
+		if (tx->tx_mclk_users <= 0) {
+			dev_err(tx->dev, "clock already disabled\n");
+			tx->tx_mclk_users = 0;
+			goto exit;
+		}
+		tx->tx_mclk_users--;
+		if (tx->tx_mclk_users == 0) {
+			regmap_update_bits(regmap, CDC_TX_CLK_RST_CTRL_FS_CNT_CONTROL,
+					   CDC_TX_FS_CNT_EN_MASK, 0x0);
+			regmap_update_bits(regmap, CDC_TX_CLK_RST_CTRL_MCLK_CONTROL,
+					   CDC_TX_MCLK_EN_MASK, 0x0);
+		}
+	}
+exit:
+	return 0;
+}
+
+static bool is_amic_enabled(struct snd_soc_component *component, int decimator)
+{
+	u16 adc_mux_reg, adc_reg, adc_n;
+
+	adc_mux_reg = CDC_TX_INP_MUX_ADC_MUXn_CFG1(decimator);
+
+	if (snd_soc_component_read(component, adc_mux_reg) & SWR_MIC) {
+		adc_reg = CDC_TX_INP_MUX_ADC_MUXn_CFG0(decimator);
+		adc_n = snd_soc_component_read_field(component, adc_reg,
+					     CDC_TX_MACRO_SWR_MIC_MUX_SEL_MASK);
+		if (adc_n < TX_ADC_MAX)
+			return true;
+	}
+
+	return false;
+}
+
+static void tx_macro_tx_hpf_corner_freq_callback(struct work_struct *work)
+{
+	struct delayed_work *hpf_delayed_work;
+	struct hpf_work *hpf_work;
+	struct tx_macro *tx;
+	struct snd_soc_component *component;
+	u16 dec_cfg_reg, hpf_gate_reg;
+	u8 hpf_cut_off_freq;
+
+	hpf_delayed_work = to_delayed_work(work);
+	hpf_work = container_of(hpf_delayed_work, struct hpf_work, dwork);
+	tx = hpf_work->tx;
+	component = tx->component;
+	hpf_cut_off_freq = hpf_work->hpf_cut_off_freq;
+
+	dec_cfg_reg = CDC_TXn_TX_PATH_CFG0(hpf_work->decimator);
+	hpf_gate_reg = CDC_TXn_TX_PATH_SEC2(hpf_work->decimator);
+
+	if (is_amic_enabled(component, hpf_work->decimator)) {
+		snd_soc_component_write_field(component,
+				dec_cfg_reg,
+				CDC_TXn_HPF_CUT_FREQ_MASK,
+				hpf_cut_off_freq);
+		snd_soc_component_update_bits(component, hpf_gate_reg,
+					      CDC_TXn_HPF_F_CHANGE_MASK |
+					      CDC_TXn_HPF_ZERO_GATE_MASK,
+					      0x02);
+		snd_soc_component_update_bits(component, hpf_gate_reg,
+					      CDC_TXn_HPF_F_CHANGE_MASK |
+					      CDC_TXn_HPF_ZERO_GATE_MASK,
+					      0x01);
+	} else {
+		snd_soc_component_write_field(component, dec_cfg_reg,
+					      CDC_TXn_HPF_CUT_FREQ_MASK,
+					      hpf_cut_off_freq);
+		snd_soc_component_write_field(component, hpf_gate_reg,
+					      CDC_TXn_HPF_F_CHANGE_MASK, 0x1);
+		/* Minimum 1 clk cycle delay is required as per HW spec */
+		usleep_range(1000, 1010);
+		snd_soc_component_write_field(component, hpf_gate_reg,
+					      CDC_TXn_HPF_F_CHANGE_MASK, 0x0);
+	}
+}
+
+static void tx_macro_mute_update_callback(struct work_struct *work)
+{
+	struct tx_mute_work *tx_mute_dwork;
+	struct snd_soc_component *component;
+	struct tx_macro *tx;
+	struct delayed_work *delayed_work;
+	u8 decimator;
+
+	delayed_work = to_delayed_work(work);
+	tx_mute_dwork = container_of(delayed_work, struct tx_mute_work, dwork);
+	tx = tx_mute_dwork->tx;
+	component = tx->component;
+	decimator = tx_mute_dwork->decimator;
+
+	snd_soc_component_write_field(component, CDC_TXn_TX_PATH_CTL(decimator),
+				      CDC_TXn_PGA_MUTE_MASK, 0x0);
+}
+
+static int tx_macro_mclk_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 tx_macro *tx = snd_soc_component_get_drvdata(component);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		tx_macro_mclk_enable(tx, true);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		tx_macro_mclk_enable(tx, false);
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static int tx_macro_put_dec_enum(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_dapm_widget *widget = snd_soc_dapm_kcontrol_widget(kcontrol);
+	struct snd_soc_component *component = snd_soc_dapm_to_component(widget->dapm);
+	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+	unsigned int val, dmic;
+	u16 mic_sel_reg;
+	u16 dmic_clk_reg;
+	struct tx_macro *tx = snd_soc_component_get_drvdata(component);
+
+	val = ucontrol->value.enumerated.item[0];
+
+	switch (e->reg) {
+	case CDC_TX_INP_MUX_ADC_MUX0_CFG0:
+		mic_sel_reg = CDC_TX0_TX_PATH_CFG0;
+		break;
+	case CDC_TX_INP_MUX_ADC_MUX1_CFG0:
+		mic_sel_reg = CDC_TX1_TX_PATH_CFG0;
+		break;
+	case CDC_TX_INP_MUX_ADC_MUX2_CFG0:
+		mic_sel_reg = CDC_TX2_TX_PATH_CFG0;
+		break;
+	case CDC_TX_INP_MUX_ADC_MUX3_CFG0:
+		mic_sel_reg = CDC_TX3_TX_PATH_CFG0;
+		break;
+	case CDC_TX_INP_MUX_ADC_MUX4_CFG0:
+		mic_sel_reg = CDC_TX4_TX_PATH_CFG0;
+		break;
+	case CDC_TX_INP_MUX_ADC_MUX5_CFG0:
+		mic_sel_reg = CDC_TX5_TX_PATH_CFG0;
+		break;
+	case CDC_TX_INP_MUX_ADC_MUX6_CFG0:
+		mic_sel_reg = CDC_TX6_TX_PATH_CFG0;
+		break;
+	case CDC_TX_INP_MUX_ADC_MUX7_CFG0:
+		mic_sel_reg = CDC_TX7_TX_PATH_CFG0;
+		break;
+	}
+
+	if (val != 0) {
+		if (val < 5) {
+			snd_soc_component_write_field(component, mic_sel_reg,
+						      CDC_TXn_ADC_DMIC_SEL_MASK, 0);
+		} else {
+			snd_soc_component_write_field(component, mic_sel_reg,
+						      CDC_TXn_ADC_DMIC_SEL_MASK, 1);
+			dmic = TX_ADC_TO_DMIC(val);
+			dmic_clk_reg = CDC_TX_TOP_CSR_SWR_DMICn_CTL(dmic);
+			snd_soc_component_write_field(component, dmic_clk_reg,
+						CDC_TX_SWR_DMIC_CLK_SEL_MASK,
+						tx->dmic_clk_div);
+		}
+	}
+
+	return snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
+}
+
+static int tx_macro_tx_mixer_get(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_dapm_widget *widget = snd_soc_dapm_kcontrol_widget(kcontrol);
+	struct snd_soc_component *component = snd_soc_dapm_to_component(widget->dapm);
+	struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value;
+	u32 dai_id = widget->shift;
+	u32 dec_id = mc->shift;
+	struct tx_macro *tx = snd_soc_component_get_drvdata(component);
+
+	if (test_bit(dec_id, &tx->active_ch_mask[dai_id]))
+		ucontrol->value.integer.value[0] = 1;
+	else
+		ucontrol->value.integer.value[0] = 0;
+
+	return 0;
+}
+
+static int tx_macro_tx_mixer_put(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_dapm_widget *widget = snd_soc_dapm_kcontrol_widget(kcontrol);
+	struct snd_soc_component *component = snd_soc_dapm_to_component(widget->dapm);
+	struct snd_soc_dapm_update *update = NULL;
+	struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value;
+	u32 dai_id = widget->shift;
+	u32 dec_id = mc->shift;
+	u32 enable = ucontrol->value.integer.value[0];
+	struct tx_macro *tx = snd_soc_component_get_drvdata(component);
+
+	if (enable) {
+		set_bit(dec_id, &tx->active_ch_mask[dai_id]);
+		tx->active_ch_cnt[dai_id]++;
+		tx->active_decimator[dai_id] = dec_id;
+	} else {
+		tx->active_ch_cnt[dai_id]--;
+		clear_bit(dec_id, &tx->active_ch_mask[dai_id]);
+		tx->active_decimator[dai_id] = -1;
+	}
+	snd_soc_dapm_mixer_update_power(widget->dapm, kcontrol, enable, update);
+
+	return 0;
+}
+
+static int tx_macro_enable_dec(struct snd_soc_dapm_widget *w,
+			       struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
+	unsigned int decimator;
+	u16 tx_vol_ctl_reg, dec_cfg_reg, hpf_gate_reg, tx_gain_ctl_reg;
+	u8 hpf_cut_off_freq;
+	int hpf_delay = TX_MACRO_DMIC_HPF_DELAY_MS;
+	int unmute_delay = TX_MACRO_DMIC_UNMUTE_DELAY_MS;
+	u16 adc_mux_reg, adc_reg, adc_n, dmic;
+	u16 dmic_clk_reg;
+	struct tx_macro *tx = snd_soc_component_get_drvdata(component);
+
+	decimator = w->shift;
+	tx_vol_ctl_reg = CDC_TXn_TX_PATH_CTL(decimator);
+	hpf_gate_reg = CDC_TXn_TX_PATH_SEC2(decimator);
+	dec_cfg_reg = CDC_TXn_TX_PATH_CFG0(decimator);
+	tx_gain_ctl_reg = CDC_TXn_TX_VOL_CTL(decimator);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		adc_mux_reg = CDC_TX_INP_MUX_ADC_MUXn_CFG1(decimator);
+		if (snd_soc_component_read(component, adc_mux_reg) & SWR_MIC) {
+			adc_reg = CDC_TX_INP_MUX_ADC_MUXn_CFG0(decimator);
+			adc_n = snd_soc_component_read(component, adc_reg) &
+				CDC_TX_MACRO_SWR_MIC_MUX_SEL_MASK;
+			if (adc_n >= TX_ADC_MAX) {
+				dmic = TX_ADC_TO_DMIC(adc_n);
+				dmic_clk_reg = CDC_TX_TOP_CSR_SWR_DMICn_CTL(dmic);
+
+				snd_soc_component_write_field(component, dmic_clk_reg,
+							CDC_TX_SWR_DMIC_CLK_SEL_MASK,
+							tx->dmic_clk_div);
+			}
+		}
+		snd_soc_component_write_field(component, dec_cfg_reg,
+					      CDC_TXn_ADC_MODE_MASK,
+					      tx->dec_mode[decimator]);
+		/* Enable TX PGA Mute */
+		snd_soc_component_write_field(component, tx_vol_ctl_reg,
+					      CDC_TXn_PGA_MUTE_MASK, 0x1);
+		break;
+	case SND_SOC_DAPM_POST_PMU:
+		snd_soc_component_write_field(component, tx_vol_ctl_reg,
+					     CDC_TXn_CLK_EN_MASK, 0x1);
+		if (!is_amic_enabled(component, decimator)) {
+			snd_soc_component_update_bits(component, hpf_gate_reg, 0x01, 0x00);
+			/* Minimum 1 clk cycle delay is required as per HW spec */
+			usleep_range(1000, 1010);
+		}
+		hpf_cut_off_freq = snd_soc_component_read_field(component, dec_cfg_reg,
+								CDC_TXn_HPF_CUT_FREQ_MASK);
+
+		tx->tx_hpf_work[decimator].hpf_cut_off_freq =
+						hpf_cut_off_freq;
+
+		if (hpf_cut_off_freq != CF_MIN_3DB_150HZ)
+			snd_soc_component_write_field(component, dec_cfg_reg,
+						      CDC_TXn_HPF_CUT_FREQ_MASK,
+						      CF_MIN_3DB_150HZ);
+
+		if (is_amic_enabled(component, decimator)) {
+			hpf_delay = TX_MACRO_AMIC_HPF_DELAY_MS;
+			unmute_delay = TX_MACRO_AMIC_UNMUTE_DELAY_MS;
+		}
+		/* schedule work queue to Remove Mute */
+		queue_delayed_work(system_freezable_wq,
+				   &tx->tx_mute_dwork[decimator].dwork,
+				   msecs_to_jiffies(unmute_delay));
+		if (tx->tx_hpf_work[decimator].hpf_cut_off_freq != CF_MIN_3DB_150HZ) {
+			queue_delayed_work(system_freezable_wq,
+				&tx->tx_hpf_work[decimator].dwork,
+				msecs_to_jiffies(hpf_delay));
+			snd_soc_component_update_bits(component, hpf_gate_reg,
+					      CDC_TXn_HPF_F_CHANGE_MASK |
+					      CDC_TXn_HPF_ZERO_GATE_MASK,
+					      0x02);
+			if (!is_amic_enabled(component, decimator))
+				snd_soc_component_update_bits(component, hpf_gate_reg,
+						      CDC_TXn_HPF_F_CHANGE_MASK |
+						      CDC_TXn_HPF_ZERO_GATE_MASK,
+						      0x00);
+			snd_soc_component_update_bits(component, hpf_gate_reg,
+					      CDC_TXn_HPF_F_CHANGE_MASK |
+					      CDC_TXn_HPF_ZERO_GATE_MASK,
+					      0x01);
+
+			/*
+			 * 6ms delay is required as per HW spec
+			 */
+			usleep_range(6000, 6010);
+		}
+		/* apply gain after decimator is enabled */
+		snd_soc_component_write(component, tx_gain_ctl_reg,
+			      snd_soc_component_read(component,
+					tx_gain_ctl_reg));
+		if (tx->bcs_enable) {
+			snd_soc_component_update_bits(component, dec_cfg_reg,
+					0x01, 0x01);
+			tx->bcs_clk_en = true;
+		}
+		break;
+	case SND_SOC_DAPM_PRE_PMD:
+		hpf_cut_off_freq =
+			tx->tx_hpf_work[decimator].hpf_cut_off_freq;
+		snd_soc_component_write_field(component, tx_vol_ctl_reg,
+					      CDC_TXn_PGA_MUTE_MASK, 0x1);
+		if (cancel_delayed_work_sync(
+		    &tx->tx_hpf_work[decimator].dwork)) {
+			if (hpf_cut_off_freq != CF_MIN_3DB_150HZ) {
+				snd_soc_component_write_field(
+						component, dec_cfg_reg,
+						CDC_TXn_HPF_CUT_FREQ_MASK,
+						hpf_cut_off_freq);
+				if (is_amic_enabled(component, decimator))
+					snd_soc_component_update_bits(component,
+					      hpf_gate_reg,
+					      CDC_TXn_HPF_F_CHANGE_MASK |
+					      CDC_TXn_HPF_ZERO_GATE_MASK,
+					      0x02);
+				else
+					snd_soc_component_update_bits(component,
+					      hpf_gate_reg,
+					      CDC_TXn_HPF_F_CHANGE_MASK |
+					      CDC_TXn_HPF_ZERO_GATE_MASK,
+					      0x03);
+
+				/*
+				 * Minimum 1 clk cycle delay is required
+				 * as per HW spec
+				 */
+				usleep_range(1000, 1010);
+				snd_soc_component_update_bits(component, hpf_gate_reg,
+					      CDC_TXn_HPF_F_CHANGE_MASK |
+					      CDC_TXn_HPF_ZERO_GATE_MASK,
+					      0x1);
+			}
+		}
+		cancel_delayed_work_sync(&tx->tx_mute_dwork[decimator].dwork);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		snd_soc_component_write_field(component, tx_vol_ctl_reg,
+					      CDC_TXn_CLK_EN_MASK, 0x0);
+		snd_soc_component_write_field(component, dec_cfg_reg,
+					      CDC_TXn_ADC_MODE_MASK, 0x0);
+		snd_soc_component_write_field(component, tx_vol_ctl_reg,
+					      CDC_TXn_PGA_MUTE_MASK, 0x0);
+		if (tx->bcs_enable) {
+			snd_soc_component_write_field(component, dec_cfg_reg,
+						      CDC_TXn_PH_EN_MASK, 0x0);
+			snd_soc_component_write_field(component,
+						      CDC_TX0_TX_PATH_SEC7,
+						      CDC_TX0_MBHC_CTL_EN_MASK,
+						      0x0);
+			tx->bcs_clk_en = false;
+		}
+		break;
+	}
+	return 0;
+}
+
+static int tx_macro_dec_mode_get(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
+	struct tx_macro *tx = snd_soc_component_get_drvdata(component);
+	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+	int path = e->shift_l;
+
+	ucontrol->value.integer.value[0] = tx->dec_mode[path];
+
+	return 0;
+}
+
+static int tx_macro_dec_mode_put(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
+	int value = ucontrol->value.integer.value[0];
+	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+	int path = e->shift_l;
+	struct tx_macro *tx = snd_soc_component_get_drvdata(component);
+
+	tx->dec_mode[path] = value;
+
+	return 0;
+}
+
+static int tx_macro_get_bcs(struct snd_kcontrol *kcontrol,
+			    struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
+	struct tx_macro *tx = snd_soc_component_get_drvdata(component);
+
+	ucontrol->value.integer.value[0] = tx->bcs_enable;
+
+	return 0;
+}
+
+static int tx_macro_set_bcs(struct snd_kcontrol *kcontrol,
+			    struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
+	int value = ucontrol->value.integer.value[0];
+	struct tx_macro *tx = snd_soc_component_get_drvdata(component);
+
+	tx->bcs_enable = value;
+
+	return 0;
+}
+
+static int tx_macro_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;
+	u32 decimator, sample_rate;
+	int tx_fs_rate;
+	struct tx_macro *tx = snd_soc_component_get_drvdata(component);
+
+	sample_rate = params_rate(params);
+	switch (sample_rate) {
+	case 8000:
+		tx_fs_rate = 0;
+		break;
+	case 16000:
+		tx_fs_rate = 1;
+		break;
+	case 32000:
+		tx_fs_rate = 3;
+		break;
+	case 48000:
+		tx_fs_rate = 4;
+		break;
+	case 96000:
+		tx_fs_rate = 5;
+		break;
+	case 192000:
+		tx_fs_rate = 6;
+		break;
+	case 384000:
+		tx_fs_rate = 7;
+		break;
+	default:
+		dev_err(component->dev, "%s: Invalid TX sample rate: %d\n",
+			__func__, params_rate(params));
+		return -EINVAL;
+	}
+
+	for_each_set_bit(decimator, &tx->active_ch_mask[dai->id], TX_MACRO_DEC_MAX)
+		snd_soc_component_update_bits(component, CDC_TXn_TX_PATH_CTL(decimator),
+					      CDC_TXn_PCM_RATE_MASK,
+					      tx_fs_rate);
+	return 0;
+}
+
+static int tx_macro_get_channel_map(struct snd_soc_dai *dai,
+				    unsigned int *tx_num, unsigned int *tx_slot,
+				    unsigned int *rx_num, unsigned int *rx_slot)
+{
+	struct snd_soc_component *component = dai->component;
+	struct tx_macro *tx = snd_soc_component_get_drvdata(component);
+
+	switch (dai->id) {
+	case TX_MACRO_AIF1_CAP:
+	case TX_MACRO_AIF2_CAP:
+	case TX_MACRO_AIF3_CAP:
+		*tx_slot = tx->active_ch_mask[dai->id];
+		*tx_num = tx->active_ch_cnt[dai->id];
+		break;
+	default:
+		break;
+	}
+	return 0;
+}
+
+static int tx_macro_digital_mute(struct snd_soc_dai *dai, int mute, int stream)
+{
+	struct snd_soc_component *component = dai->component;
+	struct tx_macro *tx = snd_soc_component_get_drvdata(component);
+	u16 decimator;
+
+	decimator = tx->active_decimator[dai->id];
+
+	if (mute)
+		snd_soc_component_write_field(component,
+					      CDC_TXn_TX_PATH_CTL(decimator),
+					      CDC_TXn_PGA_MUTE_MASK, 0x1);
+	else
+		snd_soc_component_update_bits(component,
+					      CDC_TXn_TX_PATH_CTL(decimator),
+					      CDC_TXn_PGA_MUTE_MASK, 0x0);
+
+	return 0;
+}
+
+static struct snd_soc_dai_ops tx_macro_dai_ops = {
+	.hw_params = tx_macro_hw_params,
+	.get_channel_map = tx_macro_get_channel_map,
+	.mute_stream = tx_macro_digital_mute,
+};
+
+static struct snd_soc_dai_driver tx_macro_dai[] = {
+	{
+		.name = "tx_macro_tx1",
+		.id = TX_MACRO_AIF1_CAP,
+		.capture = {
+			.stream_name = "TX_AIF1 Capture",
+			.rates = TX_MACRO_RATES,
+			.formats = TX_MACRO_FORMATS,
+			.rate_max = 192000,
+			.rate_min = 8000,
+			.channels_min = 1,
+			.channels_max = 8,
+		},
+		.ops = &tx_macro_dai_ops,
+	},
+	{
+		.name = "tx_macro_tx2",
+		.id = TX_MACRO_AIF2_CAP,
+		.capture = {
+			.stream_name = "TX_AIF2 Capture",
+			.rates = TX_MACRO_RATES,
+			.formats = TX_MACRO_FORMATS,
+			.rate_max = 192000,
+			.rate_min = 8000,
+			.channels_min = 1,
+			.channels_max = 8,
+		},
+		.ops = &tx_macro_dai_ops,
+	},
+	{
+		.name = "tx_macro_tx3",
+		.id = TX_MACRO_AIF3_CAP,
+		.capture = {
+			.stream_name = "TX_AIF3 Capture",
+			.rates = TX_MACRO_RATES,
+			.formats = TX_MACRO_FORMATS,
+			.rate_max = 192000,
+			.rate_min = 8000,
+			.channels_min = 1,
+			.channels_max = 8,
+		},
+		.ops = &tx_macro_dai_ops,
+	},
+};
+
+static const char * const adc_mux_text[] = {
+	"MSM_DMIC", "SWR_MIC", "ANC_FB_TUNE1"
+};
+
+static SOC_ENUM_SINGLE_DECL(tx_dec0_enum, CDC_TX_INP_MUX_ADC_MUX0_CFG1,
+		   0, adc_mux_text);
+static SOC_ENUM_SINGLE_DECL(tx_dec1_enum, CDC_TX_INP_MUX_ADC_MUX1_CFG1,
+		   0, adc_mux_text);
+static SOC_ENUM_SINGLE_DECL(tx_dec2_enum, CDC_TX_INP_MUX_ADC_MUX2_CFG1,
+		   0, adc_mux_text);
+static SOC_ENUM_SINGLE_DECL(tx_dec3_enum, CDC_TX_INP_MUX_ADC_MUX3_CFG1,
+		   0, adc_mux_text);
+static SOC_ENUM_SINGLE_DECL(tx_dec4_enum, CDC_TX_INP_MUX_ADC_MUX4_CFG1,
+		   0, adc_mux_text);
+static SOC_ENUM_SINGLE_DECL(tx_dec5_enum, CDC_TX_INP_MUX_ADC_MUX5_CFG1,
+		   0, adc_mux_text);
+static SOC_ENUM_SINGLE_DECL(tx_dec6_enum, CDC_TX_INP_MUX_ADC_MUX6_CFG1,
+		   0, adc_mux_text);
+static SOC_ENUM_SINGLE_DECL(tx_dec7_enum, CDC_TX_INP_MUX_ADC_MUX7_CFG1,
+		   0, adc_mux_text);
+
+static const struct snd_kcontrol_new tx_dec0_mux = SOC_DAPM_ENUM("tx_dec0", tx_dec0_enum);
+static const struct snd_kcontrol_new tx_dec1_mux = SOC_DAPM_ENUM("tx_dec1", tx_dec1_enum);
+static const struct snd_kcontrol_new tx_dec2_mux = SOC_DAPM_ENUM("tx_dec2", tx_dec2_enum);
+static const struct snd_kcontrol_new tx_dec3_mux = SOC_DAPM_ENUM("tx_dec3", tx_dec3_enum);
+static const struct snd_kcontrol_new tx_dec4_mux = SOC_DAPM_ENUM("tx_dec4", tx_dec4_enum);
+static const struct snd_kcontrol_new tx_dec5_mux = SOC_DAPM_ENUM("tx_dec5", tx_dec5_enum);
+static const struct snd_kcontrol_new tx_dec6_mux = SOC_DAPM_ENUM("tx_dec6", tx_dec6_enum);
+static const struct snd_kcontrol_new tx_dec7_mux = SOC_DAPM_ENUM("tx_dec7", tx_dec7_enum);
+
+static const char * const smic_mux_text[] = {
+	"ZERO", "ADC0", "ADC1", "ADC2", "ADC3", "SWR_DMIC0",
+	"SWR_DMIC1", "SWR_DMIC2", "SWR_DMIC3", "SWR_DMIC4",
+	"SWR_DMIC5", "SWR_DMIC6", "SWR_DMIC7"
+};
+
+static SOC_ENUM_SINGLE_DECL(tx_smic0_enum, CDC_TX_INP_MUX_ADC_MUX0_CFG0,
+			0, smic_mux_text);
+
+static SOC_ENUM_SINGLE_DECL(tx_smic1_enum, CDC_TX_INP_MUX_ADC_MUX1_CFG0,
+			0, smic_mux_text);
+
+static SOC_ENUM_SINGLE_DECL(tx_smic2_enum, CDC_TX_INP_MUX_ADC_MUX2_CFG0,
+			0, smic_mux_text);
+
+static SOC_ENUM_SINGLE_DECL(tx_smic3_enum, CDC_TX_INP_MUX_ADC_MUX3_CFG0,
+			0, smic_mux_text);
+
+static SOC_ENUM_SINGLE_DECL(tx_smic4_enum, CDC_TX_INP_MUX_ADC_MUX4_CFG0,
+			0, smic_mux_text);
+
+static SOC_ENUM_SINGLE_DECL(tx_smic5_enum, CDC_TX_INP_MUX_ADC_MUX5_CFG0,
+			0, smic_mux_text);
+
+static SOC_ENUM_SINGLE_DECL(tx_smic6_enum, CDC_TX_INP_MUX_ADC_MUX6_CFG0,
+			0, smic_mux_text);
+
+static SOC_ENUM_SINGLE_DECL(tx_smic7_enum, CDC_TX_INP_MUX_ADC_MUX7_CFG0,
+			0, smic_mux_text);
+
+static const struct snd_kcontrol_new tx_smic0_mux = SOC_DAPM_ENUM_EXT("tx_smic0", tx_smic0_enum,
+			snd_soc_dapm_get_enum_double, tx_macro_put_dec_enum);
+static const struct snd_kcontrol_new tx_smic1_mux = SOC_DAPM_ENUM_EXT("tx_smic1", tx_smic1_enum,
+			snd_soc_dapm_get_enum_double, tx_macro_put_dec_enum);
+static const struct snd_kcontrol_new tx_smic2_mux = SOC_DAPM_ENUM_EXT("tx_smic2", tx_smic2_enum,
+			snd_soc_dapm_get_enum_double, tx_macro_put_dec_enum);
+static const struct snd_kcontrol_new tx_smic3_mux = SOC_DAPM_ENUM_EXT("tx_smic3", tx_smic3_enum,
+			snd_soc_dapm_get_enum_double, tx_macro_put_dec_enum);
+static const struct snd_kcontrol_new tx_smic4_mux = SOC_DAPM_ENUM_EXT("tx_smic4", tx_smic4_enum,
+			snd_soc_dapm_get_enum_double, tx_macro_put_dec_enum);
+static const struct snd_kcontrol_new tx_smic5_mux = SOC_DAPM_ENUM_EXT("tx_smic5", tx_smic5_enum,
+			snd_soc_dapm_get_enum_double, tx_macro_put_dec_enum);
+static const struct snd_kcontrol_new tx_smic6_mux = SOC_DAPM_ENUM_EXT("tx_smic6", tx_smic6_enum,
+			snd_soc_dapm_get_enum_double, tx_macro_put_dec_enum);
+static const struct snd_kcontrol_new tx_smic7_mux = SOC_DAPM_ENUM_EXT("tx_smic7", tx_smic7_enum,
+			snd_soc_dapm_get_enum_double, tx_macro_put_dec_enum);
+
+static const char * const dec_mode_mux_text[] = {
+	"ADC_DEFAULT", "ADC_LOW_PWR", "ADC_HIGH_PERF",
+};
+
+static const struct soc_enum dec_mode_mux_enum[] = {
+	SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(dec_mode_mux_text),
+			dec_mode_mux_text),
+	SOC_ENUM_SINGLE(SND_SOC_NOPM, 1, ARRAY_SIZE(dec_mode_mux_text),
+			dec_mode_mux_text),
+	SOC_ENUM_SINGLE(SND_SOC_NOPM, 2,  ARRAY_SIZE(dec_mode_mux_text),
+			dec_mode_mux_text),
+	SOC_ENUM_SINGLE(SND_SOC_NOPM, 3, ARRAY_SIZE(dec_mode_mux_text),
+			dec_mode_mux_text),
+	SOC_ENUM_SINGLE(SND_SOC_NOPM, 4, ARRAY_SIZE(dec_mode_mux_text),
+			dec_mode_mux_text),
+	SOC_ENUM_SINGLE(SND_SOC_NOPM, 5, ARRAY_SIZE(dec_mode_mux_text),
+			dec_mode_mux_text),
+	SOC_ENUM_SINGLE(SND_SOC_NOPM, 6, ARRAY_SIZE(dec_mode_mux_text),
+			dec_mode_mux_text),
+	SOC_ENUM_SINGLE(SND_SOC_NOPM, 7, ARRAY_SIZE(dec_mode_mux_text),
+			dec_mode_mux_text),
+};
+
+static const struct snd_kcontrol_new tx_aif1_cap_mixer[] = {
+	SOC_SINGLE_EXT("DEC0", SND_SOC_NOPM, TX_MACRO_DEC0, 1, 0,
+			tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC1", SND_SOC_NOPM, TX_MACRO_DEC1, 1, 0,
+			tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC2", SND_SOC_NOPM, TX_MACRO_DEC2, 1, 0,
+			tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC3", SND_SOC_NOPM, TX_MACRO_DEC3, 1, 0,
+			tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC4", SND_SOC_NOPM, TX_MACRO_DEC4, 1, 0,
+			tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC5", SND_SOC_NOPM, TX_MACRO_DEC5, 1, 0,
+			tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC6", SND_SOC_NOPM, TX_MACRO_DEC6, 1, 0,
+			tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC7", SND_SOC_NOPM, TX_MACRO_DEC7, 1, 0,
+			tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+};
+
+static const struct snd_kcontrol_new tx_aif2_cap_mixer[] = {
+	SOC_SINGLE_EXT("DEC0", SND_SOC_NOPM, TX_MACRO_DEC0, 1, 0,
+			tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC1", SND_SOC_NOPM, TX_MACRO_DEC1, 1, 0,
+			tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC2", SND_SOC_NOPM, TX_MACRO_DEC2, 1, 0,
+			tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC3", SND_SOC_NOPM, TX_MACRO_DEC3, 1, 0,
+			tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC4", SND_SOC_NOPM, TX_MACRO_DEC4, 1, 0,
+			tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC5", SND_SOC_NOPM, TX_MACRO_DEC5, 1, 0,
+			tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC6", SND_SOC_NOPM, TX_MACRO_DEC6, 1, 0,
+			tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC7", SND_SOC_NOPM, TX_MACRO_DEC7, 1, 0,
+			tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+};
+
+static const struct snd_kcontrol_new tx_aif3_cap_mixer[] = {
+	SOC_SINGLE_EXT("DEC0", SND_SOC_NOPM, TX_MACRO_DEC0, 1, 0,
+			tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC1", SND_SOC_NOPM, TX_MACRO_DEC1, 1, 0,
+			tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC2", SND_SOC_NOPM, TX_MACRO_DEC2, 1, 0,
+			tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC3", SND_SOC_NOPM, TX_MACRO_DEC3, 1, 0,
+			tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC4", SND_SOC_NOPM, TX_MACRO_DEC4, 1, 0,
+			tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC5", SND_SOC_NOPM, TX_MACRO_DEC5, 1, 0,
+			tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC6", SND_SOC_NOPM, TX_MACRO_DEC6, 1, 0,
+			tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC7", SND_SOC_NOPM, TX_MACRO_DEC7, 1, 0,
+			tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+};
+
+static const struct snd_soc_dapm_widget tx_macro_dapm_widgets[] = {
+	SND_SOC_DAPM_AIF_OUT("TX_AIF1 CAP", "TX_AIF1 Capture", 0,
+		SND_SOC_NOPM, TX_MACRO_AIF1_CAP, 0),
+
+	SND_SOC_DAPM_AIF_OUT("TX_AIF2 CAP", "TX_AIF2 Capture", 0,
+		SND_SOC_NOPM, TX_MACRO_AIF2_CAP, 0),
+
+	SND_SOC_DAPM_AIF_OUT("TX_AIF3 CAP", "TX_AIF3 Capture", 0,
+		SND_SOC_NOPM, TX_MACRO_AIF3_CAP, 0),
+
+	SND_SOC_DAPM_MIXER("TX_AIF1_CAP Mixer", SND_SOC_NOPM, TX_MACRO_AIF1_CAP, 0,
+		tx_aif1_cap_mixer, ARRAY_SIZE(tx_aif1_cap_mixer)),
+
+	SND_SOC_DAPM_MIXER("TX_AIF2_CAP Mixer", SND_SOC_NOPM, TX_MACRO_AIF2_CAP, 0,
+		tx_aif2_cap_mixer, ARRAY_SIZE(tx_aif2_cap_mixer)),
+
+	SND_SOC_DAPM_MIXER("TX_AIF3_CAP Mixer", SND_SOC_NOPM, TX_MACRO_AIF3_CAP, 0,
+		tx_aif3_cap_mixer, ARRAY_SIZE(tx_aif3_cap_mixer)),
+
+	SND_SOC_DAPM_MUX("TX SMIC MUX0", SND_SOC_NOPM, 0, 0, &tx_smic0_mux),
+	SND_SOC_DAPM_MUX("TX SMIC MUX1", SND_SOC_NOPM, 0, 0, &tx_smic1_mux),
+	SND_SOC_DAPM_MUX("TX SMIC MUX2", SND_SOC_NOPM, 0, 0, &tx_smic2_mux),
+	SND_SOC_DAPM_MUX("TX SMIC MUX3", SND_SOC_NOPM, 0, 0, &tx_smic3_mux),
+	SND_SOC_DAPM_MUX("TX SMIC MUX4", SND_SOC_NOPM, 0, 0, &tx_smic4_mux),
+	SND_SOC_DAPM_MUX("TX SMIC MUX5", SND_SOC_NOPM, 0, 0, &tx_smic5_mux),
+	SND_SOC_DAPM_MUX("TX SMIC MUX6", SND_SOC_NOPM, 0, 0, &tx_smic6_mux),
+	SND_SOC_DAPM_MUX("TX SMIC MUX7", SND_SOC_NOPM, 0, 0, &tx_smic7_mux),
+
+	SND_SOC_DAPM_INPUT("TX SWR_ADC0"),
+	SND_SOC_DAPM_INPUT("TX SWR_ADC1"),
+	SND_SOC_DAPM_INPUT("TX SWR_ADC2"),
+	SND_SOC_DAPM_INPUT("TX SWR_ADC3"),
+	SND_SOC_DAPM_INPUT("TX SWR_DMIC0"),
+	SND_SOC_DAPM_INPUT("TX SWR_DMIC1"),
+	SND_SOC_DAPM_INPUT("TX SWR_DMIC2"),
+	SND_SOC_DAPM_INPUT("TX SWR_DMIC3"),
+	SND_SOC_DAPM_INPUT("TX SWR_DMIC4"),
+	SND_SOC_DAPM_INPUT("TX SWR_DMIC5"),
+	SND_SOC_DAPM_INPUT("TX SWR_DMIC6"),
+	SND_SOC_DAPM_INPUT("TX SWR_DMIC7"),
+
+	SND_SOC_DAPM_MUX_E("TX DEC0 MUX", SND_SOC_NOPM,
+			   TX_MACRO_DEC0, 0,
+			   &tx_dec0_mux, tx_macro_enable_dec,
+			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+			   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MUX_E("TX DEC1 MUX", SND_SOC_NOPM,
+			   TX_MACRO_DEC1, 0,
+			   &tx_dec1_mux, tx_macro_enable_dec,
+			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+			   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MUX_E("TX DEC2 MUX", SND_SOC_NOPM,
+			   TX_MACRO_DEC2, 0,
+			   &tx_dec2_mux, tx_macro_enable_dec,
+			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+			   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MUX_E("TX DEC3 MUX", SND_SOC_NOPM,
+			   TX_MACRO_DEC3, 0,
+			   &tx_dec3_mux, tx_macro_enable_dec,
+			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+			   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MUX_E("TX DEC4 MUX", SND_SOC_NOPM,
+			   TX_MACRO_DEC4, 0,
+			   &tx_dec4_mux, tx_macro_enable_dec,
+			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+			   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MUX_E("TX DEC5 MUX", SND_SOC_NOPM,
+			   TX_MACRO_DEC5, 0,
+			   &tx_dec5_mux, tx_macro_enable_dec,
+			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+			   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MUX_E("TX DEC6 MUX", SND_SOC_NOPM,
+			   TX_MACRO_DEC6, 0,
+			   &tx_dec6_mux, tx_macro_enable_dec,
+			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+			   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MUX_E("TX DEC7 MUX", SND_SOC_NOPM,
+			   TX_MACRO_DEC7, 0,
+			   &tx_dec7_mux, tx_macro_enable_dec,
+			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+			   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_SUPPLY_S("TX_MCLK", 0, SND_SOC_NOPM, 0, 0,
+	tx_macro_mclk_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_SUPPLY_S("TX_SWR_CLK", 0, SND_SOC_NOPM, 0, 0, NULL, 0),
+
+	SND_SOC_DAPM_SUPPLY_S("VA_SWR_CLK", 0, SND_SOC_NOPM, 0, 0,
+			NULL, 0),
+};
+
+static const struct snd_soc_dapm_route tx_audio_map[] = {
+	{"TX_AIF1 CAP", NULL, "TX_MCLK"},
+	{"TX_AIF2 CAP", NULL, "TX_MCLK"},
+	{"TX_AIF3 CAP", NULL, "TX_MCLK"},
+
+	{"TX_AIF1 CAP", NULL, "TX_AIF1_CAP Mixer"},
+	{"TX_AIF2 CAP", NULL, "TX_AIF2_CAP Mixer"},
+	{"TX_AIF3 CAP", NULL, "TX_AIF3_CAP Mixer"},
+
+	{"TX_AIF1_CAP Mixer", "DEC0", "TX DEC0 MUX"},
+	{"TX_AIF1_CAP Mixer", "DEC1", "TX DEC1 MUX"},
+	{"TX_AIF1_CAP Mixer", "DEC2", "TX DEC2 MUX"},
+	{"TX_AIF1_CAP Mixer", "DEC3", "TX DEC3 MUX"},
+	{"TX_AIF1_CAP Mixer", "DEC4", "TX DEC4 MUX"},
+	{"TX_AIF1_CAP Mixer", "DEC5", "TX DEC5 MUX"},
+	{"TX_AIF1_CAP Mixer", "DEC6", "TX DEC6 MUX"},
+	{"TX_AIF1_CAP Mixer", "DEC7", "TX DEC7 MUX"},
+
+	{"TX_AIF2_CAP Mixer", "DEC0", "TX DEC0 MUX"},
+	{"TX_AIF2_CAP Mixer", "DEC1", "TX DEC1 MUX"},
+	{"TX_AIF2_CAP Mixer", "DEC2", "TX DEC2 MUX"},
+	{"TX_AIF2_CAP Mixer", "DEC3", "TX DEC3 MUX"},
+	{"TX_AIF2_CAP Mixer", "DEC4", "TX DEC4 MUX"},
+	{"TX_AIF2_CAP Mixer", "DEC5", "TX DEC5 MUX"},
+	{"TX_AIF2_CAP Mixer", "DEC6", "TX DEC6 MUX"},
+	{"TX_AIF2_CAP Mixer", "DEC7", "TX DEC7 MUX"},
+
+	{"TX_AIF3_CAP Mixer", "DEC0", "TX DEC0 MUX"},
+	{"TX_AIF3_CAP Mixer", "DEC1", "TX DEC1 MUX"},
+	{"TX_AIF3_CAP Mixer", "DEC2", "TX DEC2 MUX"},
+	{"TX_AIF3_CAP Mixer", "DEC3", "TX DEC3 MUX"},
+	{"TX_AIF3_CAP Mixer", "DEC4", "TX DEC4 MUX"},
+	{"TX_AIF3_CAP Mixer", "DEC5", "TX DEC5 MUX"},
+	{"TX_AIF3_CAP Mixer", "DEC6", "TX DEC6 MUX"},
+	{"TX_AIF3_CAP Mixer", "DEC7", "TX DEC7 MUX"},
+
+	{"TX DEC0 MUX", NULL, "TX_MCLK"},
+	{"TX DEC1 MUX", NULL, "TX_MCLK"},
+	{"TX DEC2 MUX", NULL, "TX_MCLK"},
+	{"TX DEC3 MUX", NULL, "TX_MCLK"},
+	{"TX DEC4 MUX", NULL, "TX_MCLK"},
+	{"TX DEC5 MUX", NULL, "TX_MCLK"},
+	{"TX DEC6 MUX", NULL, "TX_MCLK"},
+	{"TX DEC7 MUX", NULL, "TX_MCLK"},
+
+	{"TX DEC0 MUX", "SWR_MIC", "TX SMIC MUX0"},
+	{"TX SMIC MUX0", NULL, "TX_SWR_CLK"},
+	{"TX SMIC MUX0", "ADC0", "TX SWR_ADC0"},
+	{"TX SMIC MUX0", "ADC1", "TX SWR_ADC1"},
+	{"TX SMIC MUX0", "ADC2", "TX SWR_ADC2"},
+	{"TX SMIC MUX0", "ADC3", "TX SWR_ADC3"},
+	{"TX SMIC MUX0", "SWR_DMIC0", "TX SWR_DMIC0"},
+	{"TX SMIC MUX0", "SWR_DMIC1", "TX SWR_DMIC1"},
+	{"TX SMIC MUX0", "SWR_DMIC2", "TX SWR_DMIC2"},
+	{"TX SMIC MUX0", "SWR_DMIC3", "TX SWR_DMIC3"},
+	{"TX SMIC MUX0", "SWR_DMIC4", "TX SWR_DMIC4"},
+	{"TX SMIC MUX0", "SWR_DMIC5", "TX SWR_DMIC5"},
+	{"TX SMIC MUX0", "SWR_DMIC6", "TX SWR_DMIC6"},
+	{"TX SMIC MUX0", "SWR_DMIC7", "TX SWR_DMIC7"},
+
+	{"TX DEC1 MUX", "SWR_MIC", "TX SMIC MUX1"},
+	{"TX SMIC MUX1", NULL, "TX_SWR_CLK"},
+	{"TX SMIC MUX1", "ADC0", "TX SWR_ADC0"},
+	{"TX SMIC MUX1", "ADC1", "TX SWR_ADC1"},
+	{"TX SMIC MUX1", "ADC2", "TX SWR_ADC2"},
+	{"TX SMIC MUX1", "ADC3", "TX SWR_ADC3"},
+	{"TX SMIC MUX1", "SWR_DMIC0", "TX SWR_DMIC0"},
+	{"TX SMIC MUX1", "SWR_DMIC1", "TX SWR_DMIC1"},
+	{"TX SMIC MUX1", "SWR_DMIC2", "TX SWR_DMIC2"},
+	{"TX SMIC MUX1", "SWR_DMIC3", "TX SWR_DMIC3"},
+	{"TX SMIC MUX1", "SWR_DMIC4", "TX SWR_DMIC4"},
+	{"TX SMIC MUX1", "SWR_DMIC5", "TX SWR_DMIC5"},
+	{"TX SMIC MUX1", "SWR_DMIC6", "TX SWR_DMIC6"},
+	{"TX SMIC MUX1", "SWR_DMIC7", "TX SWR_DMIC7"},
+
+	{"TX DEC2 MUX", "SWR_MIC", "TX SMIC MUX2"},
+	{"TX SMIC MUX2", NULL, "TX_SWR_CLK"},
+	{"TX SMIC MUX2", "ADC0", "TX SWR_ADC0"},
+	{"TX SMIC MUX2", "ADC1", "TX SWR_ADC1"},
+	{"TX SMIC MUX2", "ADC2", "TX SWR_ADC2"},
+	{"TX SMIC MUX2", "ADC3", "TX SWR_ADC3"},
+	{"TX SMIC MUX2", "SWR_DMIC0", "TX SWR_DMIC0"},
+	{"TX SMIC MUX2", "SWR_DMIC1", "TX SWR_DMIC1"},
+	{"TX SMIC MUX2", "SWR_DMIC2", "TX SWR_DMIC2"},
+	{"TX SMIC MUX2", "SWR_DMIC3", "TX SWR_DMIC3"},
+	{"TX SMIC MUX2", "SWR_DMIC4", "TX SWR_DMIC4"},
+	{"TX SMIC MUX2", "SWR_DMIC5", "TX SWR_DMIC5"},
+	{"TX SMIC MUX2", "SWR_DMIC6", "TX SWR_DMIC6"},
+	{"TX SMIC MUX2", "SWR_DMIC7", "TX SWR_DMIC7"},
+
+	{"TX DEC3 MUX", "SWR_MIC", "TX SMIC MUX3"},
+	{"TX SMIC MUX3", NULL, "TX_SWR_CLK"},
+	{"TX SMIC MUX3", "ADC0", "TX SWR_ADC0"},
+	{"TX SMIC MUX3", "ADC1", "TX SWR_ADC1"},
+	{"TX SMIC MUX3", "ADC2", "TX SWR_ADC2"},
+	{"TX SMIC MUX3", "ADC3", "TX SWR_ADC3"},
+	{"TX SMIC MUX3", "SWR_DMIC0", "TX SWR_DMIC0"},
+	{"TX SMIC MUX3", "SWR_DMIC1", "TX SWR_DMIC1"},
+	{"TX SMIC MUX3", "SWR_DMIC2", "TX SWR_DMIC2"},
+	{"TX SMIC MUX3", "SWR_DMIC3", "TX SWR_DMIC3"},
+	{"TX SMIC MUX3", "SWR_DMIC4", "TX SWR_DMIC4"},
+	{"TX SMIC MUX3", "SWR_DMIC5", "TX SWR_DMIC5"},
+	{"TX SMIC MUX3", "SWR_DMIC6", "TX SWR_DMIC6"},
+	{"TX SMIC MUX3", "SWR_DMIC7", "TX SWR_DMIC7"},
+
+	{"TX DEC4 MUX", "SWR_MIC", "TX SMIC MUX4"},
+	{"TX SMIC MUX4", NULL, "TX_SWR_CLK"},
+	{"TX SMIC MUX4", "ADC0", "TX SWR_ADC0"},
+	{"TX SMIC MUX4", "ADC1", "TX SWR_ADC1"},
+	{"TX SMIC MUX4", "ADC2", "TX SWR_ADC2"},
+	{"TX SMIC MUX4", "ADC3", "TX SWR_ADC3"},
+	{"TX SMIC MUX4", "SWR_DMIC0", "TX SWR_DMIC0"},
+	{"TX SMIC MUX4", "SWR_DMIC1", "TX SWR_DMIC1"},
+	{"TX SMIC MUX4", "SWR_DMIC2", "TX SWR_DMIC2"},
+	{"TX SMIC MUX4", "SWR_DMIC3", "TX SWR_DMIC3"},
+	{"TX SMIC MUX4", "SWR_DMIC4", "TX SWR_DMIC4"},
+	{"TX SMIC MUX4", "SWR_DMIC5", "TX SWR_DMIC5"},
+	{"TX SMIC MUX4", "SWR_DMIC6", "TX SWR_DMIC6"},
+	{"TX SMIC MUX4", "SWR_DMIC7", "TX SWR_DMIC7"},
+
+	{"TX DEC5 MUX", "SWR_MIC", "TX SMIC MUX5"},
+	{"TX SMIC MUX5", NULL, "TX_SWR_CLK"},
+	{"TX SMIC MUX5", "ADC0", "TX SWR_ADC0"},
+	{"TX SMIC MUX5", "ADC1", "TX SWR_ADC1"},
+	{"TX SMIC MUX5", "ADC2", "TX SWR_ADC2"},
+	{"TX SMIC MUX5", "ADC3", "TX SWR_ADC3"},
+	{"TX SMIC MUX5", "SWR_DMIC0", "TX SWR_DMIC0"},
+	{"TX SMIC MUX5", "SWR_DMIC1", "TX SWR_DMIC1"},
+	{"TX SMIC MUX5", "SWR_DMIC2", "TX SWR_DMIC2"},
+	{"TX SMIC MUX5", "SWR_DMIC3", "TX SWR_DMIC3"},
+	{"TX SMIC MUX5", "SWR_DMIC4", "TX SWR_DMIC4"},
+	{"TX SMIC MUX5", "SWR_DMIC5", "TX SWR_DMIC5"},
+	{"TX SMIC MUX5", "SWR_DMIC6", "TX SWR_DMIC6"},
+	{"TX SMIC MUX5", "SWR_DMIC7", "TX SWR_DMIC7"},
+
+	{"TX DEC6 MUX", "SWR_MIC", "TX SMIC MUX6"},
+	{"TX SMIC MUX6", NULL, "TX_SWR_CLK"},
+	{"TX SMIC MUX6", "ADC0", "TX SWR_ADC0"},
+	{"TX SMIC MUX6", "ADC1", "TX SWR_ADC1"},
+	{"TX SMIC MUX6", "ADC2", "TX SWR_ADC2"},
+	{"TX SMIC MUX6", "ADC3", "TX SWR_ADC3"},
+	{"TX SMIC MUX6", "SWR_DMIC0", "TX SWR_DMIC0"},
+	{"TX SMIC MUX6", "SWR_DMIC1", "TX SWR_DMIC1"},
+	{"TX SMIC MUX6", "SWR_DMIC2", "TX SWR_DMIC2"},
+	{"TX SMIC MUX6", "SWR_DMIC3", "TX SWR_DMIC3"},
+	{"TX SMIC MUX6", "SWR_DMIC4", "TX SWR_DMIC4"},
+	{"TX SMIC MUX6", "SWR_DMIC5", "TX SWR_DMIC5"},
+	{"TX SMIC MUX6", "SWR_DMIC6", "TX SWR_DMIC6"},
+	{"TX SMIC MUX6", "SWR_DMIC7", "TX SWR_DMIC7"},
+
+	{"TX DEC7 MUX", "SWR_MIC", "TX SMIC MUX7"},
+	{"TX SMIC MUX7", NULL, "TX_SWR_CLK"},
+	{"TX SMIC MUX7", "ADC0", "TX SWR_ADC0"},
+	{"TX SMIC MUX7", "ADC1", "TX SWR_ADC1"},
+	{"TX SMIC MUX7", "ADC2", "TX SWR_ADC2"},
+	{"TX SMIC MUX7", "ADC3", "TX SWR_ADC3"},
+	{"TX SMIC MUX7", "SWR_DMIC0", "TX SWR_DMIC0"},
+	{"TX SMIC MUX7", "SWR_DMIC1", "TX SWR_DMIC1"},
+	{"TX SMIC MUX7", "SWR_DMIC2", "TX SWR_DMIC2"},
+	{"TX SMIC MUX7", "SWR_DMIC3", "TX SWR_DMIC3"},
+	{"TX SMIC MUX7", "SWR_DMIC4", "TX SWR_DMIC4"},
+	{"TX SMIC MUX7", "SWR_DMIC5", "TX SWR_DMIC5"},
+	{"TX SMIC MUX7", "SWR_DMIC6", "TX SWR_DMIC6"},
+	{"TX SMIC MUX7", "SWR_DMIC7", "TX SWR_DMIC7"},
+};
+
+static const struct snd_kcontrol_new tx_macro_snd_controls[] = {
+	SOC_SINGLE_S8_TLV("TX_DEC0 Volume",
+			  CDC_TX0_TX_VOL_CTL,
+			  -84, 40, digital_gain),
+	SOC_SINGLE_S8_TLV("TX_DEC1 Volume",
+			  CDC_TX1_TX_VOL_CTL,
+			  -84, 40, digital_gain),
+	SOC_SINGLE_S8_TLV("TX_DEC2 Volume",
+			  CDC_TX2_TX_VOL_CTL,
+			  -84, 40, digital_gain),
+	SOC_SINGLE_S8_TLV("TX_DEC3 Volume",
+			  CDC_TX3_TX_VOL_CTL,
+			  -84, 40, digital_gain),
+	SOC_SINGLE_S8_TLV("TX_DEC4 Volume",
+			  CDC_TX4_TX_VOL_CTL,
+			  -84, 40, digital_gain),
+	SOC_SINGLE_S8_TLV("TX_DEC5 Volume",
+			  CDC_TX5_TX_VOL_CTL,
+			  -84, 40, digital_gain),
+	SOC_SINGLE_S8_TLV("TX_DEC6 Volume",
+			  CDC_TX6_TX_VOL_CTL,
+			  -84, 40, digital_gain),
+	SOC_SINGLE_S8_TLV("TX_DEC7 Volume",
+			  CDC_TX7_TX_VOL_CTL,
+			  -84, 40, digital_gain),
+
+	SOC_ENUM_EXT("DEC0 MODE", dec_mode_mux_enum[0],
+			tx_macro_dec_mode_get, tx_macro_dec_mode_put),
+
+	SOC_ENUM_EXT("DEC1 MODE", dec_mode_mux_enum[1],
+			tx_macro_dec_mode_get, tx_macro_dec_mode_put),
+
+	SOC_ENUM_EXT("DEC2 MODE", dec_mode_mux_enum[2],
+			tx_macro_dec_mode_get, tx_macro_dec_mode_put),
+
+	SOC_ENUM_EXT("DEC3 MODE", dec_mode_mux_enum[3],
+			tx_macro_dec_mode_get, tx_macro_dec_mode_put),
+
+	SOC_ENUM_EXT("DEC4 MODE", dec_mode_mux_enum[4],
+			tx_macro_dec_mode_get, tx_macro_dec_mode_put),
+
+	SOC_ENUM_EXT("DEC5 MODE", dec_mode_mux_enum[5],
+			tx_macro_dec_mode_get, tx_macro_dec_mode_put),
+
+	SOC_ENUM_EXT("DEC6 MODE", dec_mode_mux_enum[6],
+			tx_macro_dec_mode_get, tx_macro_dec_mode_put),
+
+	SOC_ENUM_EXT("DEC7 MODE", dec_mode_mux_enum[7],
+			tx_macro_dec_mode_get, tx_macro_dec_mode_put),
+
+	SOC_SINGLE_EXT("DEC0_BCS Switch", SND_SOC_NOPM, 0, 1, 0,
+		       tx_macro_get_bcs, tx_macro_set_bcs),
+};
+
+static int tx_macro_component_probe(struct snd_soc_component *comp)
+{
+	struct tx_macro *tx = snd_soc_component_get_drvdata(comp);
+	int i;
+
+	snd_soc_component_init_regmap(comp, tx->regmap);
+
+	for (i = 0; i < NUM_DECIMATORS; i++) {
+		tx->tx_hpf_work[i].tx = tx;
+		tx->tx_hpf_work[i].decimator = i;
+		INIT_DELAYED_WORK(&tx->tx_hpf_work[i].dwork,
+			tx_macro_tx_hpf_corner_freq_callback);
+	}
+
+	for (i = 0; i < NUM_DECIMATORS; i++) {
+		tx->tx_mute_dwork[i].tx = tx;
+		tx->tx_mute_dwork[i].decimator = i;
+		INIT_DELAYED_WORK(&tx->tx_mute_dwork[i].dwork,
+			  tx_macro_mute_update_callback);
+	}
+	tx->component = comp;
+
+	snd_soc_component_update_bits(comp, CDC_TX0_TX_PATH_SEC7, 0x3F,
+				      0x0A);
+
+	return 0;
+}
+
+static int swclk_gate_enable(struct clk_hw *hw)
+{
+	struct tx_macro *tx = to_tx_macro(hw);
+	struct regmap *regmap = tx->regmap;
+
+	tx_macro_mclk_enable(tx, true);
+	if (tx->reset_swr)
+		regmap_update_bits(regmap, CDC_TX_CLK_RST_CTRL_SWR_CONTROL,
+				   CDC_TX_SWR_RESET_MASK,
+				   CDC_TX_SWR_RESET_ENABLE);
+
+	regmap_update_bits(regmap, CDC_TX_CLK_RST_CTRL_SWR_CONTROL,
+			   CDC_TX_SWR_CLK_EN_MASK,
+			   CDC_TX_SWR_CLK_ENABLE);
+	if (tx->reset_swr)
+		regmap_update_bits(regmap, CDC_TX_CLK_RST_CTRL_SWR_CONTROL,
+				   CDC_TX_SWR_RESET_MASK, 0x0);
+	tx->reset_swr = false;
+
+	return 0;
+}
+
+static void swclk_gate_disable(struct clk_hw *hw)
+{
+	struct tx_macro *tx = to_tx_macro(hw);
+	struct regmap *regmap = tx->regmap;
+
+	regmap_update_bits(regmap, CDC_TX_CLK_RST_CTRL_SWR_CONTROL,
+			   CDC_TX_SWR_CLK_EN_MASK, 0x0);
+
+	tx_macro_mclk_enable(tx, false);
+}
+
+static int swclk_gate_is_enabled(struct clk_hw *hw)
+{
+	struct tx_macro *tx = to_tx_macro(hw);
+	int ret, val;
+
+	regmap_read(tx->regmap, CDC_TX_CLK_RST_CTRL_SWR_CONTROL, &val);
+	ret = val & BIT(0);
+
+	return ret;
+}
+
+static unsigned long swclk_recalc_rate(struct clk_hw *hw,
+				       unsigned long parent_rate)
+{
+	return parent_rate / 2;
+}
+
+static const struct clk_ops swclk_gate_ops = {
+	.prepare = swclk_gate_enable,
+	.unprepare = swclk_gate_disable,
+	.is_enabled = swclk_gate_is_enabled,
+	.recalc_rate = swclk_recalc_rate,
+
+};
+
+static struct clk *tx_macro_register_mclk_output(struct tx_macro *tx)
+{
+	struct device *dev = tx->dev;
+	struct device_node *np = dev->of_node;
+	const char *parent_clk_name = NULL;
+	const char *clk_name = "lpass-tx-mclk";
+	struct clk_hw *hw;
+	struct clk_init_data init;
+	int ret;
+
+	parent_clk_name = __clk_get_name(tx->clks[2].clk);
+
+	init.name = clk_name;
+	init.ops = &swclk_gate_ops;
+	init.flags = 0;
+	init.parent_names = &parent_clk_name;
+	init.num_parents = 1;
+	tx->hw.init = &init;
+	hw = &tx->hw;
+	ret = clk_hw_register(tx->dev, hw);
+	if (ret)
+		return ERR_PTR(ret);
+
+	of_clk_add_provider(np, of_clk_src_simple_get, hw->clk);
+
+	return NULL;
+}
+
+static const struct snd_soc_component_driver tx_macro_component_drv = {
+	.name = "RX-MACRO",
+	.probe = tx_macro_component_probe,
+	.controls = tx_macro_snd_controls,
+	.num_controls = ARRAY_SIZE(tx_macro_snd_controls),
+	.dapm_widgets = tx_macro_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(tx_macro_dapm_widgets),
+	.dapm_routes = tx_audio_map,
+	.num_dapm_routes = ARRAY_SIZE(tx_audio_map),
+};
+
+static int tx_macro_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct tx_macro *tx;
+	void __iomem *base;
+	int ret;
+
+	tx = devm_kzalloc(dev, sizeof(*tx), GFP_KERNEL);
+	if (!tx)
+		return -ENOMEM;
+
+	tx->clks[0].id = "macro";
+	tx->clks[1].id = "dcodec";
+	tx->clks[2].id = "mclk";
+	tx->clks[3].id = "npl";
+	tx->clks[4].id = "fsgen";
+
+	ret = devm_clk_bulk_get(dev, TX_NUM_CLKS_MAX, tx->clks);
+	if (ret) {
+		dev_err(dev, "Error getting RX Clocks (%d)\n", ret);
+		return ret;
+	}
+
+	base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+
+	tx->regmap = devm_regmap_init_mmio(dev, base, &tx_regmap_config);
+
+	dev_set_drvdata(dev, tx);
+
+	tx->reset_swr = true;
+	tx->dev = dev;
+
+	/* set MCLK and NPL rates */
+	clk_set_rate(tx->clks[2].clk, MCLK_FREQ);
+	clk_set_rate(tx->clks[3].clk, MCLK_FREQ);
+
+	ret = clk_bulk_prepare_enable(TX_NUM_CLKS_MAX, tx->clks);
+	if (ret)
+		return ret;
+
+	tx_macro_register_mclk_output(tx);
+
+	ret = devm_snd_soc_register_component(dev, &tx_macro_component_drv,
+					      tx_macro_dai,
+					      ARRAY_SIZE(tx_macro_dai));
+	if (ret)
+		goto err;
+	return ret;
+err:
+	clk_bulk_disable_unprepare(TX_NUM_CLKS_MAX, tx->clks);
+
+	return ret;
+}
+
+static int tx_macro_remove(struct platform_device *pdev)
+{
+	struct tx_macro *tx = dev_get_drvdata(&pdev->dev);
+
+	of_clk_del_provider(pdev->dev.of_node);
+
+	clk_bulk_disable_unprepare(TX_NUM_CLKS_MAX, tx->clks);
+
+	return 0;
+}
+
+static const struct of_device_id tx_macro_dt_match[] = {
+	{ .compatible = "qcom,sm8250-lpass-tx-macro" },
+	{ }
+};
+static struct platform_driver tx_macro_driver = {
+	.driver = {
+		.name = "tx_macro",
+		.of_match_table = tx_macro_dt_match,
+		.suppress_bind_attrs = true,
+	},
+	.probe = tx_macro_probe,
+	.remove = tx_macro_remove,
+};
+
+module_platform_driver(tx_macro_driver);
+
+MODULE_DESCRIPTION("TX macro driver");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/lpass-wsa-macro.c b/sound/soc/codecs/lpass-wsa-macro.c
index 25f1df214ca5..5ebcd935ba89 100644
--- a/sound/soc/codecs/lpass-wsa-macro.c
+++ b/sound/soc/codecs/lpass-wsa-macro.c
@@ -40,9 +40,11 @@
 #define CDC_WSA_TOP_I2S_CLK			(0x00A4)
 #define CDC_WSA_TOP_I2S_RESET			(0x00A8)
 #define CDC_WSA_RX_INP_MUX_RX_INT0_CFG0		(0x0100)
-#define CDC_WSA_RX_INTX_1_MIX_INP2_SEL_MASK	GENMASK(5, 3)
-#define CDC_WSA_RX_INTX_2_SEL_MASK		GENMASK(2, 0)
+#define CDC_WSA_RX_INTX_1_MIX_INP0_SEL_MASK	GENMASK(2, 0)
+#define CDC_WSA_RX_INTX_1_MIX_INP1_SEL_MASK	GENMASK(5, 3)
 #define CDC_WSA_RX_INP_MUX_RX_INT0_CFG1		(0x0104)
+#define CDC_WSA_RX_INTX_2_SEL_MASK		GENMASK(2, 0)
+#define CDC_WSA_RX_INTX_1_MIX_INP2_SEL_MASK	GENMASK(5, 3)
 #define CDC_WSA_RX_INP_MUX_RX_INT1_CFG0		(0x0108)
 #define CDC_WSA_RX_INP_MUX_RX_INT1_CFG1		(0x010C)
 #define CDC_WSA_RX_INP_MUX_RX_MIX_CFG0		(0x0110)
@@ -229,8 +231,6 @@
 #define NUM_INTERPOLATORS 2
 #define WSA_NUM_CLKS_MAX	5
 #define WSA_MACRO_MCLK_FREQ 19200000
-#define WSA_MACRO_MUX_INP_SHFT 0x3
-#define WSA_MACRO_MUX_INP_MASK1 0x07
 #define WSA_MACRO_MUX_INP_MASK2 0x38
 #define WSA_MACRO_MUX_CFG_OFFSET 0x8
 #define WSA_MACRO_MUX_CFG1_OFFSET 0x4
@@ -843,7 +843,6 @@ static int wsa_macro_set_prim_interpolator_rate(struct snd_soc_dai *dai,
 	u32 j, port;
 	u16 int_mux_cfg0, int_mux_cfg1;
 	u16 int_fs_reg;
-	u8 int_mux_cfg0_val, int_mux_cfg1_val;
 	u8 inp0_sel, inp1_sel, inp2_sel;
 	struct snd_soc_component *component = dai->component;
 	struct wsa_macro *wsa = snd_soc_component_get_drvdata(component);
@@ -865,15 +864,13 @@ static int wsa_macro_set_prim_interpolator_rate(struct snd_soc_dai *dai,
 		 */
 		for (j = 0; j < NUM_INTERPOLATORS; j++) {
 			int_mux_cfg1 = int_mux_cfg0 + WSA_MACRO_MUX_CFG1_OFFSET;
-			int_mux_cfg0_val = snd_soc_component_read(component,
-								  int_mux_cfg0);
-			int_mux_cfg1_val = snd_soc_component_read(component,
-								  int_mux_cfg1);
-			inp0_sel = int_mux_cfg0_val & WSA_MACRO_MUX_INP_MASK1;
-			inp1_sel = (int_mux_cfg0_val >> WSA_MACRO_MUX_INP_SHFT) &
-						WSA_MACRO_MUX_INP_MASK1;
-			inp2_sel = (int_mux_cfg1_val >> WSA_MACRO_MUX_INP_SHFT) &
-						WSA_MACRO_MUX_INP_MASK1;
+			inp0_sel = snd_soc_component_read_field(component, int_mux_cfg0, 
+								CDC_WSA_RX_INTX_1_MIX_INP0_SEL_MASK);
+			inp1_sel = snd_soc_component_read_field(component, int_mux_cfg0, 
+								CDC_WSA_RX_INTX_1_MIX_INP1_SEL_MASK);
+			inp2_sel = snd_soc_component_read_field(component, int_mux_cfg1,
+								CDC_WSA_RX_INTX_1_MIX_INP2_SEL_MASK);
+
 			if ((inp0_sel == int_1_mix1_inp + INTn_1_INP_SEL_RX0) ||
 			    (inp1_sel == int_1_mix1_inp + INTn_1_INP_SEL_RX0) ||
 			    (inp2_sel == int_1_mix1_inp + INTn_1_INP_SEL_RX0)) {
@@ -912,9 +909,9 @@ static int wsa_macro_set_mix_interpolator_rate(struct snd_soc_dai *dai,
 
 		int_mux_cfg1 = CDC_WSA_RX_INP_MUX_RX_INT0_CFG1;
 		for (j = 0; j < NUM_INTERPOLATORS; j++) {
-			int_mux_cfg1_val = snd_soc_component_read(component,
-							int_mux_cfg1) &
-							WSA_MACRO_MUX_INP_MASK1;
+			int_mux_cfg1_val = snd_soc_component_read_field(component, int_mux_cfg1,
+									CDC_WSA_RX_INTX_2_SEL_MASK);
+
 			if (int_mux_cfg1_val == int_2_inp + INTn_2_INP_SEL_RX0) {
 				int_fs_reg = CDC_WSA_RX0_RX_PATH_MIX_CTL +
 					WSA_MACRO_RX_PATH_OFFSET * j;
@@ -1410,25 +1407,25 @@ static bool wsa_macro_adie_lb(struct snd_soc_component *component,
 			      int interp_idx)
 {
 	u16 int_mux_cfg0,  int_mux_cfg1;
-	u8 int_mux_cfg0_val, int_mux_cfg1_val;
 	u8 int_n_inp0, int_n_inp1, int_n_inp2;
 
 	int_mux_cfg0 = CDC_WSA_RX_INP_MUX_RX_INT0_CFG0 + interp_idx * 8;
 	int_mux_cfg1 = int_mux_cfg0 + 4;
-	int_mux_cfg0_val = snd_soc_component_read(component, int_mux_cfg0);
-	int_mux_cfg1_val = snd_soc_component_read(component, int_mux_cfg1);
 
-	int_n_inp0 = int_mux_cfg0_val & 0x0F;
+	int_n_inp0 = snd_soc_component_read_field(component, int_mux_cfg0,
+						  CDC_WSA_RX_INTX_1_MIX_INP0_SEL_MASK);
 	if (int_n_inp0 == INTn_1_INP_SEL_DEC0 ||
 		int_n_inp0 == INTn_1_INP_SEL_DEC1)
 		return true;
 
-	int_n_inp1 = int_mux_cfg0_val >> 4;
+	int_n_inp1 = snd_soc_component_read_field(component, int_mux_cfg0,
+						  CDC_WSA_RX_INTX_1_MIX_INP1_SEL_MASK);
 	if (int_n_inp1 == INTn_1_INP_SEL_DEC0 ||
 		int_n_inp1 == INTn_1_INP_SEL_DEC1)
 		return true;
 
-	int_n_inp2 = int_mux_cfg1_val >> 4;
+	int_n_inp2 = snd_soc_component_read_field(component, int_mux_cfg1,
+						  CDC_WSA_RX_INTX_1_MIX_INP2_SEL_MASK);
 	if (int_n_inp2 == INTn_1_INP_SEL_DEC0 ||
 		int_n_inp2 == INTn_1_INP_SEL_DEC1)
 		return true;
diff --git a/sound/soc/codecs/max98373-sdw.c b/sound/soc/codecs/max98373-sdw.c
index b8d471d79e93..d8c47667a9ea 100644
--- a/sound/soc/codecs/max98373-sdw.c
+++ b/sound/soc/codecs/max98373-sdw.c
@@ -262,6 +262,8 @@ static __maybe_unused int max98373_suspend(struct device *dev)
 	return 0;
 }
 
+#define MAX98373_PROBE_TIMEOUT 5000
+
 static __maybe_unused int max98373_resume(struct device *dev)
 {
 	struct sdw_slave *slave = dev_to_sdw_dev(dev);
@@ -275,7 +277,7 @@ static __maybe_unused int max98373_resume(struct device *dev)
 		goto regmap_sync;
 
 	time = wait_for_completion_timeout(&slave->initialization_complete,
-					   msecs_to_jiffies(2000));
+					   msecs_to_jiffies(MAX98373_PROBE_TIMEOUT));
 	if (!time) {
 		dev_err(dev, "Initialization not complete, timed out\n");
 		return -ETIMEDOUT;
diff --git a/sound/soc/codecs/max9860.c b/sound/soc/codecs/max9860.c
index d5925c42b4b5..dd29b183ecd6 100644
--- a/sound/soc/codecs/max9860.c
+++ b/sound/soc/codecs/max9860.c
@@ -489,7 +489,7 @@ static struct snd_soc_dai_driver max9860_dai = {
 			   SNDRV_PCM_FMTBIT_S32_LE,
 	},
 	.ops = &max9860_dai_ops,
-	.symmetric_rates = 1,
+	.symmetric_rate = 1,
 };
 
 static int max9860_set_bias_level(struct snd_soc_component *component,
diff --git a/sound/soc/codecs/max9867.c b/sound/soc/codecs/max9867.c
index 512e6f2513d3..09b2d730e9fd 100644
--- a/sound/soc/codecs/max9867.c
+++ b/sound/soc/codecs/max9867.c
@@ -520,7 +520,7 @@ static struct snd_soc_dai_driver max9867_dai[] = {
 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
 	},
 	.ops = &max9867_dai_ops,
-	.symmetric_rates = 1,
+	.symmetric_rate = 1,
 	}
 };
 
diff --git a/sound/soc/codecs/mc13783.c b/sound/soc/codecs/mc13783.c
index 9e6a0cda43d0..a21072503cb9 100644
--- a/sound/soc/codecs/mc13783.c
+++ b/sound/soc/codecs/mc13783.c
@@ -712,7 +712,7 @@ static struct snd_soc_dai_driver mc13783_dai_sync[] = {
 			.formats = MC13783_FORMATS,
 		},
 		.ops = &mc13783_ops_sync,
-		.symmetric_rates = 1,
+		.symmetric_rate = 1,
 	}
 };
 
diff --git a/sound/soc/codecs/ml26124.c b/sound/soc/codecs/ml26124.c
index 70c17be455ca..4d7c0be2a4aa 100644
--- a/sound/soc/codecs/ml26124.c
+++ b/sound/soc/codecs/ml26124.c
@@ -513,7 +513,7 @@ static struct snd_soc_dai_driver ml26124_dai = {
 		.rates = ML26124_RATES,
 		.formats = ML26124_FORMATS,},
 	.ops = &ml26124_dai_ops,
-	.symmetric_rates = 1,
+	.symmetric_rate = 1,
 };
 
 static int ml26124_probe(struct snd_soc_component *component)
diff --git a/sound/soc/codecs/mt6359.c b/sound/soc/codecs/mt6359.c
index 6de0d744fa9e..6f4b1da52082 100644
--- a/sound/soc/codecs/mt6359.c
+++ b/sound/soc/codecs/mt6359.c
@@ -2754,7 +2754,8 @@ static int mt6359_parse_dt(struct mt6359_priv *priv)
 	ret = of_property_read_u32(np, "mediatek,dmic-mode",
 				   &priv->dmic_one_wire_mode);
 	if (ret) {
-		dev_warn(priv->dev, "%s() failed to read dmic-mode\n",
+		dev_info(priv->dev,
+			 "%s() failed to read dmic-mode, use default (0)\n",
 			 __func__);
 		priv->dmic_one_wire_mode = 0;
 	}
@@ -2762,24 +2763,27 @@ static int mt6359_parse_dt(struct mt6359_priv *priv)
 	ret = of_property_read_u32(np, "mediatek,mic-type-0",
 				   &priv->mux_select[MUX_MIC_TYPE_0]);
 	if (ret) {
-		dev_warn(priv->dev, "%s() failed to read mic-type-0\n",
-			 __func__);
+		dev_info(priv->dev,
+			 "%s() failed to read mic-type-0, use default (%d)\n",
+			 __func__, MIC_TYPE_MUX_IDLE);
 		priv->mux_select[MUX_MIC_TYPE_0] = MIC_TYPE_MUX_IDLE;
 	}
 
 	ret = of_property_read_u32(np, "mediatek,mic-type-1",
 				   &priv->mux_select[MUX_MIC_TYPE_1]);
 	if (ret) {
-		dev_warn(priv->dev, "%s() failed to read mic-type-1\n",
-			 __func__);
+		dev_info(priv->dev,
+			 "%s() failed to read mic-type-1, use default (%d)\n",
+			 __func__, MIC_TYPE_MUX_IDLE);
 		priv->mux_select[MUX_MIC_TYPE_1] = MIC_TYPE_MUX_IDLE;
 	}
 
 	ret = of_property_read_u32(np, "mediatek,mic-type-2",
 				   &priv->mux_select[MUX_MIC_TYPE_2]);
 	if (ret) {
-		dev_warn(priv->dev, "%s() failed to read mic-type-2\n",
-			 __func__);
+		dev_info(priv->dev,
+			 "%s() failed to read mic-type-2, use default (%d)\n",
+			 __func__, MIC_TYPE_MUX_IDLE);
 		priv->mux_select[MUX_MIC_TYPE_2] = MIC_TYPE_MUX_IDLE;
 	}
 
diff --git a/sound/soc/codecs/mt6660.c b/sound/soc/codecs/mt6660.c
index d1797003c83d..358c500377df 100644
--- a/sound/soc/codecs/mt6660.c
+++ b/sound/soc/codecs/mt6660.c
@@ -404,9 +404,9 @@ static struct snd_soc_dai_driver mt6660_codec_dai = {
 		.formats = STUB_FORMATS,
 	},
 	/* dai properties */
-	.symmetric_rates = 1,
+	.symmetric_rate = 1,
 	.symmetric_channels = 1,
-	.symmetric_samplebits = 1,
+	.symmetric_sample_bits = 1,
 	/* dai operations */
 	.ops = &mt6660_component_aif_ops,
 };
diff --git a/sound/soc/codecs/nau8810.c b/sound/soc/codecs/nau8810.c
index 33ebc6398426..13676b544f58 100644
--- a/sound/soc/codecs/nau8810.c
+++ b/sound/soc/codecs/nau8810.c
@@ -837,7 +837,7 @@ static struct snd_soc_dai_driver nau8810_dai = {
 		.formats = NAU8810_FORMATS,
 	},
 	.ops = &nau8810_ops,
-	.symmetric_rates = 1,
+	.symmetric_rate = 1,
 };
 
 static const struct regmap_config nau8810_regmap_config = {
diff --git a/sound/soc/codecs/nau8822.c b/sound/soc/codecs/nau8822.c
index 609aeeb27818..58123390c7a3 100644
--- a/sound/soc/codecs/nau8822.c
+++ b/sound/soc/codecs/nau8822.c
@@ -991,7 +991,7 @@ static struct snd_soc_dai_driver nau8822_dai = {
 		.formats = NAU8822_FORMATS,
 	},
 	.ops = &nau8822_dai_ops,
-	.symmetric_rates = 1,
+	.symmetric_rate = 1,
 };
 
 static int nau8822_suspend(struct snd_soc_component *component)
diff --git a/sound/soc/codecs/rt1015.c b/sound/soc/codecs/rt1015.c
index 32e6bcf763d1..37b5795b00d1 100644
--- a/sound/soc/codecs/rt1015.c
+++ b/sound/soc/codecs/rt1015.c
@@ -24,10 +24,10 @@
 #include <sound/initval.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
+#include <sound/rt1015.h>
 #include <sound/soc-dapm.h>
 #include <sound/soc.h>
 #include <sound/tlv.h>
-#include <sound/rt1015.h>
 
 #include "rl6231.h"
 #include "rt1015.h"
@@ -444,10 +444,9 @@ static int rt1015_boost_mode_put(struct snd_kcontrol *kcontrol,
 		snd_soc_kcontrol_component(kcontrol);
 	struct rt1015_priv *rt1015 =
 		snd_soc_component_get_drvdata(component);
+	int boost_mode = ucontrol->value.integer.value[0];
 
-	rt1015->boost_mode = ucontrol->value.integer.value[0];
-
-	switch (rt1015->boost_mode) {
+	switch (boost_mode) {
 	case BYPASS:
 		snd_soc_component_update_bits(component,
 			RT1015_SMART_BST_CTRL1, RT1015_ABST_AUTO_EN_MASK |
@@ -471,8 +470,11 @@ static int rt1015_boost_mode_put(struct snd_kcontrol *kcontrol,
 		break;
 	default:
 		dev_err(component->dev, "Unknown boost control.\n");
+		return -EINVAL;
 	}
 
+	rt1015->boost_mode = boost_mode;
+
 	return 0;
 }
 
@@ -497,40 +499,20 @@ static void rt1015_calibrate(struct rt1015_priv *rt1015)
 	snd_soc_dapm_mutex_lock(&component->dapm);
 	regcache_cache_bypass(regmap, true);
 
-	regmap_write(regmap, RT1015_PWR9, 0xAA60);
-	regmap_write(regmap, RT1015_PWR_STATE_CTRL, 0x0089);
-	regmap_write(regmap, RT1015_PWR_STATE_CTRL, 0x008A);
-	regmap_write(regmap, RT1015_PWR_STATE_CTRL, 0x008C);
-	regmap_write(regmap, RT1015_PWR_STATE_CTRL, 0x008D);
-	regmap_write(regmap, RT1015_PWR4, 0x80B2);
-	regmap_write(regmap, RT1015_CLASSD_SEQ, 0x5797);
-	regmap_write(regmap, RT1015_CLSD_INTERNAL8, 0x2100);
-	regmap_write(regmap, RT1015_CLSD_INTERNAL9, 0x0100);
-	regmap_write(regmap, RT1015_PWR5, 0x2175);
-	regmap_write(regmap, RT1015_MIXER1, 0x005D);
-	regmap_write(regmap, RT1015_CLSD_INTERNAL1, 0x00A1);
-	regmap_write(regmap, RT1015_CLSD_INTERNAL2, 0x12F7);
-	regmap_write(regmap, RT1015_DC_CALIB_CLSD1, 0x1205);
-	msleep(200);
-	regmap_write(regmap, RT1015_CLSD_INTERNAL8, 0x2000);
-	regmap_write(regmap, RT1015_CLSD_INTERNAL9, 0x0180);
-	regmap_write(regmap, RT1015_CLSD_INTERNAL1, 0x00A1);
-	regmap_write(regmap, RT1015_DC_CALIB_CLSD1, 0x0A05);
-	msleep(200);
+	regmap_write(regmap, RT1015_CLK_DET, 0x0000);
 	regmap_write(regmap, RT1015_PWR4, 0x00B2);
+	regmap_write(regmap, RT1015_PWR_STATE_CTRL, 0x0009);
+	msleep(100);
+	regmap_write(regmap, RT1015_PWR_STATE_CTRL, 0x000A);
+	msleep(100);
+	regmap_write(regmap, RT1015_PWR_STATE_CTRL, 0x000C);
+	msleep(100);
 	regmap_write(regmap, RT1015_CLSD_INTERNAL8, 0x2028);
 	regmap_write(regmap, RT1015_CLSD_INTERNAL9, 0x0140);
-	regmap_write(regmap, RT1015_PWR5, 0x0175);
-	regmap_write(regmap, RT1015_CLSD_INTERNAL1, 0x1721);
-	regmap_write(regmap, RT1015_CLASSD_SEQ, 0x570E);
-	regmap_write(regmap, RT1015_MIXER1, 0x203D);
-	regmap_write(regmap, RT1015_DC_CALIB_CLSD1, 0x5A01);
-	regmap_write(regmap, RT1015_CLSD_INTERNAL2, 0x12FF);
-	regmap_write(regmap, RT1015_GAT_BOOST, 0x0eFE);
-	regmap_write(regmap, RT1015_PWR_STATE_CTRL, 0x008E);
-	regmap_write(regmap, RT1015_PWR_STATE_CTRL, 0x0088);
+	regmap_write(regmap, RT1015_PWR_STATE_CTRL, 0x000D);
+	msleep(300);
+	regmap_write(regmap, RT1015_PWR_STATE_CTRL, 0x0008);
 	regmap_write(regmap, RT1015_SYS_RST1, 0x05F5);
-	regmap_write(regmap, RT1015_SYS_RST2, 0x0b9a);
 
 	regcache_cache_bypass(regmap, false);
 	regcache_mark_dirty(regmap);
@@ -546,17 +528,19 @@ static int rt1015_bypass_boost_put(struct snd_kcontrol *kcontrol,
 	struct rt1015_priv *rt1015 =
 		snd_soc_component_get_drvdata(component);
 
-	if (!rt1015->dac_is_used) {
-		rt1015->bypass_boost = ucontrol->value.integer.value[0];
-		if (rt1015->bypass_boost == RT1015_Bypass_Boost &&
+	if (rt1015->dac_is_used) {
+		dev_err(component->dev, "DAC is being used!\n");
+		return -EBUSY;
+	}
+
+	rt1015->bypass_boost = ucontrol->value.integer.value[0];
+	if (rt1015->bypass_boost == RT1015_Bypass_Boost &&
 			!rt1015->cali_done) {
-			rt1015_calibrate(rt1015);
-			rt1015->cali_done = 1;
+		rt1015_calibrate(rt1015);
+		rt1015->cali_done = 1;
 
-			regmap_write(rt1015->regmap, RT1015_MONO_DYNA_CTRL, 0x0010);
-		}
-	} else
-		dev_err(component->dev, "DAC is being used!\n");
+		regmap_write(rt1015->regmap, RT1015_MONO_DYNA_CTRL, 0x0010);
+	}
 
 	return 0;
 }
@@ -566,15 +550,14 @@ static void rt1015_flush_work(struct work_struct *work)
 	struct rt1015_priv *rt1015 = container_of(work, struct rt1015_priv,
 						flush_work.work);
 	struct snd_soc_component *component = rt1015->component;
-	unsigned int val, i = 0, count = 200;
+	unsigned int val, i;
 
-	while (i < count) {
+	for (i = 0; i < 200; ++i) {
 		usleep_range(1000, 1500);
 		dev_dbg(component->dev, "Flush DAC (retry:%u)\n", i);
 		regmap_read(rt1015->regmap, RT1015_CLK_DET, &val);
 		if (val & 0x800)
 			break;
-		i++;
 	}
 
 	regmap_write(rt1015->regmap, RT1015_SYS_RST1, 0x0597);
@@ -721,11 +704,11 @@ static int rt1015_hw_params(struct snd_pcm_substream *substream,
 {
 	struct snd_soc_component *component = dai->component;
 	struct rt1015_priv *rt1015 = snd_soc_component_get_drvdata(component);
-	int pre_div, bclk_ms, frame_size;
+	int pre_div, bclk_ms, frame_size, lrck;
 	unsigned int val_len = 0;
 
-	rt1015->lrck = params_rate(params);
-	pre_div = rl6231_get_clk_info(rt1015->sysclk, rt1015->lrck);
+	lrck = params_rate(params);
+	pre_div = rl6231_get_clk_info(rt1015->sysclk, lrck);
 	if (pre_div < 0) {
 		dev_err(component->dev, "Unsupported clock rate\n");
 		return -EINVAL;
@@ -739,13 +722,12 @@ static int rt1015_hw_params(struct snd_pcm_substream *substream,
 	}
 
 	bclk_ms = frame_size > 32;
-	rt1015->bclk = rt1015->lrck * (32 << bclk_ms);
 
 	dev_dbg(component->dev, "bclk_ms is %d and pre_div is %d for iis %d\n",
 				bclk_ms, pre_div, dai->id);
 
 	dev_dbg(component->dev, "lrck is %dHz and pre_div is %d for iis %d\n",
-				rt1015->lrck, pre_div, dai->id);
+				lrck, pre_div, dai->id);
 
 	switch (params_width(params)) {
 	case 16:
@@ -882,14 +864,6 @@ static int rt1015_set_component_pll(struct snd_soc_component *component,
 		freq_out == rt1015->pll_out)
 		return 0;
 
-	if (source == RT1015_PLL_S_BCLK) {
-		if (rt1015->bclk_ratio == 0) {
-			dev_err(component->dev,
-				"Can not support bclk ratio as 0.\n");
-			return -EINVAL;
-		}
-	}
-
 	switch (source) {
 	case RT1015_PLL_S_MCLK:
 		snd_soc_component_update_bits(component, RT1015_CLK2,
@@ -929,23 +903,6 @@ static int rt1015_set_component_pll(struct snd_soc_component *component,
 	return 0;
 }
 
-static int rt1015_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio)
-{
-	struct snd_soc_component *component = dai->component;
-	struct rt1015_priv *rt1015 = snd_soc_component_get_drvdata(component);
-
-	dev_dbg(component->dev, "%s ratio=%d\n", __func__, ratio);
-
-	rt1015->bclk_ratio = ratio;
-
-	if (ratio == 50) {
-		dev_dbg(component->dev, "Unsupport bclk ratio\n");
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
 static int rt1015_set_tdm_slot(struct snd_soc_dai *dai,
 	unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width)
 {
@@ -1052,9 +1009,6 @@ static int rt1015_probe(struct snd_soc_component *component)
 		snd_soc_component_get_drvdata(component);
 
 	rt1015->component = component;
-	rt1015->bclk_ratio = 0;
-	rt1015->cali_done = 0;
-
 	INIT_DELAYED_WORK(&rt1015->flush_work, rt1015_flush_work);
 
 	return 0;
@@ -1075,7 +1029,6 @@ static void rt1015_remove(struct snd_soc_component *component)
 static struct snd_soc_dai_ops rt1015_aif_dai_ops = {
 	.hw_params = rt1015_hw_params,
 	.set_fmt = rt1015_set_dai_fmt,
-	.set_bclk_ratio = rt1015_set_bclk_ratio,
 	.set_tdm_slot = rt1015_set_tdm_slot,
 };
 
@@ -1111,6 +1064,10 @@ static int rt1015_resume(struct snd_soc_component *component)
 
 	regcache_cache_only(rt1015->regmap, false);
 	regcache_sync(rt1015->regmap);
+
+	if (rt1015->cali_done)
+		rt1015_calibrate(rt1015);
+
 	return 0;
 }
 #else
@@ -1183,9 +1140,8 @@ static int rt1015_i2c_probe(struct i2c_client *i2c,
 	int ret;
 	unsigned int val;
 
-	rt1015 = devm_kzalloc(&i2c->dev, sizeof(struct rt1015_priv),
-				GFP_KERNEL);
-	if (rt1015 == NULL)
+	rt1015 = devm_kzalloc(&i2c->dev, sizeof(*rt1015), GFP_KERNEL);
+	if (!rt1015)
 		return -ENOMEM;
 
 	i2c_set_clientdata(i2c, rt1015);
diff --git a/sound/soc/codecs/rt1015.h b/sound/soc/codecs/rt1015.h
index b6ea753014e1..2aeaf65ba793 100644
--- a/sound/soc/codecs/rt1015.h
+++ b/sound/soc/codecs/rt1015.h
@@ -427,16 +427,11 @@ struct rt1015_priv {
 	struct regmap *regmap;
 	int sysclk;
 	int sysclk_src;
-	int lrck;
-	int bclk;
-	int bclk_ratio;
-	int id;
 	int pll_src;
 	int pll_in;
 	int pll_out;
 	int boost_mode;
 	int bypass_boost;
-	int amp_ver;
 	int dac_is_used;
 	int cali_done;
 	int hw_config;
diff --git a/sound/soc/codecs/rt1308-sdw.c b/sound/soc/codecs/rt1308-sdw.c
index ec5564f780e8..afd2c3b687cc 100644
--- a/sound/soc/codecs/rt1308-sdw.c
+++ b/sound/soc/codecs/rt1308-sdw.c
@@ -701,7 +701,7 @@ static int __maybe_unused rt1308_dev_suspend(struct device *dev)
 	return 0;
 }
 
-#define RT1308_PROBE_TIMEOUT 2000
+#define RT1308_PROBE_TIMEOUT 5000
 
 static int __maybe_unused rt1308_dev_resume(struct device *dev)
 {
diff --git a/sound/soc/codecs/rt274.c b/sound/soc/codecs/rt274.c
index 70cf17c0aa99..0d3773c576f8 100644
--- a/sound/soc/codecs/rt274.c
+++ b/sound/soc/codecs/rt274.c
@@ -1056,7 +1056,7 @@ static struct snd_soc_dai_driver rt274_dai[] = {
 			.formats = RT274_FORMATS,
 		},
 		.ops = &rt274_aif_dai_ops,
-		.symmetric_rates = 1,
+		.symmetric_rate = 1,
 	},
 };
 
diff --git a/sound/soc/codecs/rt286.c b/sound/soc/codecs/rt286.c
index 5fb9653d9131..8abe232ca4a4 100644
--- a/sound/soc/codecs/rt286.c
+++ b/sound/soc/codecs/rt286.c
@@ -1017,7 +1017,7 @@ static struct snd_soc_dai_driver rt286_dai[] = {
 			.formats = RT286_FORMATS,
 		},
 		.ops = &rt286_aif_dai_ops,
-		.symmetric_rates = 1,
+		.symmetric_rate = 1,
 	},
 	{
 		.name = "rt286-aif2",
@@ -1037,7 +1037,7 @@ static struct snd_soc_dai_driver rt286_dai[] = {
 			.formats = RT286_FORMATS,
 		},
 		.ops = &rt286_aif_dai_ops,
-		.symmetric_rates = 1,
+		.symmetric_rate = 1,
 	},
 
 };
diff --git a/sound/soc/codecs/rt298.c b/sound/soc/codecs/rt298.c
index dc0273a5a11f..32cc9b6287d2 100644
--- a/sound/soc/codecs/rt298.c
+++ b/sound/soc/codecs/rt298.c
@@ -1084,7 +1084,7 @@ static struct snd_soc_dai_driver rt298_dai[] = {
 			.formats = RT298_FORMATS,
 		},
 		.ops = &rt298_aif_dai_ops,
-		.symmetric_rates = 1,
+		.symmetric_rate = 1,
 	},
 	{
 		.name = "rt298-aif2",
@@ -1104,7 +1104,7 @@ static struct snd_soc_dai_driver rt298_dai[] = {
 			.formats = RT298_FORMATS,
 		},
 		.ops = &rt298_aif_dai_ops,
-		.symmetric_rates = 1,
+		.symmetric_rate = 1,
 	},
 
 };
diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c
index 420003d062c7..63a7e052eaa0 100644
--- a/sound/soc/codecs/rt5645.c
+++ b/sound/soc/codecs/rt5645.c
@@ -34,6 +34,7 @@
 #define QUIRK_INV_JD1_1(q)	((q) & 1)
 #define QUIRK_LEVEL_IRQ(q)	(((q) >> 1) & 1)
 #define QUIRK_IN2_DIFF(q)	(((q) >> 2) & 1)
+#define QUIRK_INV_HP_POL(q)	(((q) >> 3) & 1)
 #define QUIRK_JD_MODE(q)	(((q) >> 4) & 7)
 #define QUIRK_DMIC1_DATA_PIN(q)	(((q) >> 8) & 3)
 #define QUIRK_DMIC2_DATA_PIN(q)	(((q) >> 12) & 3)
@@ -42,6 +43,8 @@ static unsigned int quirk = -1;
 module_param(quirk, uint, 0444);
 MODULE_PARM_DESC(quirk, "RT5645 pdata quirk override");
 
+static const struct acpi_gpio_mapping *cht_rt5645_gpios;
+
 #define RT5645_DEVICE_ID 0x6308
 #define RT5650_DEVICE_ID 0x6419
 
@@ -435,7 +438,6 @@ struct rt5645_priv {
 
 	int jack_type;
 	bool en_button_func;
-	bool hp_on;
 	int v_id;
 };
 
@@ -1645,6 +1647,7 @@ static void hp_amp_power(struct snd_soc_component *component, int on)
 {
 	static int hp_amp_power_count;
 	struct rt5645_priv *rt5645 = snd_soc_component_get_drvdata(component);
+	int i, val;
 
 	if (on) {
 		if (hp_amp_power_count <= 0) {
@@ -1655,7 +1658,13 @@ static void hp_amp_power(struct snd_soc_component *component, int on)
 				snd_soc_component_write(component, RT5645_DEPOP_M1, 0x000d);
 				regmap_write(rt5645->regmap, RT5645_PR_BASE +
 					RT5645_HP_DCC_INT1, 0x9f01);
-				msleep(20);
+				for (i = 0; i < 20; i++) {
+					usleep_range(1000, 1500);
+					regmap_read(rt5645->regmap, RT5645_PR_BASE +
+						RT5645_HP_DCC_INT1, &val);
+					if (!(val & 0x8000))
+						break;
+				}
 				snd_soc_component_update_bits(component, RT5645_DEPOP_M1,
 					RT5645_HP_CO_MASK, RT5645_HP_CO_EN);
 				regmap_write(rt5645->regmap, RT5645_PR_BASE +
@@ -1665,7 +1674,6 @@ static void hp_amp_power(struct snd_soc_component *component, int on)
 					RT5645_MAMP_INT_REG2, 0xfc00);
 				snd_soc_component_write(component, RT5645_DEPOP_M2, 0x1140);
 				msleep(90);
-				rt5645->hp_on = true;
 			} else {
 				/* depop parameters */
 				snd_soc_component_update_bits(component, RT5645_DEPOP_M2,
@@ -1885,27 +1893,6 @@ static int rt5645_bst2_event(struct snd_soc_dapm_widget *w,
 	return 0;
 }
 
-static int rt5650_hp_event(struct snd_soc_dapm_widget *w,
-		struct snd_kcontrol *k, int  event)
-{
-	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
-	struct rt5645_priv *rt5645 = snd_soc_component_get_drvdata(component);
-
-	switch (event) {
-	case SND_SOC_DAPM_POST_PMU:
-		if (rt5645->hp_on) {
-			msleep(100);
-			rt5645->hp_on = false;
-		}
-		break;
-
-	default:
-		return 0;
-	}
-
-	return 0;
-}
-
 static int rt5645_set_micbias1_event(struct snd_soc_dapm_widget *w,
 		struct snd_kcontrol *k, int  event)
 {
@@ -2242,7 +2229,6 @@ static const struct snd_soc_dapm_widget rt5645_dapm_widgets[] = {
 	SND_SOC_DAPM_OUTPUT("PDM1R"),
 	SND_SOC_DAPM_OUTPUT("SPOL"),
 	SND_SOC_DAPM_OUTPUT("SPOR"),
-	SND_SOC_DAPM_POST("DAPM_POST", rt5650_hp_event),
 };
 
 static const struct snd_soc_dapm_widget rt5645_specific_dapm_widgets[] = {
@@ -3261,6 +3247,8 @@ static void rt5645_jack_detect_work(struct work_struct *work)
 	case 0: /* Not using rt5645 JD */
 		if (rt5645->gpiod_hp_det) {
 			gpio_state = gpiod_get_value(rt5645->gpiod_hp_det);
+			if (rt5645->pdata.inv_hp_pol)
+				gpio_state ^= 1;
 			dev_dbg(rt5645->component->dev, "gpio_state = %d\n",
 				gpio_state);
 			report = rt5645_jack_detect(rt5645->component, gpio_state);
@@ -3651,6 +3639,25 @@ static const struct rt5645_platform_data kahlee_platform_data = {
 	.jd_mode = 3,
 };
 
+static const struct rt5645_platform_data ecs_ef20_platform_data = {
+	.dmic1_data_pin = RT5645_DMIC1_DISABLE,
+	.dmic2_data_pin = RT5645_DMIC_DATA_IN2P,
+	.inv_hp_pol = 1,
+};
+
+static const struct acpi_gpio_params ef20_hp_detect = { 1, 0, false };
+
+static const struct acpi_gpio_mapping cht_rt5645_ef20_gpios[] = {
+	{ "hp-detect-gpios", &ef20_hp_detect, 1 },
+	{ },
+};
+
+static int cht_rt5645_ef20_quirk_cb(const struct dmi_system_id *id)
+{
+	cht_rt5645_gpios = cht_rt5645_ef20_gpios;
+	return 1;
+}
+
 static const struct dmi_system_id dmi_platform_data[] = {
 	{
 		.ident = "Chrome Buddy",
@@ -3780,6 +3787,22 @@ static const struct dmi_system_id dmi_platform_data[] = {
 		},
 		.driver_data = (void *)&intel_braswell_platform_data,
 	},
+	{
+		.ident = "EF20",
+		.callback = cht_rt5645_ef20_quirk_cb,
+		.matches = {
+			DMI_MATCH(DMI_PRODUCT_NAME, "EF20"),
+		},
+		.driver_data = (void *)&ecs_ef20_platform_data,
+	},
+	{
+		.ident = "EF20EA",
+		.callback = cht_rt5645_ef20_quirk_cb,
+		.matches = {
+			DMI_MATCH(DMI_PRODUCT_NAME, "EF20EA"),
+		},
+		.driver_data = (void *)&ecs_ef20_platform_data,
+	},
 	{ }
 };
 
@@ -3843,11 +3866,16 @@ static int rt5645_i2c_probe(struct i2c_client *i2c,
 		rt5645->pdata.in2_diff = QUIRK_IN2_DIFF(quirk);
 		rt5645->pdata.level_trigger_irq = QUIRK_LEVEL_IRQ(quirk);
 		rt5645->pdata.inv_jd1_1 = QUIRK_INV_JD1_1(quirk);
+		rt5645->pdata.inv_hp_pol = QUIRK_INV_HP_POL(quirk);
 		rt5645->pdata.jd_mode = QUIRK_JD_MODE(quirk);
 		rt5645->pdata.dmic1_data_pin = QUIRK_DMIC1_DATA_PIN(quirk);
 		rt5645->pdata.dmic2_data_pin = QUIRK_DMIC2_DATA_PIN(quirk);
 	}
 
+	if (cht_rt5645_gpios && has_acpi_companion(&i2c->dev))
+		if (devm_acpi_dev_add_driver_gpios(&i2c->dev, cht_rt5645_gpios))
+			dev_dbg(&i2c->dev, "Failed to add driver gpios\n");
+
 	rt5645->gpiod_hp_det = devm_gpiod_get_optional(&i2c->dev, "hp-detect",
 						       GPIOD_IN);
 
diff --git a/sound/soc/codecs/rt5670.c b/sound/soc/codecs/rt5670.c
index a0c8f58d729b..c29317ea5df2 100644
--- a/sound/soc/codecs/rt5670.c
+++ b/sound/soc/codecs/rt5670.c
@@ -2741,7 +2741,7 @@ static struct snd_soc_dai_driver rt5670_dai[] = {
 			.formats = RT5670_FORMATS,
 		},
 		.ops = &rt5670_aif_dai_ops,
-		.symmetric_rates = 1,
+		.symmetric_rate = 1,
 	},
 	{
 		.name = "rt5670-aif2",
@@ -2761,7 +2761,7 @@ static struct snd_soc_dai_driver rt5670_dai[] = {
 			.formats = RT5670_FORMATS,
 		},
 		.ops = &rt5670_aif_dai_ops,
-		.symmetric_rates = 1,
+		.symmetric_rate = 1,
 	},
 };
 
diff --git a/sound/soc/codecs/rt5682-sdw.c b/sound/soc/codecs/rt5682-sdw.c
index 35c9d2be9eeb..b49f1e16125d 100644
--- a/sound/soc/codecs/rt5682-sdw.c
+++ b/sound/soc/codecs/rt5682-sdw.c
@@ -375,18 +375,12 @@ static int rt5682_sdw_init(struct device *dev, struct regmap *regmap,
 static int rt5682_io_init(struct device *dev, struct sdw_slave *slave)
 {
 	struct rt5682_priv *rt5682 = dev_get_drvdata(dev);
-	int ret = 0;
+	int ret = 0, loop = 10;
 	unsigned int val;
 
 	if (rt5682->hw_init)
 		return 0;
 
-	regmap_read(rt5682->regmap, RT5682_DEVICE_ID, &val);
-	if (val != DEVICE_ID) {
-		dev_err(dev, "Device with ID register %x is not rt5682\n", val);
-		return -ENODEV;
-	}
-
 	/*
 	 * PM runtime is only enabled when a Slave reports as Attached
 	 */
@@ -406,6 +400,19 @@ static int rt5682_io_init(struct device *dev, struct sdw_slave *slave)
 
 	pm_runtime_get_noresume(&slave->dev);
 
+	while (loop > 0) {
+		regmap_read(rt5682->regmap, RT5682_DEVICE_ID, &val);
+		if (val == DEVICE_ID)
+			break;
+		dev_warn(dev, "Device with ID register %x is not rt5682\n", val);
+		usleep_range(30000, 30005);
+		loop--;
+	}
+	if (val != DEVICE_ID) {
+		dev_err(dev, "Device with ID register %x is not rt5682\n", val);
+		return -ENODEV;
+	}
+
 	if (rt5682->first_hw_init) {
 		regcache_cache_only(rt5682->regmap, false);
 		regcache_cache_bypass(rt5682->regmap, true);
diff --git a/sound/soc/codecs/rt5682.c b/sound/soc/codecs/rt5682.c
index fde5c4945e17..b306ac4b9b2e 100644
--- a/sound/soc/codecs/rt5682.c
+++ b/sound/soc/codecs/rt5682.c
@@ -953,6 +953,8 @@ int rt5682_headset_detect(struct snd_soc_component *component, int jack_insert)
 		case 0x1:
 		case 0x2:
 			rt5682->jack_type = SND_JACK_HEADSET;
+			snd_soc_component_update_bits(component, RT5682_CBJ_CTRL_1,
+				RT5682_FAST_OFF_MASK, RT5682_FAST_OFF_EN);
 			rt5682_enable_push_button_irq(component, true);
 			break;
 		default:
@@ -982,6 +984,8 @@ int rt5682_headset_detect(struct snd_soc_component *component, int jack_insert)
 		snd_soc_component_update_bits(component, RT5682_MICBIAS_2,
 			RT5682_PWR_CLK25M_MASK | RT5682_PWR_CLK1M_MASK,
 			RT5682_PWR_CLK25M_PD | RT5682_PWR_CLK1M_PD);
+		snd_soc_component_update_bits(component, RT5682_CBJ_CTRL_1,
+			RT5682_FAST_OFF_MASK, RT5682_FAST_OFF_DIS);
 
 		rt5682->jack_type = 0;
 	}
@@ -1012,10 +1016,12 @@ static int rt5682_set_jack_detect(struct snd_soc_component *component,
 		switch (rt5682->pdata.jd_src) {
 		case RT5682_JD1:
 			snd_soc_component_update_bits(component,
+				RT5682_CBJ_CTRL_5, 0x0700, 0x0600);
+			snd_soc_component_update_bits(component,
 				RT5682_CBJ_CTRL_2, RT5682_EXT_JD_SRC,
 				RT5682_EXT_JD_SRC_MANUAL);
 			snd_soc_component_write(component, RT5682_CBJ_CTRL_1,
-				0xd042);
+				0xd142);
 			snd_soc_component_update_bits(component,
 				RT5682_CBJ_CTRL_3, RT5682_CBJ_IN_BUF_EN,
 				RT5682_CBJ_IN_BUF_EN);
@@ -1848,8 +1854,6 @@ static const struct snd_soc_dapm_route rt5682_dapm_routes[] = {
 
 	{"CLKDET SYS", NULL, "CLKDET"},
 
-	{"IN1P", NULL, "LDO2"},
-
 	{"BST1 CBJ", NULL, "IN1P"},
 
 	{"RECMIX1L", "CBJ Switch", "BST1 CBJ"},
diff --git a/sound/soc/codecs/rt5682.h b/sound/soc/codecs/rt5682.h
index 99b85cfe6248..1f9c51a5b9bf 100644
--- a/sound/soc/codecs/rt5682.h
+++ b/sound/soc/codecs/rt5682.h
@@ -1356,7 +1356,7 @@
 #define RT5682_SAR_SOUR_TYPE			(0x0)
 
 /* soundwire timeout */
-#define RT5682_PROBE_TIMEOUT			2000
+#define RT5682_PROBE_TIMEOUT			5000
 
 
 #define RT5682_STEREO_RATES SNDRV_PCM_RATE_8000_192000
diff --git a/sound/soc/codecs/rt700-sdw.c b/sound/soc/codecs/rt700-sdw.c
index 45488325b635..4001612dfd73 100644
--- a/sound/soc/codecs/rt700-sdw.c
+++ b/sound/soc/codecs/rt700-sdw.c
@@ -490,7 +490,7 @@ static int __maybe_unused rt700_dev_suspend(struct device *dev)
 	return 0;
 }
 
-#define RT700_PROBE_TIMEOUT 2000
+#define RT700_PROBE_TIMEOUT 5000
 
 static int __maybe_unused rt700_dev_resume(struct device *dev)
 {
diff --git a/sound/soc/codecs/rt711-sdw.c b/sound/soc/codecs/rt711-sdw.c
index 308e62564841..2beb4286d997 100644
--- a/sound/soc/codecs/rt711-sdw.c
+++ b/sound/soc/codecs/rt711-sdw.c
@@ -493,7 +493,7 @@ static int __maybe_unused rt711_dev_suspend(struct device *dev)
 	return 0;
 }
 
-#define RT711_PROBE_TIMEOUT 2000
+#define RT711_PROBE_TIMEOUT 5000
 
 static int __maybe_unused rt711_dev_resume(struct device *dev)
 {
diff --git a/sound/soc/codecs/rt715-sdw.c b/sound/soc/codecs/rt715-sdw.c
index 8f0aa1e8a273..71dd3b97a459 100644
--- a/sound/soc/codecs/rt715-sdw.c
+++ b/sound/soc/codecs/rt715-sdw.c
@@ -533,7 +533,7 @@ static int __maybe_unused rt715_dev_suspend(struct device *dev)
 	return 0;
 }
 
-#define RT715_PROBE_TIMEOUT 2000
+#define RT715_PROBE_TIMEOUT 5000
 
 static int __maybe_unused rt715_dev_resume(struct device *dev)
 {
diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c
index 4d6ff8114622..73551e36695e 100644
--- a/sound/soc/codecs/sgtl5000.c
+++ b/sound/soc/codecs/sgtl5000.c
@@ -1187,7 +1187,7 @@ static struct snd_soc_dai_driver sgtl5000_dai = {
 		.formats = SGTL5000_FORMATS,
 	},
 	.ops = &sgtl5000_ops,
-	.symmetric_rates = 1,
+	.symmetric_rate = 1,
 };
 
 static bool sgtl5000_volatile(struct device *dev, unsigned int reg)
diff --git a/sound/soc/codecs/sirf-audio-codec.c b/sound/soc/codecs/sirf-audio-codec.c
deleted file mode 100644
index a061d78473ac..000000000000
--- a/sound/soc/codecs/sirf-audio-codec.c
+++ /dev/null
@@ -1,575 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * SiRF audio codec driver
- *
- * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
- */
-
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/pm_runtime.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/regmap.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/initval.h>
-#include <sound/tlv.h>
-#include <sound/soc.h>
-#include <sound/dmaengine_pcm.h>
-
-#include "sirf-audio-codec.h"
-
-struct sirf_audio_codec {
-	struct clk *clk;
-	struct regmap *regmap;
-	u32 reg_ctrl0, reg_ctrl1;
-};
-
-static const char * const input_mode_mux[] = {"Single-ended",
-	"Differential"};
-
-static const struct soc_enum input_mode_mux_enum =
-	SOC_ENUM_SINGLE(AUDIO_IC_CODEC_CTRL1, 4, 2, input_mode_mux);
-
-static const struct snd_kcontrol_new sirf_audio_codec_input_mode_control =
-	SOC_DAPM_ENUM("Route", input_mode_mux_enum);
-
-static const DECLARE_TLV_DB_SCALE(playback_vol_tlv, -12400, 100, 0);
-static const DECLARE_TLV_DB_SCALE(capture_vol_tlv_prima2, 500, 100, 0);
-static const DECLARE_TLV_DB_RANGE(capture_vol_tlv_atlas6,
-	0, 7, TLV_DB_SCALE_ITEM(-100, 100, 0),
-	0x22, 0x3F, TLV_DB_SCALE_ITEM(700, 100, 0),
-);
-
-static struct snd_kcontrol_new volume_controls_atlas6[] = {
-	SOC_DOUBLE_TLV("Playback Volume", AUDIO_IC_CODEC_CTRL0, 21, 14,
-			0x7F, 0, playback_vol_tlv),
-	SOC_DOUBLE_TLV("Capture Volume", AUDIO_IC_CODEC_CTRL1, 16, 10,
-			0x3F, 0, capture_vol_tlv_atlas6),
-};
-
-static struct snd_kcontrol_new volume_controls_prima2[] = {
-	SOC_DOUBLE_TLV("Speaker Volume", AUDIO_IC_CODEC_CTRL0, 21, 14,
-			0x7F, 0, playback_vol_tlv),
-	SOC_DOUBLE_TLV("Capture Volume", AUDIO_IC_CODEC_CTRL1, 15, 10,
-			0x1F, 0, capture_vol_tlv_prima2),
-};
-
-static struct snd_kcontrol_new left_input_path_controls[] = {
-	SOC_DAPM_SINGLE("Line Left Switch", AUDIO_IC_CODEC_CTRL1, 6, 1, 0),
-	SOC_DAPM_SINGLE("Mic Left Switch", AUDIO_IC_CODEC_CTRL1, 3, 1, 0),
-};
-
-static struct snd_kcontrol_new right_input_path_controls[] = {
-	SOC_DAPM_SINGLE("Line Right Switch", AUDIO_IC_CODEC_CTRL1, 5, 1, 0),
-	SOC_DAPM_SINGLE("Mic Right Switch", AUDIO_IC_CODEC_CTRL1, 2, 1, 0),
-};
-
-static struct snd_kcontrol_new left_dac_to_hp_left_amp_switch_control =
-	SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 9, 1, 0);
-
-static struct snd_kcontrol_new left_dac_to_hp_right_amp_switch_control =
-	SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 8, 1, 0);
-
-static struct snd_kcontrol_new right_dac_to_hp_left_amp_switch_control =
-	SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 7, 1, 0);
-
-static struct snd_kcontrol_new right_dac_to_hp_right_amp_switch_control =
-	SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 6, 1, 0);
-
-static struct snd_kcontrol_new left_dac_to_speaker_lineout_switch_control =
-	SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 11, 1, 0);
-
-static struct snd_kcontrol_new right_dac_to_speaker_lineout_switch_control =
-	SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 10, 1, 0);
-
-/* After enable adc, Delay 200ms to avoid pop noise */
-static int adc_enable_delay_event(struct snd_soc_dapm_widget *w,
-		struct snd_kcontrol *kcontrol, int event)
-{
-	switch (event) {
-	case SND_SOC_DAPM_POST_PMU:
-		msleep(200);
-		break;
-	default:
-		break;
-	}
-
-	return 0;
-}
-
-static void enable_and_reset_codec(struct regmap *regmap,
-		u32 codec_enable_bits, u32 codec_reset_bits)
-{
-	regmap_update_bits(regmap, AUDIO_IC_CODEC_CTRL1,
-			codec_enable_bits | codec_reset_bits,
-			codec_enable_bits);
-	msleep(20);
-	regmap_update_bits(regmap, AUDIO_IC_CODEC_CTRL1,
-			codec_reset_bits, codec_reset_bits);
-}
-
-static int atlas6_codec_enable_and_reset_event(struct snd_soc_dapm_widget *w,
-		struct snd_kcontrol *kcontrol, int event)
-{
-#define ATLAS6_CODEC_ENABLE_BITS (1 << 29)
-#define ATLAS6_CODEC_RESET_BITS (1 << 28)
-	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
-	struct sirf_audio_codec *sirf_audio_codec = snd_soc_component_get_drvdata(component);
-	switch (event) {
-	case SND_SOC_DAPM_PRE_PMU:
-		enable_and_reset_codec(sirf_audio_codec->regmap,
-			ATLAS6_CODEC_ENABLE_BITS, ATLAS6_CODEC_RESET_BITS);
-		break;
-	case SND_SOC_DAPM_POST_PMD:
-		regmap_update_bits(sirf_audio_codec->regmap,
-			AUDIO_IC_CODEC_CTRL1, ATLAS6_CODEC_ENABLE_BITS, 0);
-		break;
-	default:
-		break;
-	}
-
-	return 0;
-}
-
-static int prima2_codec_enable_and_reset_event(struct snd_soc_dapm_widget *w,
-		struct snd_kcontrol *kcontrol, int event)
-{
-#define PRIMA2_CODEC_ENABLE_BITS (1 << 27)
-#define PRIMA2_CODEC_RESET_BITS (1 << 26)
-	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
-	struct sirf_audio_codec *sirf_audio_codec = snd_soc_component_get_drvdata(component);
-	switch (event) {
-	case SND_SOC_DAPM_POST_PMU:
-		enable_and_reset_codec(sirf_audio_codec->regmap,
-			PRIMA2_CODEC_ENABLE_BITS, PRIMA2_CODEC_RESET_BITS);
-		break;
-	case SND_SOC_DAPM_POST_PMD:
-		regmap_update_bits(sirf_audio_codec->regmap,
-			AUDIO_IC_CODEC_CTRL1, PRIMA2_CODEC_ENABLE_BITS, 0);
-		break;
-	default:
-		break;
-	}
-
-	return 0;
-}
-
-static const struct snd_soc_dapm_widget atlas6_output_driver_dapm_widgets[] = {
-	SND_SOC_DAPM_OUT_DRV("HP Left Driver", AUDIO_IC_CODEC_CTRL1,
-			25, 0, NULL, 0),
-	SND_SOC_DAPM_OUT_DRV("HP Right Driver", AUDIO_IC_CODEC_CTRL1,
-			26, 0, NULL, 0),
-	SND_SOC_DAPM_OUT_DRV("Speaker Driver", AUDIO_IC_CODEC_CTRL1,
-			27, 0, NULL, 0),
-};
-
-static const struct snd_soc_dapm_widget prima2_output_driver_dapm_widgets[] = {
-	SND_SOC_DAPM_OUT_DRV("HP Left Driver", AUDIO_IC_CODEC_CTRL1,
-			23, 0, NULL, 0),
-	SND_SOC_DAPM_OUT_DRV("HP Right Driver", AUDIO_IC_CODEC_CTRL1,
-			24, 0, NULL, 0),
-	SND_SOC_DAPM_OUT_DRV("Speaker Driver", AUDIO_IC_CODEC_CTRL1,
-			25, 0, NULL, 0),
-};
-
-static const struct snd_soc_dapm_widget atlas6_codec_clock_dapm_widget =
-	SND_SOC_DAPM_SUPPLY("codecclk", SND_SOC_NOPM, 0, 0,
-			atlas6_codec_enable_and_reset_event,
-			SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD);
-
-static const struct snd_soc_dapm_widget prima2_codec_clock_dapm_widget =
-	SND_SOC_DAPM_SUPPLY("codecclk", SND_SOC_NOPM, 0, 0,
-			prima2_codec_enable_and_reset_event,
-			SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD);
-
-static const struct snd_soc_dapm_widget sirf_audio_codec_dapm_widgets[] = {
-	SND_SOC_DAPM_DAC("DAC left", NULL, AUDIO_IC_CODEC_CTRL0, 1, 0),
-	SND_SOC_DAPM_DAC("DAC right", NULL, AUDIO_IC_CODEC_CTRL0, 0, 0),
-	SND_SOC_DAPM_SWITCH("Left dac to hp left amp", SND_SOC_NOPM, 0, 0,
-			&left_dac_to_hp_left_amp_switch_control),
-	SND_SOC_DAPM_SWITCH("Left dac to hp right amp", SND_SOC_NOPM, 0, 0,
-			&left_dac_to_hp_right_amp_switch_control),
-	SND_SOC_DAPM_SWITCH("Right dac to hp left amp", SND_SOC_NOPM, 0, 0,
-			&right_dac_to_hp_left_amp_switch_control),
-	SND_SOC_DAPM_SWITCH("Right dac to hp right amp", SND_SOC_NOPM, 0, 0,
-			&right_dac_to_hp_right_amp_switch_control),
-	SND_SOC_DAPM_OUT_DRV("HP amp left driver", AUDIO_IC_CODEC_CTRL0, 3, 0,
-			NULL, 0),
-	SND_SOC_DAPM_OUT_DRV("HP amp right driver", AUDIO_IC_CODEC_CTRL0, 3, 0,
-			NULL, 0),
-
-	SND_SOC_DAPM_SWITCH("Left dac to speaker lineout", SND_SOC_NOPM, 0, 0,
-			&left_dac_to_speaker_lineout_switch_control),
-	SND_SOC_DAPM_SWITCH("Right dac to speaker lineout", SND_SOC_NOPM, 0, 0,
-			&right_dac_to_speaker_lineout_switch_control),
-	SND_SOC_DAPM_OUT_DRV("Speaker amp driver", AUDIO_IC_CODEC_CTRL0, 4, 0,
-			NULL, 0),
-
-	SND_SOC_DAPM_OUTPUT("HPOUTL"),
-	SND_SOC_DAPM_OUTPUT("HPOUTR"),
-	SND_SOC_DAPM_OUTPUT("SPKOUT"),
-
-	SND_SOC_DAPM_ADC_E("ADC left", NULL, AUDIO_IC_CODEC_CTRL1, 8, 0,
-			adc_enable_delay_event, SND_SOC_DAPM_POST_PMU),
-	SND_SOC_DAPM_ADC_E("ADC right", NULL, AUDIO_IC_CODEC_CTRL1, 7, 0,
-			adc_enable_delay_event, SND_SOC_DAPM_POST_PMU),
-	SND_SOC_DAPM_MIXER("Left PGA mixer", AUDIO_IC_CODEC_CTRL1, 1, 0,
-		&left_input_path_controls[0],
-		ARRAY_SIZE(left_input_path_controls)),
-	SND_SOC_DAPM_MIXER("Right PGA mixer", AUDIO_IC_CODEC_CTRL1, 0, 0,
-		&right_input_path_controls[0],
-		ARRAY_SIZE(right_input_path_controls)),
-
-	SND_SOC_DAPM_MUX("Mic input mode mux", SND_SOC_NOPM, 0, 0,
-			&sirf_audio_codec_input_mode_control),
-	SND_SOC_DAPM_MICBIAS("Mic Bias", AUDIO_IC_CODEC_PWR, 3, 0),
-	SND_SOC_DAPM_INPUT("MICIN1"),
-	SND_SOC_DAPM_INPUT("MICIN2"),
-	SND_SOC_DAPM_INPUT("LINEIN1"),
-	SND_SOC_DAPM_INPUT("LINEIN2"),
-
-	SND_SOC_DAPM_SUPPLY("HSL Phase Opposite", AUDIO_IC_CODEC_CTRL0,
-			30, 0, NULL, 0),
-};
-
-static const struct snd_soc_dapm_route sirf_audio_codec_map[] = {
-	{"SPKOUT", NULL, "Speaker Driver"},
-	{"Speaker Driver", NULL, "Speaker amp driver"},
-	{"Speaker amp driver", NULL, "Left dac to speaker lineout"},
-	{"Speaker amp driver", NULL, "Right dac to speaker lineout"},
-	{"Left dac to speaker lineout", "Switch", "DAC left"},
-	{"Right dac to speaker lineout", "Switch", "DAC right"},
-	{"HPOUTL", NULL, "HP Left Driver"},
-	{"HPOUTR", NULL, "HP Right Driver"},
-	{"HP Left Driver", NULL, "HP amp left driver"},
-	{"HP Right Driver", NULL, "HP amp right driver"},
-	{"HP amp left driver", NULL, "Right dac to hp left amp"},
-	{"HP amp right driver", NULL , "Right dac to hp right amp"},
-	{"HP amp left driver", NULL, "Left dac to hp left amp"},
-	{"HP amp right driver", NULL , "Right dac to hp right amp"},
-	{"Right dac to hp left amp", "Switch", "DAC left"},
-	{"Right dac to hp right amp", "Switch", "DAC right"},
-	{"Left dac to hp left amp", "Switch", "DAC left"},
-	{"Left dac to hp right amp", "Switch", "DAC right"},
-	{"DAC left", NULL, "codecclk"},
-	{"DAC right", NULL, "codecclk"},
-	{"DAC left", NULL, "Playback"},
-	{"DAC right", NULL, "Playback"},
-	{"DAC left", NULL, "HSL Phase Opposite"},
-	{"DAC right", NULL, "HSL Phase Opposite"},
-
-	{"Capture", NULL, "ADC left"},
-	{"Capture", NULL, "ADC right"},
-	{"ADC left", NULL, "codecclk"},
-	{"ADC right", NULL, "codecclk"},
-	{"ADC left", NULL, "Left PGA mixer"},
-	{"ADC right", NULL, "Right PGA mixer"},
-	{"Left PGA mixer", "Line Left Switch", "LINEIN2"},
-	{"Right PGA mixer", "Line Right Switch", "LINEIN1"},
-	{"Left PGA mixer", "Mic Left Switch", "MICIN2"},
-	{"Right PGA mixer", "Mic Right Switch", "Mic input mode mux"},
-	{"Mic input mode mux", "Single-ended", "MICIN1"},
-	{"Mic input mode mux", "Differential", "MICIN1"},
-};
-
-static void sirf_audio_codec_tx_enable(struct sirf_audio_codec *sirf_audio_codec)
-{
-	regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_OP,
-		AUDIO_FIFO_RESET, AUDIO_FIFO_RESET);
-	regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_OP,
-		AUDIO_FIFO_RESET, ~AUDIO_FIFO_RESET);
-	regmap_write(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_INT_MSK, 0);
-	regmap_write(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_OP, 0);
-	regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_OP,
-		AUDIO_FIFO_START, AUDIO_FIFO_START);
-	regmap_update_bits(sirf_audio_codec->regmap,
-		AUDIO_PORT_IC_CODEC_TX_CTRL, IC_TX_ENABLE, IC_TX_ENABLE);
-}
-
-static void sirf_audio_codec_tx_disable(struct sirf_audio_codec *sirf_audio_codec)
-{
-	regmap_write(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_OP, 0);
-	regmap_update_bits(sirf_audio_codec->regmap,
-		AUDIO_PORT_IC_CODEC_TX_CTRL, IC_TX_ENABLE, ~IC_TX_ENABLE);
-}
-
-static void sirf_audio_codec_rx_enable(struct sirf_audio_codec *sirf_audio_codec,
-	int channels)
-{
-	regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_RXFIFO_OP,
-		AUDIO_FIFO_RESET, AUDIO_FIFO_RESET);
-	regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_RXFIFO_OP,
-		AUDIO_FIFO_RESET, ~AUDIO_FIFO_RESET);
-	regmap_write(sirf_audio_codec->regmap,
-		AUDIO_PORT_IC_RXFIFO_INT_MSK, 0);
-	regmap_write(sirf_audio_codec->regmap, AUDIO_PORT_IC_RXFIFO_OP, 0);
-	regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_RXFIFO_OP,
-		AUDIO_FIFO_START, AUDIO_FIFO_START);
-	if (channels == 1)
-		regmap_update_bits(sirf_audio_codec->regmap,
-			AUDIO_PORT_IC_CODEC_RX_CTRL,
-			IC_RX_ENABLE_MONO, IC_RX_ENABLE_MONO);
-	else
-		regmap_update_bits(sirf_audio_codec->regmap,
-			AUDIO_PORT_IC_CODEC_RX_CTRL,
-			IC_RX_ENABLE_STEREO, IC_RX_ENABLE_STEREO);
-}
-
-static void sirf_audio_codec_rx_disable(struct sirf_audio_codec *sirf_audio_codec)
-{
-	regmap_update_bits(sirf_audio_codec->regmap,
-			AUDIO_PORT_IC_CODEC_RX_CTRL,
-			IC_RX_ENABLE_STEREO, ~IC_RX_ENABLE_STEREO);
-}
-
-static int sirf_audio_codec_trigger(struct snd_pcm_substream *substream,
-		int cmd,
-		struct snd_soc_dai *dai)
-{
-	struct snd_soc_component *component = dai->component;
-	struct sirf_audio_codec *sirf_audio_codec = snd_soc_component_get_drvdata(component);
-	int playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
-
-	/*
-	 * This is a workaround, When stop playback,
-	 * need disable HP amp, avoid the current noise.
-	 */
-	switch (cmd) {
-	case SNDRV_PCM_TRIGGER_STOP:
-	case SNDRV_PCM_TRIGGER_SUSPEND:
-	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-		if (playback) {
-			snd_soc_component_update_bits(component, AUDIO_IC_CODEC_CTRL0,
-				IC_HSLEN | IC_HSREN, 0);
-			sirf_audio_codec_tx_disable(sirf_audio_codec);
-		} else
-			sirf_audio_codec_rx_disable(sirf_audio_codec);
-		break;
-	case SNDRV_PCM_TRIGGER_START:
-	case SNDRV_PCM_TRIGGER_RESUME:
-	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-		if (playback) {
-			sirf_audio_codec_tx_enable(sirf_audio_codec);
-			snd_soc_component_update_bits(component, AUDIO_IC_CODEC_CTRL0,
-				IC_HSLEN | IC_HSREN, IC_HSLEN | IC_HSREN);
-		} else
-			sirf_audio_codec_rx_enable(sirf_audio_codec,
-				substream->runtime->channels);
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static const struct snd_soc_dai_ops sirf_audio_codec_dai_ops = {
-	.trigger = sirf_audio_codec_trigger,
-};
-
-static struct snd_soc_dai_driver sirf_audio_codec_dai = {
-	.name = "sirf-audio-codec",
-	.playback = {
-		.stream_name = "Playback",
-		.channels_min = 2,
-		.channels_max = 2,
-		.rates = SNDRV_PCM_RATE_48000,
-		.formats = SNDRV_PCM_FMTBIT_S16_LE,
-	},
-	.capture = {
-		.stream_name = "Capture",
-		.channels_min = 1,
-		.channels_max = 2,
-		.rates = SNDRV_PCM_RATE_48000,
-		.formats = SNDRV_PCM_FMTBIT_S16_LE,
-	},
-	.ops = &sirf_audio_codec_dai_ops,
-};
-
-static int sirf_audio_codec_probe(struct snd_soc_component *component)
-{
-	struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
-
-	pm_runtime_enable(component->dev);
-
-	if (of_device_is_compatible(component->dev->of_node, "sirf,prima2-audio-codec")) {
-		snd_soc_dapm_new_controls(dapm,
-			prima2_output_driver_dapm_widgets,
-			ARRAY_SIZE(prima2_output_driver_dapm_widgets));
-		snd_soc_dapm_new_controls(dapm,
-			&prima2_codec_clock_dapm_widget, 1);
-		return snd_soc_add_component_controls(component,
-			volume_controls_prima2,
-			ARRAY_SIZE(volume_controls_prima2));
-	}
-	if (of_device_is_compatible(component->dev->of_node, "sirf,atlas6-audio-codec")) {
-		snd_soc_dapm_new_controls(dapm,
-			atlas6_output_driver_dapm_widgets,
-			ARRAY_SIZE(atlas6_output_driver_dapm_widgets));
-		snd_soc_dapm_new_controls(dapm,
-			&atlas6_codec_clock_dapm_widget, 1);
-		return snd_soc_add_component_controls(component,
-			volume_controls_atlas6,
-			ARRAY_SIZE(volume_controls_atlas6));
-	}
-
-	return -EINVAL;
-}
-
-static void sirf_audio_codec_remove(struct snd_soc_component *component)
-{
-	pm_runtime_disable(component->dev);
-}
-
-static const struct snd_soc_component_driver soc_codec_device_sirf_audio_codec = {
-	.probe			= sirf_audio_codec_probe,
-	.remove			= sirf_audio_codec_remove,
-	.dapm_widgets		= sirf_audio_codec_dapm_widgets,
-	.num_dapm_widgets	= ARRAY_SIZE(sirf_audio_codec_dapm_widgets),
-	.dapm_routes		= sirf_audio_codec_map,
-	.num_dapm_routes	= ARRAY_SIZE(sirf_audio_codec_map),
-	.use_pmdown_time	= 1,
-	.endianness		= 1,
-	.non_legacy_dai_naming	= 1,
-};
-
-static const struct of_device_id sirf_audio_codec_of_match[] = {
-	{ .compatible = "sirf,prima2-audio-codec" },
-	{ .compatible = "sirf,atlas6-audio-codec" },
-	{}
-};
-MODULE_DEVICE_TABLE(of, sirf_audio_codec_of_match);
-
-static const struct regmap_config sirf_audio_codec_regmap_config = {
-	.reg_bits = 32,
-	.reg_stride = 4,
-	.val_bits = 32,
-	.max_register = AUDIO_PORT_IC_RXFIFO_INT_MSK,
-	.cache_type = REGCACHE_NONE,
-};
-
-static int sirf_audio_codec_driver_probe(struct platform_device *pdev)
-{
-	int ret;
-	struct sirf_audio_codec *sirf_audio_codec;
-	void __iomem *base;
-
-	sirf_audio_codec = devm_kzalloc(&pdev->dev,
-		sizeof(struct sirf_audio_codec), GFP_KERNEL);
-	if (!sirf_audio_codec)
-		return -ENOMEM;
-
-	platform_set_drvdata(pdev, sirf_audio_codec);
-
-	base = devm_platform_ioremap_resource(pdev, 0);
-	if (IS_ERR(base))
-		return PTR_ERR(base);
-
-	sirf_audio_codec->regmap = devm_regmap_init_mmio(&pdev->dev, base,
-					    &sirf_audio_codec_regmap_config);
-	if (IS_ERR(sirf_audio_codec->regmap))
-		return PTR_ERR(sirf_audio_codec->regmap);
-
-	sirf_audio_codec->clk = devm_clk_get(&pdev->dev, NULL);
-	if (IS_ERR(sirf_audio_codec->clk)) {
-		dev_err(&pdev->dev, "Get clock failed.\n");
-		return PTR_ERR(sirf_audio_codec->clk);
-	}
-
-	ret = clk_prepare_enable(sirf_audio_codec->clk);
-	if (ret) {
-		dev_err(&pdev->dev, "Enable clock failed.\n");
-		return ret;
-	}
-
-	ret = devm_snd_soc_register_component(&(pdev->dev),
-			&soc_codec_device_sirf_audio_codec,
-			&sirf_audio_codec_dai, 1);
-	if (ret) {
-		dev_err(&pdev->dev, "Register Audio Codec dai failed.\n");
-		goto err_clk_put;
-	}
-
-	/*
-	 * Always open charge pump, if not, when the charge pump closed the
-	 * adc will not stable
-	 */
-	regmap_update_bits(sirf_audio_codec->regmap, AUDIO_IC_CODEC_CTRL0,
-		IC_CPFREQ, IC_CPFREQ);
-
-	if (of_device_is_compatible(pdev->dev.of_node, "sirf,atlas6-audio-codec"))
-		regmap_update_bits(sirf_audio_codec->regmap,
-				AUDIO_IC_CODEC_CTRL0, IC_CPEN, IC_CPEN);
-	return 0;
-
-err_clk_put:
-	clk_disable_unprepare(sirf_audio_codec->clk);
-	return ret;
-}
-
-static int sirf_audio_codec_driver_remove(struct platform_device *pdev)
-{
-	struct sirf_audio_codec *sirf_audio_codec = platform_get_drvdata(pdev);
-
-	clk_disable_unprepare(sirf_audio_codec->clk);
-
-	return 0;
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int sirf_audio_codec_suspend(struct device *dev)
-{
-	struct sirf_audio_codec *sirf_audio_codec = dev_get_drvdata(dev);
-
-	regmap_read(sirf_audio_codec->regmap, AUDIO_IC_CODEC_CTRL0,
-		&sirf_audio_codec->reg_ctrl0);
-	regmap_read(sirf_audio_codec->regmap, AUDIO_IC_CODEC_CTRL1,
-		&sirf_audio_codec->reg_ctrl1);
-	clk_disable_unprepare(sirf_audio_codec->clk);
-
-	return 0;
-}
-
-static int sirf_audio_codec_resume(struct device *dev)
-{
-	struct sirf_audio_codec *sirf_audio_codec = dev_get_drvdata(dev);
-	int ret;
-
-	ret = clk_prepare_enable(sirf_audio_codec->clk);
-	if (ret)
-		return ret;
-
-	regmap_write(sirf_audio_codec->regmap, AUDIO_IC_CODEC_CTRL0,
-		sirf_audio_codec->reg_ctrl0);
-	regmap_write(sirf_audio_codec->regmap, AUDIO_IC_CODEC_CTRL1,
-		sirf_audio_codec->reg_ctrl1);
-
-	return 0;
-}
-#endif
-
-static const struct dev_pm_ops sirf_audio_codec_pm_ops = {
-	SET_SYSTEM_SLEEP_PM_OPS(sirf_audio_codec_suspend, sirf_audio_codec_resume)
-};
-
-static struct platform_driver sirf_audio_codec_driver = {
-	.driver = {
-		.name = "sirf-audio-codec",
-		.of_match_table = sirf_audio_codec_of_match,
-		.pm = &sirf_audio_codec_pm_ops,
-	},
-	.probe = sirf_audio_codec_driver_probe,
-	.remove = sirf_audio_codec_driver_remove,
-};
-
-module_platform_driver(sirf_audio_codec_driver);
-
-MODULE_DESCRIPTION("SiRF audio codec driver");
-MODULE_AUTHOR("RongJun Ying <Rongjun.Ying@csr.com>");
-MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c
index 905160246614..7964e922b07f 100644
--- a/sound/soc/codecs/ssm2602.c
+++ b/sound/soc/codecs/ssm2602.c
@@ -526,8 +526,8 @@ static struct snd_soc_dai_driver ssm2602_dai = {
 		.rates = SSM2602_RATES,
 		.formats = SSM2602_FORMATS,},
 	.ops = &ssm2602_dai_ops,
-	.symmetric_rates = 1,
-	.symmetric_samplebits = 1,
+	.symmetric_rate = 1,
+	.symmetric_sample_bits = 1,
 };
 
 static int ssm2602_resume(struct snd_soc_component *component)
diff --git a/sound/soc/codecs/tas2764.c b/sound/soc/codecs/tas2764.c
index 14a193e48dc7..8ff4d9e8d568 100644
--- a/sound/soc/codecs/tas2764.c
+++ b/sound/soc/codecs/tas2764.c
@@ -490,7 +490,7 @@ static struct snd_soc_dai_driver tas2764_dai_driver[] = {
 			.formats = TAS2764_FORMATS,
 		},
 		.ops = &tas2764_dai_ops,
-		.symmetric_rates = 1,
+		.symmetric_rate = 1,
 	},
 };
 
diff --git a/sound/soc/codecs/tas2770.c b/sound/soc/codecs/tas2770.c
index a91a0a31e74d..15fca5109e14 100644
--- a/sound/soc/codecs/tas2770.c
+++ b/sound/soc/codecs/tas2770.c
@@ -499,7 +499,7 @@ static struct snd_soc_dai_driver tas2770_dai_driver[] = {
 			.formats    = TAS2770_FORMATS,
 		},
 		.ops = &tas2770_dai_ops,
-		.symmetric_rates = 1,
+		.symmetric_rate = 1,
 	},
 };
 
diff --git a/sound/soc/codecs/tlv320adcx140.c b/sound/soc/codecs/tlv320adcx140.c
index 3f027c8234a6..32b120d624b2 100644
--- a/sound/soc/codecs/tlv320adcx140.c
+++ b/sound/soc/codecs/tlv320adcx140.c
@@ -1069,7 +1069,7 @@ static struct snd_soc_dai_driver adcx140_dai_driver[] = {
 			.formats	 = ADCX140_FORMATS,
 		},
 		.ops = &adcx140_dai_ops,
-		.symmetric_rates = 1,
+		.symmetric_rate = 1,
 	}
 };
 
diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c
index 5ac7ce264431..51870d50f419 100644
--- a/sound/soc/codecs/tlv320aic31xx.c
+++ b/sound/soc/codecs/tlv320aic31xx.c
@@ -1395,7 +1395,7 @@ static struct snd_soc_dai_driver dac31xx_dai_driver[] = {
 			.formats	 = AIC31XX_FORMATS,
 		},
 		.ops = &aic31xx_dai_ops,
-		.symmetric_rates = 1,
+		.symmetric_rate = 1,
 	}
 };
 
@@ -1417,7 +1417,7 @@ static struct snd_soc_dai_driver aic31xx_dai_driver[] = {
 			.formats	 = AIC31XX_FORMATS,
 		},
 		.ops = &aic31xx_dai_ops,
-		.symmetric_rates = 1,
+		.symmetric_rate = 1,
 	}
 };
 
diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c
index 9e3de9ded0ef..f04f88c8d425 100644
--- a/sound/soc/codecs/tlv320aic32x4.c
+++ b/sound/soc/codecs/tlv320aic32x4.c
@@ -916,7 +916,7 @@ static struct snd_soc_dai_driver aic32x4_dai = {
 			.rates = AIC32X4_RATES,
 			.formats = AIC32X4_FORMATS,},
 	.ops = &aic32x4_ops,
-	.symmetric_rates = 1,
+	.symmetric_rate = 1,
 };
 
 static void aic32x4_setup_gpios(struct snd_soc_component *component)
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
index 6d066bc58ac8..db1444127444 100644
--- a/sound/soc/codecs/tlv320aic3x.c
+++ b/sound/soc/codecs/tlv320aic3x.c
@@ -1503,7 +1503,7 @@ static struct snd_soc_dai_driver aic3x_dai = {
 		.rates = AIC3X_RATES,
 		.formats = AIC3X_FORMATS,},
 	.ops = &aic3x_dai_ops,
-	.symmetric_rates = 1,
+	.symmetric_rate = 1,
 };
 
 static void aic3x_mono_init(struct snd_soc_component *component)
diff --git a/sound/soc/codecs/tscs42xx.c b/sound/soc/codecs/tscs42xx.c
index 6200fab7896f..fb861baf50e8 100644
--- a/sound/soc/codecs/tscs42xx.c
+++ b/sound/soc/codecs/tscs42xx.c
@@ -1397,9 +1397,9 @@ static struct snd_soc_dai_driver tscs42xx_dai = {
 		.rates = TSCS42XX_RATES,
 		.formats = TSCS42XX_FORMATS,},
 	.ops = &tscs42xx_dai_ops,
-	.symmetric_rates = 1,
+	.symmetric_rate = 1,
 	.symmetric_channels = 1,
-	.symmetric_samplebits = 1,
+	.symmetric_sample_bits = 1,
 };
 
 static const struct reg_sequence tscs42xx_patch[] = {
diff --git a/sound/soc/codecs/tscs454.c b/sound/soc/codecs/tscs454.c
index cd1f1a592386..1bafc9d1101c 100644
--- a/sound/soc/codecs/tscs454.c
+++ b/sound/soc/codecs/tscs454.c
@@ -3346,9 +3346,9 @@ static struct snd_soc_dai_driver tscs454_dais[] = {
 			.rates = TSCS454_RATES,
 			.formats = TSCS454_FORMATS,},
 		.ops = &tscs454_dai1_ops,
-		.symmetric_rates = 1,
+		.symmetric_rate = 1,
 		.symmetric_channels = 1,
-		.symmetric_samplebits = 1,
+		.symmetric_sample_bits = 1,
 	},
 	{
 		.name = "tscs454-dai2",
@@ -3366,9 +3366,9 @@ static struct snd_soc_dai_driver tscs454_dais[] = {
 			.rates = TSCS454_RATES,
 			.formats = TSCS454_FORMATS,},
 		.ops = &tscs454_dai23_ops,
-		.symmetric_rates = 1,
+		.symmetric_rate = 1,
 		.symmetric_channels = 1,
-		.symmetric_samplebits = 1,
+		.symmetric_sample_bits = 1,
 	},
 	{
 		.name = "tscs454-dai3",
@@ -3386,9 +3386,9 @@ static struct snd_soc_dai_driver tscs454_dais[] = {
 			.rates = TSCS454_RATES,
 			.formats = TSCS454_FORMATS,},
 		.ops = &tscs454_dai23_ops,
-		.symmetric_rates = 1,
+		.symmetric_rate = 1,
 		.symmetric_channels = 1,
-		.symmetric_samplebits = 1,
+		.symmetric_sample_bits = 1,
 	},
 };
 
diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c
index 70d353b63fe0..fe33f2d88f55 100644
--- a/sound/soc/codecs/wm5102.c
+++ b/sound/soc/codecs/wm5102.c
@@ -1780,8 +1780,8 @@ static struct snd_soc_dai_driver wm5102_dai[] = {
 			 .formats = WM5102_FORMATS,
 		 },
 		.ops = &arizona_dai_ops,
-		.symmetric_rates = 1,
-		.symmetric_samplebits = 1,
+		.symmetric_rate = 1,
+		.symmetric_sample_bits = 1,
 	},
 	{
 		.name = "wm5102-aif2",
@@ -1802,8 +1802,8 @@ static struct snd_soc_dai_driver wm5102_dai[] = {
 			 .formats = WM5102_FORMATS,
 		 },
 		.ops = &arizona_dai_ops,
-		.symmetric_rates = 1,
-		.symmetric_samplebits = 1,
+		.symmetric_rate = 1,
+		.symmetric_sample_bits = 1,
 	},
 	{
 		.name = "wm5102-aif3",
@@ -1824,8 +1824,8 @@ static struct snd_soc_dai_driver wm5102_dai[] = {
 			 .formats = WM5102_FORMATS,
 		 },
 		.ops = &arizona_dai_ops,
-		.symmetric_rates = 1,
-		.symmetric_samplebits = 1,
+		.symmetric_rate = 1,
+		.symmetric_sample_bits = 1,
 	},
 	{
 		.name = "wm5102-slim1",
diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c
index 4238929b2375..52c0a575cc4f 100644
--- a/sound/soc/codecs/wm5110.c
+++ b/sound/soc/codecs/wm5110.c
@@ -2089,8 +2089,8 @@ static struct snd_soc_dai_driver wm5110_dai[] = {
 			 .formats = WM5110_FORMATS,
 		 },
 		.ops = &arizona_dai_ops,
-		.symmetric_rates = 1,
-		.symmetric_samplebits = 1,
+		.symmetric_rate = 1,
+		.symmetric_sample_bits = 1,
 	},
 	{
 		.name = "wm5110-aif2",
@@ -2111,8 +2111,8 @@ static struct snd_soc_dai_driver wm5110_dai[] = {
 			 .formats = WM5110_FORMATS,
 		 },
 		.ops = &arizona_dai_ops,
-		.symmetric_rates = 1,
-		.symmetric_samplebits = 1,
+		.symmetric_rate = 1,
+		.symmetric_sample_bits = 1,
 	},
 	{
 		.name = "wm5110-aif3",
@@ -2133,8 +2133,8 @@ static struct snd_soc_dai_driver wm5110_dai[] = {
 			 .formats = WM5110_FORMATS,
 		 },
 		.ops = &arizona_dai_ops,
-		.symmetric_rates = 1,
-		.symmetric_samplebits = 1,
+		.symmetric_rate = 1,
+		.symmetric_sample_bits = 1,
 	},
 	{
 		.name = "wm5110-slim1",
diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c
index 73c4a8b9f59e..a18e2290b8c8 100644
--- a/sound/soc/codecs/wm8510.c
+++ b/sound/soc/codecs/wm8510.c
@@ -569,7 +569,7 @@ static struct snd_soc_dai_driver wm8510_dai = {
 		.rates = WM8510_RATES,
 		.formats = WM8510_FORMATS,},
 	.ops = &wm8510_dai_ops,
-	.symmetric_rates = 1,
+	.symmetric_rate = 1,
 };
 
 static int wm8510_probe(struct snd_soc_component *component)
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c
index 304bf725a613..dcee7b2bd3d7 100644
--- a/sound/soc/codecs/wm8731.c
+++ b/sound/soc/codecs/wm8731.c
@@ -567,7 +567,7 @@ static struct snd_soc_dai_driver wm8731_dai = {
 		.rates = WM8731_RATES,
 		.formats = WM8731_FORMATS,},
 	.ops = &wm8731_dai_ops,
-	.symmetric_rates = 1,
+	.symmetric_rate = 1,
 };
 
 static int wm8731_request_supplies(struct device *dev,
diff --git a/sound/soc/codecs/wm8770.c b/sound/soc/codecs/wm8770.c
index 1176a6ad269d..5f394065030d 100644
--- a/sound/soc/codecs/wm8770.c
+++ b/sound/soc/codecs/wm8770.c
@@ -562,7 +562,7 @@ static struct snd_soc_dai_driver wm8770_dai = {
 		.formats = WM8770_FORMATS
 	},
 	.ops = &wm8770_dai_ops,
-	.symmetric_rates = 1
+	.symmetric_rate = 1
 };
 
 static int wm8770_probe(struct snd_soc_component *component)
diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c
index 4ddb5e32df5d..21bf0cfa1e7e 100644
--- a/sound/soc/codecs/wm8804.c
+++ b/sound/soc/codecs/wm8804.c
@@ -536,7 +536,7 @@ static struct snd_soc_dai_driver wm8804_dai = {
 		.formats = WM8804_FORMATS,
 	},
 	.ops = &wm8804_dai_ops,
-	.symmetric_rates = 1
+	.symmetric_rate = 1
 };
 
 static const struct snd_soc_component_driver soc_component_dev_wm8804 = {
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c
index 09f4980630c7..026603ae44ce 100644
--- a/sound/soc/codecs/wm8903.c
+++ b/sound/soc/codecs/wm8903.c
@@ -1760,7 +1760,7 @@ static struct snd_soc_dai_driver wm8903_dai = {
 		 .formats = WM8903_FORMATS,
 	 },
 	.ops = &wm8903_dai_ops,
-	.symmetric_rates = 1,
+	.symmetric_rate = 1,
 };
 
 static int wm8903_resume(struct snd_soc_component *component)
diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c
index 1c360bae5652..a02a77fef360 100644
--- a/sound/soc/codecs/wm8904.c
+++ b/sound/soc/codecs/wm8904.c
@@ -1983,7 +1983,7 @@ static struct snd_soc_dai_driver wm8904_dai = {
 		.formats = WM8904_FORMATS,
 	},
 	.ops = &wm8904_dai_ops,
-	.symmetric_rates = 1,
+	.symmetric_rate = 1,
 };
 
 static void wm8904_handle_retune_mobile_pdata(struct snd_soc_component *component)
diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c
index 016cd8aeef37..440d048ef0c0 100644
--- a/sound/soc/codecs/wm8940.c
+++ b/sound/soc/codecs/wm8940.c
@@ -688,7 +688,7 @@ static struct snd_soc_dai_driver wm8940_dai = {
 		.formats = WM8940_FORMATS,
 	},
 	.ops = &wm8940_dai_ops,
-	.symmetric_rates = 1,
+	.symmetric_rate = 1,
 };
 
 static int wm8940_probe(struct snd_soc_component *component)
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c
index 660ec46eecf2..df351519a3a6 100644
--- a/sound/soc/codecs/wm8960.c
+++ b/sound/soc/codecs/wm8960.c
@@ -1338,7 +1338,7 @@ static struct snd_soc_dai_driver wm8960_dai = {
 		.rates = WM8960_RATES,
 		.formats = WM8960_FORMATS,},
 	.ops = &wm8960_dai_ops,
-	.symmetric_rates = 1,
+	.symmetric_rate = 1,
 };
 
 static int wm8960_probe(struct snd_soc_component *component)
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c
index 3af456010b9c..ce4666a74793 100644
--- a/sound/soc/codecs/wm8962.c
+++ b/sound/soc/codecs/wm8962.c
@@ -2973,7 +2973,7 @@ static struct snd_soc_dai_driver wm8962_dai = {
 		.formats = WM8962_FORMATS,
 	},
 	.ops = &wm8962_dai_ops,
-	.symmetric_rates = 1,
+	.symmetric_rate = 1,
 };
 
 static void wm8962_mic_work(struct work_struct *work)
diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c
index c86231dfcf4f..fdc68ab49742 100644
--- a/sound/soc/codecs/wm8974.c
+++ b/sound/soc/codecs/wm8974.c
@@ -643,7 +643,7 @@ static struct snd_soc_dai_driver wm8974_dai = {
 		.rates = WM8974_RATES,
 		.formats = WM8974_FORMATS,},
 	.ops = &wm8974_ops,
-	.symmetric_rates = 1,
+	.symmetric_rate = 1,
 };
 
 static const struct regmap_config wm8974_regmap = {
diff --git a/sound/soc/codecs/wm8978.c b/sound/soc/codecs/wm8978.c
index a7acb8981715..4b5ecd142249 100644
--- a/sound/soc/codecs/wm8978.c
+++ b/sound/soc/codecs/wm8978.c
@@ -918,7 +918,7 @@ static struct snd_soc_dai_driver wm8978_dai = {
 		.formats = WM8978_FORMATS,
 	},
 	.ops = &wm8978_dai_ops,
-	.symmetric_rates = 1,
+	.symmetric_rate = 1,
 };
 
 static int wm8978_suspend(struct snd_soc_component *component)
diff --git a/sound/soc/codecs/wm8983.c b/sound/soc/codecs/wm8983.c
index d1d2d408ad95..d8ed22a9caac 100644
--- a/sound/soc/codecs/wm8983.c
+++ b/sound/soc/codecs/wm8983.c
@@ -971,7 +971,7 @@ static struct snd_soc_dai_driver wm8983_dai = {
 		.formats = WM8983_FORMATS,
 	},
 	.ops = &wm8983_dai_ops,
-	.symmetric_rates = 1
+	.symmetric_rate = 1
 };
 
 static const struct snd_soc_component_driver soc_component_dev_wm8983 = {
diff --git a/sound/soc/codecs/wm8985.c b/sound/soc/codecs/wm8985.c
index 3f27482349b2..a7e01106fbc0 100644
--- a/sound/soc/codecs/wm8985.c
+++ b/sound/soc/codecs/wm8985.c
@@ -1100,7 +1100,7 @@ static struct snd_soc_dai_driver wm8985_dai = {
 		.formats = WM8985_FORMATS,
 	},
 	.ops = &wm8985_dai_ops,
-	.symmetric_rates = 1
+	.symmetric_rate = 1
 };
 
 static const struct snd_soc_component_driver soc_component_dev_wm8985 = {
diff --git a/sound/soc/codecs/wm8988.c b/sound/soc/codecs/wm8988.c
index d2c2d0d943f0..1d2f881bbcae 100644
--- a/sound/soc/codecs/wm8988.c
+++ b/sound/soc/codecs/wm8988.c
@@ -787,7 +787,7 @@ static struct snd_soc_dai_driver wm8988_dai = {
 		.formats = WM8988_FORMATS,
 	 },
 	.ops = &wm8988_ops,
-	.symmetric_rates = 1,
+	.symmetric_rate = 1,
 };
 
 static int wm8988_probe(struct snd_soc_component *component)
diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c
index 9f310082e3c1..c4f41692b806 100644
--- a/sound/soc/codecs/wm8993.c
+++ b/sound/soc/codecs/wm8993.c
@@ -1476,7 +1476,7 @@ static struct snd_soc_dai_driver wm8993_dai = {
 		 .sig_bits = 24,
 	 },
 	.ops = &wm8993_ops,
-	.symmetric_rates = 1,
+	.symmetric_rate = 1,
 };
 
 static int wm8993_probe(struct snd_soc_component *component)
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c
index f57884113406..f117ec0c489f 100644
--- a/sound/soc/codecs/wm8994.c
+++ b/sound/soc/codecs/wm8994.c
@@ -4351,7 +4351,7 @@ static int wm8994_component_probe(struct snd_soc_component *component)
 	}
 	if ((reg & WM8994_GPN_FN_MASK) != WM8994_GP_FN_PIN_SPECIFIC) {
 		wm8994->lrclk_shared[0] = 1;
-		wm8994_dai[0].symmetric_rates = 1;
+		wm8994_dai[0].symmetric_rate = 1;
 	} else {
 		wm8994->lrclk_shared[0] = 0;
 	}
@@ -4363,7 +4363,7 @@ static int wm8994_component_probe(struct snd_soc_component *component)
 	}
 	if ((reg & WM8994_GPN_FN_MASK) != WM8994_GP_FN_PIN_SPECIFIC) {
 		wm8994->lrclk_shared[1] = 1;
-		wm8994_dai[1].symmetric_rates = 1;
+		wm8994_dai[1].symmetric_rate = 1;
 	} else {
 		wm8994->lrclk_shared[1] = 0;
 	}
diff --git a/sound/soc/codecs/wm8997.c b/sound/soc/codecs/wm8997.c
index 229f2986cd96..99c3ebae6ba6 100644
--- a/sound/soc/codecs/wm8997.c
+++ b/sound/soc/codecs/wm8997.c
@@ -969,8 +969,8 @@ static struct snd_soc_dai_driver wm8997_dai[] = {
 			 .formats = WM8997_FORMATS,
 		 },
 		.ops = &arizona_dai_ops,
-		.symmetric_rates = 1,
-		.symmetric_samplebits = 1,
+		.symmetric_rate = 1,
+		.symmetric_sample_bits = 1,
 	},
 	{
 		.name = "wm8997-aif2",
@@ -991,8 +991,8 @@ static struct snd_soc_dai_driver wm8997_dai[] = {
 			 .formats = WM8997_FORMATS,
 		 },
 		.ops = &arizona_dai_ops,
-		.symmetric_rates = 1,
-		.symmetric_samplebits = 1,
+		.symmetric_rate = 1,
+		.symmetric_sample_bits = 1,
 	},
 	{
 		.name = "wm8997-slim1",
diff --git a/sound/soc/codecs/wm8998.c b/sound/soc/codecs/wm8998.c
index 5413254295b7..b6f717aa5478 100644
--- a/sound/soc/codecs/wm8998.c
+++ b/sound/soc/codecs/wm8998.c
@@ -1161,8 +1161,8 @@ static struct snd_soc_dai_driver wm8998_dai[] = {
 			 .formats = WM8998_FORMATS,
 		 },
 		.ops = &arizona_dai_ops,
-		.symmetric_rates = 1,
-		.symmetric_samplebits = 1,
+		.symmetric_rate = 1,
+		.symmetric_sample_bits = 1,
 	},
 	{
 		.name = "wm8998-aif2",
@@ -1183,8 +1183,8 @@ static struct snd_soc_dai_driver wm8998_dai[] = {
 			 .formats = WM8998_FORMATS,
 		 },
 		.ops = &arizona_dai_ops,
-		.symmetric_rates = 1,
-		.symmetric_samplebits = 1,
+		.symmetric_rate = 1,
+		.symmetric_sample_bits = 1,
 	},
 	{
 		.name = "wm8998-aif3",
@@ -1205,8 +1205,8 @@ static struct snd_soc_dai_driver wm8998_dai[] = {
 			 .formats = WM8998_FORMATS,
 		 },
 		.ops = &arizona_dai_ops,
-		.symmetric_rates = 1,
-		.symmetric_samplebits = 1,
+		.symmetric_rate = 1,
+		.symmetric_sample_bits = 1,
 	},
 	{
 		.name = "wm8998-slim1",
diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c
index f333e2ff4a16..e0ce32dd4a81 100644
--- a/sound/soc/codecs/wm9713.c
+++ b/sound/soc/codecs/wm9713.c
@@ -1134,7 +1134,7 @@ static struct snd_soc_dai_driver wm9713_dai[] = {
 		.rates = WM9713_PCM_RATES,
 		.formats = WM9713_PCM_FORMATS,},
 	.ops = &wm9713_dai_ops_voice,
-	.symmetric_rates = 1,
+	.symmetric_rate = 1,
 	},
 };
 
diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c
index 985b2dcecf13..070ca7d8c661 100644
--- a/sound/soc/codecs/wm_adsp.c
+++ b/sound/soc/codecs/wm_adsp.c
@@ -595,13 +595,6 @@ static const struct {
 	[WM_ADSP_FW_MISC] =     { .file = "misc" },
 };
 
-struct wm_coeff_ctl_ops {
-	int (*xget)(struct snd_kcontrol *kcontrol,
-		    struct snd_ctl_elem_value *ucontrol);
-	int (*xput)(struct snd_kcontrol *kcontrol,
-		    struct snd_ctl_elem_value *ucontrol);
-};
-
 struct wm_coeff_ctl {
 	const char *name;
 	const char *fw_name;
@@ -609,7 +602,6 @@ struct wm_coeff_ctl {
 	const char *subname;
 	unsigned int subname_len;
 	struct wm_adsp_alg_region alg_region;
-	struct wm_coeff_ctl_ops ops;
 	struct wm_adsp *dsp;
 	unsigned int enabled:1;
 	struct list_head list;
@@ -619,7 +611,7 @@ struct wm_coeff_ctl {
 	unsigned int set:1;
 	struct soc_bytes_ext bytes_ext;
 	unsigned int flags;
-	unsigned int type;
+	snd_ctl_elem_type_t type;
 };
 
 static const char *wm_adsp_mem_region_name(unsigned int type)
@@ -980,7 +972,7 @@ static int wm_coeff_write_acked_control(struct wm_coeff_ctl *ctl,
 					unsigned int event_id)
 {
 	struct wm_adsp *dsp = ctl->dsp;
-	u32 val = cpu_to_be32(event_id);
+	__be32 val = cpu_to_be32(event_id);
 	unsigned int reg;
 	int i, ret;
 
@@ -1420,7 +1412,7 @@ static int wm_adsp_create_control(struct wm_adsp *dsp,
 				  const struct wm_adsp_alg_region *alg_region,
 				  unsigned int offset, unsigned int len,
 				  const char *subname, unsigned int subname_len,
-				  unsigned int flags, unsigned int type)
+				  unsigned int flags, snd_ctl_elem_type_t type)
 {
 	struct wm_coeff_ctl *ctl;
 	struct wmfw_ctl_work *ctl_work;
@@ -1497,8 +1489,6 @@ static int wm_adsp_create_control(struct wm_adsp *dsp,
 	}
 	ctl->enabled = 1;
 	ctl->set = 0;
-	ctl->ops.xget = wm_coeff_get;
-	ctl->ops.xput = wm_coeff_put;
 	ctl->dsp = dsp;
 
 	ctl->flags = flags;
@@ -1554,7 +1544,7 @@ struct wm_coeff_parsed_coeff {
 	int mem_type;
 	const u8 *name;
 	int name_len;
-	int ctl_type;
+	snd_ctl_elem_type_t ctl_type;
 	int flags;
 	int len;
 };
@@ -1649,7 +1639,7 @@ static inline void wm_coeff_parse_coeff(struct wm_adsp *dsp, const u8 **data,
 		blk->mem_type = le16_to_cpu(raw->hdr.type);
 		blk->name = raw->name;
 		blk->name_len = strlen(raw->name);
-		blk->ctl_type = le16_to_cpu(raw->ctl_type);
+		blk->ctl_type = (__force snd_ctl_elem_type_t)le16_to_cpu(raw->ctl_type);
 		blk->flags = le16_to_cpu(raw->flags);
 		blk->len = le32_to_cpu(raw->len);
 		break;
@@ -1662,7 +1652,9 @@ static inline void wm_coeff_parse_coeff(struct wm_adsp *dsp, const u8 **data,
 						      &blk->name);
 		wm_coeff_parse_string(sizeof(u8), &tmp, NULL);
 		wm_coeff_parse_string(sizeof(u16), &tmp, NULL);
-		blk->ctl_type = wm_coeff_parse_int(sizeof(raw->ctl_type), &tmp);
+		blk->ctl_type =
+			(__force snd_ctl_elem_type_t)wm_coeff_parse_int(sizeof(raw->ctl_type),
+									&tmp);
 		blk->flags = wm_coeff_parse_int(sizeof(raw->flags), &tmp);
 		blk->len = wm_coeff_parse_int(sizeof(raw->len), &tmp);
 
@@ -3667,12 +3659,12 @@ int wm_adsp_compr_get_caps(struct snd_soc_component *component,
 }
 EXPORT_SYMBOL_GPL(wm_adsp_compr_get_caps);
 
-static int wm_adsp_read_data_block(struct wm_adsp *dsp, int mem_type,
-				   unsigned int mem_addr,
-				   unsigned int num_words, u32 *data)
+static int wm_adsp_read_raw_data_block(struct wm_adsp *dsp, int mem_type,
+				       unsigned int mem_addr,
+				       unsigned int num_words, __be32 *data)
 {
 	struct wm_adsp_region const *mem = wm_adsp_find_region(dsp, mem_type);
-	unsigned int i, reg;
+	unsigned int reg;
 	int ret;
 
 	if (!mem)
@@ -3685,22 +3677,29 @@ static int wm_adsp_read_data_block(struct wm_adsp *dsp, int mem_type,
 	if (ret < 0)
 		return ret;
 
-	for (i = 0; i < num_words; ++i)
-		data[i] = be32_to_cpu(data[i]) & 0x00ffffffu;
-
 	return 0;
 }
 
 static inline int wm_adsp_read_data_word(struct wm_adsp *dsp, int mem_type,
 					 unsigned int mem_addr, u32 *data)
 {
-	return wm_adsp_read_data_block(dsp, mem_type, mem_addr, 1, data);
+	__be32 raw;
+	int ret;
+
+	ret = wm_adsp_read_raw_data_block(dsp, mem_type, mem_addr, 1, &raw);
+	if (ret < 0)
+		return ret;
+
+	*data = be32_to_cpu(raw) & 0x00ffffffu;
+
+	return 0;
 }
 
 static int wm_adsp_write_data_word(struct wm_adsp *dsp, int mem_type,
 				   unsigned int mem_addr, u32 data)
 {
 	struct wm_adsp_region const *mem = wm_adsp_find_region(dsp, mem_type);
+	__be32 val = cpu_to_be32(data & 0x00ffffffu);
 	unsigned int reg;
 
 	if (!mem)
@@ -3708,9 +3707,7 @@ static int wm_adsp_write_data_word(struct wm_adsp *dsp, int mem_type,
 
 	reg = dsp->ops->region_to_reg(mem, mem_addr);
 
-	data = cpu_to_be32(data & 0x00ffffffu);
-
-	return regmap_raw_write(dsp->regmap, reg, &data, sizeof(data));
+	return regmap_raw_write(dsp->regmap, reg, &val, sizeof(val));
 }
 
 static inline int wm_adsp_buffer_read(struct wm_adsp_compr_buf *buf,
@@ -3727,18 +3724,22 @@ static inline int wm_adsp_buffer_write(struct wm_adsp_compr_buf *buf,
 				       buf->host_buf_ptr + field_offset, data);
 }
 
-static void wm_adsp_remove_padding(u32 *buf, int nwords, int data_word_size)
+static void wm_adsp_remove_padding(u32 *buf, int nwords)
 {
-	u8 *pack_in = (u8 *)buf;
+	const __be32 *pack_in = (__be32 *)buf;
 	u8 *pack_out = (u8 *)buf;
-	int i, j;
+	int i;
 
-	/* Remove the padding bytes from the data read from the DSP */
+	/*
+	 * DSP words from the register map have pad bytes and the data bytes
+	 * are in swapped order. This swaps back to the original little-endian
+	 * order and strips the pad bytes.
+	 */
 	for (i = 0; i < nwords; i++) {
-		for (j = 0; j < data_word_size; j++)
-			*pack_out++ = *pack_in++;
-
-		pack_in += sizeof(*buf) - data_word_size;
+		u32 word = be32_to_cpu(*pack_in++);
+		*pack_out++ = (u8)word;
+		*pack_out++ = (u8)(word >> 8);
+		*pack_out++ = (u8)(word >> 16);
 	}
 }
 
@@ -3863,7 +3864,8 @@ static int wm_adsp_buffer_parse_coeff(struct wm_coeff_ctl *ctl)
 {
 	struct wm_adsp_host_buf_coeff_v1 coeff_v1;
 	struct wm_adsp_compr_buf *buf;
-	unsigned int val, reg;
+	unsigned int reg, version;
+	__be32 bufp;
 	int ret, i;
 
 	ret = wm_coeff_base_reg(ctl, &reg);
@@ -3871,17 +3873,17 @@ static int wm_adsp_buffer_parse_coeff(struct wm_coeff_ctl *ctl)
 		return ret;
 
 	for (i = 0; i < 5; ++i) {
-		ret = regmap_raw_read(ctl->dsp->regmap, reg, &val, sizeof(val));
+		ret = regmap_raw_read(ctl->dsp->regmap, reg, &bufp, sizeof(bufp));
 		if (ret < 0)
 			return ret;
 
-		if (val)
+		if (bufp)
 			break;
 
 		usleep_range(1000, 2000);
 	}
 
-	if (!val) {
+	if (!bufp) {
 		adsp_err(ctl->dsp, "Failed to acquire host buffer\n");
 		return -EIO;
 	}
@@ -3891,7 +3893,7 @@ static int wm_adsp_buffer_parse_coeff(struct wm_coeff_ctl *ctl)
 		return -ENOMEM;
 
 	buf->host_buf_mem_type = ctl->alg_region.type;
-	buf->host_buf_ptr = be32_to_cpu(val);
+	buf->host_buf_ptr = be32_to_cpu(bufp);
 
 	ret = wm_adsp_buffer_populate(buf);
 	if (ret < 0)
@@ -3911,31 +3913,25 @@ static int wm_adsp_buffer_parse_coeff(struct wm_coeff_ctl *ctl)
 	if (ret < 0)
 		return ret;
 
-	coeff_v1.versions = be32_to_cpu(coeff_v1.versions);
-	val = coeff_v1.versions & HOST_BUF_COEFF_COMPAT_VER_MASK;
-	val >>= HOST_BUF_COEFF_COMPAT_VER_SHIFT;
+	version = be32_to_cpu(coeff_v1.versions) & HOST_BUF_COEFF_COMPAT_VER_MASK;
+	version >>= HOST_BUF_COEFF_COMPAT_VER_SHIFT;
 
-	if (val > HOST_BUF_COEFF_SUPPORTED_COMPAT_VER) {
+	if (version > HOST_BUF_COEFF_SUPPORTED_COMPAT_VER) {
 		adsp_err(ctl->dsp,
 			 "Host buffer coeff ver %u > supported version %u\n",
-			 val, HOST_BUF_COEFF_SUPPORTED_COMPAT_VER);
+			 version, HOST_BUF_COEFF_SUPPORTED_COMPAT_VER);
 		return -EINVAL;
 	}
 
-	for (i = 0; i < ARRAY_SIZE(coeff_v1.name); i++)
-		coeff_v1.name[i] = be32_to_cpu(coeff_v1.name[i]);
-
-	wm_adsp_remove_padding((u32 *)&coeff_v1.name,
-			       ARRAY_SIZE(coeff_v1.name),
-			       WM_ADSP_DATA_WORD_SIZE);
+	wm_adsp_remove_padding((u32 *)&coeff_v1.name, ARRAY_SIZE(coeff_v1.name));
 
 	buf->name = kasprintf(GFP_KERNEL, "%s-dsp-%s", ctl->dsp->part,
 			      (char *)&coeff_v1.name);
 
 	compr_dbg(buf, "host_buf_ptr=%x coeff version %u\n",
-		  buf->host_buf_ptr, val);
+		  buf->host_buf_ptr, version);
 
-	return val;
+	return version;
 }
 
 static int wm_adsp_buffer_init(struct wm_adsp *dsp)
@@ -4266,12 +4262,12 @@ static int wm_adsp_buffer_capture_block(struct wm_adsp_compr *compr, int target)
 		return 0;
 
 	/* Read data from DSP */
-	ret = wm_adsp_read_data_block(buf->dsp, mem_type, adsp_addr,
-				      nwords, compr->raw_buf);
+	ret = wm_adsp_read_raw_data_block(buf->dsp, mem_type, adsp_addr,
+					  nwords, (__be32 *)compr->raw_buf);
 	if (ret < 0)
 		return ret;
 
-	wm_adsp_remove_padding(compr->raw_buf, nwords, WM_ADSP_DATA_WORD_SIZE);
+	wm_adsp_remove_padding(compr->raw_buf, nwords);
 
 	/* update read index to account for words read */
 	buf->read_index += nwords;
diff --git a/sound/soc/codecs/wmfw.h b/sound/soc/codecs/wmfw.h
index 7423272c30e9..f3d51602f85c 100644
--- a/sound/soc/codecs/wmfw.h
+++ b/sound/soc/codecs/wmfw.h
@@ -24,9 +24,9 @@
 #define WMFW_CTL_FLAG_READABLE    0x0001
 
 /* Non-ALSA coefficient types start at 0x1000 */
-#define WMFW_CTL_TYPE_ACKED       0x1000 /* acked control */
-#define WMFW_CTL_TYPE_HOSTEVENT   0x1001 /* event control */
-#define WMFW_CTL_TYPE_HOST_BUFFER 0x1002 /* host buffer pointer */
+#define WMFW_CTL_TYPE_ACKED       ((__force snd_ctl_elem_type_t)0x1000) /* acked control */
+#define WMFW_CTL_TYPE_HOSTEVENT   ((__force snd_ctl_elem_type_t)0x1001) /* event control */
+#define WMFW_CTL_TYPE_HOST_BUFFER ((__force snd_ctl_elem_type_t)0x1002) /* host buffer pointer */
 
 struct wmfw_header {
 	char magic[4];
diff --git a/sound/soc/codecs/zl38060.c b/sound/soc/codecs/zl38060.c
index 42726dc0ba39..d21a72314d37 100644
--- a/sound/soc/codecs/zl38060.c
+++ b/sound/soc/codecs/zl38060.c
@@ -360,8 +360,8 @@ static struct snd_soc_dai_driver zl38_dai = {
 		.formats = ZL38_FORMATS,
 	},
 	.ops = &zl38_dai_ops,
-	.symmetric_rates = 1,
-	.symmetric_samplebits = 1,
+	.symmetric_rate = 1,
+	.symmetric_sample_bits = 1,
 	.symmetric_channels = 1,
 };
 
diff --git a/sound/soc/codecs/zx_aud96p22.c b/sound/soc/codecs/zx_aud96p22.c
deleted file mode 100644
index 16d44efb132d..000000000000
--- a/sound/soc/codecs/zx_aud96p22.c
+++ /dev/null
@@ -1,401 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (C) 2017 Sanechips Technology Co., Ltd.
- * Copyright 2017 Linaro Ltd.
- *
- * Author: Baoyou Xie <baoyou.xie@linaro.org>
- */
-
-#include <linux/gpio/consumer.h>
-#include <linux/i2c.h>
-#include <linux/module.h>
-#include <linux/regmap.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/soc.h>
-#include <sound/soc-dai.h>
-#include <sound/tlv.h>
-
-#define AUD96P22_RESET			0x00
-#define RST_DAC_DPZ			BIT(0)
-#define RST_ADC_DPZ			BIT(1)
-#define AUD96P22_I2S1_CONFIG_0		0x03
-#define I2S1_MS_MODE			BIT(3)
-#define I2S1_MODE_MASK			0x7
-#define I2S1_MODE_RIGHT_J		0x0
-#define I2S1_MODE_I2S			0x1
-#define I2S1_MODE_LEFT_J		0x2
-#define AUD96P22_PD_0			0x15
-#define AUD96P22_PD_1			0x16
-#define AUD96P22_PD_3			0x18
-#define AUD96P22_PD_4			0x19
-#define AUD96P22_MUTE_0			0x1d
-#define AUD96P22_MUTE_2			0x1f
-#define AUD96P22_MUTE_4			0x21
-#define AUD96P22_RECVOL_0		0x24
-#define AUD96P22_RECVOL_1		0x25
-#define AUD96P22_PGA1VOL_0		0x26
-#define AUD96P22_PGA1VOL_1		0x27
-#define AUD96P22_LMVOL_0		0x34
-#define AUD96P22_LMVOL_1		0x35
-#define AUD96P22_HS1VOL_0		0x38
-#define AUD96P22_HS1VOL_1		0x39
-#define AUD96P22_PGA1SEL_0		0x47
-#define AUD96P22_PGA1SEL_1		0x48
-#define AUD96P22_LDR1SEL_0		0x59
-#define AUD96P22_LDR1SEL_1		0x60
-#define AUD96P22_LDR2SEL_0		0x5d
-#define AUD96P22_REG_MAX		0xfb
-
-struct aud96p22_priv {
-	struct regmap *regmap;
-};
-
-static int aud96p22_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 aud96p22_priv *priv = snd_soc_component_get_drvdata(component);
-	struct regmap *regmap = priv->regmap;
-
-	if (event != SND_SOC_DAPM_POST_PMU)
-		return -EINVAL;
-
-	/* Assert/de-assert the bit to reset ADC data path  */
-	regmap_update_bits(regmap, AUD96P22_RESET, RST_ADC_DPZ, 0);
-	regmap_update_bits(regmap, AUD96P22_RESET, RST_ADC_DPZ, RST_ADC_DPZ);
-
-	return 0;
-}
-
-static int aud96p22_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 aud96p22_priv *priv = snd_soc_component_get_drvdata(component);
-	struct regmap *regmap = priv->regmap;
-
-	if (event != SND_SOC_DAPM_POST_PMU)
-		return -EINVAL;
-
-	/* Assert/de-assert the bit to reset DAC data path  */
-	regmap_update_bits(regmap, AUD96P22_RESET, RST_DAC_DPZ, 0);
-	regmap_update_bits(regmap, AUD96P22_RESET, RST_DAC_DPZ, RST_DAC_DPZ);
-
-	return 0;
-}
-
-static const DECLARE_TLV_DB_SCALE(lm_tlv, -11550, 50, 0);
-static const DECLARE_TLV_DB_SCALE(hs_tlv, -3900, 300, 0);
-static const DECLARE_TLV_DB_SCALE(rec_tlv, -9550, 50, 0);
-static const DECLARE_TLV_DB_SCALE(pga_tlv, -1800, 100, 0);
-
-static const struct snd_kcontrol_new aud96p22_snd_controls[] = {
-	/* Volume control */
-	SOC_DOUBLE_R_TLV("Master Playback Volume", AUD96P22_LMVOL_0,
-			 AUD96P22_LMVOL_1, 0, 0xff, 0, lm_tlv),
-	SOC_DOUBLE_R_TLV("Headphone Volume", AUD96P22_HS1VOL_0,
-			 AUD96P22_HS1VOL_1, 0, 0xf, 0, hs_tlv),
-	SOC_DOUBLE_R_TLV("Master Capture Volume", AUD96P22_RECVOL_0,
-			 AUD96P22_RECVOL_1, 0, 0xff, 0, rec_tlv),
-	SOC_DOUBLE_R_TLV("Analogue Capture Volume", AUD96P22_PGA1VOL_0,
-			 AUD96P22_PGA1VOL_1, 0, 0x37, 0, pga_tlv),
-
-	/* Mute control */
-	SOC_DOUBLE("Master Playback Switch", AUD96P22_MUTE_2, 0, 1, 1, 1),
-	SOC_DOUBLE("Headphone Switch", AUD96P22_MUTE_2, 4, 5, 1, 1),
-	SOC_DOUBLE("Line Out Switch", AUD96P22_MUTE_4, 0, 1, 1, 1),
-	SOC_DOUBLE("Speaker Switch", AUD96P22_MUTE_4, 2, 3, 1, 1),
-	SOC_DOUBLE("Master Capture Switch", AUD96P22_MUTE_0, 0, 1, 1, 1),
-	SOC_DOUBLE("Analogue Capture Switch", AUD96P22_MUTE_0, 2, 3, 1, 1),
-};
-
-/* Input mux kcontrols */
-static const unsigned int ain_mux_values[] = {
-	0, 1, 3, 4, 5,
-};
-
-static const char * const ainl_mux_texts[] = {
-	"AINL1 differential",
-	"AINL1 single-ended",
-	"AINL3 single-ended",
-	"AINL2 differential",
-	"AINL2 single-ended",
-};
-
-static const char * const ainr_mux_texts[] = {
-	"AINR1 differential",
-	"AINR1 single-ended",
-	"AINR3 single-ended",
-	"AINR2 differential",
-	"AINR2 single-ended",
-};
-
-static SOC_VALUE_ENUM_SINGLE_DECL(ainl_mux_enum, AUD96P22_PGA1SEL_0,
-				  0, 0x7, ainl_mux_texts, ain_mux_values);
-static SOC_VALUE_ENUM_SINGLE_DECL(ainr_mux_enum, AUD96P22_PGA1SEL_1,
-				  0, 0x7, ainr_mux_texts, ain_mux_values);
-
-static const struct snd_kcontrol_new ainl_mux_kcontrol =
-			SOC_DAPM_ENUM("AINL Mux", ainl_mux_enum);
-static const struct snd_kcontrol_new ainr_mux_kcontrol =
-			SOC_DAPM_ENUM("AINR Mux", ainr_mux_enum);
-
-/* Output mixer kcontrols */
-static const struct snd_kcontrol_new ld1_left_kcontrols[] = {
-	SOC_DAPM_SINGLE("DACL LD1L Switch", AUD96P22_LDR1SEL_0, 0, 1, 0),
-	SOC_DAPM_SINGLE("AINL LD1L Switch", AUD96P22_LDR1SEL_0, 1, 1, 0),
-	SOC_DAPM_SINGLE("AINR LD1L Switch", AUD96P22_LDR1SEL_0, 2, 1, 0),
-};
-
-static const struct snd_kcontrol_new ld1_right_kcontrols[] = {
-	SOC_DAPM_SINGLE("DACR LD1R Switch", AUD96P22_LDR1SEL_1, 8, 1, 0),
-	SOC_DAPM_SINGLE("AINR LD1R Switch", AUD96P22_LDR1SEL_1, 9, 1, 0),
-	SOC_DAPM_SINGLE("AINL LD1R Switch", AUD96P22_LDR1SEL_1, 10, 1, 0),
-};
-
-static const struct snd_kcontrol_new ld2_kcontrols[] = {
-	SOC_DAPM_SINGLE("DACL LD2 Switch", AUD96P22_LDR2SEL_0, 0, 1, 0),
-	SOC_DAPM_SINGLE("AINL LD2 Switch", AUD96P22_LDR2SEL_0, 1, 1, 0),
-	SOC_DAPM_SINGLE("DACR LD2 Switch", AUD96P22_LDR2SEL_0, 2, 1, 0),
-};
-
-static const struct snd_soc_dapm_widget aud96p22_dapm_widgets[] = {
-	/* Overall power bit */
-	SND_SOC_DAPM_SUPPLY("POWER", AUD96P22_PD_0, 0, 0, NULL, 0),
-
-	/* Input pins */
-	SND_SOC_DAPM_INPUT("AINL1P"),
-	SND_SOC_DAPM_INPUT("AINL2P"),
-	SND_SOC_DAPM_INPUT("AINL3"),
-	SND_SOC_DAPM_INPUT("AINL1N"),
-	SND_SOC_DAPM_INPUT("AINL2N"),
-	SND_SOC_DAPM_INPUT("AINR2N"),
-	SND_SOC_DAPM_INPUT("AINR1N"),
-	SND_SOC_DAPM_INPUT("AINR3"),
-	SND_SOC_DAPM_INPUT("AINR2P"),
-	SND_SOC_DAPM_INPUT("AINR1P"),
-
-	/* Input muxes */
-	SND_SOC_DAPM_MUX("AINLMUX", AUD96P22_PD_1, 2, 0, &ainl_mux_kcontrol),
-	SND_SOC_DAPM_MUX("AINRMUX", AUD96P22_PD_1, 3, 0, &ainr_mux_kcontrol),
-
-	/* ADCs */
-	SND_SOC_DAPM_ADC_E("ADCL", "Capture Left", AUD96P22_PD_1, 0, 0,
-			   aud96p22_adc_event, SND_SOC_DAPM_POST_PMU),
-	SND_SOC_DAPM_ADC_E("ADCR", "Capture Right", AUD96P22_PD_1, 1, 0,
-			   aud96p22_adc_event, SND_SOC_DAPM_POST_PMU),
-
-	/* DACs */
-	SND_SOC_DAPM_DAC_E("DACL", "Playback Left", AUD96P22_PD_3, 0, 0,
-			   aud96p22_dac_event, SND_SOC_DAPM_POST_PMU),
-	SND_SOC_DAPM_DAC_E("DACR", "Playback Right", AUD96P22_PD_3, 1, 0,
-			   aud96p22_dac_event, SND_SOC_DAPM_POST_PMU),
-
-	/* Output mixers */
-	SND_SOC_DAPM_MIXER("LD1L", AUD96P22_PD_3, 6, 0, ld1_left_kcontrols,
-			   ARRAY_SIZE(ld1_left_kcontrols)),
-	SND_SOC_DAPM_MIXER("LD1R", AUD96P22_PD_3, 7, 0, ld1_right_kcontrols,
-			   ARRAY_SIZE(ld1_right_kcontrols)),
-	SND_SOC_DAPM_MIXER("LD2", AUD96P22_PD_4, 2, 0, ld2_kcontrols,
-			   ARRAY_SIZE(ld2_kcontrols)),
-
-	/* Headset power switch */
-	SND_SOC_DAPM_SUPPLY("HS1L", AUD96P22_PD_3, 4, 0, NULL, 0),
-	SND_SOC_DAPM_SUPPLY("HS1R", AUD96P22_PD_3, 5, 0, NULL, 0),
-
-	/* Output pins */
-	SND_SOC_DAPM_OUTPUT("HSOUTL"),
-	SND_SOC_DAPM_OUTPUT("LINEOUTL"),
-	SND_SOC_DAPM_OUTPUT("LINEOUTMP"),
-	SND_SOC_DAPM_OUTPUT("LINEOUTMN"),
-	SND_SOC_DAPM_OUTPUT("LINEOUTR"),
-	SND_SOC_DAPM_OUTPUT("HSOUTR"),
-};
-
-static const struct snd_soc_dapm_route aud96p22_dapm_routes[] = {
-	{ "AINLMUX", "AINL1 differential", "AINL1N" },
-	{ "AINLMUX", "AINL1 single-ended", "AINL1P" },
-	{ "AINLMUX", "AINL3 single-ended", "AINL3" },
-	{ "AINLMUX", "AINL2 differential", "AINL2N" },
-	{ "AINLMUX", "AINL2 single-ended", "AINL2P" },
-
-	{ "AINRMUX", "AINR1 differential", "AINR1N" },
-	{ "AINRMUX", "AINR1 single-ended", "AINR1P" },
-	{ "AINRMUX", "AINR3 single-ended", "AINR3" },
-	{ "AINRMUX", "AINR2 differential", "AINR2N" },
-	{ "AINRMUX", "AINR2 single-ended", "AINR2P" },
-
-	{ "ADCL", NULL, "AINLMUX" },
-	{ "ADCR", NULL, "AINRMUX" },
-
-	{ "ADCL", NULL, "POWER" },
-	{ "ADCR", NULL, "POWER" },
-	{ "DACL", NULL, "POWER" },
-	{ "DACR", NULL, "POWER" },
-
-	{ "LD1L", "DACL LD1L Switch", "DACL" },
-	{ "LD1L", "AINL LD1L Switch", "AINLMUX" },
-	{ "LD1L", "AINR LD1L Switch", "AINRMUX" },
-
-	{ "LD1R", "DACR LD1R Switch", "DACR" },
-	{ "LD1R", "AINR LD1R Switch", "AINRMUX" },
-	{ "LD1R", "AINL LD1R Switch", "AINLMUX" },
-
-	{ "LD2", "DACL LD2 Switch", "DACL" },
-	{ "LD2", "AINL LD2 Switch", "AINLMUX" },
-	{ "LD2", "DACR LD2 Switch", "DACR" },
-
-	{ "HSOUTL", NULL, "LD1L" },
-	{ "HSOUTR", NULL, "LD1R" },
-	{ "HSOUTL", NULL, "HS1L" },
-	{ "HSOUTR", NULL, "HS1R" },
-
-	{ "LINEOUTL", NULL, "LD1L" },
-	{ "LINEOUTR", NULL, "LD1R" },
-
-	{ "LINEOUTMP", NULL, "LD2" },
-	{ "LINEOUTMN", NULL, "LD2" },
-};
-
-static const struct snd_soc_component_driver aud96p22_driver = {
-	.controls		= aud96p22_snd_controls,
-	.num_controls		= ARRAY_SIZE(aud96p22_snd_controls),
-	.dapm_widgets		= aud96p22_dapm_widgets,
-	.num_dapm_widgets	= ARRAY_SIZE(aud96p22_dapm_widgets),
-	.dapm_routes		= aud96p22_dapm_routes,
-	.num_dapm_routes	= ARRAY_SIZE(aud96p22_dapm_routes),
-	.idle_bias_on		= 1,
-	.use_pmdown_time	= 1,
-	.endianness		= 1,
-	.non_legacy_dai_naming	= 1,
-};
-
-static int aud96p22_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
-{
-	struct aud96p22_priv *priv = snd_soc_component_get_drvdata(dai->component);
-	struct regmap *regmap = priv->regmap;
-	unsigned int val;
-
-	/* Master/slave mode */
-	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
-	case SND_SOC_DAIFMT_CBS_CFS:
-		val = 0;
-		break;
-	case SND_SOC_DAIFMT_CBM_CFM:
-		val = I2S1_MS_MODE;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	regmap_update_bits(regmap, AUD96P22_I2S1_CONFIG_0, I2S1_MS_MODE, val);
-
-	/* Audio format */
-	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
-	case SND_SOC_DAIFMT_RIGHT_J:
-		val = I2S1_MODE_RIGHT_J;
-		break;
-	case SND_SOC_DAIFMT_I2S:
-		val = I2S1_MODE_I2S;
-		break;
-	case SND_SOC_DAIFMT_LEFT_J:
-		val = I2S1_MODE_LEFT_J;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	regmap_update_bits(regmap, AUD96P22_I2S1_CONFIG_0, I2S1_MODE_MASK, val);
-
-	return 0;
-}
-
-static const struct snd_soc_dai_ops aud96p22_dai_ops = {
-	.set_fmt = aud96p22_set_fmt,
-};
-
-#define AUD96P22_RATES	SNDRV_PCM_RATE_8000_192000
-#define AUD96P22_FORMATS (\
-		SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S18_3LE | \
-		SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE)
-
-static struct snd_soc_dai_driver aud96p22_dai = {
-	.name = "aud96p22-dai",
-	.playback = {
-		.stream_name = "Playback",
-		.channels_min = 1,
-		.channels_max = 2,
-		.rates = AUD96P22_RATES,
-		.formats = AUD96P22_FORMATS,
-	},
-	.capture = {
-		.stream_name = "Capture",
-		.channels_min = 1,
-		.channels_max = 2,
-		.rates = AUD96P22_RATES,
-		.formats = AUD96P22_FORMATS,
-	},
-	.ops = &aud96p22_dai_ops,
-};
-
-static const struct regmap_config aud96p22_regmap = {
-	.reg_bits = 8,
-	.val_bits = 8,
-	.max_register = AUD96P22_REG_MAX,
-	.cache_type = REGCACHE_RBTREE,
-};
-
-static int aud96p22_i2c_probe(struct i2c_client *i2c,
-			      const struct i2c_device_id *id)
-{
-	struct device *dev = &i2c->dev;
-	struct aud96p22_priv *priv;
-	int ret;
-
-	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
-	if (priv == NULL)
-		return -ENOMEM;
-
-	priv->regmap = devm_regmap_init_i2c(i2c, &aud96p22_regmap);
-	if (IS_ERR(priv->regmap)) {
-		ret = PTR_ERR(priv->regmap);
-		dev_err(dev, "failed to init i2c regmap: %d\n", ret);
-		return ret;
-	}
-
-	i2c_set_clientdata(i2c, priv);
-
-	ret = devm_snd_soc_register_component(dev, &aud96p22_driver, &aud96p22_dai, 1);
-	if (ret) {
-		dev_err(dev, "failed to register component: %d\n", ret);
-		return ret;
-	}
-
-	return 0;
-}
-
-static int aud96p22_i2c_remove(struct i2c_client *i2c)
-{
-	return 0;
-}
-
-static const struct of_device_id aud96p22_dt_ids[] = {
-	{ .compatible = "zte,zx-aud96p22", },
-	{ }
-};
-MODULE_DEVICE_TABLE(of, aud96p22_dt_ids);
-
-static struct i2c_driver aud96p22_i2c_driver = {
-	.driver = {
-		.name = "zx_aud96p22",
-		.of_match_table = aud96p22_dt_ids,
-	},
-	.probe = aud96p22_i2c_probe,
-	.remove = aud96p22_i2c_remove,
-};
-module_i2c_driver(aud96p22_i2c_driver);
-
-MODULE_DESCRIPTION("ZTE ASoC AUD96P22 CODEC driver");
-MODULE_AUTHOR("Baoyou Xie <baoyou.xie@linaro.org>");
-MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index 84db0b7b9d59..d7f30036d434 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -108,6 +108,7 @@ config SND_SOC_FSL_XCVR
 config SND_SOC_FSL_AUD2HTX
 	tristate "AUDIO TO HDMI TX module support"
 	depends on ARCH_MXC || COMPILE_TEST
+	select SND_SOC_IMX_PCM_DMA if SND_IMX_SOC != n
 	help
 	  Say Y if you want to add AUDIO TO HDMI TX support for NXP.
 
diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c
index 02c81d2e34ad..c325c984d165 100644
--- a/sound/soc/fsl/fsl_asrc.c
+++ b/sound/soc/fsl/fsl_asrc.c
@@ -1083,11 +1083,6 @@ static int fsl_asrc_probe(struct platform_device *pdev)
 	}
 
 	asrc_priv->soc = of_device_get_match_data(&pdev->dev);
-	if (!asrc_priv->soc) {
-		dev_err(&pdev->dev, "failed to get soc data\n");
-		return -ENODEV;
-	}
-
 	asrc->use_edma = asrc_priv->soc->use_edma;
 	asrc->get_dma_channel = fsl_asrc_get_dma_channel;
 	asrc->request_pair = fsl_asrc_request_pair;
diff --git a/sound/soc/fsl/fsl_easrc.c b/sound/soc/fsl/fsl_easrc.c
index 60951a8aabd3..636a702f37a6 100644
--- a/sound/soc/fsl/fsl_easrc.c
+++ b/sound/soc/fsl/fsl_easrc.c
@@ -1530,7 +1530,7 @@ static int fsl_easrc_hw_free(struct snd_pcm_substream *substream,
 	return 0;
 }
 
-static struct snd_soc_dai_ops fsl_easrc_dai_ops = {
+static const struct snd_soc_dai_ops fsl_easrc_dai_ops = {
 	.startup = fsl_easrc_startup,
 	.trigger = fsl_easrc_trigger,
 	.hw_params = fsl_easrc_hw_params,
diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c
index 39637ca78cdb..08056fa0a0fa 100644
--- a/sound/soc/fsl/fsl_esai.c
+++ b/sound/soc/fsl/fsl_esai.c
@@ -23,11 +23,9 @@
 
 /**
  * struct fsl_esai_soc_data - soc specific data
- * @imx: for imx platform
  * @reset_at_xrun: flags for enable reset operaton
  */
 struct fsl_esai_soc_data {
-	bool imx;
 	bool reset_at_xrun;
 };
 
@@ -86,17 +84,14 @@ struct fsl_esai {
 };
 
 static struct fsl_esai_soc_data fsl_esai_vf610 = {
-	.imx = false,
 	.reset_at_xrun = true,
 };
 
 static struct fsl_esai_soc_data fsl_esai_imx35 = {
-	.imx = true,
 	.reset_at_xrun = true,
 };
 
 static struct fsl_esai_soc_data fsl_esai_imx6ull = {
-	.imx = true,
 	.reset_at_xrun = false,
 };
 
@@ -967,10 +962,6 @@ static int fsl_esai_probe(struct platform_device *pdev)
 	snprintf(esai_priv->name, sizeof(esai_priv->name), "%pOFn", np);
 
 	esai_priv->soc = of_device_get_match_data(&pdev->dev);
-	if (!esai_priv->soc) {
-		dev_err(&pdev->dev, "failed to get soc data\n");
-		return -ENODEV;
-	}
 
 	/* Get the addresses and IRQ */
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -1042,9 +1033,9 @@ static int fsl_esai_probe(struct platform_device *pdev)
 
 	/* Implement full symmetry for synchronous mode */
 	if (esai_priv->synchronous) {
-		fsl_esai_dai.symmetric_rates = 1;
+		fsl_esai_dai.symmetric_rate = 1;
 		fsl_esai_dai.symmetric_channels = 1;
-		fsl_esai_dai.symmetric_samplebits = 1;
+		fsl_esai_dai.symmetric_sample_bits = 1;
 	}
 
 	dev_set_drvdata(&pdev->dev, esai_priv);
diff --git a/sound/soc/fsl/fsl_micfil.c b/sound/soc/fsl/fsl_micfil.c
index efc5daf53bba..5935af2e5ff4 100644
--- a/sound/soc/fsl/fsl_micfil.c
+++ b/sound/soc/fsl/fsl_micfil.c
@@ -381,7 +381,7 @@ static int fsl_micfil_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id,
 	return ret;
 }
 
-static struct snd_soc_dai_ops fsl_micfil_dai_ops = {
+static const struct snd_soc_dai_ops fsl_micfil_dai_ops = {
 	.startup = fsl_micfil_startup,
 	.trigger = fsl_micfil_trigger,
 	.hw_params = fsl_micfil_hw_params,
@@ -637,7 +637,6 @@ static irqreturn_t micfil_err_isr(int irq, void *devid)
 static int fsl_micfil_probe(struct platform_device *pdev)
 {
 	struct device_node *np = pdev->dev.of_node;
-	const struct of_device_id *of_id;
 	struct fsl_micfil *micfil;
 	struct resource *res;
 	void __iomem *regs;
@@ -651,11 +650,7 @@ static int fsl_micfil_probe(struct platform_device *pdev)
 	micfil->pdev = pdev;
 	strncpy(micfil->name, np->name, sizeof(micfil->name) - 1);
 
-	of_id = of_match_device(fsl_micfil_dt_ids, &pdev->dev);
-	if (!of_id || !of_id->data)
-		return -EINVAL;
-
-	micfil->soc = of_id->data;
+	micfil->soc = of_device_get_match_data(&pdev->dev);
 
 	/* ipg_clk is used to control the registers
 	 * ipg_clk_app is used to operate the filter
diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c
index f3d3d20d35d7..5e65b456d3e2 100644
--- a/sound/soc/fsl/fsl_sai.c
+++ b/sound/soc/fsl/fsl_sai.c
@@ -1079,9 +1079,9 @@ static int fsl_sai_probe(struct platform_device *pdev)
 	/* Sync Tx with Rx as default by following old DT binding */
 	sai->synchronous[RX] = true;
 	sai->synchronous[TX] = false;
-	sai->cpu_dai_drv.symmetric_rates = 1;
+	sai->cpu_dai_drv.symmetric_rate = 1;
 	sai->cpu_dai_drv.symmetric_channels = 1;
-	sai->cpu_dai_drv.symmetric_samplebits = 1;
+	sai->cpu_dai_drv.symmetric_sample_bits = 1;
 
 	if (of_find_property(np, "fsl,sai-synchronous-rx", NULL) &&
 	    of_find_property(np, "fsl,sai-asynchronous", NULL)) {
@@ -1098,9 +1098,9 @@ static int fsl_sai_probe(struct platform_device *pdev)
 		/* Discard all settings for asynchronous mode */
 		sai->synchronous[RX] = false;
 		sai->synchronous[TX] = false;
-		sai->cpu_dai_drv.symmetric_rates = 0;
+		sai->cpu_dai_drv.symmetric_rate = 0;
 		sai->cpu_dai_drv.symmetric_channels = 0;
-		sai->cpu_dai_drv.symmetric_samplebits = 0;
+		sai->cpu_dai_drv.symmetric_sample_bits = 0;
 	}
 
 	if (of_find_property(np, "fsl,sai-mclk-direction-output", NULL) &&
diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c
index 5fa178f3f497..174e558224d8 100644
--- a/sound/soc/fsl/fsl_spdif.c
+++ b/sound/soc/fsl/fsl_spdif.c
@@ -1255,7 +1255,7 @@ static int fsl_spdif_probe_txclk(struct fsl_spdif_priv *spdif_priv,
 
 	for (i = 0; i < STC_TXCLK_SRC_MAX; i++) {
 		sprintf(tmp, "rxtx%d", i);
-		clk = devm_clk_get(&pdev->dev, tmp);
+		clk = devm_clk_get(dev, tmp);
 		if (IS_ERR(clk)) {
 			dev_err(dev, "no rxtx%d clock in devicetree\n", i);
 			return PTR_ERR(clk);
@@ -1277,14 +1277,14 @@ static int fsl_spdif_probe_txclk(struct fsl_spdif_priv *spdif_priv,
 			break;
 	}
 
-	dev_dbg(&pdev->dev, "use rxtx%d as tx clock source for %dHz sample rate\n",
+	dev_dbg(dev, "use rxtx%d as tx clock source for %dHz sample rate\n",
 			spdif_priv->txclk_src[index], rate[index]);
-	dev_dbg(&pdev->dev, "use txclk df %d for %dHz sample rate\n",
+	dev_dbg(dev, "use txclk df %d for %dHz sample rate\n",
 			spdif_priv->txclk_df[index], rate[index]);
 	if (clk_is_match(spdif_priv->txclk[index], spdif_priv->sysclk))
-		dev_dbg(&pdev->dev, "use sysclk df %d for %dHz sample rate\n",
+		dev_dbg(dev, "use sysclk df %d for %dHz sample rate\n",
 				spdif_priv->sysclk_df[index], rate[index]);
-	dev_dbg(&pdev->dev, "the best rate for %dHz sample rate is %dHz\n",
+	dev_dbg(dev, "the best rate for %dHz sample rate is %dHz\n",
 			rate[index], spdif_priv->txrate[index]);
 
 	return 0;
@@ -1305,10 +1305,6 @@ static int fsl_spdif_probe(struct platform_device *pdev)
 	spdif_priv->pdev = pdev;
 
 	spdif_priv->soc = of_device_get_match_data(&pdev->dev);
-	if (!spdif_priv->soc) {
-		dev_err(&pdev->dev, "failed to get soc data\n");
-		return -ENODEV;
-	}
 
 	/* Initialize this copy of the CPU DAI driver structure */
 	memcpy(&spdif_priv->cpu_dai_drv, &fsl_spdif_dai, sizeof(fsl_spdif_dai));
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 404be27c15fe..57811743c294 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -1397,18 +1397,11 @@ static int fsl_ssi_probe_from_dt(struct fsl_ssi *ssi)
 {
 	struct device *dev = ssi->dev;
 	struct device_node *np = dev->of_node;
-	const struct of_device_id *of_id;
 	const char *p, *sprop;
 	const __be32 *iprop;
 	u32 dmas[4];
 	int ret;
 
-	of_id = of_match_device(fsl_ssi_ids, dev);
-	if (!of_id || !of_id->data)
-		return -EINVAL;
-
-	ssi->soc = of_id->data;
-
 	ret = of_property_match_string(np, "clock-names", "ipg");
 	/* Get error code if not found */
 	ssi->has_ipg_clk_name = ret >= 0;
@@ -1492,6 +1485,7 @@ static int fsl_ssi_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	ssi->dev = dev;
+	ssi->soc = of_device_get_match_data(&pdev->dev);
 
 	/* Probe from DT */
 	ret = fsl_ssi_probe_from_dt(ssi);
@@ -1537,9 +1531,9 @@ static int fsl_ssi_probe(struct platform_device *pdev)
 
 	/* Set software limitations for synchronous mode except AC97 */
 	if (ssi->synchronous && !fsl_ssi_is_ac97(ssi)) {
-		ssi->cpu_dai_drv.symmetric_rates = 1;
+		ssi->cpu_dai_drv.symmetric_rate = 1;
 		ssi->cpu_dai_drv.symmetric_channels = 1;
-		ssi->cpu_dai_drv.symmetric_samplebits = 1;
+		ssi->cpu_dai_drv.symmetric_sample_bits = 1;
 	}
 
 	/*
diff --git a/sound/soc/fsl/fsl_xcvr.c b/sound/soc/fsl/fsl_xcvr.c
index 3d58c88ea603..6dd0a5fcd455 100644
--- a/sound/soc/fsl/fsl_xcvr.c
+++ b/sound/soc/fsl/fsl_xcvr.c
@@ -857,7 +857,7 @@ static struct snd_kcontrol_new fsl_xcvr_tx_ctls[] = {
 	},
 };
 
-static struct snd_soc_dai_ops fsl_xcvr_dai_ops = {
+static const struct snd_soc_dai_ops fsl_xcvr_dai_ops = {
 	.prepare = fsl_xcvr_prepare,
 	.startup = fsl_xcvr_startup,
 	.shutdown = fsl_xcvr_shutdown,
@@ -1130,16 +1130,11 @@ MODULE_DEVICE_TABLE(of, fsl_xcvr_dt_ids);
 static int fsl_xcvr_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
-	const struct of_device_id *of_id;
 	struct fsl_xcvr *xcvr;
 	struct resource *ram_res, *regs_res, *rx_res, *tx_res;
 	void __iomem *regs;
 	int ret, irq;
 
-	of_id = of_match_device(fsl_xcvr_dt_ids, dev);
-	if (!of_id)
-		return -EINVAL;
-
 	xcvr = devm_kzalloc(dev, sizeof(*xcvr), GFP_KERNEL);
 	if (!xcvr)
 		return -ENOMEM;
diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c
index 16a04a678828..8c5cdcdc8713 100644
--- a/sound/soc/generic/audio-graph-card.c
+++ b/sound/soc/generic/audio-graph-card.c
@@ -532,7 +532,7 @@ static int graph_for_each_link(struct asoc_simple_priv *priv,
 static void graph_get_dais_count(struct asoc_simple_priv *priv,
 				 struct link_info *li);
 
-int graph_parse_of(struct asoc_simple_priv *priv, struct device *dev)
+int audio_graph_parse_of(struct asoc_simple_priv *priv, struct device *dev)
 {
 	struct snd_soc_card *card = simple_priv_to_card(priv);
 	struct link_info li;
@@ -608,7 +608,7 @@ err:
 
 	return ret;
 }
-EXPORT_SYMBOL_GPL(graph_parse_of);
+EXPORT_SYMBOL_GPL(audio_graph_parse_of);
 
 static int graph_count_noml(struct asoc_simple_priv *priv,
 			    struct device_node *cpu_ep,
@@ -705,7 +705,7 @@ static void graph_get_dais_count(struct asoc_simple_priv *priv,
 		li->link, li->dais, li->conf);
 }
 
-int graph_card_probe(struct snd_soc_card *card)
+int audio_graph_card_probe(struct snd_soc_card *card)
 {
 	struct asoc_simple_priv *priv = snd_soc_card_get_drvdata(card);
 	int ret;
@@ -720,7 +720,7 @@ int graph_card_probe(struct snd_soc_card *card)
 
 	return 0;
 }
-EXPORT_SYMBOL_GPL(graph_card_probe);
+EXPORT_SYMBOL_GPL(audio_graph_card_probe);
 
 static int graph_probe(struct platform_device *pdev)
 {
@@ -736,20 +736,21 @@ static int graph_probe(struct platform_device *pdev)
 	card = simple_priv_to_card(priv);
 	card->dapm_widgets	= graph_dapm_widgets;
 	card->num_dapm_widgets	= ARRAY_SIZE(graph_dapm_widgets);
-	card->probe		= graph_card_probe;
+	card->probe		= audio_graph_card_probe;
 
 	if (of_device_get_match_data(dev))
 		priv->dpcm_selectable = 1;
 
-	return graph_parse_of(priv, dev);
+	return audio_graph_parse_of(priv, dev);
 }
 
-static int graph_remove(struct platform_device *pdev)
+int audio_graph_remove(struct platform_device *pdev)
 {
 	struct snd_soc_card *card = platform_get_drvdata(pdev);
 
 	return asoc_simple_clean_reference(card);
 }
+EXPORT_SYMBOL_GPL(audio_graph_remove);
 
 static const struct of_device_id graph_of_match[] = {
 	{ .compatible = "audio-graph-card", },
@@ -766,7 +767,7 @@ static struct platform_driver graph_card = {
 		.of_match_table = graph_of_match,
 	},
 	.probe = graph_probe,
-	.remove = graph_remove,
+	.remove = audio_graph_remove,
 };
 module_platform_driver(graph_card);
 
diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c
index 6cada4c1e283..ab31045cfc95 100644
--- a/sound/soc/generic/simple-card-utils.c
+++ b/sound/soc/generic/simple-card-utils.c
@@ -172,16 +172,15 @@ int asoc_simple_parse_clk(struct device *dev,
 	 *  or device's module clock.
 	 */
 	clk = devm_get_clk_from_child(dev, node, NULL);
-	if (!IS_ERR(clk)) {
-		simple_dai->sysclk = clk_get_rate(clk);
+	if (IS_ERR(clk))
+		clk = devm_get_clk_from_child(dev, dlc->of_node, NULL);
 
+	if (!IS_ERR(clk)) {
 		simple_dai->clk = clk;
-	} else if (!of_property_read_u32(node, "system-clock-frequency", &val)) {
+		simple_dai->sysclk = clk_get_rate(clk);
+	} else if (!of_property_read_u32(node, "system-clock-frequency",
+					 &val)) {
 		simple_dai->sysclk = val;
-	} else {
-		clk = devm_get_clk_from_child(dev, dlc->of_node, NULL);
-		if (!IS_ERR(clk))
-			simple_dai->sysclk = clk_get_rate(clk);
 	}
 
 	if (of_property_read_bool(node, "system-clock-direction-out"))
diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig
index 0c6404fc12b3..f3a4a907b29d 100644
--- a/sound/soc/intel/Kconfig
+++ b/sound/soc/intel/Kconfig
@@ -203,6 +203,8 @@ config SND_SOC_INTEL_KEEMBAY
 	tristate "Keembay Platforms"
 	depends on ARCH_KEEMBAY || COMPILE_TEST
 	depends on COMMON_CLK
+	select SND_DMAENGINE_PCM
+	select SND_SOC_GENERIC_DMAENGINE_PCM
 	help
 	  If you have a Intel Keembay platform then enable this option
 	  by saying Y or m.
diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig
index b58b9b60d37e..d1d28129a32b 100644
--- a/sound/soc/intel/boards/Kconfig
+++ b/sound/soc/intel/boards/Kconfig
@@ -111,6 +111,18 @@ config SND_SOC_INTEL_BYTCR_RT5651_MACH
 	  Say Y or m if you have such a device. This is a recommended option.
 	  If unsure select "N".
 
+config SND_SOC_INTEL_BYTCR_WM5102_MACH
+	tristate "Baytrail and Baytrail-CR with WM5102 codec"
+	depends on MFD_ARIZONA && MFD_WM5102 && SPI_MASTER && ACPI
+	depends on X86_INTEL_LPSS || COMPILE_TEST
+	select SND_SOC_ACPI
+	select SND_SOC_WM5102
+	help
+	  This adds support for ASoC machine driver for Intel(R) Baytrail and Baytrail-CR
+	  platforms with WM5102 audio codec.
+	  Say Y if you have such a device.
+	  If unsure select "N".
+
 config SND_SOC_INTEL_CHT_BSW_RT5672_MACH
 	tristate "Cherrytrail & Braswell with RT5672 codec"
 	depends on I2C && ACPI
diff --git a/sound/soc/intel/boards/Makefile b/sound/soc/intel/boards/Makefile
index 5f03e484b215..616c5fbab7d5 100644
--- a/sound/soc/intel/boards/Makefile
+++ b/sound/soc/intel/boards/Makefile
@@ -10,6 +10,7 @@ snd-soc-sst-sof-wm8804-objs := sof_wm8804.o
 snd-soc-sst-glk-rt5682_max98357a-objs := glk_rt5682_max98357a.o hda_dsp_common.o
 snd-soc-sst-bytcr-rt5640-objs := bytcr_rt5640.o
 snd-soc-sst-bytcr-rt5651-objs := bytcr_rt5651.o
+snd-soc-sst-bytcr-wm5102-objs := bytcr_wm5102.o
 snd-soc-sst-cht-bsw-rt5672-objs := cht_bsw_rt5672.o
 snd-soc-sst-cht-bsw-rt5645-objs := cht_bsw_rt5645.o
 snd-soc-sst-cht-bsw-max98090_ti-objs := cht_bsw_max98090_ti.o
@@ -51,6 +52,7 @@ obj-$(CONFIG_SND_SOC_INTEL_BDW_RT5650_MACH) += snd-soc-sst-bdw-rt5650-mach.o
 obj-$(CONFIG_SND_SOC_INTEL_BDW_RT5677_MACH) += snd-soc-sst-bdw-rt5677-mach.o
 obj-$(CONFIG_SND_SOC_INTEL_BYTCR_RT5640_MACH) += snd-soc-sst-bytcr-rt5640.o
 obj-$(CONFIG_SND_SOC_INTEL_BYTCR_RT5651_MACH) += snd-soc-sst-bytcr-rt5651.o
+obj-$(CONFIG_SND_SOC_INTEL_BYTCR_WM5102_MACH) += snd-soc-sst-bytcr-wm5102.o
 obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_RT5672_MACH) += snd-soc-sst-cht-bsw-rt5672.o
 obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_RT5645_MACH) += snd-soc-sst-cht-bsw-rt5645.o
 obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_MAX98090_TI_MACH) += snd-soc-sst-cht-bsw-max98090_ti.o
diff --git a/sound/soc/intel/boards/bytcht_es8316.c b/sound/soc/intel/boards/bytcht_es8316.c
index 892cf684216e..06df2d46d910 100644
--- a/sound/soc/intel/boards/bytcht_es8316.c
+++ b/sound/soc/intel/boards/bytcht_es8316.c
@@ -331,9 +331,6 @@ static struct snd_soc_dai_link byt_cht_es8316_dais[] = {
 
 		/* back ends */
 	{
-		/* Only SSP2 has been tested here, so BYT-CR platforms that
-		 * require SSP0 will not work.
-		 */
 		.name = "SSP2-Codec",
 		.id = 0,
 		.no_pcm = 1,
diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c
index 5520d7c80019..782f2b4d72ad 100644
--- a/sound/soc/intel/boards/bytcr_rt5640.c
+++ b/sound/soc/intel/boards/bytcr_rt5640.c
@@ -35,6 +35,7 @@ enum {
 	BYT_RT5640_DMIC2_MAP,
 	BYT_RT5640_IN1_MAP,
 	BYT_RT5640_IN3_MAP,
+	BYT_RT5640_NO_INTERNAL_MIC_MAP,
 };
 
 enum {
@@ -71,6 +72,7 @@ enum {
 #define BYT_RT5640_SSP0_AIF2		BIT(21)
 #define BYT_RT5640_MCLK_EN		BIT(22)
 #define BYT_RT5640_MCLK_25MHZ		BIT(23)
+#define BYT_RT5640_NO_SPEAKERS		BIT(24)
 
 #define BYTCR_INPUT_DEFAULTS				\
 	(BYT_RT5640_IN3_MAP |				\
@@ -116,6 +118,9 @@ static void log_quirks(struct device *dev)
 	case BYT_RT5640_IN3_MAP:
 		dev_info(dev, "quirk IN3_MAP enabled\n");
 		break;
+	case BYT_RT5640_NO_INTERNAL_MIC_MAP:
+		dev_info(dev, "quirk NO_INTERNAL_MIC_MAP enabled\n");
+		break;
 	default:
 		dev_err(dev, "quirk map 0x%x is not supported, microphone input will not work\n", map);
 		break;
@@ -132,6 +137,8 @@ static void log_quirks(struct device *dev)
 		dev_info(dev, "quirk JD_NOT_INV enabled\n");
 	if (byt_rt5640_quirk & BYT_RT5640_MONO_SPEAKER)
 		dev_info(dev, "quirk MONO_SPEAKER enabled\n");
+	if (byt_rt5640_quirk & BYT_RT5640_NO_SPEAKERS)
+		dev_info(dev, "quirk NO_SPEAKERS enabled\n");
 	if (byt_rt5640_quirk & BYT_RT5640_DIFF_MIC)
 		dev_info(dev, "quirk DIFF_MIC enabled\n");
 	if (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) {
@@ -399,6 +406,19 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = {
 					BYT_RT5640_SSP0_AIF1 |
 					BYT_RT5640_MCLK_EN),
 	},
+	{	/* Acer One 10 S1002 */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "One S1002"),
+		},
+		.driver_data = (void *)(BYT_RT5640_IN1_MAP |
+					BYT_RT5640_JD_SRC_JD2_IN4N |
+					BYT_RT5640_OVCD_TH_2000UA |
+					BYT_RT5640_OVCD_SF_0P75 |
+					BYT_RT5640_DIFF_MIC |
+					BYT_RT5640_SSP0_AIF2 |
+					BYT_RT5640_MCLK_EN),
+	},
 	{
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
@@ -524,6 +544,16 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = {
 					BYT_RT5640_MONO_SPEAKER |
 					BYT_RT5640_MCLK_EN),
 	},
+	{	/* Estar Beauty HD MID 7316R */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Estar"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "eSTAR BEAUTY HD Intel Quad core"),
+		},
+		.driver_data = (void *)(BYTCR_INPUT_DEFAULTS |
+					BYT_RT5640_MONO_SPEAKER |
+					BYT_RT5640_SSP0_AIF1 |
+					BYT_RT5640_MCLK_EN),
+	},
 	{
 		.matches = {
 			DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
@@ -613,6 +643,15 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = {
 					BYT_RT5640_SSP0_AIF1 |
 					BYT_RT5640_MCLK_EN),
 	},
+	{	/* Mele PCG03 Mini PC */
+		.matches = {
+			DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Mini PC"),
+			DMI_EXACT_MATCH(DMI_BOARD_NAME, "Mini PC"),
+		},
+		.driver_data = (void *)(BYT_RT5640_NO_INTERNAL_MIC_MAP |
+					BYT_RT5640_NO_SPEAKERS |
+					BYT_RT5640_SSP0_AIF1),
+	},
 	{	/* MPMAN Converter 9, similar hw as the I.T.Works TW891 2-in-1 */
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "MPMAN"),
@@ -798,6 +837,20 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = {
 					BYT_RT5640_SSP0_AIF2 |
 					BYT_RT5640_MCLK_EN),
 	},
+	{	/* Voyo Winpad A15 */
+		.matches = {
+			DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
+			DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
+			/* Above strings are too generic, also match on BIOS date */
+			DMI_MATCH(DMI_BIOS_DATE, "11/20/2014"),
+		},
+		.driver_data = (void *)(BYT_RT5640_IN1_MAP |
+					BYT_RT5640_JD_SRC_JD2_IN4N |
+					BYT_RT5640_OVCD_TH_2000UA |
+					BYT_RT5640_OVCD_SF_0P75 |
+					BYT_RT5640_DIFF_MIC |
+					BYT_RT5640_MCLK_EN),
+	},
 	{	/* Catch-all for generic Insyde tablets, must be last */
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
@@ -873,8 +926,8 @@ static int byt_rt5640_init(struct snd_soc_pcm_runtime *runtime)
 	struct snd_soc_card *card = runtime->card;
 	struct byt_rt5640_private *priv = snd_soc_card_get_drvdata(card);
 	struct snd_soc_component *component = asoc_rtd_to_codec(runtime, 0)->component;
-	const struct snd_soc_dapm_route *custom_map;
-	int num_routes;
+	const struct snd_soc_dapm_route *custom_map = NULL;
+	int num_routes = 0;
 	int ret;
 
 	card->dapm.idle_bias_off = true;
@@ -909,13 +962,14 @@ static int byt_rt5640_init(struct snd_soc_pcm_runtime *runtime)
 		custom_map = byt_rt5640_intmic_in3_map;
 		num_routes = ARRAY_SIZE(byt_rt5640_intmic_in3_map);
 		break;
+	case BYT_RT5640_DMIC1_MAP:
+		custom_map = byt_rt5640_intmic_dmic1_map;
+		num_routes = ARRAY_SIZE(byt_rt5640_intmic_dmic1_map);
+		break;
 	case BYT_RT5640_DMIC2_MAP:
 		custom_map = byt_rt5640_intmic_dmic2_map;
 		num_routes = ARRAY_SIZE(byt_rt5640_intmic_dmic2_map);
 		break;
-	default:
-		custom_map = byt_rt5640_intmic_dmic1_map;
-		num_routes = ARRAY_SIZE(byt_rt5640_intmic_dmic1_map);
 	}
 
 	ret = snd_soc_dapm_add_routes(&card->dapm, custom_map, num_routes);
@@ -946,7 +1000,7 @@ static int byt_rt5640_init(struct snd_soc_pcm_runtime *runtime)
 		ret = snd_soc_dapm_add_routes(&card->dapm,
 					byt_rt5640_mono_spk_map,
 					ARRAY_SIZE(byt_rt5640_mono_spk_map));
-	} else {
+	} else if (!(byt_rt5640_quirk & BYT_RT5640_NO_SPEAKERS)) {
 		ret = snd_soc_dapm_add_routes(&card->dapm,
 					byt_rt5640_stereo_spk_map,
 					ARRAY_SIZE(byt_rt5640_stereo_spk_map));
@@ -1187,7 +1241,8 @@ struct acpi_chan_package {   /* ACPICA seems to require 64 bit integers */
 static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
-	static const char * const map_name[] = { "dmic1", "dmic2", "in1", "in3" };
+	static const char * const map_name[] = { "dmic1", "dmic2", "in1", "in3", "none" };
+	__maybe_unused const char *spk_type;
 	const struct dmi_system_id *dmi_id;
 	struct byt_rt5640_private *priv;
 	struct snd_soc_acpi_mach *mach;
@@ -1196,7 +1251,7 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
 	bool sof_parent;
 	int ret_val = 0;
 	int dai_index = 0;
-	int i;
+	int i, cfg_spk;
 
 	is_bytcr = false;
 	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
@@ -1335,16 +1390,24 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
 		}
 	}
 
+	if (byt_rt5640_quirk & BYT_RT5640_NO_SPEAKERS) {
+		cfg_spk = 0;
+		spk_type = "none";
+	} else if (byt_rt5640_quirk & BYT_RT5640_MONO_SPEAKER) {
+		cfg_spk = 1;
+		spk_type = "mono";
+	} else {
+		cfg_spk = 2;
+		spk_type = "stereo";
+	}
+
 	snprintf(byt_rt5640_components, sizeof(byt_rt5640_components),
-		 "cfg-spk:%s cfg-mic:%s",
-		 (byt_rt5640_quirk & BYT_RT5640_MONO_SPEAKER) ? "1" : "2",
+		 "cfg-spk:%d cfg-mic:%s", cfg_spk,
 		 map_name[BYT_RT5640_MAP(byt_rt5640_quirk)]);
 	byt_rt5640_card.components = byt_rt5640_components;
 #if !IS_ENABLED(CONFIG_SND_SOC_INTEL_USER_FRIENDLY_LONG_NAMES)
 	snprintf(byt_rt5640_long_name, sizeof(byt_rt5640_long_name),
-		 "bytcr-rt5640-%s-spk-%s-mic",
-		 (byt_rt5640_quirk & BYT_RT5640_MONO_SPEAKER) ?
-			"mono" : "stereo",
+		 "bytcr-rt5640-%s-spk-%s-mic", spk_type,
 		 map_name[BYT_RT5640_MAP(byt_rt5640_quirk)]);
 	byt_rt5640_card.long_name = byt_rt5640_long_name;
 #endif
diff --git a/sound/soc/intel/boards/bytcr_rt5651.c b/sound/soc/intel/boards/bytcr_rt5651.c
index f289ec8563a1..148b7b1bd3e8 100644
--- a/sound/soc/intel/boards/bytcr_rt5651.c
+++ b/sound/soc/intel/boards/bytcr_rt5651.c
@@ -436,6 +436,19 @@ static const struct dmi_system_id byt_rt5651_quirk_table[] = {
 					BYT_RT5651_MONO_SPEAKER),
 	},
 	{
+		/* Jumper EZpad 7 */
+		.callback = byt_rt5651_quirk_cb,
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Jumper"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "EZpad"),
+			/* Jumper12x.WJ2012.bsBKRCP05 with the version dropped */
+			DMI_MATCH(DMI_BIOS_VERSION, "Jumper12x.WJ2012.bsBKRCP"),
+		},
+		.driver_data = (void *)(BYT_RT5651_DEFAULT_QUIRKS |
+					BYT_RT5651_IN2_MAP |
+					BYT_RT5651_JD_NOT_INV),
+	},
+	{
 		/* KIANO SlimNote 14.2 */
 		.callback = byt_rt5651_quirk_cb,
 		.matches = {
diff --git a/sound/soc/intel/boards/bytcr_wm5102.c b/sound/soc/intel/boards/bytcr_wm5102.c
new file mode 100644
index 000000000000..f38850eb2eaf
--- /dev/null
+++ b/sound/soc/intel/boards/bytcr_wm5102.c
@@ -0,0 +1,465 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ *  bytcr_wm5102.c - ASoc Machine driver for Intel Baytrail platforms with a
+ *                   Wolfson Microelectronics WM5102 codec
+ *
+ *  Copyright (C) 2020 Hans de Goede <hdegoede@redhat.com>
+ *  Loosely based on bytcr_rt5640.c which is:
+ *  Copyright (C) 2014-2020 Intel Corp
+ *  Author: Subhransu S. Prusty <subhransu.s.prusty@intel.com>
+ */
+
+#include <linux/acpi.h>
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/spi/spi.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-acpi.h>
+#include "../../codecs/wm5102.h"
+#include "../atom/sst-atom-controls.h"
+
+#define MCLK_FREQ		25000000
+
+#define WM5102_MAX_SYSCLK_4K	49152000 /* max sysclk for 4K family */
+#define WM5102_MAX_SYSCLK_11025	45158400 /* max sysclk for 11.025K family */
+
+struct byt_wm5102_private {
+	struct clk *mclk;
+	struct gpio_desc *spkvdd_en_gpio;
+};
+
+static int byt_wm5102_spkvdd_power_event(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_card *card = w->dapm->card;
+	struct byt_wm5102_private *priv = snd_soc_card_get_drvdata(card);
+
+	gpiod_set_value_cansleep(priv->spkvdd_en_gpio,
+				 !!SND_SOC_DAPM_EVENT_ON(event));
+
+	return 0;
+}
+
+static int byt_wm5102_prepare_and_enable_pll1(struct snd_soc_dai *codec_dai, int rate)
+{
+	struct snd_soc_component *codec_component = codec_dai->component;
+	int sr_mult = ((rate % 4000) == 0) ?
+		(WM5102_MAX_SYSCLK_4K / rate) :
+		(WM5102_MAX_SYSCLK_11025 / rate);
+	int ret;
+
+	/* Reset FLL1 */
+	snd_soc_dai_set_pll(codec_dai, WM5102_FLL1_REFCLK, ARIZONA_FLL_SRC_NONE, 0, 0);
+	snd_soc_dai_set_pll(codec_dai, WM5102_FLL1, ARIZONA_FLL_SRC_NONE, 0, 0);
+
+	/* Configure the FLL1 PLL before selecting it */
+	ret = snd_soc_dai_set_pll(codec_dai, WM5102_FLL1, ARIZONA_CLK_SRC_MCLK1,
+				  MCLK_FREQ, rate * sr_mult);
+	if (ret) {
+		dev_err(codec_component->dev, "Error setting PLL: %d\n", ret);
+		return ret;
+	}
+
+	ret = snd_soc_component_set_sysclk(codec_component, ARIZONA_CLK_SYSCLK,
+					   ARIZONA_CLK_SRC_FLL1, rate * sr_mult,
+					   SND_SOC_CLOCK_IN);
+	if (ret) {
+		dev_err(codec_component->dev, "Error setting SYSCLK: %d\n", ret);
+		return ret;
+	}
+
+	ret = snd_soc_dai_set_sysclk(codec_dai, ARIZONA_CLK_SYSCLK,
+				     rate * 512, SND_SOC_CLOCK_IN);
+	if (ret) {
+		dev_err(codec_component->dev, "Error setting clock: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int platform_clock_control(struct snd_soc_dapm_widget *w,
+				  struct snd_kcontrol *k, int event)
+{
+	struct snd_soc_dapm_context *dapm = w->dapm;
+	struct snd_soc_card *card = dapm->card;
+	struct snd_soc_dai *codec_dai;
+	struct byt_wm5102_private *priv = snd_soc_card_get_drvdata(card);
+	int ret;
+
+	codec_dai = snd_soc_card_get_codec_dai(card, "wm5102-aif1");
+	if (!codec_dai) {
+		dev_err(card->dev, "Error codec DAI not found\n");
+		return -EIO;
+	}
+
+	if (SND_SOC_DAPM_EVENT_ON(event)) {
+		ret = clk_prepare_enable(priv->mclk);
+		if (ret) {
+			dev_err(card->dev, "Error enabling MCLK: %d\n", ret);
+			return ret;
+		}
+		ret = byt_wm5102_prepare_and_enable_pll1(codec_dai, 48000);
+		if (ret) {
+			dev_err(card->dev, "Error setting codec sysclk: %d\n", ret);
+			return ret;
+		}
+	} else {
+		/*
+		 * The WM5102 has a separate 32KHz clock for jack-detect
+		 * so we can disable the PLL, followed by disabling the
+		 * platform clock which is the source-clock for the PLL.
+		 */
+		snd_soc_dai_set_pll(codec_dai, WM5102_FLL1, ARIZONA_FLL_SRC_NONE, 0, 0);
+		clk_disable_unprepare(priv->mclk);
+	}
+
+	return 0;
+}
+
+static const struct snd_soc_dapm_widget byt_wm5102_widgets[] = {
+	SND_SOC_DAPM_HP("Headphone", NULL),
+	SND_SOC_DAPM_MIC("Headset Mic", NULL),
+	SND_SOC_DAPM_MIC("Internal Mic", NULL),
+	SND_SOC_DAPM_SPK("Speaker", NULL),
+	SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0,
+			    platform_clock_control, SND_SOC_DAPM_PRE_PMU |
+			    SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_SUPPLY("Speaker VDD", SND_SOC_NOPM, 0, 0,
+			    byt_wm5102_spkvdd_power_event,
+			    SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+};
+
+static const struct snd_soc_dapm_route byt_wm5102_audio_map[] = {
+	{"Headphone", NULL, "Platform Clock"},
+	{"Headset Mic", NULL, "Platform Clock"},
+	{"Internal Mic", NULL, "Platform Clock"},
+	{"Speaker", NULL, "Platform Clock"},
+
+	{"Speaker", NULL, "SPKOUTLP"},
+	{"Speaker", NULL, "SPKOUTLN"},
+	{"Speaker", NULL, "SPKOUTRP"},
+	{"Speaker", NULL, "SPKOUTRN"},
+	{"Speaker", NULL, "Speaker VDD"},
+
+	{"Headphone", NULL, "HPOUT1L"},
+	{"Headphone", NULL, "HPOUT1R"},
+
+	{"Internal Mic", NULL, "MICBIAS3"},
+	{"IN3L", NULL, "Internal Mic"},
+
+	/*
+	 * The Headset Mix uses MICBIAS1 or 2 depending on if a CTIA/OMTP Headset
+	 * is connected, as the MICBIAS is applied after the CTIA/OMTP cross-switch.
+	 */
+	{"Headset Mic", NULL, "MICBIAS1"},
+	{"Headset Mic", NULL, "MICBIAS2"},
+	{"IN1L", NULL, "Headset Mic"},
+
+	{"AIF1 Playback", NULL, "ssp0 Tx"},
+	{"ssp0 Tx", NULL, "modem_out"},
+
+	{"modem_in", NULL, "ssp0 Rx"},
+	{"ssp0 Rx", NULL, "AIF1 Capture"},
+};
+
+static const struct snd_kcontrol_new byt_wm5102_controls[] = {
+	SOC_DAPM_PIN_SWITCH("Headphone"),
+	SOC_DAPM_PIN_SWITCH("Headset Mic"),
+	SOC_DAPM_PIN_SWITCH("Internal Mic"),
+	SOC_DAPM_PIN_SWITCH("Speaker"),
+};
+
+static int byt_wm5102_init(struct snd_soc_pcm_runtime *runtime)
+{
+	struct snd_soc_card *card = runtime->card;
+	struct byt_wm5102_private *priv = snd_soc_card_get_drvdata(card);
+	int ret;
+
+	card->dapm.idle_bias_off = true;
+
+	ret = snd_soc_add_card_controls(card, byt_wm5102_controls,
+					ARRAY_SIZE(byt_wm5102_controls));
+	if (ret) {
+		dev_err(card->dev, "Error adding card controls: %d\n", ret);
+		return ret;
+	}
+
+	/*
+	 * The firmware might enable the clock at boot (this information
+	 * may or may not be reflected in the enable clock register).
+	 * To change the rate we must disable the clock first to cover these
+	 * cases. Due to common clock framework restrictions that do not allow
+	 * to disable a clock that has not been enabled, we need to enable
+	 * the clock first.
+	 */
+	ret = clk_prepare_enable(priv->mclk);
+	if (!ret)
+		clk_disable_unprepare(priv->mclk);
+
+	ret = clk_set_rate(priv->mclk, MCLK_FREQ);
+	if (ret) {
+		dev_err(card->dev, "Error setting MCLK rate: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static const struct snd_soc_pcm_stream byt_wm5102_dai_params = {
+	.formats = SNDRV_PCM_FMTBIT_S16_LE,
+	.rate_min = 48000,
+	.rate_max = 48000,
+	.channels_min = 2,
+	.channels_max = 2,
+};
+
+static int byt_wm5102_codec_fixup(struct snd_soc_pcm_runtime *rtd,
+				  struct snd_pcm_hw_params *params)
+{
+	struct snd_interval *rate = hw_param_interval(params,
+						      SNDRV_PCM_HW_PARAM_RATE);
+	struct snd_interval *channels = hw_param_interval(params,
+							  SNDRV_PCM_HW_PARAM_CHANNELS);
+	int ret;
+
+	/* The DSP will covert the FE rate to 48k, stereo */
+	rate->min = 48000;
+	rate->max = 48000;
+	channels->min = 2;
+	channels->max = 2;
+
+	/* set SSP0 to 16-bit */
+	params_set_format(params, SNDRV_PCM_FORMAT_S16_LE);
+
+	/*
+	 * Default mode for SSP configuration is TDM 4 slot, override config
+	 * with explicit setting to I2S 2ch 16-bit. The word length is set with
+	 * dai_set_tdm_slot() since there is no other API exposed
+	 */
+	ret = snd_soc_dai_set_fmt(asoc_rtd_to_cpu(rtd, 0),
+				  SND_SOC_DAIFMT_I2S     |
+				  SND_SOC_DAIFMT_NB_NF   |
+				  SND_SOC_DAIFMT_CBS_CFS);
+	if (ret) {
+		dev_err(rtd->dev, "Error setting format to I2S: %d\n", ret);
+		return ret;
+	}
+
+	ret = snd_soc_dai_set_tdm_slot(asoc_rtd_to_cpu(rtd, 0), 0x3, 0x3, 2, 16);
+	if (ret) {
+		dev_err(rtd->dev, "Error setting I2S config: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int byt_wm5102_aif1_startup(struct snd_pcm_substream *substream)
+{
+	return snd_pcm_hw_constraint_single(substream->runtime,
+					    SNDRV_PCM_HW_PARAM_RATE, 48000);
+}
+
+static const struct snd_soc_ops byt_wm5102_aif1_ops = {
+	.startup = byt_wm5102_aif1_startup,
+};
+
+SND_SOC_DAILINK_DEF(dummy,
+	DAILINK_COMP_ARRAY(COMP_DUMMY()));
+
+SND_SOC_DAILINK_DEF(media,
+	DAILINK_COMP_ARRAY(COMP_CPU("media-cpu-dai")));
+
+SND_SOC_DAILINK_DEF(deepbuffer,
+	DAILINK_COMP_ARRAY(COMP_CPU("deepbuffer-cpu-dai")));
+
+SND_SOC_DAILINK_DEF(ssp0_port,
+	DAILINK_COMP_ARRAY(COMP_CPU("ssp0-port")));
+
+SND_SOC_DAILINK_DEF(ssp0_codec,
+	DAILINK_COMP_ARRAY(COMP_CODEC(
+	/*
+	 * Note there is no need to overwrite the codec-name as is done in
+	 * other bytcr machine drivers, because the codec is a MFD child-dev.
+	 */
+	"wm5102-codec",
+	"wm5102-aif1")));
+
+SND_SOC_DAILINK_DEF(platform,
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("sst-mfld-platform")));
+
+static struct snd_soc_dai_link byt_wm5102_dais[] = {
+	[MERR_DPCM_AUDIO] = {
+		.name = "Baytrail Audio Port",
+		.stream_name = "Baytrail Audio",
+		.nonatomic = true,
+		.dynamic = 1,
+		.dpcm_playback = 1,
+		.dpcm_capture = 1,
+		.ops = &byt_wm5102_aif1_ops,
+		SND_SOC_DAILINK_REG(media, dummy, platform),
+
+	},
+	[MERR_DPCM_DEEP_BUFFER] = {
+		.name = "Deep-Buffer Audio Port",
+		.stream_name = "Deep-Buffer Audio",
+		.nonatomic = true,
+		.dynamic = 1,
+		.dpcm_playback = 1,
+		.ops = &byt_wm5102_aif1_ops,
+		SND_SOC_DAILINK_REG(deepbuffer, dummy, platform),
+	},
+		/* back ends */
+	{
+		/*
+		 * This must be named SSP2-Codec even though this machine driver
+		 * always uses SSP0. Most machine drivers support both and dynamically
+		 * update the dailink to point to SSP0 or SSP2, while keeping the name
+		 * as "SSP2-Codec". The SOF tplg files hardcode the "SSP2-Codec" even
+		 * in the byt-foo-ssp0.tplg versions because the other machine-drivers
+		 * use "SSP2-Codec" even when SSP0 is used.
+		 */
+		.name = "SSP2-Codec",
+		.id = 0,
+		.no_pcm = 1,
+		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
+						| SND_SOC_DAIFMT_CBS_CFS,
+		.be_hw_params_fixup = byt_wm5102_codec_fixup,
+		.nonatomic = true,
+		.dpcm_playback = 1,
+		.dpcm_capture = 1,
+		.init = byt_wm5102_init,
+		SND_SOC_DAILINK_REG(ssp0_port, ssp0_codec, platform),
+	},
+};
+
+/* use space before codec name to simplify card ID, and simplify driver name */
+#define SOF_CARD_NAME "bytcht wm5102" /* card name will be 'sof-bytcht wm5102' */
+#define SOF_DRIVER_NAME "SOF"
+
+#define CARD_NAME "bytcr-wm5102"
+#define DRIVER_NAME NULL /* card name will be used for driver name */
+
+/* SoC card */
+static struct snd_soc_card byt_wm5102_card = {
+	.owner = THIS_MODULE,
+	.dai_link = byt_wm5102_dais,
+	.num_links = ARRAY_SIZE(byt_wm5102_dais),
+	.dapm_widgets = byt_wm5102_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(byt_wm5102_widgets),
+	.dapm_routes = byt_wm5102_audio_map,
+	.num_dapm_routes = ARRAY_SIZE(byt_wm5102_audio_map),
+	.fully_routed = true,
+};
+
+static int snd_byt_wm5102_mc_probe(struct platform_device *pdev)
+{
+	char codec_name[SND_ACPI_I2C_ID_LEN];
+	struct device *dev = &pdev->dev;
+	struct byt_wm5102_private *priv;
+	struct snd_soc_acpi_mach *mach;
+	const char *platform_name;
+	struct acpi_device *adev;
+	struct device *codec_dev;
+	bool sof_parent;
+	int ret;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_ATOMIC);
+	if (!priv)
+		return -ENOMEM;
+
+	/* Get MCLK */
+	priv->mclk = devm_clk_get(dev, "pmc_plt_clk_3");
+	if (IS_ERR(priv->mclk))
+		return dev_err_probe(dev, PTR_ERR(priv->mclk), "getting pmc_plt_clk_3\n");
+
+	/*
+	 * Get speaker VDD enable GPIO:
+	 * 1. Get codec-device-name
+	 * 2. Get codec-device
+	 * 3. Get GPIO from codec-device
+	 */
+	mach = dev->platform_data;
+	adev = acpi_dev_get_first_match_dev(mach->id, NULL, -1);
+	if (!adev) {
+		dev_err(dev, "Error cannot find acpi-dev for codec\n");
+		return -ENOENT;
+	}
+	snprintf(codec_name, sizeof(codec_name), "spi-%s", acpi_dev_name(adev));
+	put_device(&adev->dev);
+
+	codec_dev = bus_find_device_by_name(&spi_bus_type, NULL, codec_name);
+	if (!codec_dev)
+		return -EPROBE_DEFER;
+
+	/* Note no devm_ here since we call gpiod_get on codec_dev rather then dev */
+	priv->spkvdd_en_gpio = gpiod_get(codec_dev, "wlf,spkvdd-ena", GPIOD_OUT_LOW);
+	put_device(codec_dev);
+
+	if (IS_ERR(priv->spkvdd_en_gpio))
+		return dev_err_probe(dev, PTR_ERR(priv->spkvdd_en_gpio), "getting spkvdd-GPIO\n");
+
+	/* override platform name, if required */
+	byt_wm5102_card.dev = dev;
+	platform_name = mach->mach_params.platform;
+	ret = snd_soc_fixup_dai_links_platform_name(&byt_wm5102_card, platform_name);
+	if (ret)
+		goto out_put_gpio;
+
+	/* set card and driver name and pm-ops */
+	sof_parent = snd_soc_acpi_sof_parent(dev);
+	if (sof_parent) {
+		byt_wm5102_card.name = SOF_CARD_NAME;
+		byt_wm5102_card.driver_name = SOF_DRIVER_NAME;
+		dev->driver->pm = &snd_soc_pm_ops;
+	} else {
+		byt_wm5102_card.name = CARD_NAME;
+		byt_wm5102_card.driver_name = DRIVER_NAME;
+	}
+
+	snd_soc_card_set_drvdata(&byt_wm5102_card, priv);
+	ret = devm_snd_soc_register_card(dev, &byt_wm5102_card);
+	if (ret) {
+		dev_err_probe(dev, ret, "registering card\n");
+		goto out_put_gpio;
+	}
+
+	platform_set_drvdata(pdev, &byt_wm5102_card);
+	return 0;
+
+out_put_gpio:
+	gpiod_put(priv->spkvdd_en_gpio);
+	return ret;
+}
+
+static int snd_byt_wm5102_mc_remove(struct platform_device *pdev)
+{
+	struct snd_soc_card *card = platform_get_drvdata(pdev);
+	struct byt_wm5102_private *priv = snd_soc_card_get_drvdata(card);
+
+	gpiod_put(priv->spkvdd_en_gpio);
+	return 0;
+}
+
+static struct platform_driver snd_byt_wm5102_mc_driver = {
+	.driver = {
+		.name = "bytcr_wm5102",
+	},
+	.probe = snd_byt_wm5102_mc_probe,
+	.remove = snd_byt_wm5102_mc_remove,
+};
+
+module_platform_driver(snd_byt_wm5102_mc_driver);
+
+MODULE_DESCRIPTION("ASoC Baytrail with WM5102 codec machine driver");
+MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:bytcr_wm5102");
diff --git a/sound/soc/intel/boards/cht_bsw_nau8824.c b/sound/soc/intel/boards/cht_bsw_nau8824.c
index fd5e25ca05f7..da5a5cbc8759 100644
--- a/sound/soc/intel/boards/cht_bsw_nau8824.c
+++ b/sound/soc/intel/boards/cht_bsw_nau8824.c
@@ -100,13 +100,6 @@ static int cht_codec_init(struct snd_soc_pcm_runtime *runtime)
 	struct snd_soc_component *component = codec_dai->component;
 	int ret, jack_type;
 
-	/* TDM 4 slots 24 bit, set Rx & Tx bitmask to 4 active slots */
-	ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xf, 0x1, 4, 24);
-	if (ret < 0) {
-		dev_err(runtime->dev, "can't set codec TDM slot %d\n", ret);
-		return ret;
-	}
-
 	/* NAU88L24 supports 4 butons headset detection
 	 * KEY_PLAYPAUSE
 	 * KEY_VOICECOMMAND
@@ -141,6 +134,7 @@ static int cht_codec_fixup(struct snd_soc_pcm_runtime *rtd,
 		SNDRV_PCM_HW_PARAM_CHANNELS);
 	struct snd_mask *fmt =
 		hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
+	int ret;
 
 	/* The DSP will covert the FE rate to 48k, stereo, 24bits */
 	rate->min = rate->max = 48000;
@@ -150,6 +144,13 @@ static int cht_codec_fixup(struct snd_soc_pcm_runtime *rtd,
 	snd_mask_none(fmt);
 	params_set_format(params, SNDRV_PCM_FORMAT_S24_LE);
 
+	/* TDM 4 slots 24 bit, set Rx & Tx bitmask to 4 active slots */
+	ret = snd_soc_dai_set_tdm_slot(asoc_rtd_to_codec(rtd, 0), 0xf, 0x1, 4, 24);
+	if (ret < 0) {
+		dev_err(rtd->dev, "can't set codec TDM slot %d\n", ret);
+		return ret;
+	}
+
 	return 0;
 }
 
diff --git a/sound/soc/intel/boards/sof_maxim_common.c b/sound/soc/intel/boards/sof_maxim_common.c
index c2a9757181fe..437d20562753 100644
--- a/sound/soc/intel/boards/sof_maxim_common.c
+++ b/sound/soc/intel/boards/sof_maxim_common.c
@@ -63,6 +63,7 @@ int max98373_trigger(struct snd_pcm_substream *substream, int cmd)
 {
 	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
 	struct snd_soc_dai *codec_dai;
+	struct snd_soc_dai *cpu_dai;
 	int j;
 	int ret = 0;
 
@@ -70,10 +71,10 @@ int max98373_trigger(struct snd_pcm_substream *substream, int cmd)
 	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
 		return 0;
 
+	cpu_dai = asoc_rtd_to_cpu(rtd, 0);
 	for_each_rtd_codec_dais(rtd, j, codec_dai) {
-		struct snd_soc_component *component = codec_dai->component;
 		struct snd_soc_dapm_context *dapm =
-				snd_soc_component_get_dapm(component);
+				snd_soc_component_get_dapm(cpu_dai->component);
 		char pin_name[MAX_98373_PIN_NAME];
 
 		snprintf(pin_name, ARRAY_SIZE(pin_name), "%s Spk",
diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c
index 8b1ca2da9bb9..55505e207bc0 100644
--- a/sound/soc/intel/boards/sof_rt5682.c
+++ b/sound/soc/intel/boards/sof_rt5682.c
@@ -323,13 +323,6 @@ static int sof_rt1015_hw_params(struct snd_pcm_substream *substream,
 		fs = 64;
 
 	for_each_rtd_codec_dais(rtd, i, codec_dai) {
-		/* Set tdm/i2s1 master bclk ratio */
-		ret = snd_soc_dai_set_bclk_ratio(codec_dai, fs);
-		if (ret < 0) {
-			dev_err(card->dev, "failed to set bclk ratio\n");
-			return ret;
-		}
-
 		ret = snd_soc_dai_set_pll(codec_dai, 0, RT1015_PLL_S_BCLK,
 					  params_rate(params) * fs,
 					  params_rate(params) * 256);
diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c
index 152ea166eeae..8adce6417b02 100644
--- a/sound/soc/intel/boards/sof_sdw.c
+++ b/sound/soc/intel/boards/sof_sdw.c
@@ -48,37 +48,14 @@ static int sof_sdw_quirk_cb(const struct dmi_system_id *id)
 }
 
 static const struct dmi_system_id sof_sdw_quirk_table[] = {
+	/* CometLake devices */
 	{
 		.callback = sof_sdw_quirk_cb,
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
-			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A32")
-		},
-		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
-					SOF_RT711_JD_SRC_JD2 |
-					SOF_RT715_DAI_ID_FIX |
-					SOF_SDW_FOUR_SPK),
-	},
-	{
-		.callback = sof_sdw_quirk_cb,
-		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
-			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A3E")
-		},
-		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
-					SOF_RT711_JD_SRC_JD2 |
-					SOF_RT715_DAI_ID_FIX),
-	},
-	{
-		.callback = sof_sdw_quirk_cb,
-		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
-			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A5E")
+			DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "CometLake Client"),
 		},
-		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
-					SOF_RT711_JD_SRC_JD2 |
-					SOF_RT715_DAI_ID_FIX |
-					SOF_SDW_FOUR_SPK),
+		.driver_data = (void *)SOF_SDW_PCH_DMIC,
 	},
 	{
 		.callback = sof_sdw_quirk_cb,
@@ -109,7 +86,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
 					SOF_RT715_DAI_ID_FIX |
 					SOF_SDW_FOUR_SPK),
 	},
-		{
+	{
 		.callback = sof_sdw_quirk_cb,
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
@@ -119,6 +96,16 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
 					SOF_RT715_DAI_ID_FIX |
 					SOF_SDW_FOUR_SPK),
 	},
+	/* IceLake devices */
+	{
+		.callback = sof_sdw_quirk_cb,
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Ice Lake Client"),
+		},
+		.driver_data = (void *)SOF_SDW_PCH_DMIC,
+	},
+	/* TigerLake devices */
 	{
 		.callback = sof_sdw_quirk_cb,
 		.matches = {
@@ -126,25 +113,31 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
 			DMI_MATCH(DMI_PRODUCT_NAME,
 				  "Tiger Lake Client Platform"),
 		},
-		.driver_data = (void *)(SOF_RT711_JD_SRC_JD1 |
-				SOF_SDW_TGL_HDMI | SOF_SDW_PCH_DMIC |
-				SOF_SSP_PORT(SOF_I2S_SSP2)),
+		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
+					SOF_RT711_JD_SRC_JD1 |
+					SOF_SDW_PCH_DMIC |
+					SOF_SSP_PORT(SOF_I2S_SSP2)),
 	},
 	{
 		.callback = sof_sdw_quirk_cb,
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "Ice Lake Client"),
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
+			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A3E")
 		},
-		.driver_data = (void *)SOF_SDW_PCH_DMIC,
+		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
+					SOF_RT711_JD_SRC_JD2 |
+					SOF_RT715_DAI_ID_FIX),
 	},
 	{
 		.callback = sof_sdw_quirk_cb,
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "CometLake Client"),
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
+			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A5E")
 		},
-		.driver_data = (void *)SOF_SDW_PCH_DMIC,
+		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
+					SOF_RT711_JD_SRC_JD2 |
+					SOF_RT715_DAI_ID_FIX |
+					SOF_SDW_FOUR_SPK),
 	},
 	{
 		.callback = sof_sdw_quirk_cb,
@@ -152,7 +145,8 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
 			DMI_MATCH(DMI_SYS_VENDOR, "Google"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "Volteer"),
 		},
-		.driver_data = (void *)(SOF_SDW_TGL_HDMI | SOF_SDW_PCH_DMIC |
+		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
+					SOF_SDW_PCH_DMIC |
 					SOF_SDW_FOUR_SPK),
 	},
 	{
@@ -161,10 +155,38 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
 			DMI_MATCH(DMI_SYS_VENDOR, "Google"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "Ripto"),
 		},
-		.driver_data = (void *)(SOF_SDW_TGL_HDMI | SOF_SDW_PCH_DMIC |
+		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
+					SOF_SDW_PCH_DMIC |
+					SOF_SDW_FOUR_SPK),
+	},
+	{
+		/*
+		 * this entry covers multiple HP SKUs. The family name
+		 * does not seem robust enough, so we use a partial
+		 * match that ignores the product name suffix
+		 * (e.g. 15-eb1xxx, 14t-ea000 or 13-aw2xxx)
+		 */
+		.callback = sof_sdw_quirk_cb,
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "HP Spectre x360 Convertible"),
+		},
+		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
+					SOF_SDW_PCH_DMIC |
+					SOF_RT711_JD_SRC_JD2),
+	},
+	/* TigerLake-SDCA devices */
+	{
+		.callback = sof_sdw_quirk_cb,
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
+			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A32")
+		},
+		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
+					SOF_RT711_JD_SRC_JD2 |
+					SOF_RT715_DAI_ID_FIX |
 					SOF_SDW_FOUR_SPK),
 	},
-
 	{}
 };
 
@@ -454,15 +476,14 @@ static int get_sdw_dailink_info(const struct snd_soc_acpi_link_adr *links,
 	return 0;
 }
 
-static void init_dai_link(struct snd_soc_dai_link *dai_links, int be_id,
-			  char *name, int playback, int capture,
-			  struct snd_soc_dai_link_component *cpus,
-			  int cpus_num,
-			  struct snd_soc_dai_link_component *codecs,
-			  int codecs_num,
+static void init_dai_link(struct device *dev, struct snd_soc_dai_link *dai_links,
+			  int be_id, char *name, int playback, int capture,
+			  struct snd_soc_dai_link_component *cpus, int cpus_num,
+			  struct snd_soc_dai_link_component *codecs, int codecs_num,
 			  int (*init)(struct snd_soc_pcm_runtime *rtd),
 			  const struct snd_soc_ops *ops)
 {
+	dev_dbg(dev, "create dai link %s, id %d\n", name, be_id);
 	dai_links->id = be_id;
 	dai_links->name = name;
 	dai_links->platforms = platform_component;
@@ -800,7 +821,7 @@ static int create_sdw_dailink(struct device *dev, int *be_index,
 
 		playback = (stream == SNDRV_PCM_STREAM_PLAYBACK);
 		capture = (stream == SNDRV_PCM_STREAM_CAPTURE);
-		init_dai_link(dai_links + *be_index, *be_index, name,
+		init_dai_link(dev, dai_links + *be_index, *be_index, name,
 			      playback, capture,
 			      cpus + *cpu_id, cpu_dai_num,
 			      codecs, codec_num,
@@ -933,7 +954,7 @@ static int sof_card_dai_links_create(struct device *dev,
 		ctx->idisp_codec = true;
 
 	/* enable dmic01 & dmic16k */
-	dmic_num = (sof_sdw_quirk & SOF_SDW_PCH_DMIC) ? 2 : 0;
+	dmic_num = (sof_sdw_quirk & SOF_SDW_PCH_DMIC || mach_params->dmic_num) ? 2 : 0;
 	comp_num += dmic_num;
 
 	dev_dbg(dev, "sdw %d, ssp %d, dmic %d, hdmi %d", sdw_be_num, ssp_num,
@@ -1039,7 +1060,7 @@ SSP:
 
 		playback = info->direction[SNDRV_PCM_STREAM_PLAYBACK];
 		capture = info->direction[SNDRV_PCM_STREAM_CAPTURE];
-		init_dai_link(links + link_id, be_id, name,
+		init_dai_link(dev, links + link_id, be_id, name,
 			      playback, capture,
 			      cpus + cpu_id, 1,
 			      ssp_components, 1,
@@ -1056,7 +1077,7 @@ DMIC:
 	/* dmic */
 	if (dmic_num > 0) {
 		cpus[cpu_id].dai_name = "DMIC01 Pin";
-		init_dai_link(links + link_id, be_id, "dmic01",
+		init_dai_link(dev, links + link_id, be_id, "dmic01",
 			      0, 1, // DMIC only supports capture
 			      cpus + cpu_id, 1,
 			      dmic_component, 1,
@@ -1064,7 +1085,7 @@ DMIC:
 		INC_ID(be_id, cpu_id, link_id);
 
 		cpus[cpu_id].dai_name = "DMIC16k Pin";
-		init_dai_link(links + link_id, be_id, "dmic16k",
+		init_dai_link(dev, links + link_id, be_id, "dmic16k",
 			      0, 1, // DMIC only supports capture
 			      cpus + cpu_id, 1,
 			      dmic_component, 1,
@@ -1107,7 +1128,7 @@ DMIC:
 			return -ENOMEM;
 
 		cpus[cpu_id].dai_name = cpu_name;
-		init_dai_link(links + link_id, be_id, name,
+		init_dai_link(dev, links + link_id, be_id, name,
 			      1, 0, // HDMI only supports playback
 			      cpus + cpu_id, 1,
 			      idisp_components + i, 1,
@@ -1200,6 +1221,15 @@ static int mc_probe(struct platform_device *pdev)
 	if (!card->components)
 		return -ENOMEM;
 
+	if (mach->mach_params.dmic_num) {
+		card->components = devm_kasprintf(card->dev, GFP_KERNEL,
+						  "%s mic:dmic cfg-mics:%d",
+						  card->components,
+						  mach->mach_params.dmic_num);
+		if (!card->components)
+			return -ENOMEM;
+	}
+
 	card->long_name = sdw_card_long_name;
 
 	/* Register the card */
diff --git a/sound/soc/intel/catpt/pcm.c b/sound/soc/intel/catpt/pcm.c
index e5d54bb1c42a..ebb27daeb1c7 100644
--- a/sound/soc/intel/catpt/pcm.c
+++ b/sound/soc/intel/catpt/pcm.c
@@ -331,7 +331,7 @@ static int catpt_dai_apply_usettings(struct snd_soc_dai *dai,
 {
 	struct catpt_dev *cdev = dev_get_drvdata(dai->dev);
 	struct snd_soc_component *component = dai->component;
-	struct snd_kcontrol *pos, *kctl = NULL;
+	struct snd_kcontrol *pos;
 	const char *name;
 	int ret;
 	u32 id = stream->info.stream_hw_id;
@@ -352,21 +352,19 @@ static int catpt_dai_apply_usettings(struct snd_soc_dai *dai,
 		break;
 	default:
 		return 0;
-	};
+	}
 
 	list_for_each_entry(pos, &component->card->snd_card->controls, list) {
 		if (pos->private_data == component &&
-		    !strncmp(name, pos->id.name, sizeof(pos->id.name))) {
-			kctl = pos;
+		    !strncmp(name, pos->id.name, sizeof(pos->id.name)))
 			break;
-		}
 	}
-	if (!kctl)
+	if (list_entry_is_head(pos, &component->card->snd_card->controls, list))
 		return -ENOENT;
 
 	if (stream->template->type != CATPT_STRM_TYPE_LOOPBACK)
-		return catpt_set_dspvol(cdev, id, (long *)kctl->private_value);
-	ret = catpt_ipc_mute_loopback(cdev, id, *(bool *)kctl->private_value);
+		return catpt_set_dspvol(cdev, id, (long *)pos->private_value);
+	ret = catpt_ipc_mute_loopback(cdev, id, *(bool *)pos->private_value);
 	if (ret)
 		return CATPT_IPC_ERROR(ret);
 	return 0;
diff --git a/sound/soc/intel/common/soc-acpi-intel-adl-match.c b/sound/soc/intel/common/soc-acpi-intel-adl-match.c
index 06b233d63b73..0aca340ebc25 100644
--- a/sound/soc/intel/common/soc-acpi-intel-adl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-adl-match.c
@@ -44,7 +44,6 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_sdw_machines[] = {
 		.link_mask = 0x1, /* link0 required */
 		.links = adl_rvp,
 		.drv_name = "sof_sdw",
-		.sof_fw_filename = "sof-adl.ri",
 		.sof_tplg_filename = "sof-adl-rt711.tplg",
 	},
 	{},
diff --git a/sound/soc/intel/common/soc-acpi-intel-bxt-match.c b/sound/soc/intel/common/soc-acpi-intel-bxt-match.c
index 32f77e29c2ff..398cc771c835 100644
--- a/sound/soc/intel/common/soc-acpi-intel-bxt-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-bxt-match.c
@@ -85,6 +85,3 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_bxt_machines[] = {
 	{},
 };
 EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_bxt_machines);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("Intel Common ACPI Match module");
diff --git a/sound/soc/intel/common/soc-acpi-intel-byt-match.c b/sound/soc/intel/common/soc-acpi-intel-byt-match.c
index c348607b49a5..d1febbb53b70 100644
--- a/sound/soc/intel/common/soc-acpi-intel-byt-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-byt-match.c
@@ -155,6 +155,22 @@ struct snd_soc_acpi_mach  snd_soc_acpi_intel_baytrail_machines[] = {
 		.sof_tplg_filename = "sof-byt-rt5651.tplg",
 	},
 	{
+		.id = "WM510204",
+		.drv_name = "bytcr_wm5102",
+		.fw_filename = "intel/fw_sst_0f28.bin",
+		.board = "bytcr_wm5102",
+		.sof_fw_filename = "sof-byt.ri",
+		.sof_tplg_filename = "sof-byt-wm5102.tplg",
+	},
+	{
+		.id = "WM510205",
+		.drv_name = "bytcr_wm5102",
+		.fw_filename = "intel/fw_sst_0f28.bin",
+		.board = "bytcr_wm5102",
+		.sof_fw_filename = "sof-byt.ri",
+		.sof_tplg_filename = "sof-byt-wm5102.tplg",
+	},
+	{
 		.id = "DLGS7212",
 		.drv_name = "bytcht_da7213",
 		.fw_filename = "intel/fw_sst_0f28.bin",
@@ -233,6 +249,3 @@ struct snd_soc_acpi_mach  snd_soc_acpi_intel_baytrail_machines[] = {
 	{},
 };
 EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_baytrail_machines);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("Intel Common ACPI Match module");
diff --git a/sound/soc/intel/common/soc-acpi-intel-cfl-match.c b/sound/soc/intel/common/soc-acpi-intel-cfl-match.c
index 27b4b73d94d4..1733dfb23e79 100644
--- a/sound/soc/intel/common/soc-acpi-intel-cfl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-cfl-match.c
@@ -18,6 +18,3 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_cfl_sdw_machines[] = {
 	{}
 };
 EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_cfl_sdw_machines);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("Intel Common ACPI Match module");
diff --git a/sound/soc/intel/common/soc-acpi-intel-cht-match.c b/sound/soc/intel/common/soc-acpi-intel-cht-match.c
index 2752dc955733..227424236fd5 100644
--- a/sound/soc/intel/common/soc-acpi-intel-cht-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-cht-match.c
@@ -196,6 +196,3 @@ struct snd_soc_acpi_mach  snd_soc_acpi_intel_cherrytrail_machines[] = {
 	{},
 };
 EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_cherrytrail_machines);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("Intel Common ACPI Match module");
diff --git a/sound/soc/intel/common/soc-acpi-intel-cml-match.c b/sound/soc/intel/common/soc-acpi-intel-cml-match.c
index adddc91918df..2161b3b85b4a 100644
--- a/sound/soc/intel/common/soc-acpi-intel-cml-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-cml-match.c
@@ -309,6 +309,3 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_cml_sdw_machines[] = {
 	{}
 };
 EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_cml_sdw_machines);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("Intel Common ACPI Match module");
diff --git a/sound/soc/intel/common/soc-acpi-intel-cnl-match.c b/sound/soc/intel/common/soc-acpi-intel-cnl-match.c
index b80f032a8b76..ec77a57a07ba 100644
--- a/sound/soc/intel/common/soc-acpi-intel-cnl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-cnl-match.c
@@ -63,6 +63,3 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_cnl_sdw_machines[] = {
 	{}
 };
 EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_cnl_sdw_machines);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("Intel Common ACPI Match module");
diff --git a/sound/soc/intel/common/soc-acpi-intel-ehl-match.c b/sound/soc/intel/common/soc-acpi-intel-ehl-match.c
index badafc1d54d2..6222708a98e7 100644
--- a/sound/soc/intel/common/soc-acpi-intel-ehl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-ehl-match.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * soc-apci-intel-ehl-match.c - tables and support for EHL ACPI enumeration.
+ * soc-acpi-intel-ehl-match.c - tables and support for EHL ACPI enumeration.
  *
  * Copyright (c) 2019, Intel Corporation.
  *
@@ -20,6 +20,3 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_ehl_machines[] = {
 	{},
 };
 EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_ehl_machines);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("Intel Common ACPI Match module");
diff --git a/sound/soc/intel/common/soc-acpi-intel-glk-match.c b/sound/soc/intel/common/soc-acpi-intel-glk-match.c
index 26cb3b16cdd3..6ceaab19ccb6 100644
--- a/sound/soc/intel/common/soc-acpi-intel-glk-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-glk-match.c
@@ -43,6 +43,3 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_glk_machines[] = {
 	{},
 };
 EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_glk_machines);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("Intel Common ACPI Match module");
diff --git a/sound/soc/intel/common/soc-acpi-intel-hsw-bdw-match.c b/sound/soc/intel/common/soc-acpi-intel-hsw-bdw-match.c
index 35958553652e..fe343a95b5ff 100644
--- a/sound/soc/intel/common/soc-acpi-intel-hsw-bdw-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-hsw-bdw-match.c
@@ -53,6 +53,3 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_broadwell_machines[] = {
 	{}
 };
 EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_broadwell_machines);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("Intel Common ACPI Match module");
diff --git a/sound/soc/intel/common/soc-acpi-intel-icl-match.c b/sound/soc/intel/common/soc-acpi-intel-icl-match.c
index 9a529a785288..d38ff7d187c4 100644
--- a/sound/soc/intel/common/soc-acpi-intel-icl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-icl-match.c
@@ -185,6 +185,3 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_icl_sdw_machines[] = {
 	{},
 };
 EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_icl_sdw_machines);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("Intel Common ACPI Match module");
diff --git a/sound/soc/intel/common/soc-acpi-intel-jsl-match.c b/sound/soc/intel/common/soc-acpi-intel-jsl-match.c
index 34f5fcad5701..52238db0bcb5 100644
--- a/sound/soc/intel/common/soc-acpi-intel-jsl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-jsl-match.c
@@ -63,6 +63,3 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_jsl_machines[] = {
 	{},
 };
 EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_jsl_machines);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("Intel Common ACPI Match module");
diff --git a/sound/soc/intel/common/soc-acpi-intel-kbl-match.c b/sound/soc/intel/common/soc-acpi-intel-kbl-match.c
index a4fbe6707ca7..47dadc9d5d2a 100644
--- a/sound/soc/intel/common/soc-acpi-intel-kbl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-kbl-match.c
@@ -128,6 +128,3 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_kbl_machines[] = {
 	{},
 };
 EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_kbl_machines);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("Intel Common ACPI Match module");
diff --git a/sound/soc/intel/common/soc-acpi-intel-skl-match.c b/sound/soc/intel/common/soc-acpi-intel-skl-match.c
index 26f9ce146523..961df8d6b5e4 100644
--- a/sound/soc/intel/common/soc-acpi-intel-skl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-skl-match.c
@@ -42,6 +42,3 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_skl_machines[] = {
 	{},
 };
 EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_skl_machines);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("Intel Common ACPI Match module");
diff --git a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c
index 711aed06c6dd..40f31c8a3aba 100644
--- a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * soc-apci-intel-tgl-match.c - tables and support for ICL ACPI enumeration.
+ * soc-acpi-intel-tgl-match.c - tables and support for TGL ACPI enumeration.
  *
  * Copyright (c) 2019, Intel Corporation.
  *
@@ -205,6 +205,20 @@ static const struct snd_soc_acpi_link_adr tgl_rvp[] = {
 	{}
 };
 
+static const struct snd_soc_acpi_link_adr tgl_hp[] = {
+	{
+		.mask = BIT(0),
+		.num_adr = ARRAY_SIZE(rt711_0_adr),
+		.adr_d = rt711_0_adr,
+	},
+	{
+		.mask = BIT(1),
+		.num_adr = ARRAY_SIZE(rt1308_1_single_adr),
+		.adr_d = rt1308_1_single_adr,
+	},
+	{}
+};
+
 static const struct snd_soc_acpi_link_adr tgl_chromebook_base[] = {
 	{
 		.mask = BIT(0),
@@ -384,6 +398,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_tgl_sdw_machines[] = {
 		.sof_tplg_filename = "sof-tgl-rt711-rt1316-rt714.tplg",
 	},
 	{
+		.link_mask = 0x3, /* rt711 on link 0 and 1 rt1308 on link 1 */
+		.links = tgl_hp,
+		.drv_name = "sof_sdw",
+		.sof_tplg_filename = "sof-tgl-rt711-rt1308.tplg",
+	},
+	{
 		.link_mask = 0x3, /* rt711 on link 0 and 2 rt1308s on link 1 */
 		.links = tgl_rvp,
 		.drv_name = "sof_sdw",
@@ -404,6 +424,3 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_tgl_sdw_machines[] = {
 	{},
 };
 EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_tgl_sdw_machines);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("Intel Common ACPI Match module");
diff --git a/sound/soc/intel/common/soc-intel-quirks.h b/sound/soc/intel/common/soc-intel-quirks.h
index b07df3059926..a93987ab7f4d 100644
--- a/sound/soc/intel/common/soc-intel-quirks.h
+++ b/sound/soc/intel/common/soc-intel-quirks.h
@@ -11,6 +11,7 @@
 
 #if IS_ENABLED(CONFIG_X86)
 
+#include <linux/dmi.h>
 #include <asm/cpu_device_id.h>
 #include <asm/intel-family.h>
 #include <asm/iosf_mbi.h>
@@ -38,12 +39,36 @@ SOC_INTEL_IS_CPU(cml, KABYLAKE_L);
 
 static inline bool soc_intel_is_byt_cr(struct platform_device *pdev)
 {
+	/*
+	 * List of systems which:
+	 * 1. Use a non CR version of the Bay Trail SoC
+	 * 2. Contain at least 6 interrupt resources so that the
+	 *    platform_get_resource(pdev, IORESOURCE_IRQ, 5) check below
+	 *    succeeds
+	 * 3. Despite 1. and 2. still have their IPC IRQ at index 0 rather then 5
+	 *
+	 * This needs to be here so that it can be shared between the SST and
+	 * SOF drivers. We rely on the compiler to optimize this out in files
+	 * where soc_intel_is_byt_cr is not used.
+	 */
+	static const struct dmi_system_id force_bytcr_table[] = {
+		{	/* Lenovo Yoga Tablet 2 series */
+			.matches = {
+				DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+				DMI_MATCH(DMI_PRODUCT_FAMILY, "YOGATablet2"),
+			},
+		},
+		{}
+	};
 	struct device *dev = &pdev->dev;
 	int status = 0;
 
 	if (!soc_intel_is_byt())
 		return false;
 
+	if (dmi_check_system(force_bytcr_table))
+		return true;
+
 	if (iosf_mbi_available()) {
 		u32 bios_status;
 
diff --git a/sound/soc/intel/keembay/kmb_platform.c b/sound/soc/intel/keembay/kmb_platform.c
index 1c3748f33136..0fd1e8f62c89 100644
--- a/sound/soc/intel/keembay/kmb_platform.c
+++ b/sound/soc/intel/keembay/kmb_platform.c
@@ -5,11 +5,14 @@
 // Intel KeemBay Platform driver.
 //
 
+#include <linux/bitrev.h>
 #include <linux/clk.h>
+#include <linux/dma-mapping.h>
 #include <linux/io.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
+#include <sound/dmaengine_pcm.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
 #include <sound/soc.h>
@@ -37,7 +40,8 @@ static const struct snd_pcm_hardware kmb_pcm_hardware = {
 	.rate_max = 48000,
 	.formats = SNDRV_PCM_FMTBIT_S16_LE |
 		   SNDRV_PCM_FMTBIT_S24_LE |
-		   SNDRV_PCM_FMTBIT_S32_LE,
+		   SNDRV_PCM_FMTBIT_S32_LE |
+		   SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE,
 	.channels_min = 2,
 	.channels_max = 2,
 	.buffer_bytes_max = BUFFER_BYTES_MAX,
@@ -48,6 +52,50 @@ static const struct snd_pcm_hardware kmb_pcm_hardware = {
 	.fifo_size = 16,
 };
 
+/*
+ * Convert to ADV7511 HDMI hardware format.
+ * ADV7511 HDMI chip need parity bit replaced by block start bit and
+ * with the preamble bits left out.
+ * ALSA IEC958 subframe format:
+ * bit 0-3  = preamble (0x8 = block start)
+ *     4-7  = AUX (=0)
+ *     8-27 = audio data (without AUX if 24bit sample)
+ *     28   = validity
+ *     29   = user data
+ *     30   = channel status
+ *     31   = parity
+ *
+ * ADV7511 IEC958 subframe format:
+ * bit 0-23  = audio data
+ *     24    = validity
+ *     25    = user data
+ *     26    = channel status
+ *     27    = block start
+ *     28-31 = 0
+ * MSB to LSB bit reverse by software as hardware not supporting it.
+ */
+static void hdmi_reformat_iec958(struct snd_pcm_runtime *runtime,
+				 struct kmb_i2s_info *kmb_i2s,
+				 unsigned int tx_ptr)
+{
+	u32(*buf)[2] = (void *)runtime->dma_area;
+	unsigned long temp;
+	u32 i, j, sample;
+
+	for (i = 0; i < kmb_i2s->fifo_th; i++) {
+		j = 0;
+		do {
+			temp = buf[tx_ptr][j];
+			/* Replace parity with block start*/
+			assign_bit(31, &temp, (BIT(3) & temp));
+			sample = bitrev32(temp);
+			buf[tx_ptr][j] = sample << 4;
+			j++;
+		} while (j < 2);
+		tx_ptr++;
+	}
+}
+
 static unsigned int kmb_pcm_tx_fn(struct kmb_i2s_info *kmb_i2s,
 				  struct snd_pcm_runtime *runtime,
 				  unsigned int tx_ptr, bool *period_elapsed)
@@ -63,6 +111,8 @@ static unsigned int kmb_pcm_tx_fn(struct kmb_i2s_info *kmb_i2s,
 			writel(((u16(*)[2])buf)[tx_ptr][0], i2s_base + LRBR_LTHR(0));
 			writel(((u16(*)[2])buf)[tx_ptr][1], i2s_base + RRBR_RTHR(0));
 		} else {
+			if (kmb_i2s->iec958_fmt)
+				hdmi_reformat_iec958(runtime, kmb_i2s, tx_ptr);
 			writel(((u32(*)[2])buf)[tx_ptr][0], i2s_base + LRBR_LTHR(0));
 			writel(((u32(*)[2])buf)[tx_ptr][1], i2s_base + RRBR_RTHR(0));
 		}
@@ -233,6 +283,7 @@ static int kmb_pcm_trigger(struct snd_soc_component *component,
 			kmb_i2s->tx_substream = NULL;
 		else
 			kmb_i2s->rx_substream = NULL;
+		kmb_i2s->iec958_fmt = false;
 		break;
 	default:
 		return -EINVAL;
@@ -343,6 +394,53 @@ static const struct snd_soc_component_driver kmb_component = {
 	.pointer	= kmb_pcm_pointer,
 };
 
+static const struct snd_soc_component_driver kmb_component_dma = {
+	.name		= "kmb",
+};
+
+static int kmb_probe(struct snd_soc_dai *cpu_dai)
+{
+	struct kmb_i2s_info *kmb_i2s = snd_soc_dai_get_drvdata(cpu_dai);
+
+	if (kmb_i2s->use_pio)
+		return 0;
+
+	snd_soc_dai_init_dma_data(cpu_dai, &kmb_i2s->play_dma_data,
+				  &kmb_i2s->capture_dma_data);
+
+	return 0;
+}
+
+static inline void kmb_i2s_enable_dma(struct kmb_i2s_info *kmb_i2s, u32 stream)
+{
+	u32 dma_reg;
+
+	dma_reg = readl(kmb_i2s->i2s_base + I2S_DMACR);
+	/* Enable DMA handshake for stream */
+	if (stream == SNDRV_PCM_STREAM_PLAYBACK)
+		dma_reg |= I2S_DMAEN_TXBLOCK;
+	else
+		dma_reg |= I2S_DMAEN_RXBLOCK;
+
+	writel(dma_reg, kmb_i2s->i2s_base + I2S_DMACR);
+}
+
+static inline void kmb_i2s_disable_dma(struct kmb_i2s_info *kmb_i2s, u32 stream)
+{
+	u32 dma_reg;
+
+	dma_reg = readl(kmb_i2s->i2s_base + I2S_DMACR);
+	/* Disable DMA handshake for stream */
+	if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		dma_reg &= ~I2S_DMAEN_TXBLOCK;
+		writel(1, kmb_i2s->i2s_base + I2S_RTXDMA);
+	} else {
+		dma_reg &= ~I2S_DMAEN_RXBLOCK;
+		writel(1, kmb_i2s->i2s_base + I2S_RRXDMA);
+	}
+	writel(dma_reg, kmb_i2s->i2s_base + I2S_DMACR);
+}
+
 static void kmb_i2s_start(struct kmb_i2s_info *kmb_i2s,
 			  struct snd_pcm_substream *substream)
 {
@@ -356,7 +454,11 @@ static void kmb_i2s_start(struct kmb_i2s_info *kmb_i2s,
 	else
 		writel(1, kmb_i2s->i2s_base + IRER);
 
-	kmb_i2s_irq_trigger(kmb_i2s, substream->stream, config->chan_nr, true);
+	if (kmb_i2s->use_pio)
+		kmb_i2s_irq_trigger(kmb_i2s, substream->stream,
+				    config->chan_nr, true);
+	else
+		kmb_i2s_enable_dma(kmb_i2s, substream->stream);
 
 	if (kmb_i2s->clock_provider)
 		writel(1, kmb_i2s->i2s_base + CER);
@@ -434,7 +536,8 @@ static int kmb_dai_trigger(struct snd_pcm_substream *substream,
 		break;
 	case SNDRV_PCM_TRIGGER_STOP:
 		kmb_i2s->active--;
-		kmb_i2s_stop(kmb_i2s, substream);
+		if (kmb_i2s->use_pio)
+			kmb_i2s_stop(kmb_i2s, substream);
 		break;
 	default:
 		return  -EINVAL;
@@ -485,16 +588,25 @@ static int kmb_dai_hw_params(struct snd_pcm_substream *substream,
 		config->data_width = 16;
 		kmb_i2s->ccr = 0x00;
 		kmb_i2s->xfer_resolution = 0x02;
+		kmb_i2s->play_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
+		kmb_i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
 		break;
 	case SNDRV_PCM_FORMAT_S24_LE:
 		config->data_width = 32;
 		kmb_i2s->ccr = 0x14;
 		kmb_i2s->xfer_resolution = 0x05;
+		kmb_i2s->play_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+		kmb_i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
 		break;
+	case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE:
+		kmb_i2s->iec958_fmt = true;
+		fallthrough;
 	case SNDRV_PCM_FORMAT_S32_LE:
 		config->data_width = 32;
 		kmb_i2s->ccr = 0x10;
 		kmb_i2s->xfer_resolution = 0x05;
+		kmb_i2s->play_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+		kmb_i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
 		break;
 	default:
 		dev_err(kmb_i2s->dev, "kmb: unsupported PCM fmt");
@@ -572,13 +684,78 @@ static int kmb_dai_prepare(struct snd_pcm_substream *substream,
 	return 0;
 }
 
+static int kmb_dai_startup(struct snd_pcm_substream *substream,
+			   struct snd_soc_dai *cpu_dai)
+{
+	struct kmb_i2s_info *kmb_i2s = snd_soc_dai_get_drvdata(cpu_dai);
+	struct snd_dmaengine_dai_dma_data *dma_data;
+
+	if (kmb_i2s->use_pio)
+		return 0;
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		dma_data = &kmb_i2s->play_dma_data;
+	else
+		dma_data = &kmb_i2s->capture_dma_data;
+
+	snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data);
+
+	return 0;
+}
+
+static int kmb_dai_hw_free(struct snd_pcm_substream *substream,
+			   struct snd_soc_dai *cpu_dai)
+{
+	struct kmb_i2s_info *kmb_i2s = snd_soc_dai_get_drvdata(cpu_dai);
+	/* I2S Programming sequence in Keem_Bay_VPU_DB_v1.1 */
+	if (kmb_i2s->use_pio)
+		kmb_i2s_clear_irqs(kmb_i2s, substream->stream);
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		writel(0, kmb_i2s->i2s_base + ITER);
+	else
+		writel(0, kmb_i2s->i2s_base + IRER);
+
+	if (kmb_i2s->use_pio)
+		kmb_i2s_irq_trigger(kmb_i2s, substream->stream, 8, false);
+	else
+		kmb_i2s_disable_dma(kmb_i2s, substream->stream);
+
+	if (!kmb_i2s->active) {
+		writel(0, kmb_i2s->i2s_base + CER);
+		writel(0, kmb_i2s->i2s_base + IER);
+	}
+
+	return 0;
+}
+
 static struct snd_soc_dai_ops kmb_dai_ops = {
+	.startup	= kmb_dai_startup,
 	.trigger	= kmb_dai_trigger,
 	.hw_params	= kmb_dai_hw_params,
+	.hw_free	= kmb_dai_hw_free,
 	.prepare	= kmb_dai_prepare,
 	.set_fmt	= kmb_set_dai_fmt,
 };
 
+static struct snd_soc_dai_driver intel_kmb_hdmi_dai[] = {
+	{
+		.name = "intel_kmb_hdmi_i2s",
+		.playback = {
+			.channels_min = 2,
+			.channels_max = 2,
+			.rates = SNDRV_PCM_RATE_48000,
+			.rate_min = 48000,
+			.rate_max = 48000,
+			.formats = (SNDRV_PCM_FMTBIT_S16_LE |
+				    SNDRV_PCM_FMTBIT_S24_LE |
+				    SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE),
+		},
+		.ops = &kmb_dai_ops,
+		.probe = kmb_probe,
+	},
+};
+
 static struct snd_soc_dai_driver intel_kmb_i2s_dai[] = {
 	{
 		.name = "intel_kmb_i2s",
@@ -607,6 +784,7 @@ static struct snd_soc_dai_driver intel_kmb_i2s_dai[] = {
 				    SNDRV_PCM_FMTBIT_S16_LE),
 		},
 		.ops = &kmb_dai_ops,
+		.probe = kmb_probe,
 	},
 };
 
@@ -626,21 +804,25 @@ static struct snd_soc_dai_driver intel_kmb_tdm_dai[] = {
 				    SNDRV_PCM_FMTBIT_S16_LE),
 		},
 		.ops = &kmb_dai_ops,
+		.probe = kmb_probe,
 	},
 };
 
 static const struct of_device_id kmb_plat_of_match[] = {
 	{ .compatible = "intel,keembay-i2s", .data = &intel_kmb_i2s_dai},
+	{ .compatible = "intel,keembay-hdmi-i2s", .data = &intel_kmb_hdmi_dai},
 	{ .compatible = "intel,keembay-tdm", .data = &intel_kmb_tdm_dai},
 	{}
 };
 
 static int kmb_plat_dai_probe(struct platform_device *pdev)
 {
+	struct device_node *np = pdev->dev.of_node;
 	struct snd_soc_dai_driver *kmb_i2s_dai;
 	const struct of_device_id *match;
 	struct device *dev = &pdev->dev;
 	struct kmb_i2s_info *kmb_i2s;
+	struct resource *res;
 	int ret, irq;
 	u32 comp1_reg;
 
@@ -682,7 +864,7 @@ static int kmb_plat_dai_probe(struct platform_device *pdev)
 		return PTR_ERR(kmb_i2s->clk_i2s);
 	}
 
-	kmb_i2s->i2s_base = devm_platform_ioremap_resource(pdev, 0);
+	kmb_i2s->i2s_base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
 	if (IS_ERR(kmb_i2s->i2s_base))
 		return PTR_ERR(kmb_i2s->i2s_base);
 
@@ -692,22 +874,38 @@ static int kmb_plat_dai_probe(struct platform_device *pdev)
 
 	kmb_i2s->dev = &pdev->dev;
 
-	irq = platform_get_irq_optional(pdev, 0);
-	if (irq > 0) {
-		ret = devm_request_irq(dev, irq, kmb_i2s_irq_handler, 0,
-				       pdev->name, kmb_i2s);
-		if (ret < 0) {
-			dev_err(dev, "failed to request irq\n");
-			return ret;
-		}
-	}
-
 	comp1_reg = readl(kmb_i2s->i2s_base + I2S_COMP_PARAM_1);
 
 	kmb_i2s->fifo_th = (1 << COMP1_FIFO_DEPTH(comp1_reg)) / 2;
 
-	ret = devm_snd_soc_register_component(dev, &kmb_component,
-					      kmb_i2s_dai, 1);
+	kmb_i2s->use_pio = !(of_property_read_bool(np, "dmas"));
+
+	if (kmb_i2s->use_pio) {
+		irq = platform_get_irq_optional(pdev, 0);
+		if (irq > 0) {
+			ret = devm_request_irq(dev, irq, kmb_i2s_irq_handler, 0,
+					       pdev->name, kmb_i2s);
+			if (ret < 0) {
+				dev_err(dev, "failed to request irq\n");
+				return ret;
+			}
+		}
+		ret = devm_snd_soc_register_component(dev, &kmb_component,
+						      kmb_i2s_dai, 1);
+	} else {
+		kmb_i2s->play_dma_data.addr = res->start + I2S_TXDMA;
+		kmb_i2s->capture_dma_data.addr = res->start + I2S_RXDMA;
+		ret = snd_dmaengine_pcm_register(&pdev->dev,
+						 NULL, 0);
+		if (ret) {
+			dev_err(&pdev->dev, "could not register dmaengine: %d\n",
+				ret);
+			return ret;
+		}
+		ret = devm_snd_soc_register_component(dev, &kmb_component_dma,
+						      kmb_i2s_dai, 1);
+	}
+
 	if (ret) {
 		dev_err(dev, "not able to register dai\n");
 		return ret;
diff --git a/sound/soc/intel/keembay/kmb_platform.h b/sound/soc/intel/keembay/kmb_platform.h
index 0c393e5916b6..29be2cd84ddb 100644
--- a/sound/soc/intel/keembay/kmb_platform.h
+++ b/sound/soc/intel/keembay/kmb_platform.h
@@ -12,6 +12,7 @@
 #include <linux/bits.h>
 #include <linux/bitfield.h>
 #include <linux/types.h>
+#include <sound/dmaengine_pcm.h>
 
 /* Register values with reference to KMB databook v1.1 */
 /* common register for all channel */
@@ -103,7 +104,12 @@
 #define DW_I2S_PROVIDER	BIT(3)
 
 #define I2S_RXDMA	0x01C0
+#define I2S_RRXDMA	0x01C4
 #define I2S_TXDMA	0x01C8
+#define I2S_RTXDMA	0x01CC
+#define I2S_DMACR	0x0200
+#define I2S_DMAEN_RXBLOCK	(1 << 16)
+#define I2S_DMAEN_TXBLOCK	(1 << 17)
 
 /*
  * struct i2s_clk_config_data - represent i2s clk configuration data
@@ -131,6 +137,9 @@ struct kmb_i2s_info {
 	u32 xfer_resolution;
 	u32 fifo_th;
 	bool clock_provider;
+	/* data related to DMA transfers b/w i2s and DMAC */
+	struct snd_dmaengine_dai_dma_data play_dma_data;
+	struct snd_dmaengine_dai_dma_data capture_dma_data;
 
 	struct i2s_clk_config_data config;
 	int (*i2s_clk_cfg)(struct i2s_clk_config_data *config);
@@ -141,6 +150,7 @@ struct kmb_i2s_info {
 	struct snd_pcm_substream *rx_substream;
 	unsigned int tx_ptr;
 	unsigned int rx_ptr;
+	bool iec958_fmt;
 };
 
 #endif /* KMB_PLATFORM_H_ */
diff --git a/sound/soc/intel/skylake/skl.c b/sound/soc/intel/skylake/skl.c
index 8b993722f74e..5b1a15e39912 100644
--- a/sound/soc/intel/skylake/skl.c
+++ b/sound/soc/intel/skylake/skl.c
@@ -950,12 +950,8 @@ static int skl_first_init(struct hdac_bus *bus)
 	bus->num_streams = cp_streams + pb_streams;
 
 	/* allow 64bit DMA address if supported by H/W */
-	if (!dma_set_mask(bus->dev, DMA_BIT_MASK(64))) {
-		dma_set_coherent_mask(bus->dev, DMA_BIT_MASK(64));
-	} else {
-		dma_set_mask(bus->dev, DMA_BIT_MASK(32));
-		dma_set_coherent_mask(bus->dev, DMA_BIT_MASK(32));
-	}
+	if (dma_set_mask_and_coherent(bus->dev, DMA_BIT_MASK(64)))
+		dma_set_mask_and_coherent(bus->dev, DMA_BIT_MASK(32));
 
 	/* initialize streams */
 	snd_hdac_ext_stream_init_all
diff --git a/sound/soc/jz4740/jz4740-i2s.c b/sound/soc/jz4740/jz4740-i2s.c
index 0a68f4c3d15a..52ba0e3a9e95 100644
--- a/sound/soc/jz4740/jz4740-i2s.c
+++ b/sound/soc/jz4740/jz4740-i2s.c
@@ -455,7 +455,7 @@ static struct snd_soc_dai_driver jz4740_i2s_dai = {
 		.rates = SNDRV_PCM_RATE_8000_48000,
 		.formats = JZ4740_I2S_FMTS,
 	},
-	.symmetric_rates = 1,
+	.symmetric_rate = 1,
 	.ops = &jz4740_i2s_dai_ops,
 };
 
diff --git a/sound/soc/kirkwood/kirkwood-dma.c b/sound/soc/kirkwood/kirkwood-dma.c
index e037826b2451..c2a5933bfcfc 100644
--- a/sound/soc/kirkwood/kirkwood-dma.c
+++ b/sound/soc/kirkwood/kirkwood-dma.c
@@ -182,25 +182,6 @@ static int kirkwood_dma_close(struct snd_soc_component *component,
 	return 0;
 }
 
-static int kirkwood_dma_hw_params(struct snd_soc_component *component,
-				  struct snd_pcm_substream *substream,
-				  struct snd_pcm_hw_params *params)
-{
-	struct snd_pcm_runtime *runtime = substream->runtime;
-
-	snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
-	runtime->dma_bytes = params_buffer_bytes(params);
-
-	return 0;
-}
-
-static int kirkwood_dma_hw_free(struct snd_soc_component *component,
-				struct snd_pcm_substream *substream)
-{
-	snd_pcm_set_runtime_buffer(substream, NULL);
-	return 0;
-}
-
 static int kirkwood_dma_prepare(struct snd_soc_component *component,
 				struct snd_pcm_substream *substream)
 {
@@ -244,82 +225,28 @@ static snd_pcm_uframes_t kirkwood_dma_pointer(
 	return count;
 }
 
-static int kirkwood_dma_preallocate_dma_buffer(struct snd_pcm *pcm,
-		int stream)
-{
-	struct snd_pcm_substream *substream = pcm->streams[stream].substream;
-	struct snd_dma_buffer *buf = &substream->dma_buffer;
-	size_t size = kirkwood_dma_snd_hw.buffer_bytes_max;
-
-	buf->dev.type = SNDRV_DMA_TYPE_DEV;
-	buf->dev.dev = pcm->card->dev;
-	buf->area = dma_alloc_coherent(pcm->card->dev, size,
-			&buf->addr, GFP_KERNEL);
-	if (!buf->area)
-		return -ENOMEM;
-	buf->bytes = size;
-	buf->private_data = NULL;
-
-	return 0;
-}
-
 static int kirkwood_dma_new(struct snd_soc_component *component,
 			    struct snd_soc_pcm_runtime *rtd)
 {
+	size_t size = kirkwood_dma_snd_hw.buffer_bytes_max;
 	struct snd_card *card = rtd->card->snd_card;
-	struct snd_pcm *pcm = rtd->pcm;
 	int ret;
 
 	ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
 	if (ret)
 		return ret;
 
-	if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
-		ret = kirkwood_dma_preallocate_dma_buffer(pcm,
-				SNDRV_PCM_STREAM_PLAYBACK);
-		if (ret)
-			return ret;
-	}
-
-	if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
-		ret = kirkwood_dma_preallocate_dma_buffer(pcm,
-				SNDRV_PCM_STREAM_CAPTURE);
-		if (ret)
-			return ret;
-	}
+	snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV,
+				       card->dev, size, size);
 
 	return 0;
 }
 
-static void kirkwood_dma_free_dma_buffers(struct snd_soc_component *component,
-					  struct snd_pcm *pcm)
-{
-	struct snd_pcm_substream *substream;
-	struct snd_dma_buffer *buf;
-	int stream;
-
-	for (stream = 0; stream < 2; stream++) {
-		substream = pcm->streams[stream].substream;
-		if (!substream)
-			continue;
-		buf = &substream->dma_buffer;
-		if (!buf->area)
-			continue;
-
-		dma_free_coherent(pcm->card->dev, buf->bytes,
-				buf->area, buf->addr);
-		buf->area = NULL;
-	}
-}
-
 const struct snd_soc_component_driver kirkwood_soc_component = {
 	.name		= DRV_NAME,
 	.open		= kirkwood_dma_open,
 	.close		= kirkwood_dma_close,
-	.hw_params	= kirkwood_dma_hw_params,
-	.hw_free	= kirkwood_dma_hw_free,
 	.prepare	= kirkwood_dma_prepare,
 	.pointer	= kirkwood_dma_pointer,
 	.pcm_construct	= kirkwood_dma_new,
-	.pcm_destruct	= kirkwood_dma_free_dma_buffers,
 };
diff --git a/sound/soc/mediatek/Kconfig b/sound/soc/mediatek/Kconfig
index 8d3dcfb6a580..effdb76369e4 100644
--- a/sound/soc/mediatek/Kconfig
+++ b/sound/soc/mediatek/Kconfig
@@ -172,7 +172,7 @@ config SND_SOC_MT8192
 config SND_SOC_MT8192_MT6359_RT1015_RT5682
 	tristate "ASoC Audio driver for MT8192 with MT6359 RT1015 RT5682 codec"
 	depends on I2C
-	depends on SND_SOC_MT8192
+	depends on SND_SOC_MT8192 && MTK_PMIC_WRAP
 	select SND_SOC_MT6359
 	select SND_SOC_RT1015
 	select SND_SOC_RT1015P
diff --git a/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c b/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c
index df29641c74aa..d5cffe7a7e15 100644
--- a/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c
+++ b/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c
@@ -655,7 +655,7 @@ static struct snd_soc_dai_driver mt2701_afe_pcm_dais[] = {
 
 		},
 		.ops = &mt2701_afe_i2s_ops,
-		.symmetric_rates = 1,
+		.symmetric_rate = 1,
 	},
 	{
 		.name = "I2S1",
@@ -679,7 +679,7 @@ static struct snd_soc_dai_driver mt2701_afe_pcm_dais[] = {
 				| SNDRV_PCM_FMTBIT_S32_LE)
 			},
 		.ops = &mt2701_afe_i2s_ops,
-		.symmetric_rates = 1,
+		.symmetric_rate = 1,
 	},
 	{
 		.name = "I2S2",
@@ -703,7 +703,7 @@ static struct snd_soc_dai_driver mt2701_afe_pcm_dais[] = {
 				| SNDRV_PCM_FMTBIT_S32_LE)
 			},
 		.ops = &mt2701_afe_i2s_ops,
-		.symmetric_rates = 1,
+		.symmetric_rate = 1,
 	},
 	{
 		.name = "I2S3",
@@ -727,7 +727,7 @@ static struct snd_soc_dai_driver mt2701_afe_pcm_dais[] = {
 				| SNDRV_PCM_FMTBIT_S32_LE)
 			},
 		.ops = &mt2701_afe_i2s_ops,
-		.symmetric_rates = 1,
+		.symmetric_rate = 1,
 	},
 	{
 		.name = "MRG BT",
@@ -749,7 +749,7 @@ static struct snd_soc_dai_driver mt2701_afe_pcm_dais[] = {
 			.formats = SNDRV_PCM_FMTBIT_S16_LE,
 		},
 		.ops = &mt2701_btmrg_ops,
-		.symmetric_rates = 1,
+		.symmetric_rate = 1,
 	}
 };
 
diff --git a/sound/soc/mediatek/mt6797/mt6797-dai-pcm.c b/sound/soc/mediatek/mt6797/mt6797-dai-pcm.c
index 3136f0bc7827..51f736f319e4 100644
--- a/sound/soc/mediatek/mt6797/mt6797-dai-pcm.c
+++ b/sound/soc/mediatek/mt6797/mt6797-dai-pcm.c
@@ -270,8 +270,8 @@ static struct snd_soc_dai_driver mtk_dai_pcm_driver[] = {
 			.formats = MTK_PCM_FORMATS,
 		},
 		.ops = &mtk_dai_pcm_ops,
-		.symmetric_rates = 1,
-		.symmetric_samplebits = 1,
+		.symmetric_rate = 1,
+		.symmetric_sample_bits = 1,
 	},
 	{
 		.name = "PCM 2",
@@ -291,8 +291,8 @@ static struct snd_soc_dai_driver mtk_dai_pcm_driver[] = {
 			.formats = MTK_PCM_FORMATS,
 		},
 		.ops = &mtk_dai_pcm_ops,
-		.symmetric_rates = 1,
-		.symmetric_samplebits = 1,
+		.symmetric_rate = 1,
+		.symmetric_sample_bits = 1,
 	},
 };
 
diff --git a/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c b/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c
index 7e7bda70d12e..685f4074b4e0 100644
--- a/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c
+++ b/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c
@@ -571,7 +571,7 @@ static struct snd_soc_dai_driver mt8173_afe_pcm_dais[] = {
 			.formats = SNDRV_PCM_FMTBIT_S16_LE,
 		},
 		.ops = &mt8173_afe_i2s_ops,
-		.symmetric_rates = 1,
+		.symmetric_rate = 1,
 	},
 };
 
diff --git a/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c b/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c
index cfbd0c65c7a3..a4d26a6fc849 100644
--- a/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c
+++ b/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c
@@ -125,12 +125,6 @@ mt8183_da7219_rt1015_i2s_hw_params(struct snd_pcm_substream *substream,
 	for_each_rtd_codec_dais(rtd, i, codec_dai) {
 		if (!strcmp(codec_dai->component->name, RT1015_DEV0_NAME) ||
 		    !strcmp(codec_dai->component->name, RT1015_DEV1_NAME)) {
-			ret = snd_soc_dai_set_bclk_ratio(codec_dai, 64);
-			if (ret) {
-				dev_err(rtd->dev, "failed to set bclk ratio\n");
-				return ret;
-			}
-
 			ret = snd_soc_dai_set_pll(codec_dai, 0,
 						  RT1015_PLL_S_BCLK,
 						  rate * 64, rate * 256);
diff --git a/sound/soc/mediatek/mt8183/mt8183-dai-pcm.c b/sound/soc/mediatek/mt8183/mt8183-dai-pcm.c
index bc3ba3228f08..38ce0e36cdb4 100644
--- a/sound/soc/mediatek/mt8183/mt8183-dai-pcm.c
+++ b/sound/soc/mediatek/mt8183/mt8183-dai-pcm.c
@@ -270,8 +270,8 @@ static struct snd_soc_dai_driver mtk_dai_pcm_driver[] = {
 			.formats = MTK_PCM_FORMATS,
 		},
 		.ops = &mtk_dai_pcm_ops,
-		.symmetric_rates = 1,
-		.symmetric_samplebits = 1,
+		.symmetric_rate = 1,
+		.symmetric_sample_bits = 1,
 	},
 	{
 		.name = "PCM 2",
@@ -291,8 +291,8 @@ static struct snd_soc_dai_driver mtk_dai_pcm_driver[] = {
 			.formats = MTK_PCM_FORMATS,
 		},
 		.ops = &mtk_dai_pcm_ops,
-		.symmetric_rates = 1,
-		.symmetric_samplebits = 1,
+		.symmetric_rate = 1,
+		.symmetric_sample_bits = 1,
 	},
 };
 
diff --git a/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c b/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c
index 1ce3eddbee13..271413e719e3 100644
--- a/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c
+++ b/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c
@@ -68,12 +68,6 @@ mt8183_mt6358_rt1015_i2s_hw_params(struct snd_pcm_substream *substream,
 	int ret, i;
 
 	for_each_rtd_codec_dais(rtd, i, codec_dai) {
-		ret = snd_soc_dai_set_bclk_ratio(codec_dai, 64);
-		if (ret < 0) {
-			dev_err(card->dev, "failed to set bclk ratio\n");
-			return ret;
-		}
-
 		ret = snd_soc_dai_set_pll(codec_dai, 0, RT1015_PLL_S_BCLK,
 				rate * 64, rate * 256);
 		if (ret < 0) {
@@ -124,6 +118,45 @@ static int mt8183_rt1015_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
 }
 
 static int
+mt8183_mt6358_startup(struct snd_pcm_substream *substream)
+{
+	static const unsigned int rates[] = {
+		48000,
+	};
+	static const struct snd_pcm_hw_constraint_list constraints_rates = {
+		.count = ARRAY_SIZE(rates),
+		.list  = rates,
+		.mask = 0,
+	};
+	static const unsigned int channels[] = {
+		2,
+	};
+	static const struct snd_pcm_hw_constraint_list constraints_channels = {
+		.count = ARRAY_SIZE(channels),
+		.list = channels,
+		.mask = 0,
+	};
+
+	struct snd_pcm_runtime *runtime = substream->runtime;
+
+	snd_pcm_hw_constraint_list(runtime, 0,
+				   SNDRV_PCM_HW_PARAM_RATE, &constraints_rates);
+	runtime->hw.channels_max = 2;
+	snd_pcm_hw_constraint_list(runtime, 0,
+				   SNDRV_PCM_HW_PARAM_CHANNELS,
+				   &constraints_channels);
+
+	runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;
+	snd_pcm_hw_constraint_msbits(runtime, 0, 16, 16);
+
+	return 0;
+}
+
+static const struct snd_soc_ops mt8183_mt6358_ops = {
+	.startup = mt8183_mt6358_startup,
+};
+
+static int
 mt8183_mt6358_ts3a227_max98357_bt_sco_startup(
 	struct snd_pcm_substream *substream)
 {
@@ -362,6 +395,7 @@ static struct snd_soc_dai_link mt8183_mt6358_ts3a227_dai_links[] = {
 			    SND_SOC_DPCM_TRIGGER_PRE},
 		.dynamic = 1,
 		.dpcm_playback = 1,
+		.ops = &mt8183_mt6358_ops,
 		SND_SOC_DAILINK_REG(playback1),
 	},
 	{
@@ -409,6 +443,7 @@ static struct snd_soc_dai_link mt8183_mt6358_ts3a227_dai_links[] = {
 			    SND_SOC_DPCM_TRIGGER_PRE},
 		.dynamic = 1,
 		.dpcm_capture = 1,
+		.ops = &mt8183_mt6358_ops,
 		SND_SOC_DAILINK_REG(capture3),
 	},
 	{
diff --git a/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c b/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c
index e7fec2d75e3d..7a1724f5ff4c 100644
--- a/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c
+++ b/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c
@@ -42,7 +42,7 @@ static const struct snd_pcm_hardware mt8192_afe_hardware = {
 static int mt8192_memif_fs(struct snd_pcm_substream *substream,
 			   unsigned int rate)
 {
-	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
 	struct snd_soc_component *component =
 		snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME);
 	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
@@ -59,7 +59,7 @@ static int mt8192_get_dai_fs(struct mtk_base_afe *afe,
 
 static int mt8192_irq_fs(struct snd_pcm_substream *substream, unsigned int rate)
 {
-	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
 	struct snd_soc_component *component =
 		snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME);
 	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
diff --git a/sound/soc/mediatek/mt8192/mt8192-dai-pcm.c b/sound/soc/mediatek/mt8192/mt8192-dai-pcm.c
index 6e94cfdf06fc..239e3f5b53d3 100644
--- a/sound/soc/mediatek/mt8192/mt8192-dai-pcm.c
+++ b/sound/soc/mediatek/mt8192/mt8192-dai-pcm.c
@@ -360,8 +360,8 @@ static struct snd_soc_dai_driver mtk_dai_pcm_driver[] = {
 			.formats = MTK_PCM_FORMATS,
 		},
 		.ops = &mtk_dai_pcm_ops,
-		.symmetric_rates = 1,
-		.symmetric_samplebits = 1,
+		.symmetric_rate = 1,
+		.symmetric_sample_bits = 1,
 	},
 	{
 		.name = "PCM 2",
@@ -381,8 +381,8 @@ static struct snd_soc_dai_driver mtk_dai_pcm_driver[] = {
 			.formats = MTK_PCM_FORMATS,
 		},
 		.ops = &mtk_dai_pcm_ops,
-		.symmetric_rates = 1,
-		.symmetric_samplebits = 1,
+		.symmetric_rate = 1,
+		.symmetric_sample_bits = 1,
 	},
 };
 
diff --git a/sound/soc/mediatek/mt8192/mt8192-dai-tdm.c b/sound/soc/mediatek/mt8192/mt8192-dai-tdm.c
index 8383536b7ae0..f5de1d769679 100644
--- a/sound/soc/mediatek/mt8192/mt8192-dai-tdm.c
+++ b/sound/soc/mediatek/mt8192/mt8192-dai-tdm.c
@@ -738,7 +738,7 @@ static struct mtk_afe_tdm_priv *init_tdm_priv_data(struct mtk_base_afe *afe)
 	if (!tdm_priv)
 		return NULL;
 
-	tdm_priv->mclk_multiple = 128;
+	tdm_priv->mclk_multiple = 512;
 	tdm_priv->bck_id = MT8192_I2S4_BCK;
 	tdm_priv->mclk_id = MT8192_I2S4_MCK;
 	tdm_priv->id = MT8192_DAI_TDM;
diff --git a/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c b/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c
index ae2c748eb19c..a606133951b7 100644
--- a/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c
+++ b/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c
@@ -31,12 +31,15 @@
 #define RT5682_CODEC_DAI	"rt5682-aif1"
 #define RT5682_DEV0_NAME	"rt5682.1-001a"
 
-static struct snd_soc_jack headset_jack;
+struct mt8192_mt6359_priv {
+	struct snd_soc_jack headset_jack;
+	struct snd_soc_jack hdmi_jack;
+};
 
 static int mt8192_rt1015_i2s_hw_params(struct snd_pcm_substream *substream,
 				       struct snd_pcm_hw_params *params)
 {
-	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
 	struct snd_soc_card *card = rtd->card;
 	struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
 	struct snd_soc_dai *codec_dai;
@@ -46,12 +49,6 @@ static int mt8192_rt1015_i2s_hw_params(struct snd_pcm_substream *substream,
 	int ret, i;
 
 	for_each_rtd_codec_dais(rtd, i, codec_dai) {
-		ret = snd_soc_dai_set_bclk_ratio(codec_dai, 64);
-		if (ret) {
-			dev_err(card->dev, "failed to set bclk ratio\n");
-			return ret;
-		}
-
 		ret = snd_soc_dai_set_pll(codec_dai, 0,
 					  RT1015_PLL_S_BCLK,
 					  params_rate(params) * 64,
@@ -77,7 +74,7 @@ static int mt8192_rt1015_i2s_hw_params(struct snd_pcm_substream *substream,
 static int mt8192_rt5682_i2s_hw_params(struct snd_pcm_substream *substream,
 				       struct snd_pcm_hw_params *params)
 {
-	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
 	struct snd_soc_card *card = rtd->card;
 	struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
 	struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
@@ -311,7 +308,8 @@ static int mt8192_rt5682_init(struct snd_soc_pcm_runtime *rtd)
 {
 	struct snd_soc_component *cmpnt_codec =
 		asoc_rtd_to_codec(rtd, 0)->component;
-	struct snd_soc_jack *jack = &headset_jack;
+	struct mt8192_mt6359_priv *priv = snd_soc_card_get_drvdata(rtd->card);
+	struct snd_soc_jack *jack = &priv->headset_jack;
 	int ret;
 
 	ret = snd_soc_card_jack_new(rtd->card, "Headset Jack",
@@ -329,14 +327,25 @@ static int mt8192_rt5682_init(struct snd_soc_pcm_runtime *rtd)
 	snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
 	snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
 
-	ret = snd_soc_component_set_jack(cmpnt_codec, jack, NULL);
+	return snd_soc_component_set_jack(cmpnt_codec, jack, NULL);
+};
+
+static int mt8192_mt6359_hdmi_init(struct snd_soc_pcm_runtime *rtd)
+{
+	struct snd_soc_component *cmpnt_codec =
+		asoc_rtd_to_codec(rtd, 0)->component;
+	struct mt8192_mt6359_priv *priv = snd_soc_card_get_drvdata(rtd->card);
+	int ret;
+
+	ret = snd_soc_card_jack_new(rtd->card, "HDMI Jack", SND_JACK_LINEOUT,
+				    &priv->hdmi_jack, NULL, 0);
 	if (ret) {
-		dev_err(rtd->dev, "Headset Jack set failed: %d\n", ret);
+		dev_err(rtd->dev, "HDMI Jack creation failed: %d\n", ret);
 		return ret;
 	}
 
-	return 0;
-};
+	return snd_soc_component_set_jack(cmpnt_codec, &priv->hdmi_jack, NULL);
+}
 
 static int mt8192_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
 				      struct snd_pcm_hw_params *params)
@@ -351,14 +360,8 @@ static int mt8192_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
 }
 
 static int
-mt8192_mt6359_rt1015_rt5682_cap1_startup(struct snd_pcm_substream *substream)
+mt8192_mt6359_cap1_startup(struct snd_pcm_substream *substream)
 {
-	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-	struct snd_soc_component *component =
-		snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME);
-	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
-	int ret;
-
 	static const unsigned int channels[] = {
 		1, 2, 4
 	};
@@ -376,13 +379,15 @@ mt8192_mt6359_rt1015_rt5682_cap1_startup(struct snd_pcm_substream *substream)
 		.mask = 0,
 	};
 
+	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
 	struct snd_pcm_runtime *runtime = substream->runtime;
+	int ret;
 
 	ret = snd_pcm_hw_constraint_list(runtime, 0,
 					 SNDRV_PCM_HW_PARAM_CHANNELS,
 					 &constraints_channels);
 	if (ret < 0) {
-		dev_err(afe->dev, "hw_constraint_list channels failed\n");
+		dev_err(rtd->dev, "hw_constraint_list channels failed\n");
 		return ret;
 	}
 
@@ -390,15 +395,15 @@ mt8192_mt6359_rt1015_rt5682_cap1_startup(struct snd_pcm_substream *substream)
 					 SNDRV_PCM_HW_PARAM_RATE,
 					 &constraints_rates);
 	if (ret < 0) {
-		dev_err(afe->dev, "hw_constraint_list rate failed\n");
+		dev_err(rtd->dev, "hw_constraint_list rate failed\n");
 		return ret;
 	}
 
 	return 0;
 }
 
-static const struct snd_soc_ops mt8192_mt6359_rt1015_rt5682_capture1_ops = {
-	.startup = mt8192_mt6359_rt1015_rt5682_cap1_startup,
+static const struct snd_soc_ops mt8192_mt6359_capture1_ops = {
+	.startup = mt8192_mt6359_cap1_startup,
 };
 
 static int
@@ -656,7 +661,7 @@ SND_SOC_DAILINK_DEFS(pcm2,
 
 SND_SOC_DAILINK_DEFS(tdm,
 		     DAILINK_COMP_ARRAY(COMP_CPU("TDM")),
-		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
+		     DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "i2s-hifi")),
 		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
 
 static struct snd_soc_dai_link mt8192_mt6359_dai_links[] = {
@@ -759,7 +764,7 @@ static struct snd_soc_dai_link mt8192_mt6359_dai_links[] = {
 			    SND_SOC_DPCM_TRIGGER_PRE},
 		.dynamic = 1,
 		.dpcm_capture = 1,
-		.ops = &mt8192_mt6359_rt1015_rt5682_capture1_ops,
+		.ops = &mt8192_mt6359_capture1_ops,
 		SND_SOC_DAILINK_REG(capture1),
 	},
 	{
@@ -994,8 +999,14 @@ static struct snd_soc_dai_link mt8192_mt6359_dai_links[] = {
 	{
 		.name = "TDM",
 		.no_pcm = 1,
+		.dai_fmt = SND_SOC_DAIFMT_DSP_A |
+			   SND_SOC_DAIFMT_IB_NF |
+			   SND_SOC_DAIFMT_CBM_CFM,
 		.dpcm_playback = 1,
 		.ignore_suspend = 1,
+		.be_hw_params_fixup = mt8192_i2s_hw_params_fixup,
+		.ignore = 1,
+		.init = mt8192_mt6359_hdmi_init,
 		SND_SOC_DAILINK_REG(tdm),
 	},
 };
@@ -1006,6 +1017,7 @@ mt8192_mt6359_rt1015_rt5682_widgets[] = {
 	SND_SOC_DAPM_SPK("Right Spk", NULL),
 	SND_SOC_DAPM_HP("Headphone Jack", NULL),
 	SND_SOC_DAPM_MIC("Headset Mic", NULL),
+	SND_SOC_DAPM_OUTPUT("TDM Out"),
 };
 
 static const struct snd_soc_dapm_route mt8192_mt6359_rt1015_rt5682_routes[] = {
@@ -1016,6 +1028,8 @@ static const struct snd_soc_dapm_route mt8192_mt6359_rt1015_rt5682_routes[] = {
 	{ "Headphone Jack", NULL, "HPOL" },
 	{ "Headphone Jack", NULL, "HPOR" },
 	{ "IN1P", NULL, "Headset Mic" },
+	/* TDM */
+	{ "TDM Out", NULL, "TDM" },
 };
 
 static const struct snd_kcontrol_new mt8192_mt6359_rt1015_rt5682_controls[] = {
@@ -1089,10 +1103,11 @@ static struct snd_soc_card mt8192_mt6359_rt1015p_rt5682_card = {
 static int mt8192_mt6359_dev_probe(struct platform_device *pdev)
 {
 	struct snd_soc_card *card;
-	struct device_node *platform_node;
+	struct device_node *platform_node, *hdmi_codec;
 	int ret, i;
 	struct snd_soc_dai_link *dai_link;
 	const struct of_device_id *match;
+	struct mt8192_mt6359_priv *priv;
 
 	platform_node = of_parse_phandle(pdev->dev.of_node,
 					 "mediatek,platform", 0);
@@ -1108,6 +1123,9 @@ static int mt8192_mt6359_dev_probe(struct platform_device *pdev)
 	card = (struct snd_soc_card *)match->data;
 	card->dev = &pdev->dev;
 
+	hdmi_codec = of_parse_phandle(pdev->dev.of_node,
+				      "mediatek,hdmi-codec", 0);
+
 	for_each_card_prelinks(card, i, dai_link) {
 		if (strcmp(dai_link->name, "I2S3") == 0) {
 			if (card == &mt8192_mt6359_rt1015_rt5682_card) {
@@ -1134,10 +1152,20 @@ static int mt8192_mt6359_dev_probe(struct platform_device *pdev)
 			}
 		}
 
+		if (hdmi_codec && strcmp(dai_link->name, "TDM") == 0) {
+			dai_link->codecs->of_node = hdmi_codec;
+			dai_link->ignore = 0;
+		}
+
 		if (!dai_link->platforms->name)
 			dai_link->platforms->of_node = platform_node;
 	}
 
+	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+	snd_soc_card_set_drvdata(card, priv);
+
 	ret = mt8192_afe_gpio_init(&pdev->dev);
 	if (ret) {
 		dev_err(&pdev->dev, "init gpio error %d\n", ret);
diff --git a/sound/soc/meson/aiu-fifo-i2s.c b/sound/soc/meson/aiu-fifo-i2s.c
index d91b0d874342..2388a2d0b3a6 100644
--- a/sound/soc/meson/aiu-fifo-i2s.c
+++ b/sound/soc/meson/aiu-fifo-i2s.c
@@ -124,7 +124,6 @@ const struct snd_soc_dai_ops aiu_fifo_i2s_dai_ops = {
 	.trigger	= aiu_fifo_i2s_trigger,
 	.prepare	= aiu_fifo_i2s_prepare,
 	.hw_params	= aiu_fifo_i2s_hw_params,
-	.hw_free	= aiu_fifo_hw_free,
 	.startup	= aiu_fifo_startup,
 	.shutdown	= aiu_fifo_shutdown,
 };
diff --git a/sound/soc/meson/aiu-fifo-spdif.c b/sound/soc/meson/aiu-fifo-spdif.c
index 44eb6faacf44..2fb30f89bf7a 100644
--- a/sound/soc/meson/aiu-fifo-spdif.c
+++ b/sound/soc/meson/aiu-fifo-spdif.c
@@ -158,7 +158,6 @@ const struct snd_soc_dai_ops aiu_fifo_spdif_dai_ops = {
 	.trigger	= fifo_spdif_trigger,
 	.prepare	= fifo_spdif_prepare,
 	.hw_params	= fifo_spdif_hw_params,
-	.hw_free	= aiu_fifo_hw_free,
 	.startup	= aiu_fifo_startup,
 	.shutdown	= aiu_fifo_shutdown,
 };
diff --git a/sound/soc/meson/aiu-fifo.c b/sound/soc/meson/aiu-fifo.c
index aa88aae8e517..4ad23267cace 100644
--- a/sound/soc/meson/aiu-fifo.c
+++ b/sound/soc/meson/aiu-fifo.c
@@ -99,11 +99,6 @@ int aiu_fifo_hw_params(struct snd_pcm_substream *substream,
 	struct snd_soc_component *component = dai->component;
 	struct aiu_fifo *fifo = dai->playback_dma_data;
 	dma_addr_t end;
-	int ret;
-
-	ret = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
-	if (ret < 0)
-		return ret;
 
 	/* Setup the fifo boundaries */
 	end = runtime->dma_addr + runtime->dma_bytes - fifo->fifo_block;
@@ -124,12 +119,6 @@ int aiu_fifo_hw_params(struct snd_pcm_substream *substream,
 	return 0;
 }
 
-int aiu_fifo_hw_free(struct snd_pcm_substream *substream,
-		     struct snd_soc_dai *dai)
-{
-	return snd_pcm_lib_free_pages(substream);
-}
-
 static irqreturn_t aiu_fifo_isr(int irq, void *dev_id)
 {
 	struct snd_pcm_substream *playback = dev_id;
@@ -187,15 +176,12 @@ void aiu_fifo_shutdown(struct snd_pcm_substream *substream,
 int aiu_fifo_pcm_new(struct snd_soc_pcm_runtime *rtd,
 		     struct snd_soc_dai *dai)
 {
-	struct snd_pcm_substream *substream =
-		rtd->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
 	struct snd_card *card = rtd->card->snd_card;
 	struct aiu_fifo *fifo = dai->playback_dma_data;
 	size_t size = fifo->pcm->buffer_bytes_max;
 
-	snd_pcm_lib_preallocate_pages(substream,
-				      SNDRV_DMA_TYPE_DEV,
-				      card->dev, size, size);
+	snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV,
+				       card->dev, size, size);
 
 	return 0;
 }
diff --git a/sound/soc/pxa/pxa2xx-i2s.c b/sound/soc/pxa/pxa2xx-i2s.c
index 5301859a8453..bcde4a96c168 100644
--- a/sound/soc/pxa/pxa2xx-i2s.c
+++ b/sound/soc/pxa/pxa2xx-i2s.c
@@ -353,7 +353,7 @@ static struct snd_soc_dai_driver pxa_i2s_dai = {
 		.rates = PXA2XX_I2S_RATES,
 		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
 	.ops = &pxa_i2s_dai_ops,
-	.symmetric_rates = 1,
+	.symmetric_rate = 1,
 };
 
 static const struct snd_soc_component_driver pxa_i2s_component = {
diff --git a/sound/soc/qcom/lpass-cpu.c b/sound/soc/qcom/lpass-cpu.c
index 8e5415c9234f..c642e5f8f28c 100644
--- a/sound/soc/qcom/lpass-cpu.c
+++ b/sound/soc/qcom/lpass-cpu.c
@@ -475,6 +475,7 @@ static bool lpass_cpu_regmap_volatile(struct device *dev, unsigned int reg)
 }
 
 static struct regmap_config lpass_cpu_regmap_config = {
+	.name = "lpass_cpu",
 	.reg_bits = 32,
 	.reg_stride = 4,
 	.val_bits = 32,
@@ -675,6 +676,7 @@ static bool lpass_hdmi_regmap_volatile(struct device *dev, unsigned int reg)
 }
 
 static struct regmap_config lpass_hdmi_regmap_config = {
+	.name = "lpass_hdmi",
 	.reg_bits = 32,
 	.reg_stride = 4,
 	.val_bits = 32,
@@ -743,7 +745,6 @@ static void of_lpass_cpu_parse_dai_data(struct device *dev,
 		}
 		if (id == LPASS_DP_RX) {
 			data->hdmi_port_enable = 1;
-			dev_err(dev, "HDMI Port is enabled: %d\n", id);
 		} else {
 			data->mi2s_playback_sd_mode[id] =
 				of_lpass_cpu_parse_sd_lines(dev, node,
@@ -788,11 +789,8 @@ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev)
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "lpass-lpaif");
 
 	drvdata->lpaif = devm_ioremap_resource(dev, res);
-	if (IS_ERR((void const __force *)drvdata->lpaif)) {
-		dev_err(dev, "error mapping reg resource: %ld\n",
-				PTR_ERR((void const __force *)drvdata->lpaif));
-		return PTR_ERR((void const __force *)drvdata->lpaif);
-	}
+	if (IS_ERR(drvdata->lpaif))
+		return PTR_ERR(drvdata->lpaif);
 
 	lpass_cpu_regmap_config.max_register = LPAIF_WRDMAPER_REG(variant,
 						variant->wrdma_channels +
@@ -810,11 +808,8 @@ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev)
 		res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "lpass-hdmiif");
 
 		drvdata->hdmiif = devm_ioremap_resource(dev, res);
-		if (IS_ERR((void const __force *)drvdata->hdmiif)) {
-			dev_err(dev, "error mapping reg resource: %ld\n",
-					PTR_ERR((void const __force *)drvdata->hdmiif));
-			return PTR_ERR((void const __force *)drvdata->hdmiif);
-		}
+		if (IS_ERR(drvdata->hdmiif))
+			return PTR_ERR(drvdata->hdmiif);
 
 		lpass_hdmi_regmap_config.max_register = LPAIF_HDMI_RDMAPER_REG(variant,
 					variant->hdmi_rdma_channels - 1);
diff --git a/sound/soc/qcom/qdsp6/q6asm-dai.c b/sound/soc/qcom/qdsp6/q6asm-dai.c
index c9ac9c1d26c4..9766725c2916 100644
--- a/sound/soc/qcom/qdsp6/q6asm-dai.c
+++ b/sound/soc/qcom/qdsp6/q6asm-dai.c
@@ -1233,6 +1233,25 @@ static void q6asm_dai_pcm_free(struct snd_soc_component *component,
 	}
 }
 
+static const struct snd_soc_dapm_widget q6asm_dapm_widgets[] = {
+	SND_SOC_DAPM_AIF_IN("MM_DL1", "MultiMedia1 Playback", 0, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_AIF_IN("MM_DL2", "MultiMedia2 Playback", 0, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_AIF_IN("MM_DL3", "MultiMedia3 Playback", 0, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_AIF_IN("MM_DL4", "MultiMedia4 Playback", 0, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_AIF_IN("MM_DL5", "MultiMedia5 Playback", 0, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_AIF_IN("MM_DL6", "MultiMedia6 Playback", 0, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_AIF_IN("MM_DL7", "MultiMedia7 Playback", 0, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_AIF_IN("MM_DL8", "MultiMedia8 Playback", 0, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_AIF_OUT("MM_UL1", "MultiMedia1 Capture", 0, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_AIF_OUT("MM_UL2", "MultiMedia2 Capture", 0, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_AIF_OUT("MM_UL3", "MultiMedia3 Capture", 0, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_AIF_OUT("MM_UL4", "MultiMedia4 Capture", 0, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_AIF_OUT("MM_UL5", "MultiMedia5 Capture", 0, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_AIF_OUT("MM_UL6", "MultiMedia6 Capture", 0, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_AIF_OUT("MM_UL7", "MultiMedia7 Capture", 0, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_AIF_OUT("MM_UL8", "MultiMedia8 Capture", 0, SND_SOC_NOPM, 0, 0),
+};
+
 static const struct snd_soc_component_driver q6asm_fe_dai_component = {
 	.name		= DRV_NAME,
 	.open		= q6asm_dai_open,
@@ -1245,6 +1264,8 @@ static const struct snd_soc_component_driver q6asm_fe_dai_component = {
 	.pcm_construct	= q6asm_dai_pcm_new,
 	.pcm_destruct	= q6asm_dai_pcm_free,
 	.compress_ops	= &q6asm_dai_compress_ops,
+	.dapm_widgets	= q6asm_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(q6asm_dapm_widgets),
 };
 
 static struct snd_soc_dai_driver q6asm_fe_dais_template[] = {
diff --git a/sound/soc/qcom/qdsp6/q6asm.c b/sound/soc/qcom/qdsp6/q6asm.c
index a6618efe22f2..36bf8bd4edd7 100644
--- a/sound/soc/qcom/qdsp6/q6asm.c
+++ b/sound/soc/qcom/qdsp6/q6asm.c
@@ -491,7 +491,7 @@ static int __q6asm_memory_map_regions(struct audio_client *ac, int dir,
  *
  * @dir: direction of audio stream
  * @ac: audio client instanace
- * @phys: physcial address that needs mapping.
+ * @phys: physical address that needs mapping.
  * @period_sz: audio period size
  * @periods: number of periods
  *
diff --git a/sound/soc/qcom/qdsp6/q6routing.c b/sound/soc/qcom/qdsp6/q6routing.c
index 53185e26fea1..0a6b9433f6ac 100644
--- a/sound/soc/qcom/qdsp6/q6routing.c
+++ b/sound/soc/qcom/qdsp6/q6routing.c
@@ -713,24 +713,6 @@ static const struct snd_kcontrol_new mmul8_mixer_controls[] = {
 	Q6ROUTING_TX_MIXERS(MSM_FRONTEND_DAI_MULTIMEDIA8) };
 
 static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = {
-	/* Frontend AIF */
-	SND_SOC_DAPM_AIF_IN("MM_DL1", "MultiMedia1 Playback", 0, 0, 0, 0),
-	SND_SOC_DAPM_AIF_IN("MM_DL2", "MultiMedia2 Playback", 0, 0, 0, 0),
-	SND_SOC_DAPM_AIF_IN("MM_DL3", "MultiMedia3 Playback", 0, 0, 0, 0),
-	SND_SOC_DAPM_AIF_IN("MM_DL4", "MultiMedia4 Playback", 0, 0, 0, 0),
-	SND_SOC_DAPM_AIF_IN("MM_DL5", "MultiMedia5 Playback", 0, 0, 0, 0),
-	SND_SOC_DAPM_AIF_IN("MM_DL6", "MultiMedia6 Playback", 0, 0, 0, 0),
-	SND_SOC_DAPM_AIF_IN("MM_DL7", "MultiMedia7 Playback", 0, 0, 0, 0),
-	SND_SOC_DAPM_AIF_IN("MM_DL8", "MultiMedia8 Playback", 0, 0, 0, 0),
-	SND_SOC_DAPM_AIF_OUT("MM_UL1", "MultiMedia1 Capture", 0, 0, 0, 0),
-	SND_SOC_DAPM_AIF_OUT("MM_UL2", "MultiMedia2 Capture", 0, 0, 0, 0),
-	SND_SOC_DAPM_AIF_OUT("MM_UL3", "MultiMedia3 Capture", 0, 0, 0, 0),
-	SND_SOC_DAPM_AIF_OUT("MM_UL4", "MultiMedia4 Capture", 0, 0, 0, 0),
-	SND_SOC_DAPM_AIF_OUT("MM_UL5", "MultiMedia5 Capture", 0, 0, 0, 0),
-	SND_SOC_DAPM_AIF_OUT("MM_UL6", "MultiMedia6 Capture", 0, 0, 0, 0),
-	SND_SOC_DAPM_AIF_OUT("MM_UL7", "MultiMedia7 Capture", 0, 0, 0, 0),
-	SND_SOC_DAPM_AIF_OUT("MM_UL8", "MultiMedia8 Capture", 0, 0, 0, 0),
-
 	/* Mixer definitions */
 	SND_SOC_DAPM_MIXER("HDMI Mixer", SND_SOC_NOPM, 0, 0,
 			   hdmi_mixer_controls,
diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c
index eae287d905eb..0740764e7f71 100644
--- a/sound/soc/rockchip/rockchip_i2s.c
+++ b/sound/soc/rockchip/rockchip_i2s.c
@@ -373,7 +373,7 @@ static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream,
 			   I2S_DMACR_RDL(16));
 
 	val = I2S_CKR_TRCM_TXRX;
-	if (dai->driver->symmetric_rates && rtd->dai_link->symmetric_rates)
+	if (dai->driver->symmetric_rate && rtd->dai_link->symmetric_rate)
 		val = I2S_CKR_TRCM_TXONLY;
 
 	regmap_update_bits(i2s->regmap, I2S_CKR,
@@ -471,7 +471,7 @@ static struct snd_soc_dai_driver rockchip_i2s_dai = {
 			    SNDRV_PCM_FMTBIT_S32_LE),
 	},
 	.ops = &rockchip_i2s_dai_ops,
-	.symmetric_rates = 1,
+	.symmetric_rate = 1,
 };
 
 static const struct snd_soc_component_driver rockchip_i2s_component = {
diff --git a/sound/soc/rockchip/rockchip_pdm.c b/sound/soc/rockchip/rockchip_pdm.c
index e5f732747f71..9295d648624e 100644
--- a/sound/soc/rockchip/rockchip_pdm.c
+++ b/sound/soc/rockchip/rockchip_pdm.c
@@ -338,7 +338,7 @@ static struct snd_soc_dai_driver rockchip_pdm_dai = {
 		.formats = ROCKCHIP_PDM_FORMATS,
 	},
 	.ops = &rockchip_pdm_dai_ops,
-	.symmetric_rates = 1,
+	.symmetric_rate = 1,
 };
 
 static const struct snd_soc_component_driver rockchip_pdm_component = {
diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c
index 4bdc268fd981..b043183174b2 100644
--- a/sound/soc/samsung/i2s.c
+++ b/sound/soc/samsung/i2s.c
@@ -1175,7 +1175,7 @@ static int i2s_alloc_dais(struct samsung_i2s_priv *priv,
 		dai_drv->probe = samsung_i2s_dai_probe;
 		dai_drv->remove = samsung_i2s_dai_remove;
 
-		dai_drv->symmetric_rates = 1;
+		dai_drv->symmetric_rate = 1;
 		dai_drv->ops = &samsung_i2s_dai_ops;
 
 		dai_drv->playback.channels_min = 1;
diff --git a/sound/soc/samsung/pcm.c b/sound/soc/samsung/pcm.c
index 6f50c7b47326..bfd76e9cc0ca 100644
--- a/sound/soc/samsung/pcm.c
+++ b/sound/soc/samsung/pcm.c
@@ -452,7 +452,7 @@ static int s3c_pcm_dai_probe(struct snd_soc_dai *dai)
 #define S3C_PCM_RATES  SNDRV_PCM_RATE_8000_96000
 
 #define S3C_PCM_DAI_DECLARE			\
-	.symmetric_rates = 1,					\
+	.symmetric_rate = 1,					\
 	.probe = s3c_pcm_dai_probe,				\
 	.ops = &s3c_pcm_dai_ops,				\
 	.playback = {						\
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c
index 6e670b3e92a0..c405bf3b4c99 100644
--- a/sound/soc/sh/rcar/core.c
+++ b/sound/soc/sh/rcar/core.c
@@ -1320,8 +1320,8 @@ static void __rsnd_dai_probe(struct rsnd_priv *priv,
 
 	if (rsnd_ssi_is_pin_sharing(io_capture) ||
 	    rsnd_ssi_is_pin_sharing(io_playback)) {
-		/* should have symmetric_rates if pin sharing */
-		drv->symmetric_rates = 1;
+		/* should have symmetric_rate if pin sharing */
+		drv->symmetric_rate = 1;
 	}
 
 	dev_dbg(dev, "%s (%s/%s)\n", rdai->name,
diff --git a/sound/soc/sirf/Kconfig b/sound/soc/sirf/Kconfig
deleted file mode 100644
index 094a1c89c59d..000000000000
--- a/sound/soc/sirf/Kconfig
+++ /dev/null
@@ -1,21 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-config SND_SOC_SIRF
-	tristate "SoC Audio for the SiRF SoC chips"
-	depends on ARCH_SIRF || COMPILE_TEST
-	select SND_SOC_GENERIC_DMAENGINE_PCM
-
-config SND_SOC_SIRF_AUDIO
-	tristate "SoC Audio support for SiRF internal audio codec"
-	depends on SND_SOC_SIRF
-	select SND_SOC_SIRF_AUDIO_CODEC
-	select SND_SOC_SIRF_AUDIO_PORT
-
-config SND_SOC_SIRF_AUDIO_PORT
-	select REGMAP_MMIO
-	tristate
-
-config SND_SOC_SIRF_USP
-	tristate "SoC Audio (I2S protocol) for SiRF SoC USP interface"
-	depends on SND_SOC_SIRF
-	select REGMAP_MMIO
-	tristate
diff --git a/sound/soc/sirf/Makefile b/sound/soc/sirf/Makefile
deleted file mode 100644
index 16ed11965ff9..000000000000
--- a/sound/soc/sirf/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-snd-soc-sirf-audio-objs := sirf-audio.o
-snd-soc-sirf-audio-port-objs := sirf-audio-port.o
-snd-soc-sirf-usp-objs := sirf-usp.o
-
-obj-$(CONFIG_SND_SOC_SIRF_AUDIO) += snd-soc-sirf-audio.o
-obj-$(CONFIG_SND_SOC_SIRF_AUDIO_PORT) += snd-soc-sirf-audio-port.o
-obj-$(CONFIG_SND_SOC_SIRF_USP) += snd-soc-sirf-usp.o
diff --git a/sound/soc/sirf/sirf-audio-port.c b/sound/soc/sirf/sirf-audio-port.c
deleted file mode 100644
index 8be2f0bc477b..000000000000
--- a/sound/soc/sirf/sirf-audio-port.c
+++ /dev/null
@@ -1,86 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * SiRF Audio port driver
- *
- * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
- */
-#include <linux/module.h>
-#include <sound/soc.h>
-#include <sound/dmaengine_pcm.h>
-
-struct sirf_audio_port {
-	struct regmap *regmap;
-	struct snd_dmaengine_dai_dma_data playback_dma_data;
-	struct snd_dmaengine_dai_dma_data capture_dma_data;
-};
-
-
-static int sirf_audio_port_dai_probe(struct snd_soc_dai *dai)
-{
-	struct sirf_audio_port *port = snd_soc_dai_get_drvdata(dai);
-
-	snd_soc_dai_init_dma_data(dai, &port->playback_dma_data,
-			&port->capture_dma_data);
-	return 0;
-}
-
-static struct snd_soc_dai_driver sirf_audio_port_dai = {
-	.probe = sirf_audio_port_dai_probe,
-	.name = "sirf-audio-port",
-	.id = 0,
-	.playback = {
-		.channels_min = 2,
-		.channels_max = 2,
-		.rates = SNDRV_PCM_RATE_48000,
-		.formats = SNDRV_PCM_FMTBIT_S16_LE,
-	},
-	.capture = {
-		.channels_min = 1,
-		.channels_max = 2,
-		.rates = SNDRV_PCM_RATE_48000,
-		.formats = SNDRV_PCM_FMTBIT_S16_LE,
-	},
-};
-
-static const struct snd_soc_component_driver sirf_audio_port_component = {
-	.name       = "sirf-audio-port",
-};
-
-static int sirf_audio_port_probe(struct platform_device *pdev)
-{
-	int ret;
-	struct sirf_audio_port *port;
-
-	port = devm_kzalloc(&pdev->dev,
-			sizeof(struct sirf_audio_port), GFP_KERNEL);
-	if (!port)
-		return -ENOMEM;
-
-	ret = devm_snd_soc_register_component(&pdev->dev,
-			&sirf_audio_port_component, &sirf_audio_port_dai, 1);
-	if (ret)
-		return ret;
-
-	platform_set_drvdata(pdev, port);
-	return devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
-}
-
-static const struct of_device_id sirf_audio_port_of_match[] = {
-	{ .compatible = "sirf,audio-port", },
-	{}
-};
-MODULE_DEVICE_TABLE(of, sirf_audio_port_of_match);
-
-static struct platform_driver sirf_audio_port_driver = {
-	.driver = {
-		.name = "sirf-audio-port",
-		.of_match_table = sirf_audio_port_of_match,
-	},
-	.probe = sirf_audio_port_probe,
-};
-
-module_platform_driver(sirf_audio_port_driver);
-
-MODULE_DESCRIPTION("SiRF Audio Port driver");
-MODULE_AUTHOR("RongJun Ying <Rongjun.Ying@csr.com>");
-MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/sirf/sirf-audio.c b/sound/soc/sirf/sirf-audio.c
deleted file mode 100644
index c923b6772b22..000000000000
--- a/sound/soc/sirf/sirf-audio.c
+++ /dev/null
@@ -1,160 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * SiRF audio card driver
- *
- * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
- */
-
-#include <linux/platform_device.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/gpio.h>
-#include <linux/of_gpio.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/soc.h>
-
-struct sirf_audio_card {
-	unsigned int            gpio_hp_pa;
-	unsigned int            gpio_spk_pa;
-};
-
-static int sirf_audio_hp_event(struct snd_soc_dapm_widget *w,
-				struct snd_kcontrol *ctrl, int event)
-{
-	struct snd_soc_dapm_context *dapm = w->dapm;
-	struct snd_soc_card *card = dapm->card;
-	struct sirf_audio_card *sirf_audio_card = snd_soc_card_get_drvdata(card);
-	int on = !SND_SOC_DAPM_EVENT_OFF(event);
-
-	if (gpio_is_valid(sirf_audio_card->gpio_hp_pa))
-		gpio_set_value(sirf_audio_card->gpio_hp_pa, on);
-	return 0;
-}
-
-static int sirf_audio_spk_event(struct snd_soc_dapm_widget *w,
-				struct snd_kcontrol *ctrl, int event)
-{
-	struct snd_soc_dapm_context *dapm = w->dapm;
-	struct snd_soc_card *card = dapm->card;
-	struct sirf_audio_card *sirf_audio_card = snd_soc_card_get_drvdata(card);
-	int on = !SND_SOC_DAPM_EVENT_OFF(event);
-
-	if (gpio_is_valid(sirf_audio_card->gpio_spk_pa))
-		gpio_set_value(sirf_audio_card->gpio_spk_pa, on);
-
-	return 0;
-}
-static const struct snd_soc_dapm_widget sirf_audio_dapm_widgets[] = {
-	SND_SOC_DAPM_HP("Hp", sirf_audio_hp_event),
-	SND_SOC_DAPM_SPK("Ext Spk", sirf_audio_spk_event),
-	SND_SOC_DAPM_MIC("Ext Mic", NULL),
-};
-
-static const struct snd_soc_dapm_route intercon[] = {
-	{"Hp", NULL, "HPOUTL"},
-	{"Hp", NULL, "HPOUTR"},
-	{"Ext Spk", NULL, "SPKOUT"},
-	{"MICIN1", NULL, "Mic Bias"},
-	{"Mic Bias", NULL, "Ext Mic"},
-};
-
-/* Digital audio interface glue - connects codec <--> CPU */
-SND_SOC_DAILINK_DEFS(sirf,
-	DAILINK_COMP_ARRAY(COMP_EMPTY()),
-	DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "sirf-audio-codec")),
-	DAILINK_COMP_ARRAY(COMP_EMPTY()));
-
-static struct snd_soc_dai_link sirf_audio_dai_link[] = {
-	{
-		.name = "SiRF audio card",
-		.stream_name = "SiRF audio HiFi",
-		SND_SOC_DAILINK_REG(sirf),
-	},
-};
-
-/* Audio machine driver */
-static struct snd_soc_card snd_soc_sirf_audio_card = {
-	.name = "SiRF audio card",
-	.owner = THIS_MODULE,
-	.dai_link = sirf_audio_dai_link,
-	.num_links = ARRAY_SIZE(sirf_audio_dai_link),
-	.dapm_widgets = sirf_audio_dapm_widgets,
-	.num_dapm_widgets = ARRAY_SIZE(sirf_audio_dapm_widgets),
-	.dapm_routes = intercon,
-	.num_dapm_routes = ARRAY_SIZE(intercon),
-};
-
-static int sirf_audio_probe(struct platform_device *pdev)
-{
-	struct snd_soc_card *card = &snd_soc_sirf_audio_card;
-	struct sirf_audio_card *sirf_audio_card;
-	int ret;
-
-	sirf_audio_card = devm_kzalloc(&pdev->dev, sizeof(struct sirf_audio_card),
-			GFP_KERNEL);
-	if (sirf_audio_card == NULL)
-		return -ENOMEM;
-
-	sirf_audio_dai_link[0].cpus->of_node =
-		of_parse_phandle(pdev->dev.of_node, "sirf,audio-platform", 0);
-	sirf_audio_dai_link[0].platforms->of_node =
-		of_parse_phandle(pdev->dev.of_node, "sirf,audio-platform", 0);
-	sirf_audio_dai_link[0].codecs->of_node =
-		of_parse_phandle(pdev->dev.of_node, "sirf,audio-codec", 0);
-	sirf_audio_card->gpio_spk_pa = of_get_named_gpio(pdev->dev.of_node,
-			"spk-pa-gpios", 0);
-	sirf_audio_card->gpio_hp_pa =  of_get_named_gpio(pdev->dev.of_node,
-			"hp-pa-gpios", 0);
-	if (gpio_is_valid(sirf_audio_card->gpio_spk_pa)) {
-		ret = devm_gpio_request_one(&pdev->dev,
-				sirf_audio_card->gpio_spk_pa,
-				GPIOF_OUT_INIT_LOW, "SPA_PA_SD");
-		if (ret) {
-			dev_err(&pdev->dev,
-				"Failed to request GPIO_%d for reset: %d\n",
-				sirf_audio_card->gpio_spk_pa, ret);
-			return ret;
-		}
-	}
-	if (gpio_is_valid(sirf_audio_card->gpio_hp_pa)) {
-		ret = devm_gpio_request_one(&pdev->dev,
-				sirf_audio_card->gpio_hp_pa,
-				GPIOF_OUT_INIT_LOW, "HP_PA_SD");
-		if (ret) {
-			dev_err(&pdev->dev,
-				"Failed to request GPIO_%d for reset: %d\n",
-				sirf_audio_card->gpio_hp_pa, ret);
-			return ret;
-		}
-	}
-
-	card->dev = &pdev->dev;
-	snd_soc_card_set_drvdata(card, sirf_audio_card);
-
-	ret = devm_snd_soc_register_card(&pdev->dev, card);
-	if (ret)
-		dev_err(&pdev->dev, "snd_soc_register_card() failed:%d\n", ret);
-
-	return ret;
-}
-
-static const struct of_device_id sirf_audio_of_match[] = {
-	{.compatible = "sirf,sirf-audio-card", },
-	{ },
-};
-MODULE_DEVICE_TABLE(of, sirf_audio_of_match);
-
-static struct platform_driver sirf_audio_driver = {
-	.driver = {
-		.name = "sirf-audio-card",
-		.pm = &snd_soc_pm_ops,
-		.of_match_table = sirf_audio_of_match,
-	},
-	.probe = sirf_audio_probe,
-};
-module_platform_driver(sirf_audio_driver);
-
-MODULE_AUTHOR("RongJun Ying <RongJun.Ying@csr.com>");
-MODULE_DESCRIPTION("ALSA SoC SIRF audio card driver");
-MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/sirf/sirf-usp.c b/sound/soc/sirf/sirf-usp.c
deleted file mode 100644
index 2af0c6f14ee6..000000000000
--- a/sound/soc/sirf/sirf-usp.c
+++ /dev/null
@@ -1,435 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * SiRF USP in I2S/DSP mode
- *
- * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
- */
-#include <linux/module.h>
-#include <linux/io.h>
-#include <linux/of.h>
-#include <linux/clk.h>
-#include <linux/pm_runtime.h>
-#include <sound/soc.h>
-#include <sound/pcm_params.h>
-#include <sound/dmaengine_pcm.h>
-
-#include "sirf-usp.h"
-
-struct sirf_usp {
-	struct regmap *regmap;
-	struct clk *clk;
-	u32 mode1_reg;
-	u32 mode2_reg;
-	int daifmt_format;
-	struct snd_dmaengine_dai_dma_data playback_dma_data;
-	struct snd_dmaengine_dai_dma_data capture_dma_data;
-};
-
-static void sirf_usp_tx_enable(struct sirf_usp *usp)
-{
-	regmap_update_bits(usp->regmap, USP_TX_FIFO_OP,
-		USP_TX_FIFO_RESET, USP_TX_FIFO_RESET);
-	regmap_write(usp->regmap, USP_TX_FIFO_OP, 0);
-
-	regmap_update_bits(usp->regmap, USP_TX_FIFO_OP,
-		USP_TX_FIFO_START, USP_TX_FIFO_START);
-
-	regmap_update_bits(usp->regmap, USP_TX_RX_ENABLE,
-		USP_TX_ENA, USP_TX_ENA);
-}
-
-static void sirf_usp_tx_disable(struct sirf_usp *usp)
-{
-	regmap_update_bits(usp->regmap, USP_TX_RX_ENABLE,
-		USP_TX_ENA, ~USP_TX_ENA);
-	/* FIFO stop */
-	regmap_write(usp->regmap, USP_TX_FIFO_OP, 0);
-}
-
-static void sirf_usp_rx_enable(struct sirf_usp *usp)
-{
-	regmap_update_bits(usp->regmap, USP_RX_FIFO_OP,
-		USP_RX_FIFO_RESET, USP_RX_FIFO_RESET);
-	regmap_write(usp->regmap, USP_RX_FIFO_OP, 0);
-
-	regmap_update_bits(usp->regmap, USP_RX_FIFO_OP,
-		USP_RX_FIFO_START, USP_RX_FIFO_START);
-
-	regmap_update_bits(usp->regmap, USP_TX_RX_ENABLE,
-		USP_RX_ENA, USP_RX_ENA);
-}
-
-static void sirf_usp_rx_disable(struct sirf_usp *usp)
-{
-	regmap_update_bits(usp->regmap, USP_TX_RX_ENABLE,
-		USP_RX_ENA, ~USP_RX_ENA);
-	/* FIFO stop */
-	regmap_write(usp->regmap, USP_RX_FIFO_OP, 0);
-}
-
-static int sirf_usp_pcm_dai_probe(struct snd_soc_dai *dai)
-{
-	struct sirf_usp *usp = snd_soc_dai_get_drvdata(dai);
-
-	snd_soc_dai_init_dma_data(dai, &usp->playback_dma_data,
-			&usp->capture_dma_data);
-	return 0;
-}
-
-static int sirf_usp_pcm_set_dai_fmt(struct snd_soc_dai *dai,
-		unsigned int fmt)
-{
-	struct sirf_usp *usp = snd_soc_dai_get_drvdata(dai);
-
-	/* set master/slave audio interface */
-	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
-	case SND_SOC_DAIFMT_CBM_CFM:
-		break;
-	default:
-		dev_err(dai->dev, "Only CBM and CFM supported\n");
-		return -EINVAL;
-	}
-
-	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
-	case SND_SOC_DAIFMT_I2S:
-	case SND_SOC_DAIFMT_DSP_A:
-		usp->daifmt_format = (fmt & SND_SOC_DAIFMT_FORMAT_MASK);
-		break;
-	default:
-		dev_err(dai->dev, "Only I2S and DSP_A format supported\n");
-		return -EINVAL;
-	}
-
-	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
-	case SND_SOC_DAIFMT_NB_NF:
-		break;
-	case SND_SOC_DAIFMT_IB_NF:
-		usp->daifmt_format |= (fmt & SND_SOC_DAIFMT_INV_MASK);
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static void sirf_usp_i2s_init(struct sirf_usp *usp)
-{
-	/* Configure RISC mode */
-	regmap_update_bits(usp->regmap, USP_RISC_DSP_MODE,
-		USP_RISC_DSP_SEL, ~USP_RISC_DSP_SEL);
-
-	/*
-	 * Configure DMA IO Length register
-	 * Set no limit, USP can receive data continuously until it is diabled
-	 */
-	regmap_write(usp->regmap, USP_TX_DMA_IO_LEN, 0);
-	regmap_write(usp->regmap, USP_RX_DMA_IO_LEN, 0);
-
-	/* Configure Mode2 register */
-	regmap_write(usp->regmap, USP_MODE2, (1 << USP_RXD_DELAY_LEN_OFFSET) |
-		(0 << USP_TXD_DELAY_LEN_OFFSET) |
-		USP_TFS_CLK_SLAVE_MODE | USP_RFS_CLK_SLAVE_MODE);
-
-	/* Configure Mode1 register */
-	regmap_write(usp->regmap, USP_MODE1,
-		USP_SYNC_MODE | USP_EN | USP_TXD_ACT_EDGE_FALLING |
-		USP_RFS_ACT_LEVEL_LOGIC1 | USP_TFS_ACT_LEVEL_LOGIC1 |
-		USP_TX_UFLOW_REPEAT_ZERO | USP_CLOCK_MODE_SLAVE);
-
-	/* Configure RX DMA IO Control register */
-	regmap_write(usp->regmap, USP_RX_DMA_IO_CTRL, 0);
-
-	/* Congiure RX FIFO Control register */
-	regmap_write(usp->regmap, USP_RX_FIFO_CTRL,
-		(USP_RX_FIFO_THRESHOLD << USP_RX_FIFO_THD_OFFSET) |
-		(USP_TX_RX_FIFO_WIDTH_DWORD << USP_RX_FIFO_WIDTH_OFFSET));
-
-	/* Congiure RX FIFO Level Check register */
-	regmap_write(usp->regmap, USP_RX_FIFO_LEVEL_CHK,
-		RX_FIFO_SC(0x04) | RX_FIFO_LC(0x0E) | RX_FIFO_HC(0x1B));
-
-	/* Configure TX DMA IO Control register*/
-	regmap_write(usp->regmap, USP_TX_DMA_IO_CTRL, 0);
-
-	/* Configure TX FIFO Control register */
-	regmap_write(usp->regmap, USP_TX_FIFO_CTRL,
-		(USP_TX_FIFO_THRESHOLD << USP_TX_FIFO_THD_OFFSET) |
-		(USP_TX_RX_FIFO_WIDTH_DWORD << USP_TX_FIFO_WIDTH_OFFSET));
-	/* Congiure TX FIFO Level Check register */
-	regmap_write(usp->regmap, USP_TX_FIFO_LEVEL_CHK,
-		TX_FIFO_SC(0x1B) | TX_FIFO_LC(0x0E) | TX_FIFO_HC(0x04));
-}
-
-static int sirf_usp_pcm_hw_params(struct snd_pcm_substream *substream,
-		struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
-{
-	struct sirf_usp *usp = snd_soc_dai_get_drvdata(dai);
-	u32 data_len, frame_len, shifter_len;
-
-	switch (params_format(params)) {
-	case SNDRV_PCM_FORMAT_S16_LE:
-		data_len = 16;
-		frame_len = 16;
-		break;
-	case SNDRV_PCM_FORMAT_S24_LE:
-		data_len = 24;
-		frame_len = 32;
-		break;
-	case SNDRV_PCM_FORMAT_S24_3LE:
-		data_len = 24;
-		frame_len = 24;
-		break;
-	default:
-		dev_err(dai->dev, "Format unsupported\n");
-		return -EINVAL;
-	}
-
-	shifter_len = data_len;
-
-	switch (usp->daifmt_format & SND_SOC_DAIFMT_FORMAT_MASK) {
-	case SND_SOC_DAIFMT_I2S:
-		regmap_update_bits(usp->regmap, USP_RX_FRAME_CTRL,
-			USP_I2S_SYNC_CHG, USP_I2S_SYNC_CHG);
-		break;
-	case SND_SOC_DAIFMT_DSP_A:
-		regmap_update_bits(usp->regmap, USP_RX_FRAME_CTRL,
-			USP_I2S_SYNC_CHG, 0);
-		frame_len = data_len * params_channels(params);
-		data_len = frame_len;
-		break;
-	default:
-		dev_err(dai->dev, "Only support I2S and DSP_A mode\n");
-		return -EINVAL;
-	}
-
-	switch (usp->daifmt_format & SND_SOC_DAIFMT_INV_MASK) {
-	case SND_SOC_DAIFMT_NB_NF:
-		break;
-	case SND_SOC_DAIFMT_IB_NF:
-		regmap_update_bits(usp->regmap, USP_MODE1,
-			USP_RXD_ACT_EDGE_FALLING | USP_TXD_ACT_EDGE_FALLING,
-			USP_RXD_ACT_EDGE_FALLING);
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-		regmap_update_bits(usp->regmap, USP_TX_FRAME_CTRL,
-			USP_TXC_DATA_LEN_MASK | USP_TXC_FRAME_LEN_MASK
-			| USP_TXC_SHIFTER_LEN_MASK | USP_TXC_SLAVE_CLK_SAMPLE,
-			((data_len - 1) << USP_TXC_DATA_LEN_OFFSET)
-			| ((frame_len - 1) << USP_TXC_FRAME_LEN_OFFSET)
-			| ((shifter_len - 1) << USP_TXC_SHIFTER_LEN_OFFSET)
-			| USP_TXC_SLAVE_CLK_SAMPLE);
-	else
-		regmap_update_bits(usp->regmap, USP_RX_FRAME_CTRL,
-			USP_RXC_DATA_LEN_MASK | USP_RXC_FRAME_LEN_MASK
-			| USP_RXC_SHIFTER_LEN_MASK | USP_SINGLE_SYNC_MODE,
-			((data_len - 1) << USP_RXC_DATA_LEN_OFFSET)
-			| ((frame_len - 1) << USP_RXC_FRAME_LEN_OFFSET)
-			| ((shifter_len - 1) << USP_RXC_SHIFTER_LEN_OFFSET)
-			| USP_SINGLE_SYNC_MODE);
-
-	return 0;
-}
-
-static int sirf_usp_pcm_trigger(struct snd_pcm_substream *substream, int cmd,
-				struct snd_soc_dai *dai)
-{
-	struct sirf_usp *usp = snd_soc_dai_get_drvdata(dai);
-
-	switch (cmd) {
-	case SNDRV_PCM_TRIGGER_START:
-	case SNDRV_PCM_TRIGGER_RESUME:
-	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-			sirf_usp_tx_enable(usp);
-		else
-			sirf_usp_rx_enable(usp);
-		break;
-	case SNDRV_PCM_TRIGGER_STOP:
-	case SNDRV_PCM_TRIGGER_SUSPEND:
-	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-			sirf_usp_tx_disable(usp);
-		else
-			sirf_usp_rx_disable(usp);
-		break;
-	}
-
-	return 0;
-}
-
-static const struct snd_soc_dai_ops sirf_usp_pcm_dai_ops = {
-	.trigger = sirf_usp_pcm_trigger,
-	.set_fmt = sirf_usp_pcm_set_dai_fmt,
-	.hw_params = sirf_usp_pcm_hw_params,
-};
-
-static struct snd_soc_dai_driver sirf_usp_pcm_dai = {
-	.probe = sirf_usp_pcm_dai_probe,
-	.name = "sirf-usp-pcm",
-	.id = 0,
-	.playback = {
-		.stream_name = "SiRF USP PCM Playback",
-		.channels_min = 1,
-		.channels_max = 2,
-		.rates = SNDRV_PCM_RATE_8000_192000,
-		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |
-			SNDRV_PCM_FMTBIT_S24_3LE,
-	},
-	.capture = {
-		.stream_name = "SiRF USP PCM Capture",
-		.channels_min = 1,
-		.channels_max = 2,
-		.rates = SNDRV_PCM_RATE_8000_192000,
-		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |
-			SNDRV_PCM_FMTBIT_S24_3LE,
-	},
-	.ops = &sirf_usp_pcm_dai_ops,
-};
-
-static int sirf_usp_pcm_runtime_suspend(struct device *dev)
-{
-	struct sirf_usp *usp = dev_get_drvdata(dev);
-
-	clk_disable_unprepare(usp->clk);
-	return 0;
-}
-
-static int sirf_usp_pcm_runtime_resume(struct device *dev)
-{
-	struct sirf_usp *usp = dev_get_drvdata(dev);
-	int ret;
-
-	ret = clk_prepare_enable(usp->clk);
-	if (ret) {
-		dev_err(dev, "clk_enable failed: %d\n", ret);
-		return ret;
-	}
-	sirf_usp_i2s_init(usp);
-	return 0;
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int sirf_usp_pcm_suspend(struct device *dev)
-{
-	struct sirf_usp *usp = dev_get_drvdata(dev);
-
-	if (!pm_runtime_status_suspended(dev)) {
-		regmap_read(usp->regmap, USP_MODE1, &usp->mode1_reg);
-		regmap_read(usp->regmap, USP_MODE2, &usp->mode2_reg);
-		sirf_usp_pcm_runtime_suspend(dev);
-	}
-	return 0;
-}
-
-static int sirf_usp_pcm_resume(struct device *dev)
-{
-	struct sirf_usp *usp = dev_get_drvdata(dev);
-	int ret;
-
-	if (!pm_runtime_status_suspended(dev)) {
-		ret = sirf_usp_pcm_runtime_resume(dev);
-		if (ret)
-			return ret;
-		regmap_write(usp->regmap, USP_MODE1, usp->mode1_reg);
-		regmap_write(usp->regmap, USP_MODE2, usp->mode2_reg);
-	}
-	return 0;
-}
-#endif
-
-static const struct snd_soc_component_driver sirf_usp_component = {
-	.name		= "sirf-usp",
-};
-
-static const struct regmap_config sirf_usp_regmap_config = {
-	.reg_bits = 32,
-	.reg_stride = 4,
-	.val_bits = 32,
-	.max_register = USP_RX_FIFO_DATA,
-	.cache_type = REGCACHE_NONE,
-};
-
-static int sirf_usp_pcm_probe(struct platform_device *pdev)
-{
-	int ret;
-	struct sirf_usp *usp;
-	void __iomem *base;
-
-	usp = devm_kzalloc(&pdev->dev, sizeof(struct sirf_usp),
-			GFP_KERNEL);
-	if (!usp)
-		return -ENOMEM;
-
-	platform_set_drvdata(pdev, usp);
-
-	base = devm_platform_ioremap_resource(pdev, 0);
-	if (IS_ERR(base))
-		return PTR_ERR(base);
-	usp->regmap = devm_regmap_init_mmio(&pdev->dev, base,
-					    &sirf_usp_regmap_config);
-	if (IS_ERR(usp->regmap))
-		return PTR_ERR(usp->regmap);
-
-	usp->clk = devm_clk_get(&pdev->dev, NULL);
-	if (IS_ERR(usp->clk)) {
-		dev_err(&pdev->dev, "Get clock failed.\n");
-		return PTR_ERR(usp->clk);
-	}
-
-	pm_runtime_enable(&pdev->dev);
-	if (!pm_runtime_enabled(&pdev->dev)) {
-		ret = sirf_usp_pcm_runtime_resume(&pdev->dev);
-		if (ret)
-			return ret;
-	}
-
-	ret = devm_snd_soc_register_component(&pdev->dev, &sirf_usp_component,
-		&sirf_usp_pcm_dai, 1);
-	if (ret) {
-		dev_err(&pdev->dev, "Register Audio SoC dai failed.\n");
-		return ret;
-	}
-	return devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
-}
-
-static int sirf_usp_pcm_remove(struct platform_device *pdev)
-{
-	if (!pm_runtime_enabled(&pdev->dev))
-		sirf_usp_pcm_runtime_suspend(&pdev->dev);
-	else
-		pm_runtime_disable(&pdev->dev);
-	return 0;
-}
-
-static const struct of_device_id sirf_usp_pcm_of_match[] = {
-	{ .compatible = "sirf,prima2-usp-pcm", },
-	{}
-};
-MODULE_DEVICE_TABLE(of, sirf_usp_pcm_of_match);
-
-static const struct dev_pm_ops sirf_usp_pcm_pm_ops = {
-	SET_RUNTIME_PM_OPS(sirf_usp_pcm_runtime_suspend,
-		sirf_usp_pcm_runtime_resume, NULL)
-	SET_SYSTEM_SLEEP_PM_OPS(sirf_usp_pcm_suspend, sirf_usp_pcm_resume)
-};
-
-static struct platform_driver sirf_usp_pcm_driver = {
-	.driver = {
-		.name = "sirf-usp-pcm",
-		.of_match_table = sirf_usp_pcm_of_match,
-		.pm = &sirf_usp_pcm_pm_ops,
-	},
-	.probe = sirf_usp_pcm_probe,
-	.remove = sirf_usp_pcm_remove,
-};
-
-module_platform_driver(sirf_usp_pcm_driver);
-
-MODULE_DESCRIPTION("SiRF SoC USP PCM bus driver");
-MODULE_AUTHOR("RongJun Ying <Rongjun.Ying@csr.com>");
-MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/sirf/sirf-usp.h b/sound/soc/sirf/sirf-usp.h
deleted file mode 100644
index 08993b5992c4..000000000000
--- a/sound/soc/sirf/sirf-usp.h
+++ /dev/null
@@ -1,292 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * arch/arm/mach-prima2/include/mach/sirfsoc_usp.h
- *
- * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
- */
-
-#ifndef _SIRF_USP_H
-#define _SIRF_USP_H
-
-/* USP Registers */
-#define USP_MODE1		0x00
-#define USP_MODE2		0x04
-#define USP_TX_FRAME_CTRL	0x08
-#define USP_RX_FRAME_CTRL	0x0C
-#define USP_TX_RX_ENABLE	0x10
-#define USP_INT_ENABLE		0x14
-#define USP_INT_STATUS		0x18
-#define USP_PIN_IO_DATA		0x1C
-#define USP_RISC_DSP_MODE	0x20
-#define USP_AYSNC_PARAM_REG	0x24
-#define USP_IRDA_X_MODE_DIV	0x28
-#define USP_SM_CFG		0x2C
-#define USP_TX_DMA_IO_CTRL	0x100
-#define USP_TX_DMA_IO_LEN	0x104
-#define USP_TX_FIFO_CTRL	0x108
-#define USP_TX_FIFO_LEVEL_CHK	0x10C
-#define USP_TX_FIFO_OP		0x110
-#define USP_TX_FIFO_STATUS	0x114
-#define USP_TX_FIFO_DATA	0x118
-#define USP_RX_DMA_IO_CTRL	0x120
-#define USP_RX_DMA_IO_LEN	0x124
-#define USP_RX_FIFO_CTRL	0x128
-#define USP_RX_FIFO_LEVEL_CHK	0x12C
-#define USP_RX_FIFO_OP		0x130
-#define USP_RX_FIFO_STATUS	0x134
-#define USP_RX_FIFO_DATA	0x138
-
-/* USP MODE register-1 */
-#define USP_SYNC_MODE			0x00000001
-#define USP_CLOCK_MODE_SLAVE		0x00000002
-#define USP_LOOP_BACK_EN		0x00000004
-#define USP_HPSIR_EN			0x00000008
-#define USP_ENDIAN_CTRL_LSBF		0x00000010
-#define USP_EN				0x00000020
-#define USP_RXD_ACT_EDGE_FALLING	0x00000040
-#define USP_TXD_ACT_EDGE_FALLING	0x00000080
-#define USP_RFS_ACT_LEVEL_LOGIC1	0x00000100
-#define USP_TFS_ACT_LEVEL_LOGIC1	0x00000200
-#define USP_SCLK_IDLE_MODE_TOGGLE	0x00000400
-#define USP_SCLK_IDLE_LEVEL_LOGIC1	0x00000800
-#define USP_SCLK_PIN_MODE_IO	0x00001000
-#define USP_RFS_PIN_MODE_IO	0x00002000
-#define USP_TFS_PIN_MODE_IO	0x00004000
-#define USP_RXD_PIN_MODE_IO	0x00008000
-#define USP_TXD_PIN_MODE_IO	0x00010000
-#define USP_SCLK_IO_MODE_INPUT	0x00020000
-#define USP_RFS_IO_MODE_INPUT	0x00040000
-#define USP_TFS_IO_MODE_INPUT	0x00080000
-#define USP_RXD_IO_MODE_INPUT	0x00100000
-#define USP_TXD_IO_MODE_INPUT	0x00200000
-#define USP_IRDA_WIDTH_DIV_MASK	0x3FC00000
-#define USP_IRDA_WIDTH_DIV_OFFSET	0
-#define USP_IRDA_IDLE_LEVEL_HIGH	0x40000000
-#define USP_TX_UFLOW_REPEAT_ZERO	0x80000000
-#define USP_TX_ENDIAN_MODE		0x00000020
-#define USP_RX_ENDIAN_MODE		0x00000020
-
-/* USP Mode Register-2 */
-#define USP_RXD_DELAY_LEN_MASK		0x000000FF
-#define USP_RXD_DELAY_LEN_OFFSET	0
-
-#define USP_TXD_DELAY_LEN_MASK		0x0000FF00
-#define USP_TXD_DELAY_LEN_OFFSET	8
-
-#define USP_ENA_CTRL_MODE		0x00010000
-#define USP_FRAME_CTRL_MODE		0x00020000
-#define USP_TFS_SOURCE_MODE             0x00040000
-#define USP_TFS_MS_MODE                 0x00080000
-#define USP_CLK_DIVISOR_MASK		0x7FE00000
-#define USP_CLK_DIVISOR_OFFSET		21
-
-#define USP_TFS_CLK_SLAVE_MODE		(1<<20)
-#define USP_RFS_CLK_SLAVE_MODE		(1<<19)
-
-#define USP_IRDA_DATA_WIDTH		0x80000000
-
-/* USP Transmit Frame Control Register */
-
-#define USP_TXC_DATA_LEN_MASK		0x000000FF
-#define USP_TXC_DATA_LEN_OFFSET		0
-
-#define USP_TXC_SYNC_LEN_MASK		0x0000FF00
-#define USP_TXC_SYNC_LEN_OFFSET		8
-
-#define USP_TXC_FRAME_LEN_MASK		0x00FF0000
-#define USP_TXC_FRAME_LEN_OFFSET	16
-
-#define USP_TXC_SHIFTER_LEN_MASK	0x1F000000
-#define USP_TXC_SHIFTER_LEN_OFFSET	24
-
-#define USP_TXC_SLAVE_CLK_SAMPLE	0x20000000
-
-#define USP_TXC_CLK_DIVISOR_MASK	0xC0000000
-#define USP_TXC_CLK_DIVISOR_OFFSET	30
-
-/* USP Receive Frame Control Register */
-
-#define USP_RXC_DATA_LEN_MASK		0x000000FF
-#define USP_RXC_DATA_LEN_OFFSET		0
-
-#define USP_RXC_FRAME_LEN_MASK		0x0000FF00
-#define USP_RXC_FRAME_LEN_OFFSET	8
-
-#define USP_RXC_SHIFTER_LEN_MASK	0x001F0000
-#define USP_RXC_SHIFTER_LEN_OFFSET	16
-
-#define USP_START_EDGE_MODE	0x00800000
-#define USP_I2S_SYNC_CHG	0x00200000
-
-#define USP_RXC_CLK_DIVISOR_MASK	0x0F000000
-#define USP_RXC_CLK_DIVISOR_OFFSET	24
-#define USP_SINGLE_SYNC_MODE		0x00400000
-
-/* Tx - RX Enable Register */
-
-#define USP_RX_ENA		0x00000001
-#define USP_TX_ENA		0x00000002
-
-/* USP Interrupt Enable and status Register */
-#define USP_RX_DONE_INT			0x00000001
-#define USP_TX_DONE_INT			0x00000002
-#define USP_RX_OFLOW_INT		0x00000004
-#define USP_TX_UFLOW_INT		0x00000008
-#define USP_RX_IO_DMA_INT		0x00000010
-#define USP_TX_IO_DMA_INT		0x00000020
-#define USP_RXFIFO_FULL_INT		0x00000040
-#define USP_TXFIFO_EMPTY_INT		0x00000080
-#define USP_RXFIFO_THD_INT		0x00000100
-#define USP_TXFIFO_THD_INT		0x00000200
-#define USP_UART_FRM_ERR_INT		0x00000400
-#define USP_RX_TIMEOUT_INT		0x00000800
-#define USP_TX_ALLOUT_INT		0x00001000
-#define USP_RXD_BREAK_INT		0x00008000
-
-/* All possible TX interruots */
-#define USP_TX_INTERRUPT		(USP_TX_DONE_INT|USP_TX_UFLOW_INT|\
-					USP_TX_IO_DMA_INT|\
-					USP_TXFIFO_EMPTY_INT|\
-					USP_TXFIFO_THD_INT)
-/* All possible RX interruots */
-#define USP_RX_INTERRUPT		(USP_RX_DONE_INT|USP_RX_OFLOW_INT|\
-					USP_RX_IO_DMA_INT|\
-					USP_RXFIFO_FULL_INT|\
-					USP_RXFIFO_THD_INT|\
-					USP_RX_TIMEOUT_INT)
-
-#define USP_INT_ALL        0x1FFF
-
-/* USP Pin I/O Data Register */
-
-#define USP_RFS_PIN_VALUE_MASK	0x00000001
-#define USP_TFS_PIN_VALUE_MASK	0x00000002
-#define USP_RXD_PIN_VALUE_MASK	0x00000004
-#define USP_TXD_PIN_VALUE_MASK	0x00000008
-#define USP_SCLK_PIN_VALUE_MASK	0x00000010
-
-/* USP RISC/DSP Mode Register */
-#define USP_RISC_DSP_SEL	0x00000001
-
-/* USP ASYNC PARAMETER Register*/
-
-#define USP_ASYNC_TIMEOUT_MASK	0x0000FFFF
-#define USP_ASYNC_TIMEOUT_OFFSET	0
-#define USP_ASYNC_TIMEOUT(x)	(((x)&USP_ASYNC_TIMEOUT_MASK) \
-				<<USP_ASYNC_TIMEOUT_OFFSET)
-
-#define USP_ASYNC_DIV2_MASK		0x003F0000
-#define USP_ASYNC_DIV2_OFFSET		16
-
-/* USP TX DMA I/O MODE Register */
-#define USP_TX_MODE_IO			0x00000001
-
-/* USP TX DMA I/O Length Register */
-#define USP_TX_DATA_LEN_MASK		0xFFFFFFFF
-#define USP_TX_DATA_LEN_OFFSET		0
-
-/* USP TX FIFO Control Register */
-#define USP_TX_FIFO_WIDTH_MASK		0x00000003
-#define USP_TX_FIFO_WIDTH_OFFSET	0
-
-#define USP_TX_FIFO_THD_MASK		0x000001FC
-#define USP_TX_FIFO_THD_OFFSET		2
-
-/* USP TX FIFO Level Check Register */
-#define USP_TX_FIFO_LEVEL_CHECK_MASK	0x1F
-#define USP_TX_FIFO_SC_OFFSET	0
-#define USP_TX_FIFO_LC_OFFSET	10
-#define USP_TX_FIFO_HC_OFFSET	20
-
-#define TX_FIFO_SC(x)		(((x) & USP_TX_FIFO_LEVEL_CHECK_MASK) \
-				<< USP_TX_FIFO_SC_OFFSET)
-#define TX_FIFO_LC(x)		(((x) & USP_TX_FIFO_LEVEL_CHECK_MASK) \
-				<< USP_TX_FIFO_LC_OFFSET)
-#define TX_FIFO_HC(x)		(((x) & USP_TX_FIFO_LEVEL_CHECK_MASK) \
-				<< USP_TX_FIFO_HC_OFFSET)
-
-/* USP TX FIFO Operation Register */
-#define USP_TX_FIFO_RESET		0x00000001
-#define USP_TX_FIFO_START		0x00000002
-
-/* USP TX FIFO Status Register */
-#define USP_TX_FIFO_LEVEL_MASK		0x0000007F
-#define USP_TX_FIFO_LEVEL_OFFSET	0
-
-#define USP_TX_FIFO_FULL		0x00000080
-#define USP_TX_FIFO_EMPTY		0x00000100
-
-/* USP TX FIFO Data Register */
-#define USP_TX_FIFO_DATA_MASK		0xFFFFFFFF
-#define USP_TX_FIFO_DATA_OFFSET		0
-
-/* USP RX DMA I/O MODE Register */
-#define USP_RX_MODE_IO			0x00000001
-#define USP_RX_DMA_FLUSH		0x00000004
-
-/* USP RX DMA I/O Length Register */
-#define USP_RX_DATA_LEN_MASK		0xFFFFFFFF
-#define USP_RX_DATA_LEN_OFFSET		0
-
-/* USP RX FIFO Control Register */
-#define USP_RX_FIFO_WIDTH_MASK		0x00000003
-#define USP_RX_FIFO_WIDTH_OFFSET	0
-
-#define USP_RX_FIFO_THD_MASK		0x000001FC
-#define USP_RX_FIFO_THD_OFFSET		2
-
-/* USP RX FIFO Level Check Register */
-
-#define USP_RX_FIFO_LEVEL_CHECK_MASK	0x1F
-#define USP_RX_FIFO_SC_OFFSET	0
-#define USP_RX_FIFO_LC_OFFSET	10
-#define USP_RX_FIFO_HC_OFFSET	20
-
-#define RX_FIFO_SC(x)		(((x) & USP_RX_FIFO_LEVEL_CHECK_MASK) \
-				<< USP_RX_FIFO_SC_OFFSET)
-#define RX_FIFO_LC(x)		(((x) & USP_RX_FIFO_LEVEL_CHECK_MASK) \
-				<< USP_RX_FIFO_LC_OFFSET)
-#define RX_FIFO_HC(x)		(((x) & USP_RX_FIFO_LEVEL_CHECK_MASK) \
-				<< USP_RX_FIFO_HC_OFFSET)
-
-/* USP RX FIFO Operation Register */
-#define USP_RX_FIFO_RESET		0x00000001
-#define USP_RX_FIFO_START		0x00000002
-
-/* USP RX FIFO Status Register */
-
-#define USP_RX_FIFO_LEVEL_MASK		0x0000007F
-#define USP_RX_FIFO_LEVEL_OFFSET	0
-
-#define USP_RX_FIFO_FULL		0x00000080
-#define USP_RX_FIFO_EMPTY		0x00000100
-
-/* USP RX FIFO Data Register */
-
-#define USP_RX_FIFO_DATA_MASK		0xFFFFFFFF
-#define USP_RX_FIFO_DATA_OFFSET		0
-
-/*
- * When rx thd irq occur, sender just disable tx empty irq,
- * Remaining data in tx fifo wil also be sent out.
- */
-#define USP_FIFO_SIZE			128
-#define USP_TX_FIFO_THRESHOLD		(USP_FIFO_SIZE/2)
-#define USP_RX_FIFO_THRESHOLD		(USP_FIFO_SIZE/2)
-
-/* FIFO_WIDTH for the USP_TX_FIFO_CTRL and USP_RX_FIFO_CTRL registers */
-#define USP_FIFO_WIDTH_BYTE  0x00
-#define USP_FIFO_WIDTH_WORD  0x01
-#define USP_FIFO_WIDTH_DWORD 0x02
-
-#define USP_ASYNC_DIV2          16
-
-#define USP_PLUGOUT_RETRY_CNT	2
-
-#define USP_TX_RX_FIFO_WIDTH_DWORD    2
-
-#define SIRF_USP_DIV_MCLK	0
-
-#define SIRF_USP_I2S_TFS_SYNC	0
-#define SIRF_USP_I2S_RFS_SYNC	1
-#endif
diff --git a/sound/soc/soc-component.c b/sound/soc/soc-component.c
index 760523382f3c..159bf88b9f8c 100644
--- a/sound/soc/soc-component.c
+++ b/sound/soc/soc-component.c
@@ -11,6 +11,7 @@
 #include <linux/module.h>
 #include <linux/pm_runtime.h>
 #include <sound/soc.h>
+#include <linux/bitops.h>
 
 #define soc_component_ret(dai, ret) _soc_component_ret(dai, __func__, ret)
 static inline int _soc_component_ret(struct snd_soc_component *component,
@@ -34,6 +35,18 @@ static inline int _soc_component_ret(struct snd_soc_component *component,
 	return ret;
 }
 
+static inline int soc_component_field_shift(struct snd_soc_component *component,
+					    unsigned int mask)
+{
+	if (!mask) {
+		dev_err(component->dev,	"ASoC: error field mask is zero for %s\n",
+			component->name);
+		return 0;
+	}
+
+	return (ffs(mask) - 1);
+}
+
 /*
  * We might want to check substream by using list.
  * In such case, we can update these macros.
@@ -840,6 +853,47 @@ int snd_soc_component_update_bits_async(struct snd_soc_component *component,
 EXPORT_SYMBOL_GPL(snd_soc_component_update_bits_async);
 
 /**
+ * snd_soc_component_read_field() - Read register field value
+ * @component: Component to read from
+ * @reg: Register to read
+ * @mask: mask of the register field
+ *
+ * Return: read value of register field.
+ */
+unsigned int snd_soc_component_read_field(struct snd_soc_component *component,
+					  unsigned int reg, unsigned int mask)
+{
+	unsigned int val;
+
+	val = snd_soc_component_read(component, reg);
+
+	val = (val & mask) >> soc_component_field_shift(component, mask);
+
+	return val;
+}
+EXPORT_SYMBOL_GPL(snd_soc_component_read_field);
+
+/**
+ * snd_soc_component_write_field() - write to register field
+ * @component: Component to write to
+ * @reg: Register to write
+ * @mask: mask of the register field to update
+ * @val: value of the field to write
+ *
+ * Return: 1 for change, otherwise 0.
+ */
+int snd_soc_component_write_field(struct snd_soc_component *component,
+				  unsigned int reg, unsigned int mask,
+				  unsigned int val)
+{
+
+	val = (val << soc_component_field_shift(component, mask)) & mask;
+
+	return snd_soc_component_update_bits(component, reg, mask, val);
+}
+EXPORT_SYMBOL_GPL(snd_soc_component_write_field);
+
+/**
  * snd_soc_component_async_complete() - Ensure asynchronous I/O has completed
  * @component: Component for which to wait
  *
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 2b75d0139e47..b005f9eadd71 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -2528,9 +2528,20 @@ static struct snd_soc_dapm_widget *dapm_find_widget(
 {
 	struct snd_soc_dapm_widget *w;
 	struct snd_soc_dapm_widget *fallback = NULL;
+	char prefixed_pin[80];
+	const char *pin_name;
+	const char *prefix = soc_dapm_prefix(dapm);
+
+	if (prefix) {
+		snprintf(prefixed_pin, sizeof(prefixed_pin), "%s %s",
+			 prefix, pin);
+		pin_name = prefixed_pin;
+	} else {
+		pin_name = pin;
+	}
 
 	for_each_card_widgets(dapm->card, w) {
-		if (!strcmp(w->name, pin)) {
+		if (!strcmp(w->name, pin_name)) {
 			if (w->dapm == dapm)
 				return w;
 			else
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index ee51dc7fd893..14d85ca1e435 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -203,6 +203,34 @@ static inline void dpcm_remove_debugfs_state(struct snd_soc_dpcm *dpcm)
 }
 #endif
 
+/* Set FE's runtime_update state; the state is protected via PCM stream lock
+ * for avoiding the race with trigger callback.
+ * If the state is unset and a trigger is pending while the previous operation,
+ * process the pending trigger action here.
+ */
+static int dpcm_fe_dai_do_trigger(struct snd_pcm_substream *substream, int cmd);
+static void dpcm_set_fe_update_state(struct snd_soc_pcm_runtime *fe,
+				     int stream, enum snd_soc_dpcm_update state)
+{
+	struct snd_pcm_substream *substream =
+		snd_soc_dpcm_get_substream(fe, stream);
+
+	snd_pcm_stream_lock_irq(substream);
+	if (state == SND_SOC_DPCM_UPDATE_NO && fe->dpcm[stream].trigger_pending) {
+		dpcm_fe_dai_do_trigger(substream,
+				       fe->dpcm[stream].trigger_pending - 1);
+		fe->dpcm[stream].trigger_pending = 0;
+	}
+	fe->dpcm[stream].runtime_update = state;
+	snd_pcm_stream_unlock_irq(substream);
+}
+
+static void dpcm_set_be_update_state(struct snd_soc_pcm_runtime *be,
+				     int stream, enum snd_soc_dpcm_update state)
+{
+	be->dpcm[stream].runtime_update = state;
+}
+
 /**
  * snd_soc_runtime_action() - Increment/Decrement active count for
  * PCM runtime components
@@ -301,59 +329,46 @@ int dpcm_dapm_stream_event(struct snd_soc_pcm_runtime *fe, int dir,
 	return 0;
 }
 
+static void soc_pcm_set_dai_params(struct snd_soc_dai *dai,
+				   struct snd_pcm_hw_params *params)
+{
+	if (params) {
+		dai->rate	 = params_rate(params);
+		dai->channels	 = params_channels(params);
+		dai->sample_bits = snd_pcm_format_physical_width(params_format(params));
+	} else {
+		dai->rate	 = 0;
+		dai->channels	 = 0;
+		dai->sample_bits = 0;
+	}
+}
+
 static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream,
 					struct snd_soc_dai *soc_dai)
 {
 	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
 	int ret;
 
-	if (soc_dai->rate && (soc_dai->driver->symmetric_rates ||
-				rtd->dai_link->symmetric_rates)) {
-		dev_dbg(soc_dai->dev, "ASoC: Symmetry forces %dHz rate\n",
-				soc_dai->rate);
-
-		ret = snd_pcm_hw_constraint_single(substream->runtime,
-						SNDRV_PCM_HW_PARAM_RATE,
-						soc_dai->rate);
-		if (ret < 0) {
-			dev_err(soc_dai->dev,
-				"ASoC: Unable to apply rate constraint: %d\n",
-				ret);
-			return ret;
-		}
-	}
-
-	if (soc_dai->channels && (soc_dai->driver->symmetric_channels ||
-				rtd->dai_link->symmetric_channels)) {
-		dev_dbg(soc_dai->dev, "ASoC: Symmetry forces %d channel(s)\n",
-				soc_dai->channels);
-
-		ret = snd_pcm_hw_constraint_single(substream->runtime,
-						SNDRV_PCM_HW_PARAM_CHANNELS,
-						soc_dai->channels);
-		if (ret < 0) {
-			dev_err(soc_dai->dev,
-				"ASoC: Unable to apply channel symmetry constraint: %d\n",
-				ret);
-			return ret;
-		}
-	}
-
-	if (soc_dai->sample_bits && (soc_dai->driver->symmetric_samplebits ||
-				rtd->dai_link->symmetric_samplebits)) {
-		dev_dbg(soc_dai->dev, "ASoC: Symmetry forces %d sample bits\n",
-				soc_dai->sample_bits);
-
-		ret = snd_pcm_hw_constraint_single(substream->runtime,
-						SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
-						soc_dai->sample_bits);
-		if (ret < 0) {
-			dev_err(soc_dai->dev,
-				"ASoC: Unable to apply sample bits symmetry constraint: %d\n",
-				ret);
-			return ret;
-		}
-	}
+#define __soc_pcm_apply_symmetry(name, NAME)				\
+	if (soc_dai->name && (soc_dai->driver->symmetric_##name ||	\
+			      rtd->dai_link->symmetric_##name)) {	\
+		dev_dbg(soc_dai->dev, "ASoC: Symmetry forces %s to %d\n",\
+			#name, soc_dai->name);				\
+									\
+		ret = snd_pcm_hw_constraint_single(substream->runtime,	\
+						   SNDRV_PCM_HW_PARAM_##NAME,\
+						   soc_dai->name);	\
+		if (ret < 0) {						\
+			dev_err(soc_dai->dev,				\
+				"ASoC: Unable to apply %s constraint: %d\n",\
+				#name, ret);				\
+			return ret;					\
+		}							\
+	}
+
+	__soc_pcm_apply_symmetry(rate,		RATE);
+	__soc_pcm_apply_symmetry(channels,	CHANNELS);
+	__soc_pcm_apply_symmetry(sample_bits,	SAMPLE_BITS);
 
 	return 0;
 }
@@ -362,61 +377,30 @@ static int soc_pcm_params_symmetry(struct snd_pcm_substream *substream,
 				struct snd_pcm_hw_params *params)
 {
 	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
+	struct snd_soc_dai d;
 	struct snd_soc_dai *dai;
 	struct snd_soc_dai *cpu_dai;
-	unsigned int rate, channels, sample_bits, symmetry, i;
-
-	rate = params_rate(params);
-	channels = params_channels(params);
-	sample_bits = snd_pcm_format_physical_width(params_format(params));
-
-	/* reject unmatched parameters when applying symmetry */
-	symmetry = rtd->dai_link->symmetric_rates;
-
-	for_each_rtd_cpu_dais(rtd, i, dai)
-		symmetry |= dai->driver->symmetric_rates;
-
-	if (symmetry) {
-		for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
-			if (cpu_dai->rate && cpu_dai->rate != rate) {
-				dev_err(rtd->dev, "ASoC: unmatched rate symmetry: %d - %d\n",
-					cpu_dai->rate, rate);
-				return -EINVAL;
-			}
-		}
-	}
-
-	symmetry = rtd->dai_link->symmetric_channels;
+	unsigned int symmetry, i;
 
-	for_each_rtd_dais(rtd, i, dai)
-		symmetry |= dai->driver->symmetric_channels;
-
-	if (symmetry) {
-		for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
-			if (cpu_dai->channels &&
-			    cpu_dai->channels != channels) {
-				dev_err(rtd->dev, "ASoC: unmatched channel symmetry: %d - %d\n",
-					cpu_dai->channels, channels);
-				return -EINVAL;
+	soc_pcm_set_dai_params(&d, params);
+
+#define __soc_pcm_params_symmetry(name)					\
+	symmetry = rtd->dai_link->symmetric_##name;			\
+	for_each_rtd_dais(rtd, i, dai)					\
+		symmetry |= dai->driver->symmetric_##name;		\
+									\
+	if (symmetry)							\
+		for_each_rtd_cpu_dais(rtd, i, cpu_dai)			\
+			if (cpu_dai->name && cpu_dai->name != d.name) {	\
+				dev_err(rtd->dev, "ASoC: unmatched %s symmetry: %d - %d\n", \
+					#name, cpu_dai->name, d.name);	\
+				return -EINVAL;				\
 			}
-		}
-	}
 
-	symmetry = rtd->dai_link->symmetric_samplebits;
-
-	for_each_rtd_dais(rtd, i, dai)
-		symmetry |= dai->driver->symmetric_samplebits;
-
-	if (symmetry) {
-		for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
-			if (cpu_dai->sample_bits &&
-			    cpu_dai->sample_bits != sample_bits) {
-				dev_err(rtd->dev, "ASoC: unmatched sample bits symmetry: %d - %d\n",
-					cpu_dai->sample_bits, sample_bits);
-				return -EINVAL;
-			}
-		}
-	}
+	/* reject unmatched parameters when applying symmetry */
+	__soc_pcm_params_symmetry(rate);
+	__soc_pcm_params_symmetry(channels);
+	__soc_pcm_params_symmetry(sample_bits);
 
 	return 0;
 }
@@ -428,15 +412,15 @@ static bool soc_pcm_has_symmetry(struct snd_pcm_substream *substream)
 	struct snd_soc_dai *dai;
 	unsigned int symmetry, i;
 
-	symmetry = link->symmetric_rates ||
+	symmetry = link->symmetric_rate ||
 		link->symmetric_channels ||
-		link->symmetric_samplebits;
+		link->symmetric_sample_bits;
 
 	for_each_rtd_dais(rtd, i, dai)
 		symmetry = symmetry ||
-			dai->driver->symmetric_rates ||
+			dai->driver->symmetric_rate ||
 			dai->driver->symmetric_channels ||
-			dai->driver->symmetric_samplebits;
+			dai->driver->symmetric_sample_bits;
 
 	return symmetry;
 }
@@ -489,6 +473,42 @@ static void soc_pcm_apply_msb(struct snd_pcm_substream *substream)
 	soc_pcm_set_msb(substream, cpu_bits);
 }
 
+static void soc_pcm_hw_init(struct snd_pcm_hardware *hw)
+{
+	hw->rates		= UINT_MAX;
+	hw->rate_min		= 0;
+	hw->rate_max		= UINT_MAX;
+	hw->channels_min	= 0;
+	hw->channels_max	= UINT_MAX;
+	hw->formats		= ULLONG_MAX;
+}
+
+static void soc_pcm_hw_update_rate(struct snd_pcm_hardware *hw,
+				   struct snd_soc_pcm_stream *p)
+{
+	hw->rates = snd_pcm_rate_mask_intersect(hw->rates, p->rates);
+
+	/* setup hw->rate_min/max via hw->rates first */
+	snd_pcm_hw_limit_rates(hw);
+
+	/* update hw->rate_min/max by snd_soc_pcm_stream */
+	hw->rate_min = max(hw->rate_min, p->rate_min);
+	hw->rate_max = min_not_zero(hw->rate_max, p->rate_max);
+}
+
+static void soc_pcm_hw_update_chan(struct snd_pcm_hardware *hw,
+				   struct snd_soc_pcm_stream *p)
+{
+	hw->channels_min = max(hw->channels_min, p->channels_min);
+	hw->channels_max = min(hw->channels_max, p->channels_max);
+}
+
+static void soc_pcm_hw_update_format(struct snd_pcm_hardware *hw,
+				     struct snd_soc_pcm_stream *p)
+{
+	hw->formats &= p->formats;
+}
+
 /**
  * snd_soc_runtime_calc_hw() - Calculate hw limits for a PCM stream
  * @rtd: ASoC PCM runtime
@@ -505,14 +525,11 @@ int snd_soc_runtime_calc_hw(struct snd_soc_pcm_runtime *rtd,
 	struct snd_soc_dai *cpu_dai;
 	struct snd_soc_pcm_stream *codec_stream;
 	struct snd_soc_pcm_stream *cpu_stream;
-	unsigned int chan_min = 0, chan_max = UINT_MAX;
 	unsigned int cpu_chan_min = 0, cpu_chan_max = UINT_MAX;
-	unsigned int rate_min = 0, rate_max = UINT_MAX;
-	unsigned int cpu_rate_min = 0, cpu_rate_max = UINT_MAX;
-	unsigned int rates = UINT_MAX, cpu_rates = UINT_MAX;
-	u64 formats = ULLONG_MAX;
 	int i;
 
+	soc_pcm_hw_init(hw);
+
 	/* first calculate min/max only for CPUs in the DAI link */
 	for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
 
@@ -527,14 +544,12 @@ int snd_soc_runtime_calc_hw(struct snd_soc_pcm_runtime *rtd,
 
 		cpu_stream = snd_soc_dai_get_pcm_stream(cpu_dai, stream);
 
-		cpu_chan_min = max(cpu_chan_min, cpu_stream->channels_min);
-		cpu_chan_max = min(cpu_chan_max, cpu_stream->channels_max);
-		cpu_rate_min = max(cpu_rate_min, cpu_stream->rate_min);
-		cpu_rate_max = min_not_zero(cpu_rate_max, cpu_stream->rate_max);
-		formats &= cpu_stream->formats;
-		cpu_rates = snd_pcm_rate_mask_intersect(cpu_stream->rates,
-							cpu_rates);
+		soc_pcm_hw_update_chan(hw, cpu_stream);
+		soc_pcm_hw_update_rate(hw, cpu_stream);
+		soc_pcm_hw_update_format(hw, cpu_stream);
 	}
+	cpu_chan_min = hw->channels_min;
+	cpu_chan_max = hw->channels_max;
 
 	/* second calculate min/max only for CODECs in the DAI link */
 	for_each_rtd_codec_dais(rtd, i, codec_dai) {
@@ -550,16 +565,13 @@ int snd_soc_runtime_calc_hw(struct snd_soc_pcm_runtime *rtd,
 
 		codec_stream = snd_soc_dai_get_pcm_stream(codec_dai, stream);
 
-		chan_min = max(chan_min, codec_stream->channels_min);
-		chan_max = min(chan_max, codec_stream->channels_max);
-		rate_min = max(rate_min, codec_stream->rate_min);
-		rate_max = min_not_zero(rate_max, codec_stream->rate_max);
-		formats &= codec_stream->formats;
-		rates = snd_pcm_rate_mask_intersect(codec_stream->rates, rates);
+		soc_pcm_hw_update_chan(hw, codec_stream);
+		soc_pcm_hw_update_rate(hw, codec_stream);
+		soc_pcm_hw_update_format(hw, codec_stream);
 	}
 
 	/* Verify both a valid CPU DAI and a valid CODEC DAI were found */
-	if (!chan_min || !cpu_chan_min)
+	if (!hw->channels_min)
 		return -EINVAL;
 
 	/*
@@ -568,23 +580,10 @@ int snd_soc_runtime_calc_hw(struct snd_soc_pcm_runtime *rtd,
 	 * channel allocation be fixed up later
 	 */
 	if (rtd->num_codecs > 1) {
-		chan_min = cpu_chan_min;
-		chan_max = cpu_chan_max;
+		hw->channels_min = cpu_chan_min;
+		hw->channels_max = cpu_chan_max;
 	}
 
-	/* finally find a intersection between CODECs and CPUs */
-	hw->channels_min = max(chan_min, cpu_chan_min);
-	hw->channels_max = min(chan_max, cpu_chan_max);
-	hw->formats = formats;
-	hw->rates = snd_pcm_rate_mask_intersect(rates, cpu_rates);
-
-	snd_pcm_hw_limit_rates(hw);
-
-	hw->rate_min = max(hw->rate_min, cpu_rate_min);
-	hw->rate_min = max(hw->rate_min, rate_min);
-	hw->rate_max = min_not_zero(hw->rate_max, cpu_rate_max);
-	hw->rate_max = min_not_zero(hw->rate_max, rate_max);
-
 	return 0;
 }
 EXPORT_SYMBOL_GPL(snd_soc_runtime_calc_hw);
@@ -870,11 +869,8 @@ static int soc_pcm_hw_clean(struct snd_pcm_substream *substream, int rollback)
 	for_each_rtd_dais(rtd, i, dai) {
 		int active = snd_soc_dai_stream_active(dai, substream->stream);
 
-		if (snd_soc_dai_active(dai) == 1) {
-			dai->rate = 0;
-			dai->channels = 0;
-			dai->sample_bits = 0;
-		}
+		if (snd_soc_dai_active(dai) == 1)
+			soc_pcm_set_dai_params(dai, NULL);
 
 		if (active == 1)
 			snd_soc_dai_digital_mute(dai, 1, substream->stream);
@@ -971,11 +967,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
 		if(ret < 0)
 			goto out;
 
-		codec_dai->rate = params_rate(&codec_params);
-		codec_dai->channels = params_channels(&codec_params);
-		codec_dai->sample_bits = snd_pcm_format_physical_width(
-						params_format(&codec_params));
-
+		soc_pcm_set_dai_params(codec_dai, &codec_params);
 		snd_soc_dapm_update_dai(substream, &codec_params, codec_dai);
 	}
 
@@ -992,11 +984,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
 			goto out;
 
 		/* store the parameters for each DAI */
-		cpu_dai->rate = params_rate(params);
-		cpu_dai->channels = params_channels(params);
-		cpu_dai->sample_bits =
-			snd_pcm_format_physical_width(params_format(params));
-
+		soc_pcm_set_dai_params(cpu_dai, params);
 		snd_soc_dapm_update_dai(substream, params, cpu_dai);
 	}
 
@@ -1335,7 +1323,7 @@ static int dpcm_prune_paths(struct snd_soc_pcm_runtime *fe, int stream,
 			stream ? "capture" : "playback",
 			dpcm->be->dai_link->name, fe->dai_link->name);
 		dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
-		dpcm->be->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_BE;
+		dpcm_set_be_update_state(dpcm->be, stream, SND_SOC_DPCM_UPDATE_BE);
 		prune++;
 	}
 
@@ -1371,8 +1359,8 @@ static int dpcm_add_paths(struct snd_soc_pcm_runtime *fe, int stream,
 		/* is there a valid BE rtd for this widget */
 		be = dpcm_get_be(card, widget, stream);
 		if (!be) {
-			dev_err(fe->dev, "ASoC: no BE found for %s\n",
-					widget->name);
+			dev_dbg(fe->dev, "ASoC: no BE found for %s\n",
+				widget->name);
 			continue;
 		}
 
@@ -1390,7 +1378,7 @@ static int dpcm_add_paths(struct snd_soc_pcm_runtime *fe, int stream,
 			continue;
 
 		/* new */
-		be->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_BE;
+		dpcm_set_be_update_state(be, stream, SND_SOC_DPCM_UPDATE_BE);
 		new++;
 	}
 
@@ -1418,8 +1406,7 @@ void dpcm_clear_pending_state(struct snd_soc_pcm_runtime *fe, int stream)
 
 	spin_lock_irqsave(&fe->card->dpcm_lock, flags);
 	for_each_dpcm_be(fe, stream, dpcm)
-		dpcm->be->dpcm[stream].runtime_update =
-						SND_SOC_DPCM_UPDATE_NO;
+		dpcm_set_be_update_state(dpcm->be, stream, SND_SOC_DPCM_UPDATE_NO);
 	spin_unlock_irqrestore(&fe->card->dpcm_lock, flags);
 }
 
@@ -1542,21 +1529,21 @@ unwind:
 static void dpcm_init_runtime_hw(struct snd_pcm_runtime *runtime,
 				 struct snd_soc_pcm_stream *stream)
 {
-	runtime->hw.rate_min = stream->rate_min;
-	runtime->hw.rate_max = min_not_zero(stream->rate_max, UINT_MAX);
-	runtime->hw.channels_min = stream->channels_min;
-	runtime->hw.channels_max = stream->channels_max;
+	struct snd_pcm_hardware *hw = &runtime->hw;
+
+	soc_pcm_hw_update_rate(hw, stream);
+	soc_pcm_hw_update_chan(hw, stream);
 	if (runtime->hw.formats)
 		runtime->hw.formats &= stream->formats;
 	else
 		runtime->hw.formats = stream->formats;
-	runtime->hw.rates = stream->rates;
 }
 
 static void dpcm_runtime_merge_format(struct snd_pcm_substream *substream,
-				      u64 *formats)
+				      struct snd_pcm_runtime *runtime)
 {
 	struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream);
+	struct snd_pcm_hardware *hw = &runtime->hw;
 	struct snd_soc_dpcm *dpcm;
 	struct snd_soc_dai *dai;
 	int stream = substream->stream;
@@ -1584,16 +1571,16 @@ static void dpcm_runtime_merge_format(struct snd_pcm_substream *substream,
 
 			codec_stream = snd_soc_dai_get_pcm_stream(dai, stream);
 
-			*formats &= codec_stream->formats;
+			soc_pcm_hw_update_format(hw, codec_stream);
 		}
 	}
 }
 
 static void dpcm_runtime_merge_chan(struct snd_pcm_substream *substream,
-				    unsigned int *channels_min,
-				    unsigned int *channels_max)
+				    struct snd_pcm_runtime *runtime)
 {
 	struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream);
+	struct snd_pcm_hardware *hw = &runtime->hw;
 	struct snd_soc_dpcm *dpcm;
 	int stream = substream->stream;
 
@@ -1622,10 +1609,7 @@ static void dpcm_runtime_merge_chan(struct snd_pcm_substream *substream,
 
 			cpu_stream = snd_soc_dai_get_pcm_stream(dai, stream);
 
-			*channels_min = max(*channels_min,
-					    cpu_stream->channels_min);
-			*channels_max = min(*channels_max,
-					    cpu_stream->channels_max);
+			soc_pcm_hw_update_chan(hw, cpu_stream);
 		}
 
 		/*
@@ -1635,20 +1619,16 @@ static void dpcm_runtime_merge_chan(struct snd_pcm_substream *substream,
 		if (be->num_codecs == 1) {
 			codec_stream = snd_soc_dai_get_pcm_stream(asoc_rtd_to_codec(be, 0), stream);
 
-			*channels_min = max(*channels_min,
-					    codec_stream->channels_min);
-			*channels_max = min(*channels_max,
-					    codec_stream->channels_max);
+			soc_pcm_hw_update_chan(hw, codec_stream);
 		}
 	}
 }
 
 static void dpcm_runtime_merge_rate(struct snd_pcm_substream *substream,
-				    unsigned int *rates,
-				    unsigned int *rate_min,
-				    unsigned int *rate_max)
+				    struct snd_pcm_runtime *runtime)
 {
 	struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream);
+	struct snd_pcm_hardware *hw = &runtime->hw;
 	struct snd_soc_dpcm *dpcm;
 	int stream = substream->stream;
 
@@ -1676,9 +1656,7 @@ static void dpcm_runtime_merge_rate(struct snd_pcm_substream *substream,
 
 			pcm = snd_soc_dai_get_pcm_stream(dai, stream);
 
-			*rate_min = max(*rate_min, pcm->rate_min);
-			*rate_max = min_not_zero(*rate_max, pcm->rate_max);
-			*rates = snd_pcm_rate_mask_intersect(*rates, pcm->rates);
+			soc_pcm_hw_update_rate(hw, pcm);
 		}
 	}
 }
@@ -1686,10 +1664,13 @@ static void dpcm_runtime_merge_rate(struct snd_pcm_substream *substream,
 static void dpcm_set_fe_runtime(struct snd_pcm_substream *substream)
 {
 	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct snd_pcm_hardware *hw = &runtime->hw;
 	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
 	struct snd_soc_dai *cpu_dai;
 	int i;
 
+	soc_pcm_hw_init(hw);
+
 	for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
 		/*
 		 * Skip CPUs which don't support the current stream
@@ -1703,34 +1684,9 @@ static void dpcm_set_fe_runtime(struct snd_pcm_substream *substream)
 						   substream->stream));
 	}
 
-	dpcm_runtime_merge_format(substream, &runtime->hw.formats);
-	dpcm_runtime_merge_chan(substream, &runtime->hw.channels_min,
-				&runtime->hw.channels_max);
-	dpcm_runtime_merge_rate(substream, &runtime->hw.rates,
-				&runtime->hw.rate_min, &runtime->hw.rate_max);
-}
-
-static int dpcm_fe_dai_do_trigger(struct snd_pcm_substream *substream, int cmd);
-
-/* Set FE's runtime_update state; the state is protected via PCM stream lock
- * for avoiding the race with trigger callback.
- * If the state is unset and a trigger is pending while the previous operation,
- * process the pending trigger action here.
- */
-static void dpcm_set_fe_update_state(struct snd_soc_pcm_runtime *fe,
-				     int stream, enum snd_soc_dpcm_update state)
-{
-	struct snd_pcm_substream *substream =
-		snd_soc_dpcm_get_substream(fe, stream);
-
-	snd_pcm_stream_lock_irq(substream);
-	if (state == SND_SOC_DPCM_UPDATE_NO && fe->dpcm[stream].trigger_pending) {
-		dpcm_fe_dai_do_trigger(substream,
-				       fe->dpcm[stream].trigger_pending - 1);
-		fe->dpcm[stream].trigger_pending = 0;
-	}
-	fe->dpcm[stream].runtime_update = state;
-	snd_pcm_stream_unlock_irq(substream);
+	dpcm_runtime_merge_format(substream, runtime);
+	dpcm_runtime_merge_chan(substream, runtime);
+	dpcm_runtime_merge_rate(substream, runtime);
 }
 
 static int dpcm_apply_symmetry(struct snd_pcm_substream *fe_substream,
@@ -1791,7 +1747,6 @@ static int dpcm_apply_symmetry(struct snd_pcm_substream *fe_substream,
 static int dpcm_fe_dai_startup(struct snd_pcm_substream *fe_substream)
 {
 	struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(fe_substream);
-	struct snd_pcm_runtime *runtime = fe_substream->runtime;
 	int stream = fe_substream->stream, ret = 0;
 
 	dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_FE);
@@ -1814,7 +1769,6 @@ static int dpcm_fe_dai_startup(struct snd_pcm_substream *fe_substream)
 	fe->dpcm[stream].state = SND_SOC_DPCM_STATE_OPEN;
 
 	dpcm_set_fe_runtime(fe_substream);
-	snd_pcm_limit_hw_rates(runtime);
 
 	ret = dpcm_apply_symmetry(fe_substream, stream);
 	if (ret < 0)
@@ -2432,7 +2386,7 @@ static int dpcm_run_update_startup(struct snd_soc_pcm_runtime *fe, int stream)
 		snd_soc_dpcm_get_substream(fe, stream);
 	struct snd_soc_dpcm *dpcm;
 	enum snd_soc_dpcm_trigger trigger = fe->dai_link->trigger[stream];
-	int ret;
+	int ret = 0;
 	unsigned long flags;
 
 	dev_dbg(fe->dev, "ASoC: runtime %s open on FE %s\n",
@@ -2440,8 +2394,13 @@ static int dpcm_run_update_startup(struct snd_soc_pcm_runtime *fe, int stream)
 
 	/* Only start the BE if the FE is ready */
 	if (fe->dpcm[stream].state == SND_SOC_DPCM_STATE_HW_FREE ||
-		fe->dpcm[stream].state == SND_SOC_DPCM_STATE_CLOSE)
-		return -EINVAL;
+		fe->dpcm[stream].state == SND_SOC_DPCM_STATE_CLOSE) {
+		ret = -EINVAL;
+		dev_err(fe->dev, "ASoC: FE %s is not ready %d\n",
+			fe->dai_link->name, fe->dpcm[stream].state);
+		ret = -EINVAL;
+		goto disconnect;
+	}
 
 	/* startup must always be called for new BEs */
 	ret = dpcm_be_dai_startup(fe, stream);
@@ -2502,12 +2461,18 @@ hw_free:
 close:
 	dpcm_be_dai_shutdown(fe, stream);
 disconnect:
-	/* disconnect any closed BEs */
+	/* disconnect any pending BEs */
 	spin_lock_irqsave(&fe->card->dpcm_lock, flags);
 	for_each_dpcm_be(fe, stream, dpcm) {
 		struct snd_soc_pcm_runtime *be = dpcm->be;
-		if (be->dpcm[stream].state == SND_SOC_DPCM_STATE_CLOSE)
-			dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
+
+		/* is this op for this BE ? */
+		if (!snd_soc_dpcm_be_can_update(fe, be, stream))
+			continue;
+
+		if (be->dpcm[stream].state == SND_SOC_DPCM_STATE_CLOSE ||
+			be->dpcm[stream].state == SND_SOC_DPCM_STATE_NEW)
+				dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
 	}
 	spin_unlock_irqrestore(&fe->card->dpcm_lock, flags);
 
@@ -2671,15 +2636,11 @@ open_end:
 	return ret;
 }
 
-/* create a new pcm */
-int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
+static int soc_get_playback_capture(struct snd_soc_pcm_runtime *rtd,
+				    int *playback, int *capture)
 {
 	struct snd_soc_dai *codec_dai;
 	struct snd_soc_dai *cpu_dai;
-	struct snd_soc_component *component;
-	struct snd_pcm *pcm;
-	char new_name[64];
-	int ret = 0, playback = 0, capture = 0;
 	int stream;
 	int i;
 
@@ -2695,12 +2656,11 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
 
 			for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
 				if (snd_soc_dai_stream_valid(cpu_dai, stream)) {
-					playback = 1;
+					*playback = 1;
 					break;
 				}
 			}
-
-			if (!playback) {
+			if (!*playback) {
 				dev_err(rtd->card->dev,
 					"No CPU DAIs support playback for stream %s\n",
 					rtd->dai_link->stream_name);
@@ -2712,12 +2672,12 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
 
 			for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
 				if (snd_soc_dai_stream_valid(cpu_dai, stream)) {
-					capture = 1;
+					*capture = 1;
 					break;
 				}
 			}
 
-			if (!capture) {
+			if (!*capture) {
 				dev_err(rtd->card->dev,
 					"No CPU DAIs support capture for stream %s\n",
 					rtd->dai_link->stream_name);
@@ -2744,36 +2704,46 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
 
 			if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_PLAYBACK) &&
 			    snd_soc_dai_stream_valid(cpu_dai,   cpu_playback))
-				playback = 1;
+				*playback = 1;
 			if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_CAPTURE) &&
 			    snd_soc_dai_stream_valid(cpu_dai,   cpu_capture))
-				capture = 1;
+				*capture = 1;
 		}
 	}
 
 	if (rtd->dai_link->playback_only) {
-		playback = 1;
-		capture = 0;
+		*playback = 1;
+		*capture = 0;
 	}
 
 	if (rtd->dai_link->capture_only) {
-		playback = 0;
-		capture = 1;
+		*playback = 0;
+		*capture = 1;
 	}
 
+	return 0;
+}
+
+static int soc_create_pcm(struct snd_pcm **pcm,
+			  struct snd_soc_pcm_runtime *rtd,
+			  int playback, int capture, int num)
+{
+	char new_name[64];
+	int ret;
+
 	/* create the PCM */
 	if (rtd->dai_link->params) {
 		snprintf(new_name, sizeof(new_name), "codec2codec(%s)",
 			 rtd->dai_link->stream_name);
 
 		ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, num,
-					   playback, capture, &pcm);
+					   playback, capture, pcm);
 	} else if (rtd->dai_link->no_pcm) {
 		snprintf(new_name, sizeof(new_name), "(%s)",
 			rtd->dai_link->stream_name);
 
 		ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, num,
-				playback, capture, &pcm);
+				playback, capture, pcm);
 	} else {
 		if (rtd->dai_link->dynamic)
 			snprintf(new_name, sizeof(new_name), "%s (*)",
@@ -2785,7 +2755,7 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
 				"multicodec" : asoc_rtd_to_codec(rtd, 0)->name, num);
 
 		ret = snd_pcm_new(rtd->card->snd_card, new_name, num, playback,
-			capture, &pcm);
+			capture, pcm);
 	}
 	if (ret < 0) {
 		dev_err(rtd->card->dev, "ASoC: can't create pcm %s for dailink %s: %d\n",
@@ -2794,14 +2764,33 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
 	}
 	dev_dbg(rtd->card->dev, "ASoC: registered pcm #%d %s\n",num, new_name);
 
+	return 0;
+}
+
+/* create a new pcm */
+int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
+{
+	struct snd_soc_component *component;
+	struct snd_pcm *pcm;
+	int ret = 0, playback = 0, capture = 0;
+	int i;
+
+	ret = soc_get_playback_capture(rtd, &playback, &capture);
+	if (ret < 0)
+		return ret;
+
+	ret = soc_create_pcm(&pcm, rtd, playback, capture, num);
+	if (ret < 0)
+		return ret;
+
 	/* DAPM dai link stream work */
 	if (rtd->dai_link->params)
 		rtd->close_delayed_work_func = codec2codec_close_delayed_work;
 	else
 		rtd->close_delayed_work_func = snd_soc_close_delayed_work;
 
-	pcm->nonatomic = rtd->dai_link->nonatomic;
 	rtd->pcm = pcm;
+	pcm->nonatomic = rtd->dai_link->nonatomic;
 	pcm->private_data = rtd;
 
 	if (rtd->dai_link->no_pcm || rtd->dai_link->params) {
@@ -2854,8 +2843,8 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
 
 	ret = snd_soc_pcm_component_new(rtd);
 	if (ret < 0) {
-		dev_err(rtd->dev, "ASoC: pcm %s constructor failed for dailink %s: %d\n",
-			new_name, rtd->dai_link->name, ret);
+		dev_err(rtd->dev, "ASoC: pcm constructor failed for dailink %s: %d\n",
+			rtd->dai_link->name, ret);
 		return ret;
 	}
 
diff --git a/sound/soc/soc-topology-test.c b/sound/soc/soc-topology-test.c
new file mode 100644
index 000000000000..ae3968161509
--- /dev/null
+++ b/sound/soc/soc-topology-test.c
@@ -0,0 +1,843 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * soc-topology-test.c  --  ALSA SoC Topology Kernel Unit Tests
+ *
+ * Copyright(c) 2021 Intel Corporation. All rights reserved.
+ */
+
+#include <linux/firmware.h>
+#include <sound/core.h>
+#include <sound/soc.h>
+#include <sound/soc-topology.h>
+#include <kunit/test.h>
+
+/* ===== HELPER FUNCTIONS =================================================== */
+
+/*
+ * snd_soc_component needs device to operate on (primarily for prints), create
+ * fake one, as we don't register with PCI or anything else
+ * device_driver name is used in some of the prints (fmt_single_name) so
+ * we also mock up minimal one
+ */
+static struct device *test_dev;
+
+static struct device_driver test_drv = {
+	.name = "sound-soc-topology-test-driver",
+};
+
+static int snd_soc_tplg_test_init(struct kunit *test)
+{
+	test_dev = root_device_register("sound-soc-topology-test");
+	test_dev = get_device(test_dev);
+	if (!test_dev)
+		return -ENODEV;
+
+	test_dev->driver = &test_drv;
+
+	return 0;
+}
+
+static void snd_soc_tplg_test_exit(struct kunit *test)
+{
+	put_device(test_dev);
+	root_device_unregister(test_dev);
+}
+
+/*
+ * helper struct we use when registering component, as we load topology during
+ * component probe, we need to pass struct kunit somehow to probe function, so
+ * we can report test result
+ */
+struct kunit_soc_component {
+	struct kunit *kunit;
+	int expect; /* what result we expect when loading topology */
+	struct snd_soc_component comp;
+	struct snd_soc_card card;
+	struct firmware fw;
+};
+
+static int d_probe(struct snd_soc_component *component)
+{
+	struct kunit_soc_component *kunit_comp =
+			container_of(component, struct kunit_soc_component, comp);
+	int ret;
+
+	ret = snd_soc_tplg_component_load(component, NULL, &kunit_comp->fw);
+	KUNIT_EXPECT_EQ_MSG(kunit_comp->kunit, kunit_comp->expect, ret,
+			    "Failed topology load");
+
+	return 0;
+}
+
+static void d_remove(struct snd_soc_component *component)
+{
+	struct kunit_soc_component *kunit_comp =
+			container_of(component, struct kunit_soc_component, comp);
+	int ret;
+
+	ret = snd_soc_tplg_component_remove(component);
+	KUNIT_EXPECT_EQ(kunit_comp->kunit, 0, ret);
+}
+
+/*
+ * ASoC minimal boiler plate
+ */
+SND_SOC_DAILINK_DEF(dummy, DAILINK_COMP_ARRAY(COMP_DUMMY()));
+
+SND_SOC_DAILINK_DEF(platform, DAILINK_COMP_ARRAY(COMP_PLATFORM("sound-soc-topology-test")));
+
+static struct snd_soc_dai_link kunit_dai_links[] = {
+	{
+		.name = "KUNIT Audio Port",
+		.id = 0,
+		.stream_name = "Audio Playback/Capture",
+		.nonatomic = 1,
+		.dynamic = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
+		.dpcm_playback = 1,
+		.dpcm_capture = 1,
+		SND_SOC_DAILINK_REG(dummy, dummy, platform),
+	},
+};
+
+static const struct snd_soc_component_driver test_component = {
+	.name = "sound-soc-topology-test",
+	.probe = d_probe,
+	.remove = d_remove,
+	.non_legacy_dai_naming = 1,
+};
+
+/* ===== TOPOLOGY TEMPLATES ================================================= */
+
+// Structural representation of topology which can be generated with:
+// $ touch empty
+// $ alsatplg -c empty -o empty.tplg
+// $ xxd -i empty.tplg
+
+struct tplg_tmpl_001 {
+	struct snd_soc_tplg_hdr header;
+	struct snd_soc_tplg_manifest manifest;
+} __packed;
+
+static struct tplg_tmpl_001 tplg_tmpl_empty = {
+	.header = {
+		.magic = cpu_to_le32(SND_SOC_TPLG_MAGIC),
+		.abi = cpu_to_le32(5),
+		.version = 0,
+		.type = cpu_to_le32(SND_SOC_TPLG_TYPE_MANIFEST),
+		.size = cpu_to_le32(sizeof(struct snd_soc_tplg_hdr)),
+		.vendor_type = 0,
+		.payload_size = cpu_to_le32(sizeof(struct snd_soc_tplg_manifest)),
+		.index = 0,
+		.count = cpu_to_le32(1),
+	},
+
+	.manifest = {
+		.size = cpu_to_le32(sizeof(struct snd_soc_tplg_manifest)),
+		/* rest of fields is 0 */
+	},
+};
+
+// Structural representation of topology containing SectionPCM
+
+struct tplg_tmpl_002 {
+	struct snd_soc_tplg_hdr header;
+	struct snd_soc_tplg_manifest manifest;
+	struct snd_soc_tplg_hdr pcm_header;
+	struct snd_soc_tplg_pcm pcm;
+} __packed;
+
+static struct tplg_tmpl_002 tplg_tmpl_with_pcm = {
+	.header = {
+		.magic = cpu_to_le32(SND_SOC_TPLG_MAGIC),
+		.abi = cpu_to_le32(5),
+		.version = 0,
+		.type = cpu_to_le32(SND_SOC_TPLG_TYPE_MANIFEST),
+		.size = cpu_to_le32(sizeof(struct snd_soc_tplg_hdr)),
+		.vendor_type = 0,
+		.payload_size = cpu_to_le32(sizeof(struct snd_soc_tplg_manifest)),
+		.index = 0,
+		.count = cpu_to_le32(1),
+	},
+	.manifest = {
+		.size = cpu_to_le32(sizeof(struct snd_soc_tplg_manifest)),
+		.pcm_elems = cpu_to_le32(1),
+		/* rest of fields is 0 */
+	},
+	.pcm_header = {
+		.magic = cpu_to_le32(SND_SOC_TPLG_MAGIC),
+		.abi = cpu_to_le32(5),
+		.version = 0,
+		.type = cpu_to_le32(SND_SOC_TPLG_TYPE_PCM),
+		.size = cpu_to_le32(sizeof(struct snd_soc_tplg_hdr)),
+		.vendor_type = 0,
+		.payload_size = cpu_to_le32(sizeof(struct snd_soc_tplg_pcm)),
+		.index = 0,
+		.count = cpu_to_le32(1),
+	},
+	.pcm = {
+		.size = cpu_to_le32(sizeof(struct snd_soc_tplg_pcm)),
+		.pcm_name = "KUNIT Audio",
+		.dai_name = "kunit-audio-dai",
+		.pcm_id = 0,
+		.dai_id = 0,
+		.playback = cpu_to_le32(1),
+		.capture = cpu_to_le32(1),
+		.compress = 0,
+		.stream = {
+			[0] = {
+				.channels = cpu_to_le32(2),
+			},
+			[1] = {
+				.channels = cpu_to_le32(2),
+			},
+		},
+		.num_streams = 0,
+		.caps = {
+			[0] = {
+				.name = "kunit-audio-playback",
+				.channels_min = cpu_to_le32(2),
+				.channels_max = cpu_to_le32(2),
+			},
+			[1] = {
+				.name = "kunit-audio-capture",
+				.channels_min = cpu_to_le32(2),
+				.channels_max = cpu_to_le32(2),
+			},
+		},
+		.flag_mask = 0,
+		.flags = 0,
+		.priv = { 0 },
+	},
+};
+
+/* ===== TEST CASES ========================================================= */
+
+// TEST CASE
+// Test passing NULL component as parameter to snd_soc_tplg_component_load
+
+/*
+ * need to override generic probe function with one using NULL when calling
+ * topology load during component initialization, we don't need .remove
+ * handler as load should fail
+ */
+static int d_probe_null_comp(struct snd_soc_component *component)
+{
+	struct kunit_soc_component *kunit_comp =
+			container_of(component, struct kunit_soc_component, comp);
+	int ret;
+
+	/* instead of passing component pointer as first argument, pass NULL here */
+	ret = snd_soc_tplg_component_load(NULL, NULL, &kunit_comp->fw);
+	KUNIT_EXPECT_EQ_MSG(kunit_comp->kunit, kunit_comp->expect, ret,
+			    "Failed topology load");
+
+	return 0;
+}
+
+static const struct snd_soc_component_driver test_component_null_comp = {
+	.name = "sound-soc-topology-test",
+	.probe = d_probe_null_comp,
+	.non_legacy_dai_naming = 1,
+};
+
+static void snd_soc_tplg_test_load_with_null_comp(struct kunit *test)
+{
+	struct kunit_soc_component *kunit_comp;
+	int ret;
+
+	/* prepare */
+	kunit_comp = kunit_kzalloc(test, sizeof(*kunit_comp), GFP_KERNEL);
+	KUNIT_EXPECT_NOT_ERR_OR_NULL(test, kunit_comp);
+	kunit_comp->kunit = test;
+	kunit_comp->expect = -EINVAL; /* expect failure */
+
+	kunit_comp->card.dev = test_dev,
+	kunit_comp->card.name = "kunit-card",
+	kunit_comp->card.owner = THIS_MODULE,
+	kunit_comp->card.dai_link = kunit_dai_links,
+	kunit_comp->card.num_links = ARRAY_SIZE(kunit_dai_links),
+	kunit_comp->card.fully_routed = true,
+
+	/* run test */
+	ret = snd_soc_register_card(&kunit_comp->card);
+	if (ret != 0 && ret != -EPROBE_DEFER)
+		KUNIT_FAIL(test, "Failed to register card");
+
+	ret = snd_soc_component_initialize(&kunit_comp->comp, &test_component_null_comp, test_dev);
+	KUNIT_EXPECT_EQ(test, 0, ret);
+
+	ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0);
+	KUNIT_EXPECT_EQ(test, 0, ret);
+
+	/* cleanup */
+	ret = snd_soc_unregister_card(&kunit_comp->card);
+	KUNIT_EXPECT_EQ(test, 0, ret);
+
+	snd_soc_unregister_component(test_dev);
+}
+
+// TEST CASE
+// Test passing NULL ops as parameter to snd_soc_tplg_component_load
+
+/*
+ * NULL ops is default case, we pass empty topology (fw), so we don't have
+ * anything to parse and just do nothing, which results in return 0; from
+ * calling soc_tplg_dapm_complete in soc_tplg_process_headers
+ */
+static void snd_soc_tplg_test_load_with_null_ops(struct kunit *test)
+{
+	struct kunit_soc_component *kunit_comp;
+	int ret;
+
+	/* prepare */
+	kunit_comp = kunit_kzalloc(test, sizeof(*kunit_comp), GFP_KERNEL);
+	KUNIT_EXPECT_NOT_ERR_OR_NULL(test, kunit_comp);
+	kunit_comp->kunit = test;
+	kunit_comp->expect = 0; /* expect success */
+
+	kunit_comp->card.dev = test_dev,
+	kunit_comp->card.name = "kunit-card",
+	kunit_comp->card.owner = THIS_MODULE,
+	kunit_comp->card.dai_link = kunit_dai_links,
+	kunit_comp->card.num_links = ARRAY_SIZE(kunit_dai_links),
+	kunit_comp->card.fully_routed = true,
+
+	/* run test */
+	ret = snd_soc_register_card(&kunit_comp->card);
+	if (ret != 0 && ret != -EPROBE_DEFER)
+		KUNIT_FAIL(test, "Failed to register card");
+
+	ret = snd_soc_component_initialize(&kunit_comp->comp, &test_component, test_dev);
+	KUNIT_EXPECT_EQ(test, 0, ret);
+
+	ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0);
+	KUNIT_EXPECT_EQ(test, 0, ret);
+
+	/* cleanup */
+	ret = snd_soc_unregister_card(&kunit_comp->card);
+	KUNIT_EXPECT_EQ(test, 0, ret);
+
+	snd_soc_unregister_component(test_dev);
+}
+
+// TEST CASE
+// Test passing NULL fw as parameter to snd_soc_tplg_component_load
+
+/*
+ * need to override generic probe function with one using NULL pointer to fw
+ * when calling topology load during component initialization, we don't need
+ * .remove handler as load should fail
+ */
+static int d_probe_null_fw(struct snd_soc_component *component)
+{
+	struct kunit_soc_component *kunit_comp =
+			container_of(component, struct kunit_soc_component, comp);
+	int ret;
+
+	/* instead of passing fw pointer as third argument, pass NULL here */
+	ret = snd_soc_tplg_component_load(component, NULL, NULL);
+	KUNIT_EXPECT_EQ_MSG(kunit_comp->kunit, kunit_comp->expect, ret,
+			    "Failed topology load");
+
+	return 0;
+}
+
+static const struct snd_soc_component_driver test_component_null_fw = {
+	.name = "sound-soc-topology-test",
+	.probe = d_probe_null_fw,
+	.non_legacy_dai_naming = 1,
+};
+
+static void snd_soc_tplg_test_load_with_null_fw(struct kunit *test)
+{
+	struct kunit_soc_component *kunit_comp;
+	int ret;
+
+	/* prepare */
+	kunit_comp = kunit_kzalloc(test, sizeof(*kunit_comp), GFP_KERNEL);
+	KUNIT_EXPECT_NOT_ERR_OR_NULL(test, kunit_comp);
+	kunit_comp->kunit = test;
+	kunit_comp->expect = -EINVAL; /* expect failure */
+
+	kunit_comp->card.dev = test_dev,
+	kunit_comp->card.name = "kunit-card",
+	kunit_comp->card.owner = THIS_MODULE,
+	kunit_comp->card.dai_link = kunit_dai_links,
+	kunit_comp->card.num_links = ARRAY_SIZE(kunit_dai_links),
+	kunit_comp->card.fully_routed = true,
+
+	/* run test */
+	ret = snd_soc_register_card(&kunit_comp->card);
+	if (ret != 0 && ret != -EPROBE_DEFER)
+		KUNIT_FAIL(test, "Failed to register card");
+
+	ret = snd_soc_component_initialize(&kunit_comp->comp, &test_component_null_fw, test_dev);
+	KUNIT_EXPECT_EQ(test, 0, ret);
+
+	ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0);
+	KUNIT_EXPECT_EQ(test, 0, ret);
+
+	/* cleanup */
+	ret = snd_soc_unregister_card(&kunit_comp->card);
+	KUNIT_EXPECT_EQ(test, 0, ret);
+
+	snd_soc_unregister_component(test_dev);
+}
+
+// TEST CASE
+// Test passing "empty" topology file
+static void snd_soc_tplg_test_load_empty_tplg(struct kunit *test)
+{
+	struct kunit_soc_component *kunit_comp;
+	struct tplg_tmpl_001 *data;
+	int size;
+	int ret;
+
+	/* prepare */
+	kunit_comp = kunit_kzalloc(test, sizeof(*kunit_comp), GFP_KERNEL);
+	KUNIT_EXPECT_NOT_ERR_OR_NULL(test, kunit_comp);
+	kunit_comp->kunit = test;
+	kunit_comp->expect = 0; /* expect success */
+
+	size = sizeof(tplg_tmpl_empty);
+	data = kunit_kzalloc(kunit_comp->kunit, size, GFP_KERNEL);
+	KUNIT_EXPECT_NOT_ERR_OR_NULL(kunit_comp->kunit, data);
+
+	memcpy(data, &tplg_tmpl_empty, sizeof(tplg_tmpl_empty));
+
+	kunit_comp->fw.data = (u8 *)data;
+	kunit_comp->fw.size = size;
+
+	kunit_comp->card.dev = test_dev,
+	kunit_comp->card.name = "kunit-card",
+	kunit_comp->card.owner = THIS_MODULE,
+	kunit_comp->card.dai_link = kunit_dai_links,
+	kunit_comp->card.num_links = ARRAY_SIZE(kunit_dai_links),
+	kunit_comp->card.fully_routed = true,
+
+	/* run test */
+	ret = snd_soc_register_card(&kunit_comp->card);
+	if (ret != 0 && ret != -EPROBE_DEFER)
+		KUNIT_FAIL(test, "Failed to register card");
+
+	ret = snd_soc_component_initialize(&kunit_comp->comp, &test_component, test_dev);
+	KUNIT_EXPECT_EQ(test, 0, ret);
+
+	ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0);
+	KUNIT_EXPECT_EQ(test, 0, ret);
+
+	/* cleanup */
+	ret = snd_soc_unregister_card(&kunit_comp->card);
+	KUNIT_EXPECT_EQ(test, 0, ret);
+
+	snd_soc_unregister_component(test_dev);
+}
+
+// TEST CASE
+// Test "empty" topology file, but with bad "magic"
+// In theory we could loop through all possible bad values, but it takes too
+// long, so just use SND_SOC_TPLG_MAGIC + 1
+static void snd_soc_tplg_test_load_empty_tplg_bad_magic(struct kunit *test)
+{
+	struct kunit_soc_component *kunit_comp;
+	struct tplg_tmpl_001 *data;
+	int size;
+	int ret;
+
+	/* prepare */
+	kunit_comp = kunit_kzalloc(test, sizeof(*kunit_comp), GFP_KERNEL);
+	KUNIT_EXPECT_NOT_ERR_OR_NULL(test, kunit_comp);
+	kunit_comp->kunit = test;
+	kunit_comp->expect = -EINVAL; /* expect failure */
+
+	size = sizeof(tplg_tmpl_empty);
+	data = kunit_kzalloc(kunit_comp->kunit, size, GFP_KERNEL);
+	KUNIT_EXPECT_NOT_ERR_OR_NULL(kunit_comp->kunit, data);
+
+	memcpy(data, &tplg_tmpl_empty, sizeof(tplg_tmpl_empty));
+	/*
+	 * override abi
+	 * any value != magic number is wrong
+	 */
+	data->header.magic = cpu_to_le32(SND_SOC_TPLG_MAGIC + 1);
+
+	kunit_comp->fw.data = (u8 *)data;
+	kunit_comp->fw.size = size;
+
+	kunit_comp->card.dev = test_dev,
+	kunit_comp->card.name = "kunit-card",
+	kunit_comp->card.owner = THIS_MODULE,
+	kunit_comp->card.dai_link = kunit_dai_links,
+	kunit_comp->card.num_links = ARRAY_SIZE(kunit_dai_links),
+	kunit_comp->card.fully_routed = true,
+
+	/* run test */
+	ret = snd_soc_register_card(&kunit_comp->card);
+	if (ret != 0 && ret != -EPROBE_DEFER)
+		KUNIT_FAIL(test, "Failed to register card");
+
+	ret = snd_soc_component_initialize(&kunit_comp->comp, &test_component, test_dev);
+	KUNIT_EXPECT_EQ(test, 0, ret);
+
+	ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0);
+	KUNIT_EXPECT_EQ(test, 0, ret);
+
+	/* cleanup */
+	ret = snd_soc_unregister_card(&kunit_comp->card);
+	KUNIT_EXPECT_EQ(test, 0, ret);
+
+	snd_soc_unregister_component(test_dev);
+}
+
+// TEST CASE
+// Test "empty" topology file, but with bad "abi"
+// In theory we could loop through all possible bad values, but it takes too
+// long, so just use SND_SOC_TPLG_ABI_VERSION + 1
+static void snd_soc_tplg_test_load_empty_tplg_bad_abi(struct kunit *test)
+{
+	struct kunit_soc_component *kunit_comp;
+	struct tplg_tmpl_001 *data;
+	int size;
+	int ret;
+
+	/* prepare */
+	kunit_comp = kunit_kzalloc(test, sizeof(*kunit_comp), GFP_KERNEL);
+	KUNIT_EXPECT_NOT_ERR_OR_NULL(test, kunit_comp);
+	kunit_comp->kunit = test;
+	kunit_comp->expect = -EINVAL; /* expect failure */
+
+	size = sizeof(tplg_tmpl_empty);
+	data = kunit_kzalloc(kunit_comp->kunit, size, GFP_KERNEL);
+	KUNIT_EXPECT_NOT_ERR_OR_NULL(kunit_comp->kunit, data);
+
+	memcpy(data, &tplg_tmpl_empty, sizeof(tplg_tmpl_empty));
+	/*
+	 * override abi
+	 * any value != accepted range is wrong
+	 */
+	data->header.abi = cpu_to_le32(SND_SOC_TPLG_ABI_VERSION + 1);
+
+	kunit_comp->fw.data = (u8 *)data;
+	kunit_comp->fw.size = size;
+
+	kunit_comp->card.dev = test_dev,
+	kunit_comp->card.name = "kunit-card",
+	kunit_comp->card.owner = THIS_MODULE,
+	kunit_comp->card.dai_link = kunit_dai_links,
+	kunit_comp->card.num_links = ARRAY_SIZE(kunit_dai_links),
+	kunit_comp->card.fully_routed = true,
+
+	/* run test */
+	ret = snd_soc_register_card(&kunit_comp->card);
+	if (ret != 0 && ret != -EPROBE_DEFER)
+		KUNIT_FAIL(test, "Failed to register card");
+
+	ret = snd_soc_component_initialize(&kunit_comp->comp, &test_component, test_dev);
+	KUNIT_EXPECT_EQ(test, 0, ret);
+
+	ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0);
+	KUNIT_EXPECT_EQ(test, 0, ret);
+
+	/* cleanup */
+	ret = snd_soc_unregister_card(&kunit_comp->card);
+	KUNIT_EXPECT_EQ(test, 0, ret);
+
+	snd_soc_unregister_component(test_dev);
+}
+
+// TEST CASE
+// Test "empty" topology file, but with bad "size"
+// In theory we could loop through all possible bad values, but it takes too
+// long, so just use sizeof(struct snd_soc_tplg_hdr) + 1
+static void snd_soc_tplg_test_load_empty_tplg_bad_size(struct kunit *test)
+{
+	struct kunit_soc_component *kunit_comp;
+	struct tplg_tmpl_001 *data;
+	int size;
+	int ret;
+
+	/* prepare */
+	kunit_comp = kunit_kzalloc(test, sizeof(*kunit_comp), GFP_KERNEL);
+	KUNIT_EXPECT_NOT_ERR_OR_NULL(test, kunit_comp);
+	kunit_comp->kunit = test;
+	kunit_comp->expect = -EINVAL; /* expect failure */
+
+	size = sizeof(tplg_tmpl_empty);
+	data = kunit_kzalloc(kunit_comp->kunit, size, GFP_KERNEL);
+	KUNIT_EXPECT_NOT_ERR_OR_NULL(kunit_comp->kunit, data);
+
+	memcpy(data, &tplg_tmpl_empty, sizeof(tplg_tmpl_empty));
+	/*
+	 * override size
+	 * any value != struct size is wrong
+	 */
+	data->header.size = cpu_to_le32(sizeof(struct snd_soc_tplg_hdr) + 1);
+
+	kunit_comp->fw.data = (u8 *)data;
+	kunit_comp->fw.size = size;
+
+	kunit_comp->card.dev = test_dev,
+	kunit_comp->card.name = "kunit-card",
+	kunit_comp->card.owner = THIS_MODULE,
+	kunit_comp->card.dai_link = kunit_dai_links,
+	kunit_comp->card.num_links = ARRAY_SIZE(kunit_dai_links),
+	kunit_comp->card.fully_routed = true,
+
+	/* run test */
+	ret = snd_soc_register_card(&kunit_comp->card);
+	if (ret != 0 && ret != -EPROBE_DEFER)
+		KUNIT_FAIL(test, "Failed to register card");
+
+	ret = snd_soc_component_initialize(&kunit_comp->comp, &test_component, test_dev);
+	KUNIT_EXPECT_EQ(test, 0, ret);
+
+	ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0);
+	KUNIT_EXPECT_EQ(test, 0, ret);
+
+	/* cleanup */
+	ret = snd_soc_unregister_card(&kunit_comp->card);
+	KUNIT_EXPECT_EQ(test, 0, ret);
+
+	snd_soc_unregister_component(test_dev);
+}
+
+// TEST CASE
+// Test "empty" topology file, but with bad "payload_size"
+// In theory we could loop through all possible bad values, but it takes too
+// long, so just use the known wrong one
+static void snd_soc_tplg_test_load_empty_tplg_bad_payload_size(struct kunit *test)
+{
+	struct kunit_soc_component *kunit_comp;
+	struct tplg_tmpl_001 *data;
+	int size;
+	int ret;
+
+	/* prepare */
+	kunit_comp = kunit_kzalloc(test, sizeof(*kunit_comp), GFP_KERNEL);
+	KUNIT_EXPECT_NOT_ERR_OR_NULL(test, kunit_comp);
+	kunit_comp->kunit = test;
+	kunit_comp->expect = -EINVAL; /* expect failure */
+
+	size = sizeof(tplg_tmpl_empty);
+	data = kunit_kzalloc(kunit_comp->kunit, size, GFP_KERNEL);
+	KUNIT_EXPECT_NOT_ERR_OR_NULL(kunit_comp->kunit, data);
+
+	memcpy(data, &tplg_tmpl_empty, sizeof(tplg_tmpl_empty));
+	/*
+	 * override payload size
+	 * there is only explicit check for 0, so check with it, other values
+	 * are handled by just not reading behind EOF
+	 */
+	data->header.payload_size = 0;
+
+	kunit_comp->fw.data = (u8 *)data;
+	kunit_comp->fw.size = size;
+
+	kunit_comp->card.dev = test_dev,
+	kunit_comp->card.name = "kunit-card",
+	kunit_comp->card.owner = THIS_MODULE,
+	kunit_comp->card.dai_link = kunit_dai_links,
+	kunit_comp->card.num_links = ARRAY_SIZE(kunit_dai_links),
+	kunit_comp->card.fully_routed = true,
+
+	/* run test */
+	ret = snd_soc_register_card(&kunit_comp->card);
+	if (ret != 0 && ret != -EPROBE_DEFER)
+		KUNIT_FAIL(test, "Failed to register card");
+
+	ret = snd_soc_component_initialize(&kunit_comp->comp, &test_component, test_dev);
+	KUNIT_EXPECT_EQ(test, 0, ret);
+
+	ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0);
+	KUNIT_EXPECT_EQ(test, 0, ret);
+
+	/* cleanup */
+	snd_soc_unregister_component(test_dev);
+
+	ret = snd_soc_unregister_card(&kunit_comp->card);
+	KUNIT_EXPECT_EQ(test, 0, ret);
+}
+
+// TEST CASE
+// Test passing topology file with PCM definition
+static void snd_soc_tplg_test_load_pcm_tplg(struct kunit *test)
+{
+	struct kunit_soc_component *kunit_comp;
+	u8 *data;
+	int size;
+	int ret;
+
+	/* prepare */
+	kunit_comp = kunit_kzalloc(test, sizeof(*kunit_comp), GFP_KERNEL);
+	KUNIT_EXPECT_NOT_ERR_OR_NULL(test, kunit_comp);
+	kunit_comp->kunit = test;
+	kunit_comp->expect = 0; /* expect success */
+
+	size = sizeof(tplg_tmpl_with_pcm);
+	data = kunit_kzalloc(kunit_comp->kunit, size, GFP_KERNEL);
+	KUNIT_EXPECT_NOT_ERR_OR_NULL(kunit_comp->kunit, data);
+
+	memcpy(data, &tplg_tmpl_with_pcm, sizeof(tplg_tmpl_with_pcm));
+
+	kunit_comp->fw.data = data;
+	kunit_comp->fw.size = size;
+
+	kunit_comp->card.dev = test_dev,
+	kunit_comp->card.name = "kunit-card",
+	kunit_comp->card.owner = THIS_MODULE,
+	kunit_comp->card.dai_link = kunit_dai_links,
+	kunit_comp->card.num_links = ARRAY_SIZE(kunit_dai_links),
+	kunit_comp->card.fully_routed = true,
+
+	/* run test */
+	ret = snd_soc_register_card(&kunit_comp->card);
+	if (ret != 0 && ret != -EPROBE_DEFER)
+		KUNIT_FAIL(test, "Failed to register card");
+
+	ret = snd_soc_component_initialize(&kunit_comp->comp, &test_component, test_dev);
+	KUNIT_EXPECT_EQ(test, 0, ret);
+
+	ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0);
+	KUNIT_EXPECT_EQ(test, 0, ret);
+
+	snd_soc_unregister_component(test_dev);
+
+	/* cleanup */
+	ret = snd_soc_unregister_card(&kunit_comp->card);
+	KUNIT_EXPECT_EQ(test, 0, ret);
+}
+
+// TEST CASE
+// Test passing topology file with PCM definition
+// with component reload
+static void snd_soc_tplg_test_load_pcm_tplg_reload_comp(struct kunit *test)
+{
+	struct kunit_soc_component *kunit_comp;
+	u8 *data;
+	int size;
+	int ret;
+	int i;
+
+	/* prepare */
+	kunit_comp = kunit_kzalloc(test, sizeof(*kunit_comp), GFP_KERNEL);
+	KUNIT_EXPECT_NOT_ERR_OR_NULL(test, kunit_comp);
+	kunit_comp->kunit = test;
+	kunit_comp->expect = 0; /* expect success */
+
+	size = sizeof(tplg_tmpl_with_pcm);
+	data = kunit_kzalloc(kunit_comp->kunit, size, GFP_KERNEL);
+	KUNIT_EXPECT_NOT_ERR_OR_NULL(kunit_comp->kunit, data);
+
+	memcpy(data, &tplg_tmpl_with_pcm, sizeof(tplg_tmpl_with_pcm));
+
+	kunit_comp->fw.data = data;
+	kunit_comp->fw.size = size;
+
+	kunit_comp->card.dev = test_dev,
+	kunit_comp->card.name = "kunit-card",
+	kunit_comp->card.owner = THIS_MODULE,
+	kunit_comp->card.dai_link = kunit_dai_links,
+	kunit_comp->card.num_links = ARRAY_SIZE(kunit_dai_links),
+	kunit_comp->card.fully_routed = true,
+
+	/* run test */
+	ret = snd_soc_register_card(&kunit_comp->card);
+	if (ret != 0 && ret != -EPROBE_DEFER)
+		KUNIT_FAIL(test, "Failed to register card");
+
+	for (i = 0; i < 100; i++) {
+		ret = snd_soc_component_initialize(&kunit_comp->comp, &test_component, test_dev);
+		KUNIT_EXPECT_EQ(test, 0, ret);
+
+		ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0);
+		KUNIT_EXPECT_EQ(test, 0, ret);
+
+		snd_soc_unregister_component(test_dev);
+	}
+
+	/* cleanup */
+	ret = snd_soc_unregister_card(&kunit_comp->card);
+	KUNIT_EXPECT_EQ(test, 0, ret);
+}
+
+// TEST CASE
+// Test passing topology file with PCM definition
+// with card reload
+static void snd_soc_tplg_test_load_pcm_tplg_reload_card(struct kunit *test)
+{
+	struct kunit_soc_component *kunit_comp;
+	u8 *data;
+	int size;
+	int ret;
+	int i;
+
+	/* prepare */
+	kunit_comp = kunit_kzalloc(test, sizeof(*kunit_comp), GFP_KERNEL);
+	KUNIT_EXPECT_NOT_ERR_OR_NULL(test, kunit_comp);
+	kunit_comp->kunit = test;
+	kunit_comp->expect = 0; /* expect success */
+
+	size = sizeof(tplg_tmpl_with_pcm);
+	data = kunit_kzalloc(kunit_comp->kunit, size, GFP_KERNEL);
+	KUNIT_EXPECT_NOT_ERR_OR_NULL(kunit_comp->kunit, data);
+
+	memcpy(data, &tplg_tmpl_with_pcm, sizeof(tplg_tmpl_with_pcm));
+
+	kunit_comp->fw.data = data;
+	kunit_comp->fw.size = size;
+
+	kunit_comp->card.dev = test_dev,
+	kunit_comp->card.name = "kunit-card",
+	kunit_comp->card.owner = THIS_MODULE,
+	kunit_comp->card.dai_link = kunit_dai_links,
+	kunit_comp->card.num_links = ARRAY_SIZE(kunit_dai_links),
+	kunit_comp->card.fully_routed = true,
+
+	/* run test */
+	ret = snd_soc_component_initialize(&kunit_comp->comp, &test_component, test_dev);
+	KUNIT_EXPECT_EQ(test, 0, ret);
+
+	ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0);
+	KUNIT_EXPECT_EQ(test, 0, ret);
+
+	for (i = 0; i < 100; i++) {
+		ret = snd_soc_register_card(&kunit_comp->card);
+		if (ret != 0 && ret != -EPROBE_DEFER)
+			KUNIT_FAIL(test, "Failed to register card");
+
+		ret = snd_soc_unregister_card(&kunit_comp->card);
+		KUNIT_EXPECT_EQ(test, 0, ret);
+	}
+
+	/* cleanup */
+	snd_soc_unregister_component(test_dev);
+}
+
+/* ===== KUNIT MODULE DEFINITIONS =========================================== */
+
+static struct kunit_case snd_soc_tplg_test_cases[] = {
+	KUNIT_CASE(snd_soc_tplg_test_load_with_null_comp),
+	KUNIT_CASE(snd_soc_tplg_test_load_with_null_ops),
+	KUNIT_CASE(snd_soc_tplg_test_load_with_null_fw),
+	KUNIT_CASE(snd_soc_tplg_test_load_empty_tplg),
+	KUNIT_CASE(snd_soc_tplg_test_load_empty_tplg_bad_magic),
+	KUNIT_CASE(snd_soc_tplg_test_load_empty_tplg_bad_abi),
+	KUNIT_CASE(snd_soc_tplg_test_load_empty_tplg_bad_size),
+	KUNIT_CASE(snd_soc_tplg_test_load_empty_tplg_bad_payload_size),
+	KUNIT_CASE(snd_soc_tplg_test_load_pcm_tplg),
+	KUNIT_CASE(snd_soc_tplg_test_load_pcm_tplg_reload_comp),
+	KUNIT_CASE(snd_soc_tplg_test_load_pcm_tplg_reload_card),
+	{}
+};
+
+static struct kunit_suite snd_soc_tplg_test_suite = {
+	.name = "snd_soc_tplg_test",
+	.init = snd_soc_tplg_test_init,
+	.exit = snd_soc_tplg_test_exit,
+	.test_cases = snd_soc_tplg_test_cases,
+};
+
+kunit_test_suites(&snd_soc_tplg_test_suite);
+
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c
index 22e7b4c9115b..1b0cd33a1348 100644
--- a/sound/soc/soc-topology.c
+++ b/sound/soc/soc-topology.c
@@ -1672,7 +1672,7 @@ static void set_dai_flags(struct snd_soc_dai_driver *dai_drv,
 			  unsigned int flag_mask, unsigned int flags)
 {
 	if (flag_mask & SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_RATES)
-		dai_drv->symmetric_rates =
+		dai_drv->symmetric_rate =
 			flags & SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_RATES ? 1 : 0;
 
 	if (flag_mask & SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_CHANNELS)
@@ -1681,7 +1681,7 @@ static void set_dai_flags(struct snd_soc_dai_driver *dai_drv,
 			1 : 0;
 
 	if (flag_mask & SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_SAMPLEBITS)
-		dai_drv->symmetric_samplebits =
+		dai_drv->symmetric_sample_bits =
 			flags & SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_SAMPLEBITS ?
 			1 : 0;
 }
@@ -1764,7 +1764,7 @@ static void set_link_flags(struct snd_soc_dai_link *link,
 		unsigned int flag_mask, unsigned int flags)
 {
 	if (flag_mask & SND_SOC_TPLG_LNK_FLGBIT_SYMMETRIC_RATES)
-		link->symmetric_rates =
+		link->symmetric_rate =
 			flags & SND_SOC_TPLG_LNK_FLGBIT_SYMMETRIC_RATES ? 1 : 0;
 
 	if (flag_mask & SND_SOC_TPLG_LNK_FLGBIT_SYMMETRIC_CHANNELS)
@@ -1773,7 +1773,7 @@ static void set_link_flags(struct snd_soc_dai_link *link,
 			1 : 0;
 
 	if (flag_mask & SND_SOC_TPLG_LNK_FLGBIT_SYMMETRIC_SAMPLEBITS)
-		link->symmetric_samplebits =
+		link->symmetric_sample_bits =
 			flags & SND_SOC_TPLG_LNK_FLGBIT_SYMMETRIC_SAMPLEBITS ?
 			1 : 0;
 
@@ -2660,8 +2660,14 @@ int snd_soc_tplg_component_load(struct snd_soc_component *comp,
 	struct soc_tplg tplg;
 	int ret;
 
-	/* component needs to exist to keep and reference data while parsing */
-	if (!comp)
+	/*
+	 * check if we have sane parameters:
+	 * comp - needs to exist to keep and reference data while parsing
+	 * comp->dev - used for resource management and prints
+	 * comp->card - used for setting card related parameters
+	 * fw - we need it, as it is the very thing we parse
+	 */
+	if (!comp || !comp->dev || !comp->card || !fw)
 		return -EINVAL;
 
 	/* setup parsing context */
@@ -2669,11 +2675,13 @@ int snd_soc_tplg_component_load(struct snd_soc_component *comp,
 	tplg.fw = fw;
 	tplg.dev = comp->dev;
 	tplg.comp = comp;
-	tplg.ops = ops;
-	tplg.io_ops = ops->io_ops;
-	tplg.io_ops_count = ops->io_ops_count;
-	tplg.bytes_ext_ops = ops->bytes_ext_ops;
-	tplg.bytes_ext_ops_count = ops->bytes_ext_ops_count;
+	if (ops) {
+		tplg.ops = ops;
+		tplg.io_ops = ops->io_ops;
+		tplg.io_ops_count = ops->io_ops_count;
+		tplg.bytes_ext_ops = ops->bytes_ext_ops;
+		tplg.bytes_ext_ops_count = ops->bytes_ext_ops_count;
+	}
 
 	ret = soc_tplg_load(&tplg);
 	/* free the created components if fail to load topology */
diff --git a/sound/soc/sof/core.c b/sound/soc/sof/core.c
index adc7c37145d6..6d8f7d9fd192 100644
--- a/sound/soc/sof/core.c
+++ b/sound/soc/sof/core.c
@@ -246,6 +246,8 @@ static int sof_probe_continue(struct snd_sof_dev *sdev)
 	if (plat_data->sof_probe_complete)
 		plat_data->sof_probe_complete(sdev->dev);
 
+	sdev->probe_completed = true;
+
 	return 0;
 
 fw_trace_err:
@@ -316,6 +318,7 @@ int snd_sof_device_probe(struct device *dev, struct snd_sof_pdata *plat_data)
 	INIT_LIST_HEAD(&sdev->route_list);
 	spin_lock_init(&sdev->ipc_lock);
 	spin_lock_init(&sdev->hw_lock);
+	mutex_init(&sdev->power_state_access);
 
 	if (IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE))
 		INIT_WORK(&sdev->probe_work, sof_probe_work);
@@ -339,6 +342,14 @@ int snd_sof_device_probe(struct device *dev, struct snd_sof_pdata *plat_data)
 }
 EXPORT_SYMBOL(snd_sof_device_probe);
 
+bool snd_sof_device_probe_completed(struct device *dev)
+{
+	struct snd_sof_dev *sdev = dev_get_drvdata(dev);
+
+	return sdev->probe_completed;
+}
+EXPORT_SYMBOL(snd_sof_device_probe_completed);
+
 int snd_sof_device_remove(struct device *dev)
 {
 	struct snd_sof_dev *sdev = dev_get_drvdata(dev);
@@ -384,6 +395,14 @@ int snd_sof_device_remove(struct device *dev)
 }
 EXPORT_SYMBOL(snd_sof_device_remove);
 
+int snd_sof_device_shutdown(struct device *dev)
+{
+	struct snd_sof_dev *sdev = dev_get_drvdata(dev);
+
+	return snd_sof_shutdown(sdev);
+}
+EXPORT_SYMBOL(snd_sof_device_shutdown);
+
 MODULE_AUTHOR("Liam Girdwood");
 MODULE_DESCRIPTION("Sound Open Firmware (SOF) Core");
 MODULE_LICENSE("Dual BSD/GPL");
diff --git a/sound/soc/sof/intel/hda-compress.c b/sound/soc/sof/intel/hda-compress.c
index 53c08034fa22..fe2f3f7d236b 100644
--- a/sound/soc/sof/intel/hda-compress.c
+++ b/sound/soc/sof/intel/hda-compress.c
@@ -25,7 +25,7 @@ int hda_probe_compr_assign(struct snd_sof_dev *sdev,
 {
 	struct hdac_ext_stream *stream;
 
-	stream = hda_dsp_stream_get(sdev, cstream->direction);
+	stream = hda_dsp_stream_get(sdev, cstream->direction, 0);
 	if (!stream)
 		return -EBUSY;
 
@@ -82,7 +82,7 @@ int hda_probe_compr_set_params(struct snd_sof_dev *sdev,
 
 	ret = hda_dsp_stream_hw_params(sdev, stream, dmab, NULL);
 	if (ret < 0) {
-		dev_err(sdev->dev, "error: hdac prepare failed: %x\n", ret);
+		dev_err(sdev->dev, "error: hdac prepare failed: %d\n", ret);
 		return ret;
 	}
 
diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c
index 1799fc56a3e4..5788fe356960 100644
--- a/sound/soc/sof/intel/hda-dsp.c
+++ b/sound/soc/sof/intel/hda-dsp.c
@@ -624,7 +624,7 @@ static int hda_suspend(struct snd_sof_dev *sdev, bool runtime_suspend)
 #endif
 
 	/* power down DSP */
-	ret = hda_dsp_core_reset_power_down(sdev, chip->host_managed_cores_mask);
+	ret = snd_sof_dsp_core_power_down(sdev, chip->host_managed_cores_mask);
 	if (ret < 0) {
 		dev_err(sdev->dev,
 			"error: failed to power down core during suspend\n");
@@ -732,7 +732,7 @@ int hda_dsp_resume(struct snd_sof_dev *sdev)
 				ret = snd_hdac_ext_bus_link_power_up(hlink);
 				if (ret < 0) {
 					dev_dbg(sdev->dev,
-						"error %x in %s: failed to power up links",
+						"error %d in %s: failed to power up links",
 						ret, __func__);
 					return ret;
 				}
@@ -934,19 +934,15 @@ void hda_dsp_d0i3_work(struct work_struct *work)
 						      d0i3_work.work);
 	struct hdac_bus *bus = &hdev->hbus.core;
 	struct snd_sof_dev *sdev = dev_get_drvdata(bus->dev);
-	struct sof_dsp_power_state target_state;
+	struct sof_dsp_power_state target_state = {
+		.state = SOF_DSP_PM_D0,
+		.substate = SOF_HDA_DSP_PM_D0I3,
+	};
 	int ret;
 
-	target_state.state = SOF_DSP_PM_D0;
-
 	/* DSP can enter D0I3 iff only D0I3-compatible streams are active */
-	if (snd_sof_dsp_only_d0i3_compatible_stream_active(sdev))
-		target_state.substate = SOF_HDA_DSP_PM_D0I3;
-	else
-		target_state.substate = SOF_HDA_DSP_PM_D0I0;
-
-	/* remain in D0I0 */
-	if (target_state.substate == SOF_HDA_DSP_PM_D0I0)
+	if (!snd_sof_dsp_only_d0i3_compatible_stream_active(sdev))
+		/* remain in D0I0 */
 		return;
 
 	/* This can fail but error cannot be propagated */
diff --git a/sound/soc/sof/intel/hda-loader.c b/sound/soc/sof/intel/hda-loader.c
index ed773696b495..fc25ee8f68dc 100644
--- a/sound/soc/sof/intel/hda-loader.c
+++ b/sound/soc/sof/intel/hda-loader.c
@@ -35,7 +35,7 @@ static struct hdac_ext_stream *cl_stream_prepare(struct snd_sof_dev *sdev, unsig
 	struct pci_dev *pci = to_pci_dev(sdev->dev);
 	int ret;
 
-	dsp_stream = hda_dsp_stream_get(sdev, direction);
+	dsp_stream = hda_dsp_stream_get(sdev, direction, 0);
 
 	if (!dsp_stream) {
 		dev_err(sdev->dev, "error: no stream available\n");
@@ -47,7 +47,7 @@ static struct hdac_ext_stream *cl_stream_prepare(struct snd_sof_dev *sdev, unsig
 	/* allocate DMA buffer */
 	ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV_SG, &pci->dev, size, dmab);
 	if (ret < 0) {
-		dev_err(sdev->dev, "error: memory alloc failed: %x\n", ret);
+		dev_err(sdev->dev, "error: memory alloc failed: %d\n", ret);
 		goto error;
 	}
 
@@ -58,13 +58,13 @@ static struct hdac_ext_stream *cl_stream_prepare(struct snd_sof_dev *sdev, unsig
 	if (direction == SNDRV_PCM_STREAM_CAPTURE) {
 		ret = hda_dsp_iccmax_stream_hw_params(sdev, dsp_stream, dmab, NULL);
 		if (ret < 0) {
-			dev_err(sdev->dev, "error: iccmax stream prepare failed: %x\n", ret);
+			dev_err(sdev->dev, "error: iccmax stream prepare failed: %d\n", ret);
 			goto error;
 		}
 	} else {
 		ret = hda_dsp_stream_hw_params(sdev, dsp_stream, dmab, NULL);
 		if (ret < 0) {
-			dev_err(sdev->dev, "error: hdac prepare failed: %x\n", ret);
+			dev_err(sdev->dev, "error: hdac prepare failed: %d\n", ret);
 			goto error;
 		}
 		hda_dsp_stream_spib_config(sdev, dsp_stream, HDA_DSP_SPIB_ENABLE, size);
@@ -93,7 +93,7 @@ static int cl_dsp_init(struct snd_sof_dev *sdev, int stream_tag)
 	int i;
 
 	/* step 1: power up corex */
-	ret = hda_dsp_core_power_up(sdev, chip->host_managed_cores_mask);
+	ret = snd_sof_dsp_core_power_up(sdev, chip->host_managed_cores_mask);
 	if (ret < 0) {
 		if (hda->boot_iteration == HDA_FW_BOOT_ATTEMPTS)
 			dev_err(sdev->dev, "error: dsp core 0/1 power up failed\n");
@@ -147,8 +147,9 @@ static int cl_dsp_init(struct snd_sof_dev *sdev, int stream_tag)
 				       chip->ipc_ack_mask,
 				       chip->ipc_ack_mask);
 
-	/* step 5: power down corex */
-	ret = hda_dsp_core_power_down(sdev, chip->host_managed_cores_mask & ~(BIT(0)));
+	/* step 5: power down cores that are no longer needed */
+	ret = snd_sof_dsp_core_power_down(sdev, chip->host_managed_cores_mask &
+					  ~(chip->init_core_mask));
 	if (ret < 0) {
 		if (hda->boot_iteration == HDA_FW_BOOT_ATTEMPTS)
 			dev_err(sdev->dev,
@@ -183,7 +184,7 @@ err:
 		flags |= SOF_DBG_DUMP_FORCE_ERR_LEVEL;
 
 	hda_dsp_dump(sdev, flags);
-	hda_dsp_core_reset_power_down(sdev, chip->host_managed_cores_mask);
+	snd_sof_dsp_core_power_down(sdev, chip->host_managed_cores_mask);
 
 	return ret;
 }
diff --git a/sound/soc/sof/intel/hda-pcm.c b/sound/soc/sof/intel/hda-pcm.c
index 5d35bb18660a..df00db8369c7 100644
--- a/sound/soc/sof/intel/hda-pcm.c
+++ b/sound/soc/sof/intel/hda-pcm.c
@@ -111,7 +111,7 @@ int hda_dsp_pcm_hw_params(struct snd_sof_dev *sdev,
 
 	ret = hda_dsp_stream_hw_params(sdev, stream, dmab, params);
 	if (ret < 0) {
-		dev_err(sdev->dev, "error: hdac prepare failed: %x\n", ret);
+		dev_err(sdev->dev, "error: hdac prepare failed: %d\n", ret);
 		return ret;
 	}
 
@@ -215,11 +215,25 @@ found:
 int hda_dsp_pcm_open(struct snd_sof_dev *sdev,
 		     struct snd_pcm_substream *substream)
 {
+	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
+	struct snd_soc_component *scomp = sdev->component;
 	struct hdac_ext_stream *dsp_stream;
+	struct snd_sof_pcm *spcm;
 	int direction = substream->stream;
+	u32 flags = 0;
+
+	spcm = snd_sof_find_spcm_dai(scomp, rtd);
+	if (!spcm) {
+		dev_err(sdev->dev, "error: can't find PCM with DAI ID %d\n", rtd->dai_link->id);
+		return -EINVAL;
+	}
 
-	dsp_stream = hda_dsp_stream_get(sdev, direction);
+	/* All playback and D0i3 compatible streams are DMI L1 capable */
+	if (direction == SNDRV_PCM_STREAM_PLAYBACK ||
+	    spcm->stream[substream->stream].d0i3_compatible)
+		flags |= SOF_HDA_STREAM_DMI_L1_COMPATIBLE;
 
+	dsp_stream = hda_dsp_stream_get(sdev, direction, flags);
 	if (!dsp_stream) {
 		dev_err(sdev->dev, "error: no stream available\n");
 		return -ENODEV;
diff --git a/sound/soc/sof/intel/hda-stream.c b/sound/soc/sof/intel/hda-stream.c
index 0e09ede922c7..40a3993ae2cb 100644
--- a/sound/soc/sof/intel/hda-stream.c
+++ b/sound/soc/sof/intel/hda-stream.c
@@ -155,7 +155,7 @@ int hda_dsp_stream_spib_config(struct snd_sof_dev *sdev,
 
 /* get next unused stream */
 struct hdac_ext_stream *
-hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction)
+hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction, u32 flags)
 {
 	struct hdac_bus *bus = sof_to_bus(sdev);
 	struct sof_intel_hda_stream *hda_stream;
@@ -183,18 +183,22 @@ hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction)
 	spin_unlock_irq(&bus->reg_lock);
 
 	/* stream found ? */
-	if (!stream)
+	if (!stream) {
 		dev_err(sdev->dev, "error: no free %s streams\n",
 			direction == SNDRV_PCM_STREAM_PLAYBACK ?
 			"playback" : "capture");
+		return stream;
+	}
+
+	hda_stream->flags = flags;
 
 	/*
-	 * Disable DMI Link L1 entry when capture stream is opened.
+	 * Prevent DMI Link L1 entry for streams that don't support it.
 	 * Workaround to address a known issue with host DMA that results
 	 * in xruns during pause/release in capture scenarios.
 	 */
 	if (!IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_ALWAYS_ENABLE_DMI_L1))
-		if (stream && direction == SNDRV_PCM_STREAM_CAPTURE)
+		if (stream && !(flags & SOF_HDA_STREAM_DMI_L1_COMPATIBLE))
 			snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR,
 						HDA_VS_INTEL_EM2,
 						HDA_VS_INTEL_EM2_L1SEN, 0);
@@ -206,37 +210,39 @@ hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction)
 int hda_dsp_stream_put(struct snd_sof_dev *sdev, int direction, int stream_tag)
 {
 	struct hdac_bus *bus = sof_to_bus(sdev);
+	struct sof_intel_hda_stream *hda_stream;
+	struct hdac_ext_stream *stream;
 	struct hdac_stream *s;
-	bool active_capture_stream = false;
+	bool dmi_l1_enable = true;
 	bool found = false;
 
 	spin_lock_irq(&bus->reg_lock);
 
 	/*
-	 * close stream matching the stream tag
-	 * and check if there are any open capture streams.
+	 * close stream matching the stream tag and check if there are any open streams
+	 * that are DMI L1 incompatible.
 	 */
 	list_for_each_entry(s, &bus->stream_list, list) {
+		stream = stream_to_hdac_ext_stream(s);
+		hda_stream = container_of(stream, struct sof_intel_hda_stream, hda_stream);
+
 		if (!s->opened)
 			continue;
 
 		if (s->direction == direction && s->stream_tag == stream_tag) {
 			s->opened = false;
 			found = true;
-		} else if (s->direction == SNDRV_PCM_STREAM_CAPTURE) {
-			active_capture_stream = true;
+		} else if (!(hda_stream->flags & SOF_HDA_STREAM_DMI_L1_COMPATIBLE)) {
+			dmi_l1_enable = false;
 		}
 	}
 
 	spin_unlock_irq(&bus->reg_lock);
 
-	/* Enable DMI L1 entry if there are no capture streams open */
-	if (!IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_ALWAYS_ENABLE_DMI_L1))
-		if (!active_capture_stream)
-			snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR,
-						HDA_VS_INTEL_EM2,
-						HDA_VS_INTEL_EM2_L1SEN,
-						HDA_VS_INTEL_EM2_L1SEN);
+	/* Enable DMI L1 if permitted */
+	if (!IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_ALWAYS_ENABLE_DMI_L1) && dmi_l1_enable)
+		snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, HDA_VS_INTEL_EM2,
+					HDA_VS_INTEL_EM2_L1SEN, HDA_VS_INTEL_EM2_L1SEN);
 
 	if (!found) {
 		dev_dbg(sdev->dev, "stream_tag %d not opened!\n", stream_tag);
diff --git a/sound/soc/sof/intel/hda-trace.c b/sound/soc/sof/intel/hda-trace.c
index 1eb746d5adeb..29e3da3c63db 100644
--- a/sound/soc/sof/intel/hda-trace.c
+++ b/sound/soc/sof/intel/hda-trace.c
@@ -32,7 +32,7 @@ static int hda_dsp_trace_prepare(struct snd_sof_dev *sdev)
 
 	ret = hda_dsp_stream_hw_params(sdev, stream, dmab, NULL);
 	if (ret < 0)
-		dev_err(sdev->dev, "error: hdac prepare failed: %x\n", ret);
+		dev_err(sdev->dev, "error: hdac prepare failed: %d\n", ret);
 
 	return ret;
 }
@@ -42,8 +42,8 @@ int hda_dsp_trace_init(struct snd_sof_dev *sdev, u32 *stream_tag)
 	struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
 	int ret;
 
-	hda->dtrace_stream = hda_dsp_stream_get(sdev,
-						SNDRV_PCM_STREAM_CAPTURE);
+	hda->dtrace_stream = hda_dsp_stream_get(sdev, SNDRV_PCM_STREAM_CAPTURE,
+						SOF_HDA_STREAM_DMI_L1_COMPATIBLE);
 
 	if (!hda->dtrace_stream) {
 		dev_err(sdev->dev,
@@ -59,7 +59,7 @@ int hda_dsp_trace_init(struct snd_sof_dev *sdev, u32 *stream_tag)
 	 */
 	ret = hda_dsp_trace_prepare(sdev);
 	if (ret < 0) {
-		dev_err(sdev->dev, "error: hdac trace init failed: %x\n", ret);
+		dev_err(sdev->dev, "error: hdac trace init failed: %d\n", ret);
 		hda_dsp_stream_put(sdev, SNDRV_PCM_STREAM_CAPTURE, *stream_tag);
 		hda->dtrace_stream = NULL;
 		*stream_tag = 0;
diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c
index b625d852b999..0dc3a8c0f5e3 100644
--- a/sound/soc/sof/intel/hda.c
+++ b/sound/soc/sof/intel/hda.c
@@ -285,11 +285,13 @@ static char *hda_model;
 module_param(hda_model, charp, 0444);
 MODULE_PARM_DESC(hda_model, "Use the given HDA board model.");
 
-#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
+#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) || IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE)
 static int hda_dmic_num = -1;
 module_param_named(dmic_num, hda_dmic_num, int, 0444);
 MODULE_PARM_DESC(dmic_num, "SOF HDA DMIC number");
+#endif
 
+#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
 static bool hda_codec_use_common_hdmi = IS_ENABLED(CONFIG_SND_HDA_CODEC_HDMI);
 module_param_named(use_common_hdmi, hda_codec_use_common_hdmi, bool, 0444);
 MODULE_PARM_DESC(use_common_hdmi, "SOF HDA use common HDMI codec driver");
@@ -317,26 +319,6 @@ static const struct hda_dsp_msg_code hda_dsp_rom_msg[] = {
 	{HDA_DSP_ROM_NULL_FW_ENTRY,	"error: null FW entry point"},
 };
 
-static void hda_dsp_get_status_skl(struct snd_sof_dev *sdev)
-{
-	u32 status;
-	int i;
-
-	status = snd_sof_dsp_read(sdev, HDA_DSP_BAR,
-				  HDA_ADSP_FW_STATUS_SKL);
-
-	for (i = 0; i < ARRAY_SIZE(hda_dsp_rom_msg); i++) {
-		if (status == hda_dsp_rom_msg[i].code) {
-			dev_err(sdev->dev, "%s - code %8.8x\n",
-				hda_dsp_rom_msg[i].msg, status);
-			return;
-		}
-	}
-
-	/* not for us, must be generic sof message */
-	dev_dbg(sdev->dev, "unknown ROM status value %8.8x\n", status);
-}
-
 static void hda_dsp_get_status(struct snd_sof_dev *sdev)
 {
 	u32 status;
@@ -385,36 +367,6 @@ static void hda_dsp_get_registers(struct snd_sof_dev *sdev,
 		       stack_words * sizeof(u32));
 }
 
-void hda_dsp_dump_skl(struct snd_sof_dev *sdev, u32 flags)
-{
-	struct sof_ipc_dsp_oops_xtensa xoops;
-	struct sof_ipc_panic_info panic_info;
-	u32 stack[HDA_DSP_STACK_DUMP_SIZE];
-	u32 status, panic;
-
-	/* try APL specific status message types first */
-	hda_dsp_get_status_skl(sdev);
-
-	/* now try generic SOF status messages */
-	status = snd_sof_dsp_read(sdev, HDA_DSP_BAR,
-				  HDA_ADSP_ERROR_CODE_SKL);
-
-	/*TODO: Check: there is no define in spec, but it is used in the code*/
-	panic = snd_sof_dsp_read(sdev, HDA_DSP_BAR,
-				 HDA_ADSP_ERROR_CODE_SKL + 0x4);
-
-	if (sdev->fw_state == SOF_FW_BOOT_COMPLETE) {
-		hda_dsp_get_registers(sdev, &xoops, &panic_info, stack,
-				      HDA_DSP_STACK_DUMP_SIZE);
-		snd_sof_get_status(sdev, status, panic, &xoops, &panic_info,
-				   stack, HDA_DSP_STACK_DUMP_SIZE);
-	} else {
-		dev_err(sdev->dev, "error: status = 0x%8.8x panic = 0x%8.8x\n",
-			status, panic);
-		hda_dsp_get_status_skl(sdev);
-	}
-}
-
 /* dump the first 8 dwords representing the extended ROM status */
 static void hda_dsp_dump_ext_rom_status(struct snd_sof_dev *sdev, u32 flags)
 {
@@ -555,7 +507,7 @@ static int hda_init(struct snd_sof_dev *sdev)
 	return ret;
 }
 
-#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
+#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) || IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE)
 
 static int check_nhlt_dmic(struct snd_sof_dev *sdev)
 {
@@ -579,25 +531,76 @@ static const char *fixup_tplg_name(struct snd_sof_dev *sdev,
 				   const char *dmic_str)
 {
 	const char *tplg_filename = NULL;
-	char *filename;
-	char *split_ext;
+	char *filename, *tmp;
+	const char *split_ext;
 
-	filename = devm_kstrdup(sdev->dev, sof_tplg_filename, GFP_KERNEL);
+	filename = kstrdup(sof_tplg_filename, GFP_KERNEL);
 	if (!filename)
 		return NULL;
 
 	/* this assumes a .tplg extension */
-	split_ext = strsep(&filename, ".");
-	if (split_ext) {
+	tmp = filename;
+	split_ext = strsep(&tmp, ".");
+	if (split_ext)
 		tplg_filename = devm_kasprintf(sdev->dev, GFP_KERNEL,
 					       "%s%s%s.tplg",
 					       split_ext, idisp_str, dmic_str);
-		if (!tplg_filename)
-			return NULL;
-	}
+	kfree(filename);
+
 	return tplg_filename;
 }
 
+static int dmic_topology_fixup(struct snd_sof_dev *sdev,
+			       const char **tplg_filename,
+			       const char *idisp_str,
+			       int *dmic_found)
+{
+	const char *default_tplg_filename = *tplg_filename;
+	const char *fixed_tplg_filename;
+	const char *dmic_str;
+	int dmic_num;
+
+	/* first check NHLT for DMICs */
+	dmic_num = check_nhlt_dmic(sdev);
+
+	/* allow for module parameter override */
+	if (hda_dmic_num != -1) {
+		dev_dbg(sdev->dev,
+			"overriding DMICs detected in NHLT tables %d by kernel param %d\n",
+			dmic_num, hda_dmic_num);
+		dmic_num = hda_dmic_num;
+	}
+
+	switch (dmic_num) {
+	case 1:
+		dmic_str = "-1ch";
+		break;
+	case 2:
+		dmic_str = "-2ch";
+		break;
+	case 3:
+		dmic_str = "-3ch";
+		break;
+	case 4:
+		dmic_str = "-4ch";
+		break;
+	default:
+		dmic_num = 0;
+		dmic_str = "";
+		break;
+	}
+
+	fixed_tplg_filename = fixup_tplg_name(sdev, default_tplg_filename,
+					      idisp_str, dmic_str);
+	if (!fixed_tplg_filename)
+		return -ENOMEM;
+
+	dev_info(sdev->dev, "DMICs detected in NHLT tables: %d\n", dmic_num);
+	*dmic_found = dmic_num;
+	*tplg_filename = fixed_tplg_filename;
+
+	return 0;
+}
 #endif
 
 static int hda_init_caps(struct snd_sof_dev *sdev)
@@ -809,13 +812,9 @@ int hda_dsp_probe(struct snd_sof_dev *sdev)
 	sdev->mailbox_bar = HDA_DSP_BAR;
 
 	/* allow 64bit DMA address if supported by H/W */
-	if (!dma_set_mask(&pci->dev, DMA_BIT_MASK(64))) {
-		dev_dbg(sdev->dev, "DMA mask is 64 bit\n");
-		dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(64));
-	} else {
+	if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(64))) {
 		dev_dbg(sdev->dev, "DMA mask is 32 bit\n");
-		dma_set_mask(&pci->dev, DMA_BIT_MASK(32));
-		dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(32));
+		dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(32));
 	}
 
 	/* init streams */
@@ -932,7 +931,7 @@ int hda_dsp_remove(struct snd_sof_dev *sdev)
 
 	/* disable cores */
 	if (chip)
-		hda_dsp_core_reset_power_down(sdev, chip->host_managed_cores_mask);
+		snd_sof_dsp_core_power_down(sdev, chip->host_managed_cores_mask);
 
 	/* disable DSP */
 	snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR, SOF_HDA_REG_PP_PPCTL,
@@ -967,9 +966,9 @@ static int hda_generic_machine_select(struct snd_sof_dev *sdev)
 	struct snd_sof_pdata *pdata = sdev->pdata;
 	const char *tplg_filename;
 	const char *idisp_str;
-	const char *dmic_str;
 	int dmic_num = 0;
 	int codec_num = 0;
+	int ret;
 	int i;
 
 	/* codec detection */
@@ -994,10 +993,6 @@ static int hda_generic_machine_select(struct snd_sof_dev *sdev)
 		if (!pdata->machine && codec_num <= 2) {
 			hda_mach = snd_soc_acpi_intel_hda_machines;
 
-			/* topology: use the info from hda_machines */
-			pdata->tplg_filename =
-				hda_mach->sof_tplg_filename;
-
 			dev_info(bus->dev, "using HDA machine driver %s now\n",
 				 hda_mach->drv_name);
 
@@ -1006,42 +1001,13 @@ static int hda_generic_machine_select(struct snd_sof_dev *sdev)
 			else
 				idisp_str = "";
 
-			/* first check NHLT for DMICs */
-			dmic_num = check_nhlt_dmic(sdev);
-
-			/* allow for module parameter override */
-			if (hda_dmic_num != -1)
-				dmic_num = hda_dmic_num;
-
-			switch (dmic_num) {
-			case 1:
-				dmic_str = "-1ch";
-				break;
-			case 2:
-				dmic_str = "-2ch";
-				break;
-			case 3:
-				dmic_str = "-3ch";
-				break;
-			case 4:
-				dmic_str = "-4ch";
-				break;
-			default:
-				dmic_num = 0;
-				dmic_str = "";
-				break;
-			}
-
-			tplg_filename = pdata->tplg_filename;
-			tplg_filename = fixup_tplg_name(sdev, tplg_filename,
-							idisp_str, dmic_str);
-			if (!tplg_filename)
-				return -EINVAL;
-
-			dev_info(bus->dev,
-				 "DMICs detected in NHLT tables: %d\n",
-				 dmic_num);
+			/* topology: use the info from hda_machines */
+			tplg_filename = hda_mach->sof_tplg_filename;
+			ret = dmic_topology_fixup(sdev, &tplg_filename, idisp_str, &dmic_num);
+			if (ret < 0)
+				return ret;
 
+			hda_mach->mach_params.dmic_num = dmic_num;
 			pdata->machine = hda_mach;
 			pdata->tplg_filename = tplg_filename;
 		}
@@ -1053,7 +1019,6 @@ static int hda_generic_machine_select(struct snd_sof_dev *sdev)
 			&pdata->machine->mach_params;
 		mach_params->codec_mask = bus->codec_mask;
 		mach_params->common_hdmi_codec_drv = hda_codec_use_common_hdmi;
-		mach_params->dmic_num = dmic_num;
 	}
 
 	return 0;
@@ -1075,32 +1040,63 @@ static bool link_slaves_found(struct snd_sof_dev *sdev,
 	struct sdw_intel_slave_id *ids = sdw->ids;
 	int num_slaves = sdw->num_slaves;
 	unsigned int part_id, link_id, unique_id, mfg_id;
-	int i, j;
+	int i, j, k;
 
 	for (i = 0; i < link->num_adr; i++) {
 		u64 adr = link->adr_d[i].adr;
+		int reported_part_count = 0;
 
 		mfg_id = SDW_MFG_ID(adr);
 		part_id = SDW_PART_ID(adr);
 		link_id = SDW_DISCO_LINK_ID(adr);
+
+		for (j = 0; j < num_slaves; j++) {
+			/* find out how many identical parts were reported on that link */
+			if (ids[j].link_id == link_id &&
+			    ids[j].id.part_id == part_id &&
+			    ids[j].id.mfg_id == mfg_id)
+				reported_part_count++;
+		}
+
 		for (j = 0; j < num_slaves; j++) {
+			int expected_part_count = 0;
+
 			if (ids[j].link_id != link_id ||
 			    ids[j].id.part_id != part_id ||
 			    ids[j].id.mfg_id != mfg_id)
 				continue;
-			/*
-			 * we have to check unique id
-			 * if there is more than one
-			 * Slave on the link
-			 */
-			unique_id = SDW_UNIQUE_ID(adr);
-			if (link->num_adr == 1 ||
-			    ids[j].id.unique_id == SDW_IGNORED_UNIQUE_ID ||
-			    ids[j].id.unique_id == unique_id) {
-				dev_dbg(bus->dev,
-					"found %x at link %d\n",
-					part_id, link_id);
-				break;
+
+			/* find out how many identical parts are expected */
+			for (k = 0; k < link->num_adr; k++) {
+				u64 adr2 = link->adr_d[i].adr;
+				unsigned int part_id2, link_id2, mfg_id2;
+
+				mfg_id2 = SDW_MFG_ID(adr2);
+				part_id2 = SDW_PART_ID(adr2);
+				link_id2 = SDW_DISCO_LINK_ID(adr2);
+
+				if (link_id2 == link_id &&
+				    part_id2 == part_id &&
+				    mfg_id2 == mfg_id)
+					expected_part_count++;
+			}
+
+			if (reported_part_count == expected_part_count) {
+				/*
+				 * we have to check unique id
+				 * if there is more than one
+				 * Slave on the link
+				 */
+				unique_id = SDW_UNIQUE_ID(adr);
+				if (reported_part_count == 1 ||
+				    ids[j].id.unique_id == unique_id) {
+					dev_dbg(bus->dev, "found %x at link %d\n",
+						part_id, link_id);
+					break;
+				}
+			} else {
+				dev_dbg(bus->dev, "part %x reported %d expected %d on link %d, skipping\n",
+					part_id, reported_part_count, expected_part_count, link_id);
 			}
 		}
 		if (j == num_slaves) {
@@ -1117,7 +1113,6 @@ static int hda_sdw_machine_select(struct snd_sof_dev *sdev)
 {
 	struct snd_sof_pdata *pdata = sdev->pdata;
 	const struct snd_soc_acpi_link_adr *link;
-	struct hdac_bus *bus = sof_to_bus(sdev);
 	struct snd_soc_acpi_mach *mach;
 	struct sof_intel_hda_dev *hdev;
 	u32 link_mask;
@@ -1165,10 +1160,8 @@ static int hda_sdw_machine_select(struct snd_sof_dev *sdev)
 				break;
 		}
 		if (mach && mach->link_mask) {
-			dev_dbg(bus->dev,
-				"SoundWire machine driver %s topology %s\n",
-				mach->drv_name,
-				mach->sof_tplg_filename);
+			int dmic_num = 0;
+
 			pdata->machine = mach;
 			mach->mach_params.links = mach->links;
 			mach->mach_params.link_mask = mach->link_mask;
@@ -1178,6 +1171,31 @@ static int hda_sdw_machine_select(struct snd_sof_dev *sdev)
 			else
 				pdata->fw_filename = pdata->desc->default_fw_filename;
 			pdata->tplg_filename = mach->sof_tplg_filename;
+
+			/*
+			 * DMICs use up to 4 pins and are typically pin-muxed with SoundWire
+			 * link 2 and 3, thus we only try to enable dmics if all conditions
+			 * are true:
+			 * a) link 2 and 3 are not used by SoundWire
+			 * b) the NHLT table reports the presence of microphones
+			 */
+			if (!(mach->link_mask & GENMASK(3, 2))) {
+				const char *tplg_filename = mach->sof_tplg_filename;
+				int ret;
+
+				ret = dmic_topology_fixup(sdev, &tplg_filename, "", &dmic_num);
+
+				if (ret < 0)
+					return ret;
+
+				pdata->tplg_filename = tplg_filename;
+			}
+			mach->mach_params.dmic_num = dmic_num;
+
+			dev_dbg(sdev->dev,
+				"SoundWire machine driver %s topology %s\n",
+				mach->drv_name,
+				pdata->tplg_filename);
 		} else {
 			dev_info(sdev->dev,
 				 "No SoundWire machine driver found\n");
diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h
index a3b6f3e9121c..d979411b4041 100644
--- a/sound/soc/sof/intel/hda.h
+++ b/sound/soc/sof/intel/hda.h
@@ -402,6 +402,9 @@ struct sof_intel_dsp_bdl {
 #define SOF_HDA_PLAYBACK		0
 #define SOF_HDA_CAPTURE			1
 
+/* stream flags */
+#define SOF_HDA_STREAM_DMI_L1_COMPATIBLE	1
+
 /*
  * Time in ms for opportunistic D0I3 entry delay.
  * This has been deliberately chosen to be long to avoid race conditions.
@@ -471,6 +474,7 @@ struct sof_intel_hda_stream {
 	struct hdac_ext_stream hda_stream;
 	struct sof_intel_stream stream;
 	int host_reserved; /* reserve host DMA channel */
+	u32 flags;
 };
 
 #define hstream_to_sof_hda_stream(hstream) \
@@ -513,7 +517,6 @@ int hda_dsp_runtime_suspend(struct snd_sof_dev *sdev);
 int hda_dsp_runtime_resume(struct snd_sof_dev *sdev);
 int hda_dsp_runtime_idle(struct snd_sof_dev *sdev);
 int hda_dsp_set_hw_params_upon_resume(struct snd_sof_dev *sdev);
-void hda_dsp_dump_skl(struct snd_sof_dev *sdev, u32 flags);
 void hda_dsp_dump(struct snd_sof_dev *sdev, u32 flags);
 void hda_ipc_dump(struct snd_sof_dev *sdev);
 void hda_ipc_irq_dump(struct snd_sof_dev *sdev);
@@ -562,7 +565,7 @@ bool hda_dsp_check_ipc_irq(struct snd_sof_dev *sdev);
 bool hda_dsp_check_stream_irq(struct snd_sof_dev *sdev);
 
 struct hdac_ext_stream *
-	hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction);
+	hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction, u32 flags);
 int hda_dsp_stream_put(struct snd_sof_dev *sdev, int direction, int stream_tag);
 int hda_dsp_stream_spib_config(struct snd_sof_dev *sdev,
 			       struct hdac_ext_stream *stream,
diff --git a/sound/soc/sof/intel/tgl.c b/sound/soc/sof/intel/tgl.c
index 2252ca38ff4b..419f05ba1920 100644
--- a/sound/soc/sof/intel/tgl.c
+++ b/sound/soc/sof/intel/tgl.c
@@ -22,9 +22,10 @@ static const struct snd_sof_debugfs_map tgl_dsp_debugfs[] = {
 
 /* Tigerlake ops */
 const struct snd_sof_dsp_ops sof_tgl_ops = {
-	/* probe and remove */
+	/* probe/remove/shutdown */
 	.probe		= hda_dsp_probe,
 	.remove		= hda_dsp_remove,
+	.shutdown	= hda_dsp_remove,
 
 	/* Register IO */
 	.write		= sof_io_write,
diff --git a/sound/soc/sof/ipc.c b/sound/soc/sof/ipc.c
index fc13bb06dbf3..c2d07b783f60 100644
--- a/sound/soc/sof/ipc.c
+++ b/sound/soc/sof/ipc.c
@@ -106,6 +106,8 @@ static void ipc_log_header(struct device *dev, u8 *text, u32 cmd)
 			str2 = "CLK_REQ"; break;
 		case SOF_IPC_PM_CORE_ENABLE:
 			str2 = "CORE_ENABLE"; break;
+		case SOF_IPC_PM_GATE:
+			str2 = "GATE"; break;
 		default:
 			str2 = "unknown type"; break;
 		}
@@ -796,7 +798,7 @@ int snd_sof_ipc_valid(struct snd_sof_dev *sdev)
 		return -EINVAL;
 	}
 
-	if (v->abi_version > SOF_ABI_VERSION) {
+	if (SOF_ABI_VERSION_MINOR(v->abi_version) > SOF_ABI_MINOR) {
 		if (!IS_ENABLED(CONFIG_SND_SOC_SOF_STRICT_ABI_CHECKS)) {
 			dev_warn(sdev->dev, "warn: FW ABI is more recent than kernel\n");
 		} else {
diff --git a/sound/soc/sof/loader.c b/sound/soc/sof/loader.c
index eabeaf7b260e..6efaf766f2ab 100644
--- a/sound/soc/sof/loader.c
+++ b/sound/soc/sof/loader.c
@@ -813,7 +813,6 @@ EXPORT_SYMBOL(snd_sof_load_firmware);
 int snd_sof_run_firmware(struct snd_sof_dev *sdev)
 {
 	int ret;
-	int init_core_mask;
 
 	init_waitqueue_head(&sdev->boot_wait);
 
@@ -845,8 +844,6 @@ int snd_sof_run_firmware(struct snd_sof_dev *sdev)
 		return ret;
 	}
 
-	init_core_mask = ret;
-
 	/*
 	 * now wait for the DSP to boot. There are 3 possible outcomes:
 	 * 1. Boot wait times out indicating FW boot failure.
@@ -876,9 +873,6 @@ int snd_sof_run_firmware(struct snd_sof_dev *sdev)
 		return ret;
 	}
 
-	/* fw boot is complete. Update the active cores mask */
-	sdev->enabled_cores_mask = init_core_mask;
-
 	return 0;
 }
 EXPORT_SYMBOL(snd_sof_run_firmware);
diff --git a/sound/soc/sof/ops.h b/sound/soc/sof/ops.h
index 95e748b36903..5099ad03df72 100644
--- a/sound/soc/sof/ops.h
+++ b/sound/soc/sof/ops.h
@@ -37,6 +37,14 @@ static inline int snd_sof_remove(struct snd_sof_dev *sdev)
 	return 0;
 }
 
+static inline int snd_sof_shutdown(struct snd_sof_dev *sdev)
+{
+	if (sof_ops(sdev)->shutdown)
+		return sof_ops(sdev)->shutdown(sdev);
+
+	return 0;
+}
+
 /* control */
 
 /*
@@ -68,19 +76,31 @@ static inline int snd_sof_dsp_reset(struct snd_sof_dev *sdev)
 static inline int snd_sof_dsp_core_power_up(struct snd_sof_dev *sdev,
 					    unsigned int core_mask)
 {
-	if (sof_ops(sdev)->core_power_up)
-		return sof_ops(sdev)->core_power_up(sdev, core_mask);
+	int ret = 0;
 
-	return 0;
+	core_mask &= ~sdev->enabled_cores_mask;
+	if (sof_ops(sdev)->core_power_up && core_mask) {
+		ret = sof_ops(sdev)->core_power_up(sdev, core_mask);
+		if (!ret)
+			sdev->enabled_cores_mask |= core_mask;
+	}
+
+	return ret;
 }
 
 static inline int snd_sof_dsp_core_power_down(struct snd_sof_dev *sdev,
 					      unsigned int core_mask)
 {
-	if (sof_ops(sdev)->core_power_down)
-		return sof_ops(sdev)->core_power_down(sdev, core_mask);
+	int ret = 0;
 
-	return 0;
+	core_mask &= sdev->enabled_cores_mask;
+	if (sof_ops(sdev)->core_power_down && core_mask) {
+		ret = sof_ops(sdev)->core_power_down(sdev, core_mask);
+		if (!ret)
+			sdev->enabled_cores_mask &= ~core_mask;
+	}
+
+	return ret;
 }
 
 /* pre/post fw load */
@@ -208,11 +228,16 @@ static inline int
 snd_sof_dsp_set_power_state(struct snd_sof_dev *sdev,
 			    const struct sof_dsp_power_state *target_state)
 {
+	int ret = 0;
+
+	mutex_lock(&sdev->power_state_access);
+
 	if (sof_ops(sdev)->set_power_state)
-		return sof_ops(sdev)->set_power_state(sdev, target_state);
+		ret = sof_ops(sdev)->set_power_state(sdev, target_state);
 
-	/* D0 substate is not supported, do nothing here. */
-	return 0;
+	mutex_unlock(&sdev->power_state_access);
+
+	return ret;
 }
 
 /* debug */
diff --git a/sound/soc/sof/pm.c b/sound/soc/sof/pm.c
index c83fb6255961..fd265803f7bc 100644
--- a/sound/soc/sof/pm.c
+++ b/sound/soc/sof/pm.c
@@ -256,7 +256,6 @@ suspend:
 
 	/* reset FW state */
 	sdev->fw_state = SOF_FW_BOOT_NOT_STARTED;
-	sdev->enabled_cores_mask = 0;
 
 	return ret;
 }
diff --git a/sound/soc/sof/sof-pci-dev.c b/sound/soc/sof/sof-pci-dev.c
index 9adf50b20a73..fd1f0d8c2853 100644
--- a/sound/soc/sof/sof-pci-dev.c
+++ b/sound/soc/sof/sof-pci-dev.c
@@ -220,7 +220,7 @@ static const struct sof_dev_desc icl_desc = {
 };
 #endif
 
-#if IS_ENABLED(CONFIG_SND_SOC_SOF_TIGERLAKE)
+#if IS_ENABLED(CONFIG_SND_SOC_SOF_TIGERLAKE) || IS_ENABLED(CONFIG_SND_SOC_SOF_ALDERLAKE)
 static const struct sof_dev_desc tgl_desc = {
 	.machines               = snd_soc_acpi_intel_tgl_machines,
 	.alt_machines		= snd_soc_acpi_intel_tgl_sdw_machines,
@@ -237,7 +237,9 @@ static const struct sof_dev_desc tgl_desc = {
 	.nocodec_tplg_filename = "sof-tgl-nocodec.tplg",
 	.ops = &sof_tgl_ops,
 };
+#endif
 
+#if IS_ENABLED(CONFIG_SND_SOC_SOF_TIGERLAKE)
 static const struct sof_dev_desc tglh_desc = {
 	.machines               = snd_soc_acpi_intel_tgl_machines,
 	.alt_machines		= snd_soc_acpi_intel_tgl_sdw_machines,
@@ -452,13 +454,19 @@ static void sof_pci_remove(struct pci_dev *pci)
 	snd_sof_device_remove(&pci->dev);
 
 	/* follow recommendation in pci-driver.c to increment usage counter */
-	if (!(sof_pci_debug & SOF_PCI_DISABLE_PM_RUNTIME))
+	if (snd_sof_device_probe_completed(&pci->dev) &&
+	    !(sof_pci_debug & SOF_PCI_DISABLE_PM_RUNTIME))
 		pm_runtime_get_noresume(&pci->dev);
 
 	/* release pci regions and disable device */
 	pci_release_regions(pci);
 }
 
+static void sof_pci_shutdown(struct pci_dev *pci)
+{
+	snd_sof_device_shutdown(&pci->dev);
+}
+
 /* PCI IDs */
 static const struct pci_device_id sof_pci_ids[] = {
 #if IS_ENABLED(CONFIG_SND_SOC_SOF_MERRIFIELD)
@@ -521,6 +529,8 @@ static const struct pci_device_id sof_pci_ids[] = {
 #if IS_ENABLED(CONFIG_SND_SOC_SOF_ALDERLAKE)
 	{ PCI_DEVICE(0x8086, 0x7ad0),
 		.driver_data = (unsigned long)&adls_desc},
+	{ PCI_DEVICE(0x8086, 0x51c8),
+		.driver_data = (unsigned long)&tgl_desc},
 #endif
 	{ 0, }
 };
@@ -532,6 +542,7 @@ static struct pci_driver snd_sof_pci_driver = {
 	.id_table = sof_pci_ids,
 	.probe = sof_pci_probe,
 	.remove = sof_pci_remove,
+	.shutdown = sof_pci_shutdown,
 	.driver = {
 		.pm = &sof_pci_pm,
 	},
diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h
index 68da8f797403..ad0d7ba2708c 100644
--- a/sound/soc/sof/sof-priv.h
+++ b/sound/soc/sof/sof-priv.h
@@ -98,9 +98,10 @@ struct snd_sof_pdata;
  */
 struct snd_sof_dsp_ops {
 
-	/* probe and remove */
+	/* probe/remove/shutdown */
 	int (*probe)(struct snd_sof_dev *sof_dev); /* mandatory */
 	int (*remove)(struct snd_sof_dev *sof_dev); /* optional */
+	int (*shutdown)(struct snd_sof_dev *sof_dev); /* optional */
 
 	/* DSP core boot / reset */
 	int (*run)(struct snd_sof_dev *sof_dev); /* mandatory */
@@ -375,6 +376,8 @@ struct snd_sof_dev {
 
 	/* current DSP power state */
 	struct sof_dsp_power_state dsp_power_state;
+	/* mutex to protect the dsp_power_state access */
+	struct mutex power_state_access;
 
 	/* Intended power target of system suspend */
 	enum sof_system_suspend_state system_suspend_target;
@@ -386,6 +389,7 @@ struct snd_sof_dev {
 
 	/* work queue in case the probe is implemented in two steps */
 	struct work_struct probe_work;
+	bool probe_completed;
 
 	/* DSP HW differentiation */
 	struct snd_sof_pdata *pdata;
@@ -460,6 +464,8 @@ struct snd_sof_dev {
 
 int snd_sof_device_probe(struct device *dev, struct snd_sof_pdata *plat_data);
 int snd_sof_device_remove(struct device *dev);
+int snd_sof_device_shutdown(struct device *dev);
+bool snd_sof_device_probe_completed(struct device *dev);
 
 int snd_sof_runtime_suspend(struct device *dev);
 int snd_sof_runtime_resume(struct device *dev);
diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c
index 480cf75a7575..10f99620eb31 100644
--- a/sound/soc/sof/topology.c
+++ b/sound/soc/sof/topology.c
@@ -1352,10 +1352,6 @@ static int sof_core_enable(struct snd_sof_dev *sdev, int core)
 			core, ret);
 		goto err;
 	}
-
-	/* update enabled cores mask */
-	sdev->enabled_cores_mask |= BIT(core);
-
 	return ret;
 err:
 	/* power down core if it is host managed and return the original error if this fails too */
@@ -2603,10 +2599,6 @@ static int sof_widget_unload(struct snd_soc_component *scomp,
 		if (ret < 0)
 			dev_err(scomp->dev, "error: powering down pipeline schedule core %d\n",
 				pipeline->core);
-
-		/* update enabled cores mask */
-		sdev->enabled_cores_mask &= ~(1 << pipeline->core);
-
 		break;
 	default:
 		break;
@@ -3666,7 +3658,7 @@ static int sof_manifest(struct snd_soc_component *scomp, int index,
 		return -EINVAL;
 	}
 
-	if (abi_version > SOF_ABI_VERSION) {
+	if (SOF_ABI_VERSION_MINOR(abi_version) > SOF_ABI_MINOR) {
 		if (!IS_ENABLED(CONFIG_SND_SOC_SOF_STRICT_ABI_CHECKS)) {
 			dev_warn(scomp->dev, "warn: topology ABI is more recent than kernel\n");
 		} else {
diff --git a/sound/soc/sprd/sprd-mcdt.c b/sound/soc/sprd/sprd-mcdt.c
index f439e5503a3c..34b2ce733b54 100644
--- a/sound/soc/sprd/sprd-mcdt.c
+++ b/sound/soc/sprd/sprd-mcdt.c
@@ -866,23 +866,23 @@ EXPORT_SYMBOL_GPL(sprd_mcdt_chan_dma_disable);
 struct sprd_mcdt_chan *sprd_mcdt_request_chan(u8 channel,
 					      enum sprd_mcdt_channel_type type)
 {
-	struct sprd_mcdt_chan *temp, *chan = NULL;
+	struct sprd_mcdt_chan *temp;
 
 	mutex_lock(&sprd_mcdt_list_mutex);
 
 	list_for_each_entry(temp, &sprd_mcdt_chan_list, list) {
 		if (temp->type == type && temp->id == channel) {
-			chan = temp;
+			list_del_init(&temp->list);
 			break;
 		}
 	}
 
-	if (chan)
-		list_del(&chan->list);
+	if (list_entry_is_head(temp, &sprd_mcdt_chan_list, list))
+		temp = NULL;
 
 	mutex_unlock(&sprd_mcdt_list_mutex);
 
-	return chan;
+	return temp;
 }
 EXPORT_SYMBOL_GPL(sprd_mcdt_request_chan);
 
diff --git a/sound/soc/stm/stm32_i2s.c b/sound/soc/stm/stm32_i2s.c
index 7c4d63c33f15..7d1672cf78cc 100644
--- a/sound/soc/stm/stm32_i2s.c
+++ b/sound/soc/stm/stm32_i2s.c
@@ -8,6 +8,7 @@
 
 #include <linux/bitfield.h>
 #include <linux/clk.h>
+#include <linux/clk-provider.h>
 #include <linux/delay.h>
 #include <linux/module.h>
 #include <linux/of_irq.h>
@@ -196,6 +197,9 @@ enum i2s_datlen {
 #define STM32_I2S_IS_MASTER(x)		((x)->ms_flg == I2S_MS_MASTER)
 #define STM32_I2S_IS_SLAVE(x)		((x)->ms_flg == I2S_MS_SLAVE)
 
+#define STM32_I2S_NAME_LEN		32
+#define STM32_I2S_RATE_11K		11025
+
 /**
  * struct stm32_i2s_data - private data of I2S
  * @regmap_conf: I2S register map configuration pointer
@@ -206,6 +210,7 @@ enum i2s_datlen {
  * @dma_data_rx: dma configuration data for tx channel
  * @substream: PCM substream data pointer
  * @i2sclk: kernel clock feeding the I2S clock generator
+ * @i2smclk: master clock from I2S mclk provider
  * @pclk: peripheral clock driving bus interface
  * @x8kclk: I2S parent clock for sampling frequencies multiple of 8kHz
  * @x11kclk: I2S parent clock for sampling frequencies multiple of 11kHz
@@ -215,6 +220,9 @@ enum i2s_datlen {
  * @irq_lock: prevent race condition with IRQ
  * @mclk_rate: master clock frequency (Hz)
  * @fmt: DAI protocol
+ * @divider: prescaler division ratio
+ * @div: prescaler div field
+ * @odd: prescaler odd field
  * @refcount: keep count of opened streams on I2S
  * @ms_flg: master mode flag.
  */
@@ -227,6 +235,7 @@ struct stm32_i2s_data {
 	struct snd_dmaengine_dai_dma_data dma_data_rx;
 	struct snd_pcm_substream *substream;
 	struct clk *i2sclk;
+	struct clk *i2smclk;
 	struct clk *pclk;
 	struct clk *x8kclk;
 	struct clk *x11kclk;
@@ -236,10 +245,210 @@ struct stm32_i2s_data {
 	spinlock_t irq_lock; /* used to prevent race condition with IRQ */
 	unsigned int mclk_rate;
 	unsigned int fmt;
+	unsigned int divider;
+	unsigned int div;
+	bool odd;
 	int refcount;
 	int ms_flg;
 };
 
+struct stm32_i2smclk_data {
+	struct clk_hw hw;
+	unsigned long freq;
+	struct stm32_i2s_data *i2s_data;
+};
+
+#define to_mclk_data(_hw) container_of(_hw, struct stm32_i2smclk_data, hw)
+
+static int stm32_i2s_calc_clk_div(struct stm32_i2s_data *i2s,
+				  unsigned long input_rate,
+				  unsigned long output_rate)
+{
+	unsigned int ratio, div, divider = 1;
+	bool odd;
+
+	ratio = DIV_ROUND_CLOSEST(input_rate, output_rate);
+
+	/* Check the parity of the divider */
+	odd = ratio & 0x1;
+
+	/* Compute the div prescaler */
+	div = ratio >> 1;
+
+	/* If div is 0 actual divider is 1 */
+	if (div) {
+		divider = ((2 * div) + odd);
+		dev_dbg(&i2s->pdev->dev, "Divider: 2*%d(div)+%d(odd) = %d\n",
+			div, odd, divider);
+	}
+
+	/* Division by three is not allowed by I2S prescaler */
+	if ((div == 1 && odd) || div > I2S_CGFR_I2SDIV_MAX) {
+		dev_err(&i2s->pdev->dev, "Wrong divider setting\n");
+		return -EINVAL;
+	}
+
+	if (input_rate % divider)
+		dev_dbg(&i2s->pdev->dev,
+			"Rate not accurate. requested (%ld), actual (%ld)\n",
+			output_rate, input_rate / divider);
+
+	i2s->div = div;
+	i2s->odd = odd;
+	i2s->divider = divider;
+
+	return 0;
+}
+
+static int stm32_i2s_set_clk_div(struct stm32_i2s_data *i2s)
+{
+	u32 cgfr, cgfr_mask;
+
+	cgfr = I2S_CGFR_I2SDIV_SET(i2s->div) | (i2s->odd << I2S_CGFR_ODD_SHIFT);
+	cgfr_mask = I2S_CGFR_I2SDIV_MASK | I2S_CGFR_ODD;
+
+	return regmap_update_bits(i2s->regmap, STM32_I2S_CGFR_REG,
+				  cgfr_mask, cgfr);
+}
+
+static int stm32_i2s_set_parent_clock(struct stm32_i2s_data *i2s,
+				      unsigned int rate)
+{
+	struct platform_device *pdev = i2s->pdev;
+	struct clk *parent_clk;
+	int ret;
+
+	if (!(rate % STM32_I2S_RATE_11K))
+		parent_clk = i2s->x11kclk;
+	else
+		parent_clk = i2s->x8kclk;
+
+	ret = clk_set_parent(i2s->i2sclk, parent_clk);
+	if (ret)
+		dev_err(&pdev->dev,
+			"Error %d setting i2sclk parent clock\n", ret);
+
+	return ret;
+}
+
+static long stm32_i2smclk_round_rate(struct clk_hw *hw, unsigned long rate,
+				     unsigned long *prate)
+{
+	struct stm32_i2smclk_data *mclk = to_mclk_data(hw);
+	struct stm32_i2s_data *i2s = mclk->i2s_data;
+	int ret;
+
+	ret = stm32_i2s_calc_clk_div(i2s, *prate, rate);
+	if (ret)
+		return ret;
+
+	mclk->freq = *prate / i2s->divider;
+
+	return mclk->freq;
+}
+
+static unsigned long stm32_i2smclk_recalc_rate(struct clk_hw *hw,
+					       unsigned long parent_rate)
+{
+	struct stm32_i2smclk_data *mclk = to_mclk_data(hw);
+
+	return mclk->freq;
+}
+
+static int stm32_i2smclk_set_rate(struct clk_hw *hw, unsigned long rate,
+				  unsigned long parent_rate)
+{
+	struct stm32_i2smclk_data *mclk = to_mclk_data(hw);
+	struct stm32_i2s_data *i2s = mclk->i2s_data;
+	int ret;
+
+	ret = stm32_i2s_calc_clk_div(i2s, parent_rate, rate);
+	if (ret)
+		return ret;
+
+	ret = stm32_i2s_set_clk_div(i2s);
+	if (ret)
+		return ret;
+
+	mclk->freq = rate;
+
+	return 0;
+}
+
+static int stm32_i2smclk_enable(struct clk_hw *hw)
+{
+	struct stm32_i2smclk_data *mclk = to_mclk_data(hw);
+	struct stm32_i2s_data *i2s = mclk->i2s_data;
+
+	dev_dbg(&i2s->pdev->dev, "Enable master clock\n");
+
+	return regmap_update_bits(i2s->regmap, STM32_I2S_CGFR_REG,
+				    I2S_CGFR_MCKOE, I2S_CGFR_MCKOE);
+}
+
+static void stm32_i2smclk_disable(struct clk_hw *hw)
+{
+	struct stm32_i2smclk_data *mclk = to_mclk_data(hw);
+	struct stm32_i2s_data *i2s = mclk->i2s_data;
+
+	dev_dbg(&i2s->pdev->dev, "Disable master clock\n");
+
+	regmap_update_bits(i2s->regmap, STM32_I2S_CGFR_REG, I2S_CGFR_MCKOE, 0);
+}
+
+static const struct clk_ops mclk_ops = {
+	.enable = stm32_i2smclk_enable,
+	.disable = stm32_i2smclk_disable,
+	.recalc_rate = stm32_i2smclk_recalc_rate,
+	.round_rate = stm32_i2smclk_round_rate,
+	.set_rate = stm32_i2smclk_set_rate,
+};
+
+static int stm32_i2s_add_mclk_provider(struct stm32_i2s_data *i2s)
+{
+	struct clk_hw *hw;
+	struct stm32_i2smclk_data *mclk;
+	struct device *dev = &i2s->pdev->dev;
+	const char *pname = __clk_get_name(i2s->i2sclk);
+	char *mclk_name, *p, *s = (char *)pname;
+	int ret, i = 0;
+
+	mclk = devm_kzalloc(dev, sizeof(*mclk), GFP_KERNEL);
+	if (!mclk)
+		return -ENOMEM;
+
+	mclk_name = devm_kcalloc(dev, sizeof(char),
+				 STM32_I2S_NAME_LEN, GFP_KERNEL);
+	if (!mclk_name)
+		return -ENOMEM;
+
+	/*
+	 * Forge mclk clock name from parent clock name and suffix.
+	 * String after "_" char is stripped in parent name.
+	 */
+	p = mclk_name;
+	while (*s && *s != '_' && (i < (STM32_I2S_NAME_LEN - 7))) {
+		*p++ = *s++;
+		i++;
+	}
+	strcat(p, "_mclk");
+
+	mclk->hw.init = CLK_HW_INIT(mclk_name, pname, &mclk_ops, 0);
+	mclk->i2s_data = i2s;
+	hw = &mclk->hw;
+
+	dev_dbg(dev, "Register master clock %s\n", mclk_name);
+	ret = devm_clk_hw_register(&i2s->pdev->dev, hw);
+	if (ret) {
+		dev_err(dev, "mclk register fails with error %d\n", ret);
+		return ret;
+	}
+	i2s->i2smclk = hw->clk;
+
+	/* register mclk provider */
+	return devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, hw);
+}
+
 static irqreturn_t stm32_i2s_isr(int irq, void *devid)
 {
 	struct stm32_i2s_data *i2s = (struct stm32_i2s_data *)devid;
@@ -405,18 +614,46 @@ static int stm32_i2s_set_sysclk(struct snd_soc_dai *cpu_dai,
 				int clk_id, unsigned int freq, int dir)
 {
 	struct stm32_i2s_data *i2s = snd_soc_dai_get_drvdata(cpu_dai);
+	int ret = 0;
 
-	dev_dbg(cpu_dai->dev, "I2S MCLK frequency is %uHz\n", freq);
+	dev_dbg(cpu_dai->dev, "I2S MCLK frequency is %uHz. mode: %s, dir: %s\n",
+		freq, STM32_I2S_IS_MASTER(i2s) ? "master" : "slave",
+		dir ? "output" : "input");
 
-	if ((dir == SND_SOC_CLOCK_OUT) && STM32_I2S_IS_MASTER(i2s)) {
-		i2s->mclk_rate = freq;
+	/* MCLK generation is available only in master mode */
+	if (dir == SND_SOC_CLOCK_OUT && STM32_I2S_IS_MASTER(i2s)) {
+		if (!i2s->i2smclk) {
+			dev_dbg(cpu_dai->dev, "No MCLK registered\n");
+			return 0;
+		}
 
-		/* Enable master clock if master mode and mclk-fs are set */
-		return regmap_update_bits(i2s->regmap, STM32_I2S_CGFR_REG,
-					  I2S_CGFR_MCKOE, I2S_CGFR_MCKOE);
+		/* Assume shutdown if requested frequency is 0Hz */
+		if (!freq) {
+			/* Release mclk rate only if rate was actually set */
+			if (i2s->mclk_rate) {
+				clk_rate_exclusive_put(i2s->i2smclk);
+				i2s->mclk_rate = 0;
+			}
+			return regmap_update_bits(i2s->regmap,
+						  STM32_I2S_CGFR_REG,
+						  I2S_CGFR_MCKOE, 0);
+		}
+		/* If master clock is used, set parent clock now */
+		ret = stm32_i2s_set_parent_clock(i2s, freq);
+		if (ret)
+			return ret;
+		ret = clk_set_rate_exclusive(i2s->i2smclk, freq);
+		if (ret) {
+			dev_err(cpu_dai->dev, "Could not set mclk rate\n");
+			return ret;
+		}
+		ret = regmap_update_bits(i2s->regmap, STM32_I2S_CGFR_REG,
+					 I2S_CGFR_MCKOE, I2S_CGFR_MCKOE);
+		if (!ret)
+			i2s->mclk_rate = freq;
 	}
 
-	return 0;
+	return ret;
 }
 
 static int stm32_i2s_configure_clock(struct snd_soc_dai *cpu_dai,
@@ -424,11 +661,10 @@ static int stm32_i2s_configure_clock(struct snd_soc_dai *cpu_dai,
 {
 	struct stm32_i2s_data *i2s = snd_soc_dai_get_drvdata(cpu_dai);
 	unsigned long i2s_clock_rate;
-	unsigned int tmp, div, real_div, nb_bits, frame_len;
+	unsigned int nb_bits, frame_len;
 	unsigned int rate = params_rate(params);
+	u32 cgfr;
 	int ret;
-	u32 cgfr, cgfr_mask;
-	bool odd;
 
 	if (!(rate % 11025))
 		clk_set_parent(i2s->i2sclk, i2s->x11kclk);
@@ -449,7 +685,10 @@ static int stm32_i2s_configure_clock(struct snd_soc_dai *cpu_dai,
 	 *   dsp mode : div = i2s_clk / (nb_bits x ws)
 	 */
 	if (i2s->mclk_rate) {
-		tmp = DIV_ROUND_CLOSEST(i2s_clock_rate, i2s->mclk_rate);
+		ret = stm32_i2s_calc_clk_div(i2s, i2s_clock_rate,
+					     i2s->mclk_rate);
+		if (ret)
+			return ret;
 	} else {
 		frame_len = 32;
 		if ((i2s->fmt & SND_SOC_DAIFMT_FORMAT_MASK) ==
@@ -462,34 +701,13 @@ static int stm32_i2s_configure_clock(struct snd_soc_dai *cpu_dai,
 			return ret;
 
 		nb_bits = frame_len * ((cgfr & I2S_CGFR_CHLEN) + 1);
-		tmp = DIV_ROUND_CLOSEST(i2s_clock_rate, (nb_bits * rate));
-	}
-
-	/* Check the parity of the divider */
-	odd = tmp & 0x1;
-
-	/* Compute the div prescaler */
-	div = tmp >> 1;
-
-	cgfr = I2S_CGFR_I2SDIV_SET(div) | (odd << I2S_CGFR_ODD_SHIFT);
-	cgfr_mask = I2S_CGFR_I2SDIV_MASK | I2S_CGFR_ODD;
-
-	real_div = ((2 * div) + odd);
-	dev_dbg(cpu_dai->dev, "I2S clk: %ld, SCLK: %d\n",
-		i2s_clock_rate, rate);
-	dev_dbg(cpu_dai->dev, "Divider: 2*%d(div)+%d(odd) = %d\n",
-		div, odd, real_div);
-
-	if (((div == 1) && odd) || (div > I2S_CGFR_I2SDIV_MAX)) {
-		dev_err(cpu_dai->dev, "Wrong divider setting\n");
-		return -EINVAL;
+		ret = stm32_i2s_calc_clk_div(i2s, i2s_clock_rate,
+					     (nb_bits * rate));
+		if (ret)
+			return ret;
 	}
 
-	if (!div && !odd)
-		dev_warn(cpu_dai->dev, "real divider forced to 1\n");
-
-	ret = regmap_update_bits(i2s->regmap, STM32_I2S_CGFR_REG,
-				 cgfr_mask, cgfr);
+	ret = stm32_i2s_set_clk_div(i2s);
 	if (ret < 0)
 		return ret;
 
@@ -694,9 +912,6 @@ static void stm32_i2s_shutdown(struct snd_pcm_substream *substream,
 	struct stm32_i2s_data *i2s = snd_soc_dai_get_drvdata(cpu_dai);
 	unsigned long flags;
 
-	regmap_update_bits(i2s->regmap, STM32_I2S_CGFR_REG,
-			   I2S_CGFR_MCKOE, (unsigned int)~I2S_CGFR_MCKOE);
-
 	clk_disable_unprepare(i2s->i2sclk);
 
 	spin_lock_irqsave(&i2s->irq_lock, flags);
@@ -861,6 +1076,13 @@ static int stm32_i2s_parse_dt(struct platform_device *pdev,
 		return PTR_ERR(i2s->x11kclk);
 	}
 
+	/* Register mclk provider if requested */
+	if (of_find_property(np, "#clock-cells", NULL)) {
+		ret = stm32_i2s_add_mclk_provider(i2s);
+		if (ret < 0)
+			return ret;
+	}
+
 	/* Get irqs */
 	irq = platform_get_irq(pdev, 0);
 	if (irq < 0)
@@ -906,16 +1128,16 @@ static int stm32_i2s_probe(struct platform_device *pdev)
 	if (!i2s)
 		return -ENOMEM;
 
-	ret = stm32_i2s_parse_dt(pdev, i2s);
-	if (ret)
-		return ret;
-
 	i2s->pdev = pdev;
 	i2s->ms_flg = I2S_MS_NOT_SET;
 	spin_lock_init(&i2s->lock_fd);
 	spin_lock_init(&i2s->irq_lock);
 	platform_set_drvdata(pdev, i2s);
 
+	ret = stm32_i2s_parse_dt(pdev, i2s);
+	if (ret)
+		return ret;
+
 	ret = stm32_i2s_dais_init(pdev, i2s);
 	if (ret)
 		return ret;
diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c
index 4b8ca5be0a29..78506c3811dc 100644
--- a/sound/soc/sunxi/sun4i-i2s.c
+++ b/sound/soc/sunxi/sun4i-i2s.c
@@ -1105,7 +1105,7 @@ static struct snd_soc_dai_driver sun4i_i2s_dai = {
 		.formats = SUN4I_FORMATS,
 	},
 	.ops = &sun4i_i2s_dai_ops,
-	.symmetric_rates = 1,
+	.symmetric_rate = 1,
 };
 
 static const struct snd_soc_component_driver sun4i_i2s_component = {
diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c
index 180442c62be1..460924fc173f 100644
--- a/sound/soc/sunxi/sun8i-codec.c
+++ b/sound/soc/sunxi/sun8i-codec.c
@@ -640,9 +640,9 @@ static struct snd_soc_dai_driver sun8i_codec_dais[] = {
 			.rates		= SUN8I_CODEC_PCM_RATES,
 			.formats	= SUN8I_CODEC_PCM_FORMATS,
 		},
-		.symmetric_rates	= true,
+		.symmetric_rate		= true,
 		.symmetric_channels	= true,
-		.symmetric_samplebits	= true,
+		.symmetric_sample_bits	= true,
 	},
 	{
 		.name	= "sun8i-codec-aif2",
@@ -665,9 +665,9 @@ static struct snd_soc_dai_driver sun8i_codec_dais[] = {
 			.rates		= SUN8I_CODEC_PCM_RATES,
 			.formats	= SUN8I_CODEC_PCM_FORMATS,
 		},
-		.symmetric_rates	= true,
+		.symmetric_rate		= true,
 		.symmetric_channels	= true,
-		.symmetric_samplebits	= true,
+		.symmetric_sample_bits	= true,
 	},
 	{
 		.name	= "sun8i-codec-aif3",
@@ -690,9 +690,9 @@ static struct snd_soc_dai_driver sun8i_codec_dais[] = {
 			.rates		= SUN8I_CODEC_PCM_RATES,
 			.formats	= SUN8I_CODEC_PCM_FORMATS,
 		},
-		.symmetric_rates	= true,
+		.symmetric_rate		= true,
 		.symmetric_channels	= true,
-		.symmetric_samplebits	= true,
+		.symmetric_sample_bits	= true,
 	},
 };
 
diff --git a/sound/soc/tegra/Kconfig b/sound/soc/tegra/Kconfig
index a62cc87551ac..a4e6760944d0 100644
--- a/sound/soc/tegra/Kconfig
+++ b/sound/soc/tegra/Kconfig
@@ -9,9 +9,10 @@ config SND_SOC_TEGRA
 	help
 	  Say Y or M here if you want support for SoC audio on Tegra.
 
+if SND_SOC_TEGRA
+
 config SND_SOC_TEGRA20_AC97
 	tristate "Tegra20 AC97 interface"
-	depends on SND_SOC_TEGRA
 	select SND_SOC_AC97_BUS
 	select SND_SOC_TEGRA20_DAS
 	help
@@ -21,7 +22,6 @@ config SND_SOC_TEGRA20_AC97
 
 config SND_SOC_TEGRA20_DAS
 	tristate "Tegra20 DAS module"
-	depends on SND_SOC_TEGRA
 	help
 	  Say Y or M if you want to add support for the Tegra20 DAS module.
 	  You will also need to select the individual machine drivers to
@@ -29,7 +29,6 @@ config SND_SOC_TEGRA20_DAS
 
 config SND_SOC_TEGRA20_I2S
 	tristate "Tegra20 I2S interface"
-	depends on SND_SOC_TEGRA
 	select SND_SOC_TEGRA20_DAS
 	help
 	  Say Y or M if you want to add support for codecs attached to the
@@ -38,7 +37,6 @@ config SND_SOC_TEGRA20_I2S
 
 config SND_SOC_TEGRA20_SPDIF
 	tristate "Tegra20 SPDIF interface"
-	depends on SND_SOC_TEGRA
 	help
 	  Say Y or M if you want to add support for the Tegra20 SPDIF interface.
 	  You will also need to select the individual machine drivers to support
@@ -46,7 +44,6 @@ config SND_SOC_TEGRA20_SPDIF
 
 config SND_SOC_TEGRA30_AHUB
 	tristate "Tegra30 AHUB module"
-	depends on SND_SOC_TEGRA
 	help
 	  Say Y or M if you want to add support for the Tegra30 AHUB module.
 	  You will also need to select the individual machine drivers to
@@ -54,7 +51,6 @@ config SND_SOC_TEGRA30_AHUB
 
 config SND_SOC_TEGRA30_I2S
 	tristate "Tegra30 I2S interface"
-	depends on SND_SOC_TEGRA
 	select SND_SOC_TEGRA30_AHUB
 	help
 	  Say Y or M if you want to add support for codecs attached to the
@@ -63,7 +59,6 @@ config SND_SOC_TEGRA30_I2S
 
 config SND_SOC_TEGRA210_AHUB
 	tristate "Tegra210 AHUB module"
-	depends on SND_SOC_TEGRA
 	help
 	  Config to enable Audio Hub (AHUB) module, which comprises of a
 	  switch called Audio Crossbar (AXBAR) used to configure or modify
@@ -73,7 +68,6 @@ config SND_SOC_TEGRA210_AHUB
 
 config SND_SOC_TEGRA210_DMIC
 	tristate "Tegra210 DMIC module"
-	depends on SND_SOC_TEGRA
 	help
 	  Config to enable the Digital MIC (DMIC) controller which is used
 	  to interface with Pulse Density Modulation (PDM) input devices.
@@ -84,7 +78,6 @@ config SND_SOC_TEGRA210_DMIC
 
 config SND_SOC_TEGRA210_I2S
 	tristate "Tegra210 I2S module"
-	depends on SND_SOC_TEGRA
 	help
 	  Config to enable the Inter-IC Sound (I2S) Controller which
 	  implements full-duplex and bidirectional and single direction
@@ -94,7 +87,6 @@ config SND_SOC_TEGRA210_I2S
 
 config SND_SOC_TEGRA186_DSPK
 	tristate "Tegra186 DSPK module"
-	depends on SND_SOC_TEGRA
 	help
 	  Config to enable the Digital Speaker Controller (DSPK) which
 	  converts the multi-bit Pulse Code Modulation (PCM) audio input to
@@ -107,7 +99,6 @@ config SND_SOC_TEGRA186_DSPK
 
 config SND_SOC_TEGRA210_ADMAIF
 	tristate "Tegra210 ADMAIF module"
-	depends on SND_SOC_TEGRA
 	help
 	  Config to enable ADMAIF which is the interface between ADMA and
 	  Audio Hub (AHUB). Each ADMA channel that sends/receives data to/
@@ -117,9 +108,18 @@ config SND_SOC_TEGRA210_ADMAIF
 	  channel. Buffer size is configurable for each ADMAIIF channel.
 	  Say Y or M if you want to add support for Tegra210 ADMAIF module.
 
+config SND_SOC_TEGRA_AUDIO_GRAPH_CARD
+	tristate "Audio Graph Card based Tegra driver"
+	depends on SND_AUDIO_GRAPH_CARD
+	help
+	  Config to enable Tegra audio machine driver based on generic
+	  audio graph driver. It is a thin driver written to customize
+	  few things for Tegra audio. Most of the code is re-used from
+	  audio graph driver and the same DT bindings are used.
+
 config SND_SOC_TEGRA_RT5640
 	tristate "SoC Audio support for Tegra boards using an RT5640 codec"
-	depends on SND_SOC_TEGRA && I2C && GPIOLIB
+	depends on I2C && GPIOLIB
 	select SND_SOC_RT5640
 	help
 	  Say Y or M here if you want to add support for SoC audio on Tegra
@@ -127,7 +127,7 @@ config SND_SOC_TEGRA_RT5640
 
 config SND_SOC_TEGRA_WM8753
 	tristate "SoC Audio support for Tegra boards using a WM8753 codec"
-	depends on SND_SOC_TEGRA && I2C && GPIOLIB
+	depends on I2C && GPIOLIB
 	select SND_SOC_WM8753
 	help
 	  Say Y or M here if you want to add support for SoC audio on Tegra
@@ -135,7 +135,7 @@ config SND_SOC_TEGRA_WM8753
 
 config SND_SOC_TEGRA_WM8903
 	tristate "SoC Audio support for Tegra boards using a WM8903 codec"
-	depends on SND_SOC_TEGRA && I2C && GPIOLIB
+	depends on I2C && GPIOLIB
 	select SND_SOC_WM8903
 	help
 	  Say Y or M here if you want to add support for SoC audio on Tegra
@@ -144,7 +144,7 @@ config SND_SOC_TEGRA_WM8903
 
 config SND_SOC_TEGRA_WM9712
 	tristate "SoC Audio support for Tegra boards using a WM9712 codec"
-	depends on SND_SOC_TEGRA && GPIOLIB
+	depends on GPIOLIB
 	select SND_SOC_TEGRA20_AC97
 	select SND_SOC_WM9712
 	help
@@ -153,7 +153,7 @@ config SND_SOC_TEGRA_WM9712
 
 config SND_SOC_TEGRA_TRIMSLICE
 	tristate "SoC Audio support for TrimSlice board"
-	depends on SND_SOC_TEGRA && I2C
+	depends on I2C
 	select SND_SOC_TLV320AIC23_I2C
 	help
 	  Say Y or M here if you want to add support for SoC audio on the
@@ -161,7 +161,7 @@ config SND_SOC_TEGRA_TRIMSLICE
 
 config SND_SOC_TEGRA_ALC5632
 	tristate "SoC Audio support for Tegra boards using an ALC5632 codec"
-	depends on SND_SOC_TEGRA && I2C && GPIOLIB
+	depends on I2C && GPIOLIB
 	select SND_SOC_ALC5632
 	help
 	  Say Y or M here if you want to add support for SoC audio on the
@@ -169,7 +169,7 @@ config SND_SOC_TEGRA_ALC5632
 
 config SND_SOC_TEGRA_MAX98090
 	tristate "SoC Audio support for Tegra boards using a MAX98090 codec"
-	depends on SND_SOC_TEGRA && I2C && GPIOLIB
+	depends on I2C && GPIOLIB
 	select SND_SOC_MAX98090
 	help
 	  Say Y or M here if you want to add support for SoC audio on Tegra
@@ -177,7 +177,7 @@ config SND_SOC_TEGRA_MAX98090
 
 config SND_SOC_TEGRA_RT5677
 	tristate "SoC Audio support for Tegra boards using a RT5677 codec"
-	depends on SND_SOC_TEGRA && I2C && GPIOLIB
+	depends on I2C && GPIOLIB
 	select SND_SOC_RT5677
 	help
 	  Say Y or M here if you want to add support for SoC audio on Tegra
@@ -185,9 +185,11 @@ config SND_SOC_TEGRA_RT5677
 
 config SND_SOC_TEGRA_SGTL5000
 	tristate "SoC Audio support for Tegra boards using a SGTL5000 codec"
-	depends on SND_SOC_TEGRA && I2C && GPIOLIB
+	depends on I2C && GPIOLIB
 	select SND_SOC_SGTL5000
 	help
 	  Say Y or M here if you want to add support for SoC audio on Tegra
 	  boards using the SGTL5000 codec, such as Apalis T30, Apalis TK1 or
 	  Colibri T30.
+
+endif
diff --git a/sound/soc/tegra/Makefile b/sound/soc/tegra/Makefile
index 60040a06b814..b17dd6eef92a 100644
--- a/sound/soc/tegra/Makefile
+++ b/sound/soc/tegra/Makefile
@@ -38,6 +38,7 @@ snd-soc-tegra-trimslice-objs := trimslice.o
 snd-soc-tegra-alc5632-objs := tegra_alc5632.o
 snd-soc-tegra-max98090-objs := tegra_max98090.o
 snd-soc-tegra-sgtl5000-objs := tegra_sgtl5000.o
+snd-soc-tegra-audio-graph-card-objs := tegra_audio_graph_card.o
 
 obj-$(CONFIG_SND_SOC_TEGRA_RT5640) += snd-soc-tegra-rt5640.o
 obj-$(CONFIG_SND_SOC_TEGRA_RT5677) += snd-soc-tegra-rt5677.o
@@ -48,3 +49,4 @@ obj-$(CONFIG_SND_SOC_TEGRA_TRIMSLICE) += snd-soc-tegra-trimslice.o
 obj-$(CONFIG_SND_SOC_TEGRA_ALC5632) += snd-soc-tegra-alc5632.o
 obj-$(CONFIG_SND_SOC_TEGRA_MAX98090) += snd-soc-tegra-max98090.o
 obj-$(CONFIG_SND_SOC_TEGRA_SGTL5000) += snd-soc-tegra-sgtl5000.o
+obj-$(CONFIG_SND_SOC_TEGRA_AUDIO_GRAPH_CARD) += snd-soc-tegra-audio-graph-card.o
diff --git a/sound/soc/tegra/tegra186_dspk.c b/sound/soc/tegra/tegra186_dspk.c
index 7d9948fb2ca7..8ee9a77bd83d 100644
--- a/sound/soc/tegra/tegra186_dspk.c
+++ b/sound/soc/tegra/tegra186_dspk.c
@@ -217,7 +217,7 @@ static struct snd_soc_dai_driver tegra186_dspk_dais[] = {
 			   SNDRV_PCM_FMTBIT_S32_LE,
 	    },
 	    .ops = &tegra186_dspk_dai_ops,
-	    .symmetric_rates = 1,
+	    .symmetric_rate = 1,
 	},
 };
 
diff --git a/sound/soc/tegra/tegra20_i2s.c b/sound/soc/tegra/tegra20_i2s.c
index 005fc4e645aa..d7a3d046c8f8 100644
--- a/sound/soc/tegra/tegra20_i2s.c
+++ b/sound/soc/tegra/tegra20_i2s.c
@@ -260,7 +260,7 @@ static const struct snd_soc_dai_driver tegra20_i2s_dai_template = {
 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
 	},
 	.ops = &tegra20_i2s_dai_ops,
-	.symmetric_rates = 1,
+	.symmetric_rate = 1,
 };
 
 static const struct snd_soc_component_driver tegra20_i2s_component = {
diff --git a/sound/soc/tegra/tegra210_dmic.c b/sound/soc/tegra/tegra210_dmic.c
index ead2c99bf72e..b096478cd2ef 100644
--- a/sound/soc/tegra/tegra210_dmic.c
+++ b/sound/soc/tegra/tegra210_dmic.c
@@ -228,7 +228,7 @@ static struct snd_soc_dai_driver tegra210_dmic_dais[] = {
 				   SNDRV_PCM_FMTBIT_S32_LE,
 		},
 		.ops = &tegra210_dmic_dai_ops,
-		.symmetric_rates = 1,
+		.symmetric_rate = 1,
 	},
 };
 
diff --git a/sound/soc/tegra/tegra210_i2s.c b/sound/soc/tegra/tegra210_i2s.c
index ca31ec92e508..45f31ccb49d8 100644
--- a/sound/soc/tegra/tegra210_i2s.c
+++ b/sound/soc/tegra/tegra210_i2s.c
@@ -577,7 +577,7 @@ static struct snd_soc_dai_driver tegra210_i2s_dais[] = {
 				SNDRV_PCM_FMTBIT_S32_LE,
 		},
 		.ops = &tegra210_i2s_dai_ops,
-		.symmetric_rates = 1,
+		.symmetric_rate = 1,
 	},
 };
 
diff --git a/sound/soc/tegra/tegra30_ahub.c b/sound/soc/tegra/tegra30_ahub.c
index 156e3b9d613c..9ef05ca4f6c4 100644
--- a/sound/soc/tegra/tegra30_ahub.c
+++ b/sound/soc/tegra/tegra30_ahub.c
@@ -45,8 +45,7 @@ static int tegra30_ahub_runtime_suspend(struct device *dev)
 	regcache_cache_only(ahub->regmap_apbif, true);
 	regcache_cache_only(ahub->regmap_ahub, true);
 
-	clk_disable_unprepare(ahub->clk_apbif);
-	clk_disable_unprepare(ahub->clk_d_audio);
+	clk_bulk_disable_unprepare(ahub->nclocks, ahub->clocks);
 
 	return 0;
 }
@@ -66,22 +65,39 @@ static int tegra30_ahub_runtime_resume(struct device *dev)
 {
 	int ret;
 
-	ret = clk_prepare_enable(ahub->clk_d_audio);
-	if (ret) {
-		dev_err(dev, "clk_enable d_audio failed: %d\n", ret);
+	ret = reset_control_assert(ahub->reset);
+	if (ret)
 		return ret;
-	}
-	ret = clk_prepare_enable(ahub->clk_apbif);
-	if (ret) {
-		dev_err(dev, "clk_enable apbif failed: %d\n", ret);
-		clk_disable(ahub->clk_d_audio);
+
+	ret = clk_bulk_prepare_enable(ahub->nclocks, ahub->clocks);
+	if (ret)
 		return ret;
-	}
+
+	usleep_range(10, 100);
+
+	ret = reset_control_deassert(ahub->reset);
+	if (ret)
+		goto disable_clocks;
 
 	regcache_cache_only(ahub->regmap_apbif, false);
 	regcache_cache_only(ahub->regmap_ahub, false);
+	regcache_mark_dirty(ahub->regmap_apbif);
+	regcache_mark_dirty(ahub->regmap_ahub);
+
+	ret = regcache_sync(ahub->regmap_apbif);
+	if (ret)
+		goto disable_clocks;
+
+	ret = regcache_sync(ahub->regmap_ahub);
+	if (ret)
+		goto disable_clocks;
 
 	return 0;
+
+disable_clocks:
+	clk_bulk_disable_unprepare(ahub->nclocks, ahub->clocks);
+
+	return ret;
 }
 
 int tegra30_ahub_allocate_rx_fifo(enum tegra30_ahub_rxcif *rxcif,
@@ -337,6 +353,8 @@ static const struct {
 	const char *rst_name;
 	u32 mod_list_mask;
 } configlink_mods[] = {
+	{ "d_audio", MOD_LIST_MASK_TEGRA30_OR_LATER },
+	{ "apbif", MOD_LIST_MASK_TEGRA30_OR_LATER },
 	{ "i2s0", MOD_LIST_MASK_TEGRA30_OR_LATER },
 	{ "i2s1", MOD_LIST_MASK_TEGRA30_OR_LATER },
 	{ "i2s2", MOD_LIST_MASK_TEGRA30_OR_LATER },
@@ -526,7 +544,6 @@ static int tegra30_ahub_probe(struct platform_device *pdev)
 	/*
 	 * The AHUB hosts a register bus: the "configlink". For this to
 	 * operate correctly, all devices on this bus must be out of reset.
-	 * Ensure that here.
 	 */
 	for (i = 0; i < ARRAY_SIZE(configlink_mods); i++) {
 		if (!(configlink_mods[i].mod_list_mask &
@@ -542,10 +559,8 @@ static int tegra30_ahub_probe(struct platform_device *pdev)
 			return ret;
 		}
 
-		ret = reset_control_deassert(rst);
+		/* just check presence of the reset control in DT */
 		reset_control_put(rst);
-		if (ret)
-			return ret;
 	}
 
 	ahub = devm_kzalloc(&pdev->dev, sizeof(struct tegra30_ahub),
@@ -557,18 +572,17 @@ static int tegra30_ahub_probe(struct platform_device *pdev)
 	ahub->soc_data = soc_data;
 	ahub->dev = &pdev->dev;
 
-	ahub->clk_d_audio = devm_clk_get(&pdev->dev, "d_audio");
-	if (IS_ERR(ahub->clk_d_audio)) {
-		dev_err(&pdev->dev, "Can't retrieve ahub d_audio clock\n");
-		ret = PTR_ERR(ahub->clk_d_audio);
-		return ret;
-	}
+	ahub->clocks[ahub->nclocks++].id = "apbif";
+	ahub->clocks[ahub->nclocks++].id = "d_audio";
 
-	ahub->clk_apbif = devm_clk_get(&pdev->dev, "apbif");
-	if (IS_ERR(ahub->clk_apbif)) {
-		dev_err(&pdev->dev, "Can't retrieve ahub apbif clock\n");
-		ret = PTR_ERR(ahub->clk_apbif);
+	ret = devm_clk_bulk_get(&pdev->dev, ahub->nclocks, ahub->clocks);
+	if (ret)
 		return ret;
+
+	ahub->reset = devm_reset_control_array_get_exclusive(&pdev->dev);
+	if (IS_ERR(ahub->reset)) {
+		dev_err(&pdev->dev, "Can't get resets: %pe\n", ahub->reset);
+		return PTR_ERR(ahub->reset);
 	}
 
 	res0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
diff --git a/sound/soc/tegra/tegra30_ahub.h b/sound/soc/tegra/tegra30_ahub.h
index 6889c5f23d02..3b85244f87f1 100644
--- a/sound/soc/tegra/tegra30_ahub.h
+++ b/sound/soc/tegra/tegra30_ahub.h
@@ -511,8 +511,9 @@ struct tegra30_ahub_soc_data {
 struct tegra30_ahub {
 	const struct tegra30_ahub_soc_data *soc_data;
 	struct device *dev;
-	struct clk *clk_d_audio;
-	struct clk *clk_apbif;
+	struct reset_control *reset;
+	struct clk_bulk_data clocks[2];
+	unsigned int nclocks;
 	resource_size_t apbif_addr;
 	struct regmap *regmap_apbif;
 	struct regmap *regmap_ahub;
diff --git a/sound/soc/tegra/tegra30_i2s.c b/sound/soc/tegra/tegra30_i2s.c
index db5a8587bfa4..6740df541508 100644
--- a/sound/soc/tegra/tegra30_i2s.c
+++ b/sound/soc/tegra/tegra30_i2s.c
@@ -316,7 +316,7 @@ static const struct snd_soc_dai_driver tegra30_i2s_dai_template = {
 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
 	},
 	.ops = &tegra30_i2s_dai_ops,
-	.symmetric_rates = 1,
+	.symmetric_rate = 1,
 };
 
 static const struct snd_soc_component_driver tegra30_i2s_component = {
diff --git a/sound/soc/tegra/tegra_audio_graph_card.c b/sound/soc/tegra/tegra_audio_graph_card.c
new file mode 100644
index 000000000000..ddedf18adde1
--- /dev/null
+++ b/sound/soc/tegra/tegra_audio_graph_card.c
@@ -0,0 +1,252 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// tegra_audio_graph_card.c - Audio Graph based Tegra Machine Driver
+//
+// Copyright (c) 2020-2021 NVIDIA CORPORATION.  All rights reserved.
+
+#include <linux/math64.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <sound/graph_card.h>
+#include <sound/pcm_params.h>
+
+#define MAX_PLLA_OUT0_DIV 128
+
+#define simple_to_tegra_priv(simple) \
+		container_of(simple, struct tegra_audio_priv, simple)
+
+enum srate_type {
+	/*
+	 * Sample rates multiple of 8000 Hz and below are supported:
+	 * ( 8000, 16000, 32000, 48000, 96000, 192000 Hz )
+	 */
+	x8_RATE,
+
+	/*
+	 * Sample rates multiple of 11025 Hz and below are supported:
+	 * ( 11025, 22050, 44100, 88200, 176400 Hz )
+	 */
+	x11_RATE,
+
+	NUM_RATE_TYPE,
+};
+
+struct tegra_audio_priv {
+	struct asoc_simple_priv simple;
+	struct clk *clk_plla_out0;
+	struct clk *clk_plla;
+};
+
+/* Tegra audio chip data */
+struct tegra_audio_cdata {
+	unsigned int plla_rates[NUM_RATE_TYPE];
+	unsigned int plla_out0_rates[NUM_RATE_TYPE];
+};
+
+/* Setup PLL clock as per the given sample rate */
+static int tegra_audio_graph_update_pll(struct snd_pcm_substream *substream,
+					struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
+	struct asoc_simple_priv *simple = snd_soc_card_get_drvdata(rtd->card);
+	struct tegra_audio_priv *priv = simple_to_tegra_priv(simple);
+	struct device *dev = rtd->card->dev;
+	const struct tegra_audio_cdata *data = of_device_get_match_data(dev);
+	unsigned int plla_rate, plla_out0_rate, bclk;
+	unsigned int srate = params_rate(params);
+	int err;
+
+	switch (srate) {
+	case 11025:
+	case 22050:
+	case 44100:
+	case 88200:
+	case 176400:
+		plla_out0_rate = data->plla_out0_rates[x11_RATE];
+		plla_rate = data->plla_rates[x11_RATE];
+		break;
+	case 8000:
+	case 16000:
+	case 32000:
+	case 48000:
+	case 96000:
+	case 192000:
+		plla_out0_rate = data->plla_out0_rates[x8_RATE];
+		plla_rate = data->plla_rates[x8_RATE];
+		break;
+	default:
+		dev_err(rtd->card->dev, "Unsupported sample rate %u\n",
+			srate);
+		return -EINVAL;
+	}
+
+	/*
+	 * Below is the clock relation:
+	 *
+	 *	PLLA
+	 *	  |
+	 *	  |--> PLLA_OUT0
+	 *		  |
+	 *		  |---> I2S modules
+	 *		  |
+	 *		  |---> DMIC modules
+	 *		  |
+	 *		  |---> DSPK modules
+	 *
+	 *
+	 * Default PLLA_OUT0 rate might be too high when I/O is running
+	 * at minimum PCM configurations. This may result in incorrect
+	 * clock rates and glitchy audio. The maximum divider is 128
+	 * and any thing higher than that won't work. Thus reduce PLLA_OUT0
+	 * to work for lower configurations.
+	 *
+	 * This problem is seen for I2S only, as DMIC and DSPK minimum
+	 * clock requirements are under allowed divider limits.
+	 */
+	bclk = srate * params_channels(params) * params_width(params);
+	if (div_u64(plla_out0_rate, bclk) > MAX_PLLA_OUT0_DIV)
+		plla_out0_rate >>= 1;
+
+	dev_dbg(rtd->card->dev,
+		"Update clock rates: PLLA(= %u Hz) and PLLA_OUT0(= %u Hz)\n",
+		plla_rate, plla_out0_rate);
+
+	/* Set PLLA rate */
+	err = clk_set_rate(priv->clk_plla, plla_rate);
+	if (err) {
+		dev_err(rtd->card->dev,
+			"Can't set plla rate for %u, err: %d\n",
+			plla_rate, err);
+		return err;
+	}
+
+	/* Set PLLA_OUT0 rate */
+	err = clk_set_rate(priv->clk_plla_out0, plla_out0_rate);
+	if (err) {
+		dev_err(rtd->card->dev,
+			"Can't set plla_out0 rate %u, err: %d\n",
+			plla_out0_rate, err);
+		return err;
+	}
+
+	return err;
+}
+
+static int tegra_audio_graph_hw_params(struct snd_pcm_substream *substream,
+				       struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
+	struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
+	int err;
+
+	/*
+	 * This gets called for each DAI link (FE or BE) when DPCM is used.
+	 * We may not want to update PLLA rate for each call. So PLLA update
+	 * must be restricted to external I/O links (I2S, DMIC or DSPK) since
+	 * they actually depend on it. I/O modules update their clocks in
+	 * hw_param() of their respective component driver and PLLA rate
+	 * update here helps them to derive appropriate rates.
+	 *
+	 * TODO: When more HW accelerators get added (like sample rate
+	 * converter, volume gain controller etc., which don't really
+	 * depend on PLLA) we need a better way to filter here.
+	 */
+	if (cpu_dai->driver->ops && rtd->dai_link->no_pcm) {
+		err = tegra_audio_graph_update_pll(substream, params);
+		if (err)
+			return err;
+	}
+
+	return asoc_simple_hw_params(substream, params);
+}
+
+static const struct snd_soc_ops tegra_audio_graph_ops = {
+	.startup	= asoc_simple_startup,
+	.shutdown	= asoc_simple_shutdown,
+	.hw_params	= tegra_audio_graph_hw_params,
+};
+
+static int tegra_audio_graph_card_probe(struct snd_soc_card *card)
+{
+	struct asoc_simple_priv *simple = snd_soc_card_get_drvdata(card);
+	struct tegra_audio_priv *priv = simple_to_tegra_priv(simple);
+
+	priv->clk_plla = devm_clk_get(card->dev, "pll_a");
+	if (IS_ERR(priv->clk_plla)) {
+		dev_err(card->dev, "Can't retrieve clk pll_a\n");
+		return PTR_ERR(priv->clk_plla);
+	}
+
+	priv->clk_plla_out0 = devm_clk_get(card->dev, "plla_out0");
+	if (IS_ERR(priv->clk_plla_out0)) {
+		dev_err(card->dev, "Can't retrieve clk plla_out0\n");
+		return PTR_ERR(priv->clk_plla_out0);
+	}
+
+	return audio_graph_card_probe(card);
+}
+
+static int tegra_audio_graph_probe(struct platform_device *pdev)
+{
+	struct tegra_audio_priv *priv;
+	struct device *dev = &pdev->dev;
+	struct snd_soc_card *card;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	card = simple_priv_to_card(&priv->simple);
+
+	card->probe = tegra_audio_graph_card_probe;
+
+	/* audio_graph_parse_of() depends on below */
+	card->component_chaining = 1;
+	priv->simple.ops = &tegra_audio_graph_ops;
+	priv->simple.force_dpcm = 1;
+
+	return audio_graph_parse_of(&priv->simple, dev);
+}
+
+static const struct tegra_audio_cdata tegra210_data = {
+	/* PLLA */
+	.plla_rates[x8_RATE] = 368640000,
+	.plla_rates[x11_RATE] = 338688000,
+	/* PLLA_OUT0 */
+	.plla_out0_rates[x8_RATE] = 49152000,
+	.plla_out0_rates[x11_RATE] = 45158400,
+};
+
+static const struct tegra_audio_cdata tegra186_data = {
+	/* PLLA */
+	.plla_rates[x8_RATE] = 245760000,
+	.plla_rates[x11_RATE] = 270950400,
+	/* PLLA_OUT0 */
+	.plla_out0_rates[x8_RATE] = 49152000,
+	.plla_out0_rates[x11_RATE] = 45158400,
+};
+
+static const struct of_device_id graph_of_tegra_match[] = {
+	{ .compatible = "nvidia,tegra210-audio-graph-card",
+	  .data = &tegra210_data },
+	{ .compatible = "nvidia,tegra186-audio-graph-card",
+	  .data = &tegra186_data },
+	{},
+};
+MODULE_DEVICE_TABLE(of, graph_of_tegra_match);
+
+static struct platform_driver tegra_audio_graph_card = {
+	.driver = {
+		.name = "tegra-audio-graph-card",
+		.pm = &snd_soc_pm_ops,
+		.of_match_table = graph_of_tegra_match,
+	},
+	.probe = tegra_audio_graph_probe,
+	.remove = audio_graph_remove,
+};
+module_platform_driver(tegra_audio_graph_card);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("ASoC Tegra Audio Graph Sound Card");
+MODULE_AUTHOR("Sameer Pujar <spujar@nvidia.com>");
diff --git a/sound/soc/tegra/tegra_pcm.c b/sound/soc/tegra/tegra_pcm.c
index b3f36515cbc1..573374b89b10 100644
--- a/sound/soc/tegra/tegra_pcm.c
+++ b/sound/soc/tegra/tegra_pcm.c
@@ -255,11 +255,7 @@ static int tegra_pcm_dma_allocate(struct snd_soc_pcm_runtime *rtd,
 	struct snd_pcm *pcm = rtd->pcm;
 	int ret;
 
-	ret = dma_set_mask(card->dev, DMA_BIT_MASK(32));
-	if (ret < 0)
-		return ret;
-
-	ret = dma_set_coherent_mask(card->dev, DMA_BIT_MASK(32));
+	ret = dma_set_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
 	if (ret < 0)
 		return ret;
 
diff --git a/sound/soc/ti/davinci-mcasp.c b/sound/soc/ti/davinci-mcasp.c
index 6247ec3d3a09..b94220306d1a 100644
--- a/sound/soc/ti/davinci-mcasp.c
+++ b/sound/soc/ti/davinci-mcasp.c
@@ -1641,7 +1641,7 @@ static struct snd_soc_dai_driver davinci_mcasp_dai[] = {
 		},
 		.ops 		= &davinci_mcasp_dai_ops,
 
-		.symmetric_rates	= 1,
+		.symmetric_rate		= 1,
 	},
 	{
 		.name		= "davinci-mcasp.1",
diff --git a/sound/soc/txx9/Kconfig b/sound/soc/txx9/Kconfig
deleted file mode 100644
index d928edf9f5a9..000000000000
--- a/sound/soc/txx9/Kconfig
+++ /dev/null
@@ -1,30 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-##
-## TXx9 ACLC
-##
-config SND_SOC_TXX9ACLC
-	tristate "SoC Audio for TXx9"
-	depends on HAS_TXX9_ACLC && TXX9_DMAC
-	help
-	  This option enables support for the AC Link Controllers in TXx9 SoC.
-
-config HAS_TXX9_ACLC
-	bool
-
-config SND_SOC_TXX9ACLC_AC97
-	tristate
-	select AC97_BUS
-	select SND_AC97_CODEC
-	select SND_SOC_AC97_BUS
-
-
-##
-## Boards
-##
-config SND_SOC_TXX9ACLC_GENERIC
-	tristate "Generic TXx9 ACLC sound machine"
-	depends on SND_SOC_TXX9ACLC
-	select SND_SOC_TXX9ACLC_AC97
-	select SND_SOC_AC97_CODEC
-	help
-	  This is a generic AC97 sound machine for use in TXx9 based systems.
diff --git a/sound/soc/txx9/Makefile b/sound/soc/txx9/Makefile
deleted file mode 100644
index 37ad833eb329..000000000000
--- a/sound/soc/txx9/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-# Platform
-snd-soc-txx9aclc-objs := txx9aclc.o
-snd-soc-txx9aclc-ac97-objs := txx9aclc-ac97.o
-
-obj-$(CONFIG_SND_SOC_TXX9ACLC) += snd-soc-txx9aclc.o
-obj-$(CONFIG_SND_SOC_TXX9ACLC_AC97) += snd-soc-txx9aclc-ac97.o
-
-# Machine
-snd-soc-txx9aclc-generic-objs := txx9aclc-generic.o
-
-obj-$(CONFIG_SND_SOC_TXX9ACLC_GENERIC) += snd-soc-txx9aclc-generic.o
diff --git a/sound/soc/txx9/txx9aclc-ac97.c b/sound/soc/txx9/txx9aclc-ac97.c
deleted file mode 100644
index d9e348444bd0..000000000000
--- a/sound/soc/txx9/txx9aclc-ac97.c
+++ /dev/null
@@ -1,230 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * TXx9 ACLC AC97 driver
- *
- * Copyright (C) 2009 Atsushi Nemoto
- *
- * Based on RBTX49xx patch from CELF patch archive.
- * (C) Copyright TOSHIBA CORPORATION 2004-2006
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/gfp.h>
-#include <asm/mach-tx39xx/ioremap.h> /* for TXX9_DIRECTMAP_BASE */
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/soc.h>
-#include "txx9aclc.h"
-
-#define AC97_DIR	\
-	(SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE)
-
-#define AC97_RATES	\
-	SNDRV_PCM_RATE_8000_48000
-
-#ifdef __BIG_ENDIAN
-#define AC97_FMTS	SNDRV_PCM_FMTBIT_S16_BE
-#else
-#define AC97_FMTS	SNDRV_PCM_FMTBIT_S16_LE
-#endif
-
-static DECLARE_WAIT_QUEUE_HEAD(ac97_waitq);
-
-/* REVISIT: How to find txx9aclc_drvdata from snd_ac97? */
-static struct txx9aclc_plat_drvdata *txx9aclc_drvdata;
-
-static int txx9aclc_regready(struct txx9aclc_plat_drvdata *drvdata)
-{
-	return __raw_readl(drvdata->base + ACINTSTS) & ACINT_REGACCRDY;
-}
-
-/* AC97 controller reads codec register */
-static unsigned short txx9aclc_ac97_read(struct snd_ac97 *ac97,
-					 unsigned short reg)
-{
-	struct txx9aclc_plat_drvdata *drvdata = txx9aclc_drvdata;
-	void __iomem *base = drvdata->base;
-	u32 dat;
-
-	if (!(__raw_readl(base + ACINTSTS) & ACINT_CODECRDY(ac97->num)))
-		return 0xffff;
-	reg |= ac97->num << 7;
-	dat = (reg << ACREGACC_REG_SHIFT) | ACREGACC_READ;
-	__raw_writel(dat, base + ACREGACC);
-	__raw_writel(ACINT_REGACCRDY, base + ACINTEN);
-	if (!wait_event_timeout(ac97_waitq, txx9aclc_regready(txx9aclc_drvdata), HZ)) {
-		__raw_writel(ACINT_REGACCRDY, base + ACINTDIS);
-		printk(KERN_ERR "ac97 read timeout (reg %#x)\n", reg);
-		dat = 0xffff;
-		goto done;
-	}
-	dat = __raw_readl(base + ACREGACC);
-	if (((dat >> ACREGACC_REG_SHIFT) & 0xff) != reg) {
-		printk(KERN_ERR "reg mismatch %x with %x\n",
-			dat, reg);
-		dat = 0xffff;
-		goto done;
-	}
-	dat = (dat >> ACREGACC_DAT_SHIFT) & 0xffff;
-done:
-	__raw_writel(ACINT_REGACCRDY, base + ACINTDIS);
-	return dat;
-}
-
-/* AC97 controller writes to codec register */
-static void txx9aclc_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
-				unsigned short val)
-{
-	struct txx9aclc_plat_drvdata *drvdata = txx9aclc_drvdata;
-	void __iomem *base = drvdata->base;
-
-	__raw_writel(((reg | (ac97->num << 7)) << ACREGACC_REG_SHIFT) |
-		     (val << ACREGACC_DAT_SHIFT),
-		     base + ACREGACC);
-	__raw_writel(ACINT_REGACCRDY, base + ACINTEN);
-	if (!wait_event_timeout(ac97_waitq, txx9aclc_regready(txx9aclc_drvdata), HZ)) {
-		printk(KERN_ERR
-			"ac97 write timeout (reg %#x)\n", reg);
-	}
-	__raw_writel(ACINT_REGACCRDY, base + ACINTDIS);
-}
-
-static void txx9aclc_ac97_cold_reset(struct snd_ac97 *ac97)
-{
-	struct txx9aclc_plat_drvdata *drvdata = txx9aclc_drvdata;
-	void __iomem *base = drvdata->base;
-	u32 ready = ACINT_CODECRDY(ac97->num) | ACINT_REGACCRDY;
-
-	__raw_writel(ACCTL_ENLINK, base + ACCTLDIS);
-	udelay(1);
-	__raw_writel(ACCTL_ENLINK, base + ACCTLEN);
-	/* wait for primary codec ready status */
-	__raw_writel(ready, base + ACINTEN);
-	if (!wait_event_timeout(ac97_waitq,
-				(__raw_readl(base + ACINTSTS) & ready) == ready,
-				HZ)) {
-		dev_err(&ac97->dev, "primary codec is not ready "
-			"(status %#x)\n",
-			__raw_readl(base + ACINTSTS));
-	}
-	__raw_writel(ACINT_REGACCRDY, base + ACINTSTS);
-	__raw_writel(ready, base + ACINTDIS);
-}
-
-/* AC97 controller operations */
-static struct snd_ac97_bus_ops txx9aclc_ac97_ops = {
-	.read		= txx9aclc_ac97_read,
-	.write		= txx9aclc_ac97_write,
-	.reset		= txx9aclc_ac97_cold_reset,
-};
-
-static irqreturn_t txx9aclc_ac97_irq(int irq, void *dev_id)
-{
-	struct txx9aclc_plat_drvdata *drvdata = dev_id;
-	void __iomem *base = drvdata->base;
-
-	__raw_writel(__raw_readl(base + ACINTMSTS), base + ACINTDIS);
-	wake_up(&ac97_waitq);
-	return IRQ_HANDLED;
-}
-
-static int txx9aclc_ac97_probe(struct snd_soc_dai *dai)
-{
-	txx9aclc_drvdata = snd_soc_dai_get_drvdata(dai);
-	return 0;
-}
-
-static int txx9aclc_ac97_remove(struct snd_soc_dai *dai)
-{
-	struct txx9aclc_plat_drvdata *drvdata = snd_soc_dai_get_drvdata(dai);
-
-	/* disable AC-link */
-	__raw_writel(ACCTL_ENLINK, drvdata->base + ACCTLDIS);
-	txx9aclc_drvdata = NULL;
-	return 0;
-}
-
-static struct snd_soc_dai_driver txx9aclc_ac97_dai = {
-	.probe			= txx9aclc_ac97_probe,
-	.remove			= txx9aclc_ac97_remove,
-	.playback = {
-		.rates		= AC97_RATES,
-		.formats	= AC97_FMTS,
-		.channels_min	= 2,
-		.channels_max	= 2,
-	},
-	.capture = {
-		.rates		= AC97_RATES,
-		.formats	= AC97_FMTS,
-		.channels_min	= 2,
-		.channels_max	= 2,
-	},
-};
-
-static const struct snd_soc_component_driver txx9aclc_ac97_component = {
-	.name		= "txx9aclc-ac97",
-};
-
-static int txx9aclc_ac97_dev_probe(struct platform_device *pdev)
-{
-	struct txx9aclc_plat_drvdata *drvdata;
-	struct resource *r;
-	int err;
-	int irq;
-
-	irq = platform_get_irq(pdev, 0);
-	if (irq < 0)
-		return irq;
-
-	drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL);
-	if (!drvdata)
-		return -ENOMEM;
-
-	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	drvdata->base = devm_ioremap_resource(&pdev->dev, r);
-	if (IS_ERR(drvdata->base))
-		return PTR_ERR(drvdata->base);
-
-	platform_set_drvdata(pdev, drvdata);
-	drvdata->physbase = r->start;
-	if (sizeof(drvdata->physbase) > sizeof(r->start) &&
-	    r->start >= TXX9_DIRECTMAP_BASE &&
-	    r->start < TXX9_DIRECTMAP_BASE + 0x400000)
-		drvdata->physbase |= 0xf00000000ull;
-	err = devm_request_irq(&pdev->dev, irq, txx9aclc_ac97_irq,
-			       0, dev_name(&pdev->dev), drvdata);
-	if (err < 0)
-		return err;
-
-	err = snd_soc_set_ac97_ops(&txx9aclc_ac97_ops);
-	if (err < 0)
-		return err;
-
-	return devm_snd_soc_register_component(&pdev->dev, &txx9aclc_ac97_component,
-					  &txx9aclc_ac97_dai, 1);
-}
-
-static int txx9aclc_ac97_dev_remove(struct platform_device *pdev)
-{
-	snd_soc_set_ac97_ops(NULL);
-	return 0;
-}
-
-static struct platform_driver txx9aclc_ac97_driver = {
-	.probe		= txx9aclc_ac97_dev_probe,
-	.remove		= txx9aclc_ac97_dev_remove,
-	.driver		= {
-		.name	= "txx9aclc-ac97",
-	},
-};
-
-module_platform_driver(txx9aclc_ac97_driver);
-
-MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>");
-MODULE_DESCRIPTION("TXx9 ACLC AC97 driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:txx9aclc-ac97");
diff --git a/sound/soc/txx9/txx9aclc-generic.c b/sound/soc/txx9/txx9aclc-generic.c
deleted file mode 100644
index d6893721ba1d..000000000000
--- a/sound/soc/txx9/txx9aclc-generic.c
+++ /dev/null
@@ -1,88 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Generic TXx9 ACLC machine driver
- *
- * Copyright (C) 2009 Atsushi Nemoto
- *
- * Based on RBTX49xx patch from CELF patch archive.
- * (C) Copyright TOSHIBA CORPORATION 2004-2006
- *
- * This is a very generic AC97 sound machine driver for boards which
- * have (AC97) audio at ACLC (e.g. RBTX49XX boards).
- */
-
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/soc.h>
-#include "txx9aclc.h"
-
-SND_SOC_DAILINK_DEFS(hifi,
-	DAILINK_COMP_ARRAY(COMP_CPU("txx9aclc-ac97")),
-	DAILINK_COMP_ARRAY(COMP_CODEC("ac97-codec", "ac97-hifi")),
-	DAILINK_COMP_ARRAY(COMP_PLATFORM("txx9aclc-pcm-audio")));
-
-static struct snd_soc_dai_link txx9aclc_generic_dai = {
-	.name = "AC97",
-	.stream_name = "AC97 HiFi",
-	SND_SOC_DAILINK_REG(hifi),
-};
-
-static struct snd_soc_card txx9aclc_generic_card = {
-	.name		= "Generic TXx9 ACLC Audio",
-	.owner		= THIS_MODULE,
-	.dai_link	= &txx9aclc_generic_dai,
-	.num_links	= 1,
-};
-
-static struct platform_device *soc_pdev;
-
-static int __init txx9aclc_generic_probe(struct platform_device *pdev)
-{
-	int ret;
-
-	soc_pdev = platform_device_alloc("soc-audio", -1);
-	if (!soc_pdev)
-		return -ENOMEM;
-	platform_set_drvdata(soc_pdev, &txx9aclc_generic_card);
-	ret = platform_device_add(soc_pdev);
-	if (ret) {
-		platform_device_put(soc_pdev);
-		return ret;
-	}
-
-	return 0;
-}
-
-static int __exit txx9aclc_generic_remove(struct platform_device *pdev)
-{
-	platform_device_unregister(soc_pdev);
-	return 0;
-}
-
-static struct platform_driver txx9aclc_generic_driver = {
-	.remove = __exit_p(txx9aclc_generic_remove),
-	.driver = {
-		.name = "txx9aclc-generic",
-	},
-};
-
-static int __init txx9aclc_generic_init(void)
-{
-	return platform_driver_probe(&txx9aclc_generic_driver,
-				     txx9aclc_generic_probe);
-}
-
-static void __exit txx9aclc_generic_exit(void)
-{
-	platform_driver_unregister(&txx9aclc_generic_driver);
-}
-
-module_init(txx9aclc_generic_init);
-module_exit(txx9aclc_generic_exit);
-
-MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>");
-MODULE_DESCRIPTION("Generic TXx9 ACLC ALSA SoC audio driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:txx9aclc-generic");
diff --git a/sound/soc/txx9/txx9aclc.c b/sound/soc/txx9/txx9aclc.c
deleted file mode 100644
index 1d2d0d9b57b0..000000000000
--- a/sound/soc/txx9/txx9aclc.c
+++ /dev/null
@@ -1,422 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Generic TXx9 ACLC platform driver
- *
- * Copyright (C) 2009 Atsushi Nemoto
- *
- * Based on RBTX49xx patch from CELF patch archive.
- * (C) Copyright TOSHIBA CORPORATION 2004-2006
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/scatterlist.h>
-#include <linux/slab.h>
-#include <linux/dmaengine.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/soc.h>
-#include "txx9aclc.h"
-
-#define DRV_NAME "txx9aclc"
-
-static struct txx9aclc_soc_device {
-	struct txx9aclc_dmadata dmadata[2];
-} txx9aclc_soc_device;
-
-/* REVISIT: How to find txx9aclc_drvdata from snd_ac97? */
-static struct txx9aclc_plat_drvdata *txx9aclc_drvdata;
-
-static int txx9aclc_dma_init(struct txx9aclc_soc_device *dev,
-			     struct txx9aclc_dmadata *dmadata);
-
-static const struct snd_pcm_hardware txx9aclc_pcm_hardware = {
-	/*
-	 * REVISIT: SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID
-	 * needs more works for noncoherent MIPS.
-	 */
-	.info		  = SNDRV_PCM_INFO_INTERLEAVED |
-			    SNDRV_PCM_INFO_BATCH |
-			    SNDRV_PCM_INFO_PAUSE,
-	.period_bytes_min = 1024,
-	.period_bytes_max = 8 * 1024,
-	.periods_min	  = 2,
-	.periods_max	  = 4096,
-	.buffer_bytes_max = 32 * 1024,
-};
-
-static int txx9aclc_pcm_hw_params(struct snd_soc_component *component,
-				  struct snd_pcm_substream *substream,
-				  struct snd_pcm_hw_params *params)
-{
-	struct snd_pcm_runtime *runtime = substream->runtime;
-	struct txx9aclc_dmadata *dmadata = runtime->private_data;
-
-	dev_dbg(component->dev,
-		"runtime->dma_area = %#lx dma_addr = %#lx dma_bytes = %zd "
-		"runtime->min_align %ld\n",
-		(unsigned long)runtime->dma_area,
-		(unsigned long)runtime->dma_addr, runtime->dma_bytes,
-		runtime->min_align);
-	dev_dbg(component->dev,
-		"periods %d period_bytes %d stream %d\n",
-		params_periods(params), params_period_bytes(params),
-		substream->stream);
-
-	dmadata->substream = substream;
-	dmadata->pos = 0;
-	return 0;
-}
-
-static int txx9aclc_pcm_prepare(struct snd_soc_component *component,
-				struct snd_pcm_substream *substream)
-{
-	struct snd_pcm_runtime *runtime = substream->runtime;
-	struct txx9aclc_dmadata *dmadata = runtime->private_data;
-
-	dmadata->dma_addr = runtime->dma_addr;
-	dmadata->buffer_bytes = snd_pcm_lib_buffer_bytes(substream);
-	dmadata->period_bytes = snd_pcm_lib_period_bytes(substream);
-
-	if (dmadata->buffer_bytes == dmadata->period_bytes) {
-		dmadata->frag_bytes = dmadata->period_bytes >> 1;
-		dmadata->frags = 2;
-	} else {
-		dmadata->frag_bytes = dmadata->period_bytes;
-		dmadata->frags = dmadata->buffer_bytes / dmadata->period_bytes;
-	}
-	dmadata->frag_count = 0;
-	dmadata->pos = 0;
-	return 0;
-}
-
-static void txx9aclc_dma_complete(void *arg)
-{
-	struct txx9aclc_dmadata *dmadata = arg;
-	unsigned long flags;
-
-	/* dma completion handler cannot submit new operations */
-	spin_lock_irqsave(&dmadata->dma_lock, flags);
-	if (dmadata->frag_count >= 0) {
-		dmadata->dmacount--;
-		if (!WARN_ON(dmadata->dmacount < 0))
-			queue_work(system_highpri_wq, &dmadata->work);
-	}
-	spin_unlock_irqrestore(&dmadata->dma_lock, flags);
-}
-
-static struct dma_async_tx_descriptor *
-txx9aclc_dma_submit(struct txx9aclc_dmadata *dmadata, dma_addr_t buf_dma_addr)
-{
-	struct dma_chan *chan = dmadata->dma_chan;
-	struct dma_async_tx_descriptor *desc;
-	struct scatterlist sg;
-
-	sg_init_table(&sg, 1);
-	sg_set_page(&sg, pfn_to_page(PFN_DOWN(buf_dma_addr)),
-		    dmadata->frag_bytes, buf_dma_addr & (PAGE_SIZE - 1));
-	sg_dma_address(&sg) = buf_dma_addr;
-	desc = dmaengine_prep_slave_sg(chan, &sg, 1,
-		dmadata->substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
-		DMA_MEM_TO_DEV : DMA_DEV_TO_MEM,
-		DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
-	if (!desc) {
-		dev_err(&chan->dev->device, "cannot prepare slave dma\n");
-		return NULL;
-	}
-	desc->callback = txx9aclc_dma_complete;
-	desc->callback_param = dmadata;
-	dmaengine_submit(desc);
-	return desc;
-}
-
-#define NR_DMA_CHAIN		2
-
-static void txx9aclc_dma_work(struct work_struct *work)
-{
-	struct txx9aclc_dmadata *dmadata =
-		container_of(work, struct txx9aclc_dmadata, work);
-	struct dma_chan *chan = dmadata->dma_chan;
-	struct dma_async_tx_descriptor *desc;
-	struct snd_pcm_substream *substream = dmadata->substream;
-	u32 ctlbit = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
-		ACCTL_AUDODMA : ACCTL_AUDIDMA;
-	int i;
-	unsigned long flags;
-
-	spin_lock_irqsave(&dmadata->dma_lock, flags);
-	if (dmadata->frag_count < 0) {
-		struct txx9aclc_plat_drvdata *drvdata = txx9aclc_drvdata;
-		void __iomem *base = drvdata->base;
-
-		spin_unlock_irqrestore(&dmadata->dma_lock, flags);
-		dmaengine_terminate_all(chan);
-		/* first time */
-		for (i = 0; i < NR_DMA_CHAIN; i++) {
-			desc = txx9aclc_dma_submit(dmadata,
-				dmadata->dma_addr + i * dmadata->frag_bytes);
-			if (!desc)
-				return;
-		}
-		dmadata->dmacount = NR_DMA_CHAIN;
-		dma_async_issue_pending(chan);
-		spin_lock_irqsave(&dmadata->dma_lock, flags);
-		__raw_writel(ctlbit, base + ACCTLEN);
-		dmadata->frag_count = NR_DMA_CHAIN % dmadata->frags;
-		spin_unlock_irqrestore(&dmadata->dma_lock, flags);
-		return;
-	}
-	if (WARN_ON(dmadata->dmacount >= NR_DMA_CHAIN)) {
-		spin_unlock_irqrestore(&dmadata->dma_lock, flags);
-		return;
-	}
-	while (dmadata->dmacount < NR_DMA_CHAIN) {
-		dmadata->dmacount++;
-		spin_unlock_irqrestore(&dmadata->dma_lock, flags);
-		desc = txx9aclc_dma_submit(dmadata,
-			dmadata->dma_addr +
-			dmadata->frag_count * dmadata->frag_bytes);
-		if (!desc)
-			return;
-		dma_async_issue_pending(chan);
-
-		spin_lock_irqsave(&dmadata->dma_lock, flags);
-		dmadata->frag_count++;
-		dmadata->frag_count %= dmadata->frags;
-		dmadata->pos += dmadata->frag_bytes;
-		dmadata->pos %= dmadata->buffer_bytes;
-		if ((dmadata->frag_count * dmadata->frag_bytes) %
-		    dmadata->period_bytes == 0)
-			snd_pcm_period_elapsed(substream);
-	}
-	spin_unlock_irqrestore(&dmadata->dma_lock, flags);
-}
-
-static int txx9aclc_pcm_trigger(struct snd_soc_component *component,
-				struct snd_pcm_substream *substream, int cmd)
-{
-	struct txx9aclc_dmadata *dmadata = substream->runtime->private_data;
-	struct txx9aclc_plat_drvdata *drvdata = txx9aclc_drvdata;
-	void __iomem *base = drvdata->base;
-	unsigned long flags;
-	int ret = 0;
-	u32 ctlbit = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
-		ACCTL_AUDODMA : ACCTL_AUDIDMA;
-
-	spin_lock_irqsave(&dmadata->dma_lock, flags);
-	switch (cmd) {
-	case SNDRV_PCM_TRIGGER_START:
-		dmadata->frag_count = -1;
-		queue_work(system_highpri_wq, &dmadata->work);
-		break;
-	case SNDRV_PCM_TRIGGER_STOP:
-	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-	case SNDRV_PCM_TRIGGER_SUSPEND:
-		__raw_writel(ctlbit, base + ACCTLDIS);
-		break;
-	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-	case SNDRV_PCM_TRIGGER_RESUME:
-		__raw_writel(ctlbit, base + ACCTLEN);
-		break;
-	default:
-		ret = -EINVAL;
-	}
-	spin_unlock_irqrestore(&dmadata->dma_lock, flags);
-	return ret;
-}
-
-static snd_pcm_uframes_t
-txx9aclc_pcm_pointer(struct snd_soc_component *component,
-		     struct snd_pcm_substream *substream)
-{
-	struct txx9aclc_dmadata *dmadata = substream->runtime->private_data;
-
-	return bytes_to_frames(substream->runtime, dmadata->pos);
-}
-
-static int txx9aclc_pcm_open(struct snd_soc_component *component,
-			     struct snd_pcm_substream *substream)
-{
-	struct txx9aclc_soc_device *dev = &txx9aclc_soc_device;
-	struct txx9aclc_dmadata *dmadata = &dev->dmadata[substream->stream];
-	int ret;
-
-	ret = snd_soc_set_runtime_hwparams(substream, &txx9aclc_pcm_hardware);
-	if (ret)
-		return ret;
-	/* ensure that buffer size is a multiple of period size */
-	ret = snd_pcm_hw_constraint_integer(substream->runtime,
-					    SNDRV_PCM_HW_PARAM_PERIODS);
-	if (ret < 0)
-		return ret;
-	substream->runtime->private_data = dmadata;
-	return 0;
-}
-
-static int txx9aclc_pcm_close(struct snd_soc_component *component,
-			      struct snd_pcm_substream *substream)
-{
-	struct txx9aclc_dmadata *dmadata = substream->runtime->private_data;
-	struct dma_chan *chan = dmadata->dma_chan;
-
-	dmadata->frag_count = -1;
-	dmaengine_terminate_all(chan);
-	return 0;
-}
-
-static int txx9aclc_pcm_new(struct snd_soc_component *component,
-			    struct snd_soc_pcm_runtime *rtd)
-{
-	struct snd_card *card = rtd->card->snd_card;
-	struct snd_soc_dai *dai = asoc_rtd_to_cpu(rtd, 0);
-	struct snd_pcm *pcm = rtd->pcm;
-	struct platform_device *pdev = to_platform_device(component->dev);
-	struct txx9aclc_soc_device *dev;
-	struct resource *r;
-	int i;
-	int ret;
-
-	/* at this point onwards the AC97 component has probed and this will be valid */
-	dev = snd_soc_dai_get_drvdata(dai);
-
-	dev->dmadata[0].stream = SNDRV_PCM_STREAM_PLAYBACK;
-	dev->dmadata[1].stream = SNDRV_PCM_STREAM_CAPTURE;
-	for (i = 0; i < 2; i++) {
-		r = platform_get_resource(pdev, IORESOURCE_DMA, i);
-		if (!r) {
-			ret = -EBUSY;
-			goto exit;
-		}
-		dev->dmadata[i].dma_res = r;
-		ret = txx9aclc_dma_init(dev, &dev->dmadata[i]);
-		if (ret)
-			goto exit;
-	}
-
-	snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
-		card->dev, 64 * 1024, 4 * 1024 * 1024);
-	return 0;
-
-exit:
-	for (i = 0; i < 2; i++) {
-		if (dev->dmadata[i].dma_chan)
-			dma_release_channel(dev->dmadata[i].dma_chan);
-		dev->dmadata[i].dma_chan = NULL;
-	}
-	return ret;
-}
-
-static bool filter(struct dma_chan *chan, void *param)
-{
-	struct txx9aclc_dmadata *dmadata = param;
-	char *devname;
-	bool found = false;
-
-	devname = kasprintf(GFP_KERNEL, "%s.%d", dmadata->dma_res->name,
-		(int)dmadata->dma_res->start);
-	if (strcmp(dev_name(chan->device->dev), devname) == 0) {
-		chan->private = &dmadata->dma_slave;
-		found = true;
-	}
-	kfree(devname);
-	return found;
-}
-
-static int txx9aclc_dma_init(struct txx9aclc_soc_device *dev,
-			     struct txx9aclc_dmadata *dmadata)
-{
-	struct txx9aclc_plat_drvdata *drvdata = txx9aclc_drvdata;
-	struct txx9dmac_slave *ds = &dmadata->dma_slave;
-	dma_cap_mask_t mask;
-
-	spin_lock_init(&dmadata->dma_lock);
-
-	ds->reg_width = sizeof(u32);
-	if (dmadata->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-		ds->tx_reg = drvdata->physbase + ACAUDODAT;
-		ds->rx_reg = 0;
-	} else {
-		ds->tx_reg = 0;
-		ds->rx_reg = drvdata->physbase + ACAUDIDAT;
-	}
-
-	/* Try to grab a DMA channel */
-	dma_cap_zero(mask);
-	dma_cap_set(DMA_SLAVE, mask);
-	dmadata->dma_chan = dma_request_channel(mask, filter, dmadata);
-	if (!dmadata->dma_chan) {
-		printk(KERN_ERR
-			"DMA channel for %s is not available\n",
-			dmadata->stream == SNDRV_PCM_STREAM_PLAYBACK ?
-			"playback" : "capture");
-		return -EBUSY;
-	}
-	INIT_WORK(&dmadata->work, txx9aclc_dma_work);
-	return 0;
-}
-
-static int txx9aclc_pcm_probe(struct snd_soc_component *component)
-{
-	snd_soc_component_set_drvdata(component, &txx9aclc_soc_device);
-	return 0;
-}
-
-static void txx9aclc_pcm_remove(struct snd_soc_component *component)
-{
-	struct txx9aclc_soc_device *dev = snd_soc_component_get_drvdata(component);
-	struct txx9aclc_plat_drvdata *drvdata = txx9aclc_drvdata;
-	void __iomem *base = drvdata->base;
-	int i;
-
-	/* disable all FIFO DMAs */
-	__raw_writel(ACCTL_AUDODMA | ACCTL_AUDIDMA, base + ACCTLDIS);
-	/* dummy R/W to clear pending DMAREQ if any */
-	__raw_writel(__raw_readl(base + ACAUDIDAT), base + ACAUDODAT);
-
-	for (i = 0; i < 2; i++) {
-		struct txx9aclc_dmadata *dmadata = &dev->dmadata[i];
-		struct dma_chan *chan = dmadata->dma_chan;
-
-		if (chan) {
-			dmadata->frag_count = -1;
-			dmaengine_terminate_all(chan);
-			dma_release_channel(chan);
-		}
-		dev->dmadata[i].dma_chan = NULL;
-	}
-}
-
-static const struct snd_soc_component_driver txx9aclc_soc_component = {
-	.name		= DRV_NAME,
-	.probe		= txx9aclc_pcm_probe,
-	.remove		= txx9aclc_pcm_remove,
-	.open		= txx9aclc_pcm_open,
-	.close		= txx9aclc_pcm_close,
-	.hw_params	= txx9aclc_pcm_hw_params,
-	.prepare	= txx9aclc_pcm_prepare,
-	.trigger	= txx9aclc_pcm_trigger,
-	.pointer	= txx9aclc_pcm_pointer,
-	.pcm_construct	= txx9aclc_pcm_new,
-};
-
-static int txx9aclc_soc_platform_probe(struct platform_device *pdev)
-{
-	return devm_snd_soc_register_component(&pdev->dev,
-					&txx9aclc_soc_component, NULL, 0);
-}
-
-static struct platform_driver txx9aclc_pcm_driver = {
-	.driver = {
-			.name = "txx9aclc-pcm-audio",
-	},
-
-	.probe = txx9aclc_soc_platform_probe,
-};
-
-module_platform_driver(txx9aclc_pcm_driver);
-
-MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>");
-MODULE_DESCRIPTION("TXx9 ACLC Audio DMA driver");
-MODULE_LICENSE("GPL");
diff --git a/sound/soc/txx9/txx9aclc.h b/sound/soc/txx9/txx9aclc.h
deleted file mode 100644
index 37c691ba56ed..000000000000
--- a/sound/soc/txx9/txx9aclc.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * TXx9 SoC AC Link Controller
- */
-
-#ifndef __TXX9ACLC_H
-#define __TXX9ACLC_H
-
-#include <linux/interrupt.h>
-#include <asm/txx9/dmac.h>
-
-#define ACCTLEN			0x00	/* control enable */
-#define ACCTLDIS		0x04	/* control disable */
-#define   ACCTL_ENLINK		0x00000001	/* enable/disable AC-link */
-#define   ACCTL_AUDODMA		0x00000100	/* AUDODMA enable/disable */
-#define   ACCTL_AUDIDMA		0x00001000	/* AUDIDMA enable/disable */
-#define   ACCTL_AUDOEHLT	0x00010000	/* AUDO error halt
-						   enable/disable */
-#define   ACCTL_AUDIEHLT	0x00100000	/* AUDI error halt
-						   enable/disable */
-#define ACREGACC		0x08	/* codec register access */
-#define   ACREGACC_DAT_SHIFT	0	/* data field */
-#define   ACREGACC_REG_SHIFT	16	/* address field */
-#define   ACREGACC_CODECID_SHIFT	24	/* CODEC ID field */
-#define   ACREGACC_READ		0x80000000	/* CODEC read */
-#define   ACREGACC_WRITE	0x00000000	/* CODEC write */
-#define ACINTSTS		0x10	/* interrupt status */
-#define ACINTMSTS		0x14	/* interrupt masked status */
-#define ACINTEN			0x18	/* interrupt enable */
-#define ACINTDIS		0x1c	/* interrupt disable */
-#define   ACINT_CODECRDY(n)	(0x00000001 << (n))	/* CODECn ready */
-#define   ACINT_REGACCRDY	0x00000010	/* ACREGACC ready */
-#define   ACINT_AUDOERR		0x00000100	/* AUDO underrun error */
-#define   ACINT_AUDIERR		0x00001000	/* AUDI overrun error */
-#define ACDMASTS		0x80	/* DMA request status */
-#define   ACDMA_AUDO		0x00000001	/* AUDODMA pending */
-#define   ACDMA_AUDI		0x00000010	/* AUDIDMA pending */
-#define ACAUDODAT		0xa0	/* audio out data */
-#define ACAUDIDAT		0xb0	/* audio in data */
-#define ACREVID			0xfc	/* revision ID */
-
-struct txx9aclc_dmadata {
-	struct resource *dma_res;
-	struct txx9dmac_slave dma_slave;
-	struct dma_chan *dma_chan;
-	struct work_struct work;
-	spinlock_t dma_lock;
-	int stream; /* SNDRV_PCM_STREAM_PLAYBACK or SNDRV_PCM_STREAM_CAPTURE */
-	struct snd_pcm_substream *substream;
-	unsigned long pos;
-	dma_addr_t dma_addr;
-	unsigned long buffer_bytes;
-	unsigned long period_bytes;
-	unsigned long frag_bytes;
-	int frags;
-	int frag_count;
-	int dmacount;
-};
-
-struct txx9aclc_plat_drvdata {
-	void __iomem *base;
-	u64 physbase;
-};
-
-static inline struct txx9aclc_plat_drvdata *txx9aclc_get_plat_drvdata(
-	struct snd_soc_dai *dai)
-{
-	return dev_get_drvdata(dai->dev);
-}
-
-#endif /* __TXX9ACLC_H */
diff --git a/sound/soc/zte/Kconfig b/sound/soc/zte/Kconfig
deleted file mode 100644
index a23d4f13ca19..000000000000
--- a/sound/soc/zte/Kconfig
+++ /dev/null
@@ -1,26 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-config ZX_SPDIF
-	tristate "ZTE ZX SPDIF Driver Support"
-	depends on ARCH_ZX || COMPILE_TEST
-	depends on COMMON_CLK
-	select SND_SOC_GENERIC_DMAENGINE_PCM
-	help
-	  Say Y or M if you want to add support for codecs attached to the
-	  ZTE ZX SPDIF interface
-
-config ZX_I2S
-	tristate "ZTE ZX I2S Driver Support"
-	depends on ARCH_ZX || COMPILE_TEST
-	depends on COMMON_CLK
-	select SND_SOC_GENERIC_DMAENGINE_PCM
-	help
-	  Say Y or M if you want to add support for codecs attached to the
-	  ZTE ZX I2S interface
-
-config ZX_TDM
-	tristate "ZTE ZX TDM Driver Support"
-	depends on COMMON_CLK
-	select SND_SOC_GENERIC_DMAENGINE_PCM
-	help
-	  Say Y or M if you want to add support for codecs attached to the
-	  ZTE ZX TDM interface
diff --git a/sound/soc/zte/Makefile b/sound/soc/zte/Makefile
deleted file mode 100644
index 2f7cdefa42df..000000000000
--- a/sound/soc/zte/Makefile
+++ /dev/null
@@ -1,4 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-obj-$(CONFIG_ZX_SPDIF)	+= zx-spdif.o
-obj-$(CONFIG_ZX_I2S)	+= zx-i2s.o
-obj-$(CONFIG_ZX_TDM)	+= zx-tdm.o
diff --git a/sound/soc/zte/zx-i2s.c b/sound/soc/zte/zx-i2s.c
deleted file mode 100644
index 1c1a44e08a67..000000000000
--- a/sound/soc/zte/zx-i2s.c
+++ /dev/null
@@ -1,452 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (C) 2015 Linaro
- *
- * Author: Jun Nie <jun.nie@linaro.org>
- */
-
-#include <linux/clk.h>
-#include <linux/device.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/soc.h>
-#include <sound/soc-dai.h>
-
-#include <sound/core.h>
-#include <sound/dmaengine_pcm.h>
-#include <sound/initval.h>
-
-#define ZX_I2S_PROCESS_CTRL	0x04
-#define ZX_I2S_TIMING_CTRL	0x08
-#define	ZX_I2S_FIFO_CTRL	0x0C
-#define	ZX_I2S_FIFO_STATUS	0x10
-#define ZX_I2S_INT_EN		0x14
-#define ZX_I2S_INT_STATUS	0x18
-#define ZX_I2S_DATA		0x1C
-#define ZX_I2S_FRAME_CNTR	0x20
-
-#define I2S_DEAGULT_FIFO_THRES	(0x10)
-#define I2S_MAX_FIFO_THRES	(0x20)
-
-#define ZX_I2S_PROCESS_TX_EN	(1 << 0)
-#define ZX_I2S_PROCESS_TX_DIS	(0 << 0)
-#define ZX_I2S_PROCESS_RX_EN	(1 << 1)
-#define ZX_I2S_PROCESS_RX_DIS	(0 << 1)
-#define ZX_I2S_PROCESS_I2S_EN	(1 << 2)
-#define ZX_I2S_PROCESS_I2S_DIS	(0 << 2)
-
-#define ZX_I2S_TIMING_MAST		(1 << 0)
-#define ZX_I2S_TIMING_SLAVE		(0 << 0)
-#define ZX_I2S_TIMING_MS_MASK		(1 << 0)
-#define ZX_I2S_TIMING_LOOP		(1 << 1)
-#define ZX_I2S_TIMING_NOR		(0 << 1)
-#define ZX_I2S_TIMING_LOOP_MASK		(1 << 1)
-#define ZX_I2S_TIMING_PTNR		(1 << 2)
-#define ZX_I2S_TIMING_NTPR		(0 << 2)
-#define ZX_I2S_TIMING_PHASE_MASK	(1 << 2)
-#define ZX_I2S_TIMING_TDM		(1 << 3)
-#define ZX_I2S_TIMING_I2S		(0 << 3)
-#define ZX_I2S_TIMING_TIMING_MASK	(1 << 3)
-#define ZX_I2S_TIMING_LONG_SYNC		(1 << 4)
-#define ZX_I2S_TIMING_SHORT_SYNC	(0 << 4)
-#define ZX_I2S_TIMING_SYNC_MASK		(1 << 4)
-#define ZX_I2S_TIMING_TEAK_EN		(1 << 5)
-#define ZX_I2S_TIMING_TEAK_DIS		(0 << 5)
-#define ZX_I2S_TIMING_TEAK_MASK		(1 << 5)
-#define ZX_I2S_TIMING_STD_I2S		(0 << 6)
-#define ZX_I2S_TIMING_MSB_JUSTIF	(1 << 6)
-#define ZX_I2S_TIMING_LSB_JUSTIF	(2 << 6)
-#define ZX_I2S_TIMING_ALIGN_MASK	(3 << 6)
-#define ZX_I2S_TIMING_CHN_MASK		(7 << 8)
-#define ZX_I2S_TIMING_CHN(x)		((x - 1) << 8)
-#define ZX_I2S_TIMING_LANE_MASK		(3 << 11)
-#define ZX_I2S_TIMING_LANE(x)		((x - 1) << 11)
-#define ZX_I2S_TIMING_TSCFG_MASK	(7 << 13)
-#define ZX_I2S_TIMING_TSCFG(x)		(x << 13)
-#define ZX_I2S_TIMING_TS_WIDTH_MASK	(0x1f << 16)
-#define ZX_I2S_TIMING_TS_WIDTH(x)	((x - 1) << 16)
-#define ZX_I2S_TIMING_DATA_SIZE_MASK	(0x1f << 21)
-#define ZX_I2S_TIMING_DATA_SIZE(x)	((x - 1) << 21)
-#define ZX_I2S_TIMING_CFG_ERR_MASK	(1 << 31)
-
-#define ZX_I2S_FIFO_CTRL_TX_RST		(1 << 0)
-#define ZX_I2S_FIFO_CTRL_TX_RST_MASK	(1 << 0)
-#define ZX_I2S_FIFO_CTRL_RX_RST		(1 << 1)
-#define ZX_I2S_FIFO_CTRL_RX_RST_MASK	(1 << 1)
-#define ZX_I2S_FIFO_CTRL_TX_DMA_EN	(1 << 4)
-#define ZX_I2S_FIFO_CTRL_TX_DMA_DIS	(0 << 4)
-#define ZX_I2S_FIFO_CTRL_TX_DMA_MASK	(1 << 4)
-#define ZX_I2S_FIFO_CTRL_RX_DMA_EN	(1 << 5)
-#define ZX_I2S_FIFO_CTRL_RX_DMA_DIS	(0 << 5)
-#define ZX_I2S_FIFO_CTRL_RX_DMA_MASK	(1 << 5)
-#define ZX_I2S_FIFO_CTRL_TX_THRES_MASK	(0x1F << 8)
-#define ZX_I2S_FIFO_CTRL_RX_THRES_MASK	(0x1F << 16)
-
-#define CLK_RAT (32 * 4)
-
-struct zx_i2s_info {
-	struct snd_dmaengine_dai_dma_data	dma_playback;
-	struct snd_dmaengine_dai_dma_data	dma_capture;
-	struct clk				*dai_wclk;
-	struct clk				*dai_pclk;
-	void __iomem				*reg_base;
-	int					master;
-	resource_size_t				mapbase;
-};
-
-static void zx_i2s_tx_en(void __iomem *base, bool on)
-{
-	unsigned long val;
-
-	val = readl_relaxed(base + ZX_I2S_PROCESS_CTRL);
-	if (on)
-		val |= ZX_I2S_PROCESS_TX_EN | ZX_I2S_PROCESS_I2S_EN;
-	else
-		val &= ~(ZX_I2S_PROCESS_TX_EN | ZX_I2S_PROCESS_I2S_EN);
-	writel_relaxed(val, base + ZX_I2S_PROCESS_CTRL);
-}
-
-static void zx_i2s_rx_en(void __iomem *base, bool on)
-{
-	unsigned long val;
-
-	val = readl_relaxed(base + ZX_I2S_PROCESS_CTRL);
-	if (on)
-		val |= ZX_I2S_PROCESS_RX_EN | ZX_I2S_PROCESS_I2S_EN;
-	else
-		val &= ~(ZX_I2S_PROCESS_RX_EN | ZX_I2S_PROCESS_I2S_EN);
-	writel_relaxed(val, base + ZX_I2S_PROCESS_CTRL);
-}
-
-static void zx_i2s_tx_dma_en(void __iomem *base, bool on)
-{
-	unsigned long val;
-
-	val = readl_relaxed(base + ZX_I2S_FIFO_CTRL);
-	val |= ZX_I2S_FIFO_CTRL_TX_RST | (I2S_DEAGULT_FIFO_THRES << 8);
-	if (on)
-		val |= ZX_I2S_FIFO_CTRL_TX_DMA_EN;
-	else
-		val &= ~ZX_I2S_FIFO_CTRL_TX_DMA_EN;
-	writel_relaxed(val, base + ZX_I2S_FIFO_CTRL);
-}
-
-static void zx_i2s_rx_dma_en(void __iomem *base, bool on)
-{
-	unsigned long val;
-
-	val = readl_relaxed(base + ZX_I2S_FIFO_CTRL);
-	val |= ZX_I2S_FIFO_CTRL_RX_RST | (I2S_DEAGULT_FIFO_THRES << 16);
-	if (on)
-		val |= ZX_I2S_FIFO_CTRL_RX_DMA_EN;
-	else
-		val &= ~ZX_I2S_FIFO_CTRL_RX_DMA_EN;
-	writel_relaxed(val, base + ZX_I2S_FIFO_CTRL);
-}
-
-#define ZX_I2S_RATES \
-	(SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_16000 | \
-	 SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
-	 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000| \
-	 SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000)
-
-#define ZX_I2S_FMTBIT \
-	(SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | \
-	SNDRV_PCM_FMTBIT_S32_LE)
-
-static int zx_i2s_dai_probe(struct snd_soc_dai *dai)
-{
-	struct zx_i2s_info *zx_i2s = dev_get_drvdata(dai->dev);
-
-	snd_soc_dai_set_drvdata(dai, zx_i2s);
-	zx_i2s->dma_playback.addr = zx_i2s->mapbase + ZX_I2S_DATA;
-	zx_i2s->dma_playback.maxburst = 16;
-	zx_i2s->dma_capture.addr = zx_i2s->mapbase + ZX_I2S_DATA;
-	zx_i2s->dma_capture.maxburst = 16;
-	snd_soc_dai_init_dma_data(dai, &zx_i2s->dma_playback,
-				  &zx_i2s->dma_capture);
-	return 0;
-}
-
-static int zx_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
-{
-	struct zx_i2s_info *i2s = snd_soc_dai_get_drvdata(cpu_dai);
-	unsigned long val;
-
-	val = readl_relaxed(i2s->reg_base + ZX_I2S_TIMING_CTRL);
-	val &= ~(ZX_I2S_TIMING_TIMING_MASK | ZX_I2S_TIMING_ALIGN_MASK |
-			ZX_I2S_TIMING_TEAK_MASK | ZX_I2S_TIMING_SYNC_MASK |
-			ZX_I2S_TIMING_MS_MASK);
-
-	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
-	case SND_SOC_DAIFMT_I2S:
-		val |= (ZX_I2S_TIMING_I2S | ZX_I2S_TIMING_STD_I2S);
-		break;
-	case SND_SOC_DAIFMT_LEFT_J:
-		val |= (ZX_I2S_TIMING_I2S | ZX_I2S_TIMING_MSB_JUSTIF);
-		break;
-	case SND_SOC_DAIFMT_RIGHT_J:
-		val |= (ZX_I2S_TIMING_I2S | ZX_I2S_TIMING_LSB_JUSTIF);
-		break;
-	default:
-		dev_err(cpu_dai->dev, "Unknown i2s timing\n");
-		return -EINVAL;
-	}
-
-	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
-	case SND_SOC_DAIFMT_CBM_CFM:
-		/* Codec is master, and I2S is slave. */
-		i2s->master = 0;
-		val |= ZX_I2S_TIMING_SLAVE;
-		break;
-	case SND_SOC_DAIFMT_CBS_CFS:
-		/* Codec is slave, and I2S is master. */
-		i2s->master = 1;
-		val |= ZX_I2S_TIMING_MAST;
-		break;
-	default:
-		dev_err(cpu_dai->dev, "Unknown master/slave format\n");
-		return -EINVAL;
-	}
-
-	writel_relaxed(val, i2s->reg_base + ZX_I2S_TIMING_CTRL);
-	return 0;
-}
-
-static int zx_i2s_hw_params(struct snd_pcm_substream *substream,
-			    struct snd_pcm_hw_params *params,
-			    struct snd_soc_dai *socdai)
-{
-	struct zx_i2s_info *i2s = snd_soc_dai_get_drvdata(socdai);
-	struct snd_dmaengine_dai_dma_data *dma_data;
-	unsigned int lane, ch_num, len, ret = 0;
-	unsigned int ts_width = 32;
-	unsigned long val;
-	unsigned long chn_cfg;
-
-	dma_data = snd_soc_dai_get_dma_data(socdai, substream);
-	dma_data->addr_width = ts_width >> 3;
-
-	val = readl_relaxed(i2s->reg_base + ZX_I2S_TIMING_CTRL);
-	val &= ~(ZX_I2S_TIMING_TS_WIDTH_MASK | ZX_I2S_TIMING_DATA_SIZE_MASK |
-		ZX_I2S_TIMING_LANE_MASK | ZX_I2S_TIMING_CHN_MASK |
-		ZX_I2S_TIMING_TSCFG_MASK);
-
-	switch (params_format(params)) {
-	case SNDRV_PCM_FORMAT_S16_LE:
-		len = 16;
-		break;
-	case SNDRV_PCM_FORMAT_S24_LE:
-		len = 24;
-		break;
-	case SNDRV_PCM_FORMAT_S32_LE:
-		len = 32;
-		break;
-	default:
-		dev_err(socdai->dev, "Unknown data format\n");
-		return -EINVAL;
-	}
-	val |= ZX_I2S_TIMING_TS_WIDTH(ts_width) | ZX_I2S_TIMING_DATA_SIZE(len);
-
-	ch_num = params_channels(params);
-	switch (ch_num) {
-	case 1:
-		lane = 1;
-		chn_cfg = 2;
-		break;
-	case 2:
-	case 4:
-	case 6:
-	case 8:
-		lane = ch_num / 2;
-		chn_cfg = 3;
-		break;
-	default:
-		dev_err(socdai->dev, "Not support channel num %d\n", ch_num);
-		return -EINVAL;
-	}
-	val |= ZX_I2S_TIMING_LANE(lane);
-	val |= ZX_I2S_TIMING_TSCFG(chn_cfg);
-	val |= ZX_I2S_TIMING_CHN(ch_num);
-	writel_relaxed(val, i2s->reg_base + ZX_I2S_TIMING_CTRL);
-
-	if (i2s->master)
-		ret = clk_set_rate(i2s->dai_wclk,
-				params_rate(params) * ch_num * CLK_RAT);
-
-	return ret;
-}
-
-static int zx_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
-			  struct snd_soc_dai *dai)
-{
-	struct zx_i2s_info *zx_i2s = dev_get_drvdata(dai->dev);
-	int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE);
-	int ret = 0;
-
-	switch (cmd) {
-	case SNDRV_PCM_TRIGGER_START:
-		if (capture)
-			zx_i2s_rx_dma_en(zx_i2s->reg_base, true);
-		else
-			zx_i2s_tx_dma_en(zx_i2s->reg_base, true);
-		fallthrough;
-	case SNDRV_PCM_TRIGGER_RESUME:
-	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-		if (capture)
-			zx_i2s_rx_en(zx_i2s->reg_base, true);
-		else
-			zx_i2s_tx_en(zx_i2s->reg_base, true);
-		break;
-
-	case SNDRV_PCM_TRIGGER_STOP:
-		if (capture)
-			zx_i2s_rx_dma_en(zx_i2s->reg_base, false);
-		else
-			zx_i2s_tx_dma_en(zx_i2s->reg_base, false);
-		fallthrough;
-	case SNDRV_PCM_TRIGGER_SUSPEND:
-	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-		if (capture)
-			zx_i2s_rx_en(zx_i2s->reg_base, false);
-		else
-			zx_i2s_tx_en(zx_i2s->reg_base, false);
-		break;
-
-	default:
-		ret = -EINVAL;
-		break;
-	}
-
-	return ret;
-}
-
-static int zx_i2s_startup(struct snd_pcm_substream *substream,
-			  struct snd_soc_dai *dai)
-{
-	struct zx_i2s_info *zx_i2s = dev_get_drvdata(dai->dev);
-	int ret;
-
-	ret = clk_prepare_enable(zx_i2s->dai_wclk);
-	if (ret)
-		return ret;
-
-	ret = clk_prepare_enable(zx_i2s->dai_pclk);
-	if (ret) {
-		clk_disable_unprepare(zx_i2s->dai_wclk);
-		return ret;
-	}
-
-	return ret;
-}
-
-static void zx_i2s_shutdown(struct snd_pcm_substream *substream,
-			    struct snd_soc_dai *dai)
-{
-	struct zx_i2s_info *zx_i2s = dev_get_drvdata(dai->dev);
-
-	clk_disable_unprepare(zx_i2s->dai_wclk);
-	clk_disable_unprepare(zx_i2s->dai_pclk);
-}
-
-static const struct snd_soc_dai_ops zx_i2s_dai_ops = {
-	.trigger	= zx_i2s_trigger,
-	.hw_params	= zx_i2s_hw_params,
-	.set_fmt	= zx_i2s_set_fmt,
-	.startup	= zx_i2s_startup,
-	.shutdown	= zx_i2s_shutdown,
-};
-
-static const struct snd_soc_component_driver zx_i2s_component = {
-	.name			= "zx-i2s",
-};
-
-static struct snd_soc_dai_driver zx_i2s_dai = {
-	.name	= "zx-i2s-dai",
-	.id	= 0,
-	.probe	= zx_i2s_dai_probe,
-	.playback   = {
-		.channels_min	= 1,
-		.channels_max	= 8,
-		.rates		= ZX_I2S_RATES,
-		.formats	= ZX_I2S_FMTBIT,
-	},
-	.capture = {
-		.channels_min	= 1,
-		.channels_max	= 2,
-		.rates		= ZX_I2S_RATES,
-		.formats	= ZX_I2S_FMTBIT,
-	},
-	.ops	= &zx_i2s_dai_ops,
-};
-
-static int zx_i2s_probe(struct platform_device *pdev)
-{
-	struct resource *res;
-	struct zx_i2s_info *zx_i2s;
-	int ret;
-
-	zx_i2s = devm_kzalloc(&pdev->dev, sizeof(*zx_i2s), GFP_KERNEL);
-	if (!zx_i2s)
-		return -ENOMEM;
-
-	zx_i2s->dai_wclk = devm_clk_get(&pdev->dev, "wclk");
-	if (IS_ERR(zx_i2s->dai_wclk)) {
-		dev_err(&pdev->dev, "Fail to get wclk\n");
-		return PTR_ERR(zx_i2s->dai_wclk);
-	}
-
-	zx_i2s->dai_pclk = devm_clk_get(&pdev->dev, "pclk");
-	if (IS_ERR(zx_i2s->dai_pclk)) {
-		dev_err(&pdev->dev, "Fail to get pclk\n");
-		return PTR_ERR(zx_i2s->dai_pclk);
-	}
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	zx_i2s->mapbase = res->start;
-	zx_i2s->reg_base = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(zx_i2s->reg_base)) {
-		dev_err(&pdev->dev, "ioremap failed!\n");
-		return PTR_ERR(zx_i2s->reg_base);
-	}
-
-	writel_relaxed(0, zx_i2s->reg_base + ZX_I2S_FIFO_CTRL);
-	platform_set_drvdata(pdev, zx_i2s);
-
-	ret = devm_snd_soc_register_component(&pdev->dev, &zx_i2s_component,
-					      &zx_i2s_dai, 1);
-	if (ret) {
-		dev_err(&pdev->dev, "Register DAI failed: %d\n", ret);
-		return ret;
-	}
-
-	ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
-	if (ret)
-		dev_err(&pdev->dev, "Register platform PCM failed: %d\n", ret);
-
-	return ret;
-}
-
-static const struct of_device_id zx_i2s_dt_ids[] = {
-	{ .compatible = "zte,zx296702-i2s", },
-	{}
-};
-MODULE_DEVICE_TABLE(of, zx_i2s_dt_ids);
-
-static struct platform_driver i2s_driver = {
-	.probe = zx_i2s_probe,
-	.driver = {
-		.name = "zx-i2s",
-		.of_match_table = zx_i2s_dt_ids,
-	},
-};
-
-module_platform_driver(i2s_driver);
-
-MODULE_AUTHOR("Jun Nie <jun.nie@linaro.org>");
-MODULE_DESCRIPTION("ZTE I2S SoC DAI");
-MODULE_LICENSE("GPL");
diff --git a/sound/soc/zte/zx-spdif.c b/sound/soc/zte/zx-spdif.c
deleted file mode 100644
index b4168bd532b7..000000000000
--- a/sound/soc/zte/zx-spdif.c
+++ /dev/null
@@ -1,363 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (C) 2015 Linaro
- *
- * Author: Jun Nie <jun.nie@linaro.org>
- */
-
-#include <linux/clk.h>
-#include <linux/device.h>
-#include <linux/dmaengine.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/of_address.h>
-#include <sound/asoundef.h>
-#include <sound/core.h>
-#include <sound/dmaengine_pcm.h>
-#include <sound/initval.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/soc.h>
-#include <sound/soc-dai.h>
-
-#define ZX_CTRL				0x04
-#define ZX_FIFOCTRL			0x08
-#define ZX_INT_STATUS			0x10
-#define ZX_INT_MASK			0x14
-#define ZX_DATA				0x18
-#define ZX_VALID_BIT			0x1c
-#define ZX_CH_STA_1			0x20
-#define ZX_CH_STA_2			0x24
-#define ZX_CH_STA_3			0x28
-#define ZX_CH_STA_4			0x2c
-#define ZX_CH_STA_5			0x30
-#define ZX_CH_STA_6			0x34
-
-#define ZX_CTRL_MODA_16			(0 << 6)
-#define ZX_CTRL_MODA_18			BIT(6)
-#define ZX_CTRL_MODA_20			(2 << 6)
-#define ZX_CTRL_MODA_24			(3 << 6)
-#define ZX_CTRL_MODA_MASK		(3 << 6)
-
-#define ZX_CTRL_ENB			BIT(4)
-#define ZX_CTRL_DNB			(0 << 4)
-#define ZX_CTRL_ENB_MASK		BIT(4)
-
-#define ZX_CTRL_TX_OPEN			BIT(0)
-#define ZX_CTRL_TX_CLOSE		(0 << 0)
-#define ZX_CTRL_TX_MASK			BIT(0)
-
-#define ZX_CTRL_OPEN			(ZX_CTRL_TX_OPEN | ZX_CTRL_ENB)
-#define ZX_CTRL_CLOSE			(ZX_CTRL_TX_CLOSE | ZX_CTRL_DNB)
-
-#define ZX_CTRL_DOUBLE_TRACK		(0 << 8)
-#define ZX_CTRL_LEFT_TRACK		BIT(8)
-#define ZX_CTRL_RIGHT_TRACK		(2 << 8)
-#define ZX_CTRL_TRACK_MASK		(3 << 8)
-
-#define ZX_FIFOCTRL_TXTH_MASK		(0x1f << 8)
-#define ZX_FIFOCTRL_TXTH(x)		(x << 8)
-#define ZX_FIFOCTRL_TX_DMA_EN		BIT(2)
-#define ZX_FIFOCTRL_TX_DMA_DIS		(0 << 2)
-#define ZX_FIFOCTRL_TX_DMA_EN_MASK	BIT(2)
-#define ZX_FIFOCTRL_TX_FIFO_RST		BIT(0)
-#define ZX_FIFOCTRL_TX_FIFO_RST_MASK	BIT(0)
-
-#define ZX_VALID_DOUBLE_TRACK		(0 << 0)
-#define ZX_VALID_LEFT_TRACK		BIT(1)
-#define ZX_VALID_RIGHT_TRACK		(2 << 0)
-#define ZX_VALID_TRACK_MASK		(3 << 0)
-
-#define ZX_SPDIF_CLK_RAT		(2 * 32)
-
-struct zx_spdif_info {
-	struct snd_dmaengine_dai_dma_data	dma_data;
-	struct clk				*dai_clk;
-	void __iomem				*reg_base;
-	resource_size_t				mapbase;
-};
-
-static int zx_spdif_dai_probe(struct snd_soc_dai *dai)
-{
-	struct zx_spdif_info *zx_spdif = dev_get_drvdata(dai->dev);
-
-	snd_soc_dai_set_drvdata(dai, zx_spdif);
-	zx_spdif->dma_data.addr = zx_spdif->mapbase + ZX_DATA;
-	zx_spdif->dma_data.maxburst = 8;
-	snd_soc_dai_init_dma_data(dai, &zx_spdif->dma_data, NULL);
-	return 0;
-}
-
-static int zx_spdif_chanstats(void __iomem *base, unsigned int rate)
-{
-	u32 cstas1;
-
-	switch (rate) {
-	case 22050:
-		cstas1 = IEC958_AES3_CON_FS_22050;
-		break;
-	case 24000:
-		cstas1 = IEC958_AES3_CON_FS_24000;
-		break;
-	case 32000:
-		cstas1 = IEC958_AES3_CON_FS_32000;
-		break;
-	case 44100:
-		cstas1 = IEC958_AES3_CON_FS_44100;
-		break;
-	case 48000:
-		cstas1 = IEC958_AES3_CON_FS_48000;
-		break;
-	case 88200:
-		cstas1 = IEC958_AES3_CON_FS_88200;
-		break;
-	case 96000:
-		cstas1 = IEC958_AES3_CON_FS_96000;
-		break;
-	case 176400:
-		cstas1 = IEC958_AES3_CON_FS_176400;
-		break;
-	case 192000:
-		cstas1 = IEC958_AES3_CON_FS_192000;
-		break;
-	default:
-		return -EINVAL;
-	}
-	cstas1 = cstas1 << 24;
-	cstas1 |= IEC958_AES0_CON_NOT_COPYRIGHT;
-
-	writel_relaxed(cstas1, base + ZX_CH_STA_1);
-	return 0;
-}
-
-static int zx_spdif_hw_params(struct snd_pcm_substream *substream,
-			      struct snd_pcm_hw_params *params,
-			      struct snd_soc_dai *socdai)
-{
-	struct zx_spdif_info *zx_spdif = dev_get_drvdata(socdai->dev);
-	struct zx_spdif_info *spdif = snd_soc_dai_get_drvdata(socdai);
-	struct snd_dmaengine_dai_dma_data *dma_data =
-		snd_soc_dai_get_dma_data(socdai, substream);
-	u32 val, ch_num, rate;
-	int ret;
-
-	dma_data->addr_width = params_width(params) >> 3;
-
-	val = readl_relaxed(zx_spdif->reg_base + ZX_CTRL);
-	val &= ~ZX_CTRL_MODA_MASK;
-	switch (params_format(params)) {
-	case SNDRV_PCM_FORMAT_S16_LE:
-		val |= ZX_CTRL_MODA_16;
-		break;
-
-	case SNDRV_PCM_FORMAT_S18_3LE:
-		val |= ZX_CTRL_MODA_18;
-		break;
-
-	case SNDRV_PCM_FORMAT_S20_3LE:
-		val |= ZX_CTRL_MODA_20;
-		break;
-
-	case SNDRV_PCM_FORMAT_S24_LE:
-		val |= ZX_CTRL_MODA_24;
-		break;
-	default:
-		dev_err(socdai->dev, "Format not support!\n");
-		return -EINVAL;
-	}
-
-	ch_num = params_channels(params);
-	if (ch_num == 2)
-		val |= ZX_CTRL_DOUBLE_TRACK;
-	else
-		val |= ZX_CTRL_LEFT_TRACK;
-	writel_relaxed(val, zx_spdif->reg_base + ZX_CTRL);
-
-	val = readl_relaxed(zx_spdif->reg_base + ZX_VALID_BIT);
-	val &= ~ZX_VALID_TRACK_MASK;
-	if (ch_num == 2)
-		val |= ZX_VALID_DOUBLE_TRACK;
-	else
-		val |= ZX_VALID_RIGHT_TRACK;
-	writel_relaxed(val, zx_spdif->reg_base + ZX_VALID_BIT);
-
-	rate = params_rate(params);
-	ret = zx_spdif_chanstats(zx_spdif->reg_base, rate);
-	if (ret)
-		return ret;
-	return clk_set_rate(spdif->dai_clk, rate * ch_num * ZX_SPDIF_CLK_RAT);
-}
-
-static void zx_spdif_cfg_tx(void __iomem *base, int on)
-{
-	u32 val;
-
-	val = readl_relaxed(base + ZX_CTRL);
-	val &= ~(ZX_CTRL_ENB_MASK | ZX_CTRL_TX_MASK);
-	val |= on ? ZX_CTRL_OPEN : ZX_CTRL_CLOSE;
-	writel_relaxed(val, base + ZX_CTRL);
-
-	val = readl_relaxed(base + ZX_FIFOCTRL);
-	val &= ~ZX_FIFOCTRL_TX_DMA_EN_MASK;
-	if (on)
-		val |= ZX_FIFOCTRL_TX_DMA_EN;
-	writel_relaxed(val, base + ZX_FIFOCTRL);
-}
-
-static int zx_spdif_trigger(struct snd_pcm_substream *substream, int cmd,
-			    struct snd_soc_dai *dai)
-{
-	u32 val;
-	struct zx_spdif_info *zx_spdif = dev_get_drvdata(dai->dev);
-	int  ret = 0;
-
-	switch (cmd) {
-	case SNDRV_PCM_TRIGGER_START:
-		val = readl_relaxed(zx_spdif->reg_base + ZX_FIFOCTRL);
-		val |= ZX_FIFOCTRL_TX_FIFO_RST;
-		writel_relaxed(val, zx_spdif->reg_base + ZX_FIFOCTRL);
-		fallthrough;
-	case SNDRV_PCM_TRIGGER_RESUME:
-	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-		zx_spdif_cfg_tx(zx_spdif->reg_base, true);
-		break;
-
-	case SNDRV_PCM_TRIGGER_STOP:
-	case SNDRV_PCM_TRIGGER_SUSPEND:
-	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-		zx_spdif_cfg_tx(zx_spdif->reg_base, false);
-		break;
-
-	default:
-		ret = -EINVAL;
-		break;
-	}
-
-	return ret;
-}
-
-static int zx_spdif_startup(struct snd_pcm_substream *substream,
-			    struct snd_soc_dai *dai)
-{
-	struct zx_spdif_info *zx_spdif = dev_get_drvdata(dai->dev);
-
-	return clk_prepare_enable(zx_spdif->dai_clk);
-}
-
-static void zx_spdif_shutdown(struct snd_pcm_substream *substream,
-			      struct snd_soc_dai *dai)
-{
-	struct zx_spdif_info *zx_spdif = dev_get_drvdata(dai->dev);
-
-	clk_disable_unprepare(zx_spdif->dai_clk);
-}
-
-#define ZX_RATES \
-	(SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
-	SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |\
-	SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000)
-
-#define ZX_FORMAT \
-	(SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S18_3LE \
-	| SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE)
-
-static const struct snd_soc_dai_ops zx_spdif_dai_ops = {
-	.trigger	= zx_spdif_trigger,
-	.startup	= zx_spdif_startup,
-	.shutdown	= zx_spdif_shutdown,
-	.hw_params	= zx_spdif_hw_params,
-};
-
-static struct snd_soc_dai_driver zx_spdif_dai = {
-	.name = "spdif",
-	.id = 0,
-	.probe = zx_spdif_dai_probe,
-	.playback = {
-		.channels_min = 1,
-		.channels_max = 2,
-		.rates = ZX_RATES,
-		.formats = ZX_FORMAT,
-	},
-	.ops = &zx_spdif_dai_ops,
-};
-
-static const struct snd_soc_component_driver zx_spdif_component = {
-	.name	= "spdif",
-};
-
-static void zx_spdif_dev_init(void __iomem *base)
-{
-	u32 val;
-
-	writel_relaxed(0, base + ZX_CTRL);
-	writel_relaxed(0, base + ZX_INT_MASK);
-	writel_relaxed(0xf, base + ZX_INT_STATUS);
-	writel_relaxed(0x1, base + ZX_FIFOCTRL);
-
-	val = readl_relaxed(base + ZX_FIFOCTRL);
-	val &= ~(ZX_FIFOCTRL_TXTH_MASK | ZX_FIFOCTRL_TX_FIFO_RST_MASK);
-	val |= ZX_FIFOCTRL_TXTH(8);
-	writel_relaxed(val, base + ZX_FIFOCTRL);
-}
-
-static int zx_spdif_probe(struct platform_device *pdev)
-{
-	struct resource *res;
-	struct zx_spdif_info *zx_spdif;
-	int ret;
-
-	zx_spdif = devm_kzalloc(&pdev->dev, sizeof(*zx_spdif), GFP_KERNEL);
-	if (!zx_spdif)
-		return -ENOMEM;
-
-	zx_spdif->dai_clk = devm_clk_get(&pdev->dev, "tx");
-	if (IS_ERR(zx_spdif->dai_clk)) {
-		dev_err(&pdev->dev, "Fail to get clk\n");
-		return PTR_ERR(zx_spdif->dai_clk);
-	}
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	zx_spdif->mapbase = res->start;
-	zx_spdif->reg_base = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(zx_spdif->reg_base)) {
-		return PTR_ERR(zx_spdif->reg_base);
-	}
-
-	zx_spdif_dev_init(zx_spdif->reg_base);
-	platform_set_drvdata(pdev, zx_spdif);
-
-	ret = devm_snd_soc_register_component(&pdev->dev, &zx_spdif_component,
-					 &zx_spdif_dai, 1);
-	if (ret) {
-		dev_err(&pdev->dev, "Register DAI failed: %d\n", ret);
-		return ret;
-	}
-
-	ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
-	if (ret)
-		dev_err(&pdev->dev, "Register platform PCM failed: %d\n", ret);
-
-	return ret;
-}
-
-static const struct of_device_id zx_spdif_dt_ids[] = {
-	{ .compatible = "zte,zx296702-spdif", },
-	{}
-};
-MODULE_DEVICE_TABLE(of, zx_spdif_dt_ids);
-
-static struct platform_driver spdif_driver = {
-	.probe = zx_spdif_probe,
-	.driver = {
-		.name = "zx-spdif",
-		.of_match_table = zx_spdif_dt_ids,
-	},
-};
-
-module_platform_driver(spdif_driver);
-
-MODULE_AUTHOR("Jun Nie <jun.nie@linaro.org>");
-MODULE_DESCRIPTION("ZTE SPDIF SoC DAI");
-MODULE_LICENSE("GPL");
diff --git a/sound/soc/zte/zx-tdm.c b/sound/soc/zte/zx-tdm.c
deleted file mode 100644
index 4f787185d630..000000000000
--- a/sound/soc/zte/zx-tdm.c
+++ /dev/null
@@ -1,458 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * ZTE's TDM driver
- *
- * Copyright (C) 2017 ZTE Ltd
- *
- * Author: Baoyou Xie <baoyou.xie@linaro.org>
- */
-
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/mfd/syscon.h>
-#include <linux/module.h>
-#include <sound/dmaengine_pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/soc.h>
-#include <sound/soc-dai.h>
-
-#define	REG_TIMING_CTRL		0x04
-#define	REG_TX_FIFO_CTRL	0x0C
-#define	REG_RX_FIFO_CTRL	0x10
-#define REG_INT_EN		0x1C
-#define REG_INT_STATUS		0x20
-#define REG_DATABUF		0x24
-#define REG_TS_MASK0		0x44
-#define REG_PROCESS_CTRL	0x54
-
-#define FIFO_CTRL_TX_RST	BIT(0)
-#define FIFO_CTRL_RX_RST	BIT(0)
-#define DEAGULT_FIFO_THRES	GENMASK(4, 2)
-
-#define FIFO_CTRL_TX_DMA_EN	BIT(1)
-#define FIFO_CTRL_RX_DMA_EN	BIT(1)
-
-#define TX_FIFO_RST_MASK	BIT(0)
-#define RX_FIFO_RST_MASK	BIT(0)
-
-#define FIFOCTRL_TX_FIFO_RST	BIT(0)
-#define FIFOCTRL_RX_FIFO_RST	BIT(0)
-
-#define TXTH_MASK		GENMASK(5, 2)
-#define RXTH_MASK		GENMASK(5, 2)
-
-#define FIFOCTRL_THRESHOLD(x)	((x) << 2)
-
-#define TIMING_MS_MASK		BIT(1)
-/*
- * 00: 8 clk cycles every timeslot
- * 01: 16 clk cycles every timeslot
- * 10: 32 clk cycles every timeslot
- */
-#define TIMING_SYNC_WIDTH_MASK	GENMASK(6, 5)
-#define TIMING_WIDTH_SHIFT      5
-#define TIMING_DEFAULT_WIDTH    0
-#define TIMING_TS_WIDTH(x)	((x) << TIMING_WIDTH_SHIFT)
-#define TIMING_WIDTH_FACTOR     8
-
-#define TIMING_MASTER_MODE	BIT(21)
-#define TIMING_LSB_FIRST	BIT(20)
-#define TIMING_TS_NUM(x)	(((x) - 1) << 7)
-#define TIMING_CLK_SEL_MASK	GENMASK(2, 0)
-#define TIMING_CLK_SEL_DEF	BIT(2)
-
-#define PROCESS_TX_EN		BIT(0)
-#define PROCESS_RX_EN		BIT(1)
-#define PROCESS_TDM_EN		BIT(2)
-#define PROCESS_DISABLE_ALL	0
-
-#define INT_DISABLE_ALL		0
-#define INT_STATUS_MASK		GENMASK(6, 0)
-
-struct zx_tdm_info {
-	struct snd_dmaengine_dai_dma_data	dma_playback;
-	struct snd_dmaengine_dai_dma_data	dma_capture;
-	resource_size_t				phy_addr;
-	void __iomem				*regbase;
-	struct clk				*dai_wclk;
-	struct clk				*dai_pclk;
-	int					master;
-	struct device				*dev;
-};
-
-static inline u32 zx_tdm_readl(struct zx_tdm_info *tdm, u16 reg)
-{
-	return readl_relaxed(tdm->regbase + reg);
-}
-
-static inline void zx_tdm_writel(struct zx_tdm_info *tdm, u16 reg, u32 val)
-{
-	writel_relaxed(val, tdm->regbase + reg);
-}
-
-static void zx_tdm_tx_en(struct zx_tdm_info *tdm, bool on)
-{
-	unsigned long val;
-
-	val = zx_tdm_readl(tdm, REG_PROCESS_CTRL);
-	if (on)
-		val |= PROCESS_TX_EN | PROCESS_TDM_EN;
-	else
-		val &= ~(PROCESS_TX_EN | PROCESS_TDM_EN);
-	zx_tdm_writel(tdm, REG_PROCESS_CTRL, val);
-}
-
-static void zx_tdm_rx_en(struct zx_tdm_info *tdm, bool on)
-{
-	unsigned long val;
-
-	val = zx_tdm_readl(tdm, REG_PROCESS_CTRL);
-	if (on)
-		val |= PROCESS_RX_EN | PROCESS_TDM_EN;
-	else
-		val &= ~(PROCESS_RX_EN | PROCESS_TDM_EN);
-	zx_tdm_writel(tdm, REG_PROCESS_CTRL, val);
-}
-
-static void zx_tdm_tx_dma_en(struct zx_tdm_info *tdm, bool on)
-{
-	unsigned long val;
-
-	val = zx_tdm_readl(tdm, REG_TX_FIFO_CTRL);
-	val |= FIFO_CTRL_TX_RST | DEAGULT_FIFO_THRES;
-	if (on)
-		val |= FIFO_CTRL_TX_DMA_EN;
-	else
-		val &= ~FIFO_CTRL_TX_DMA_EN;
-	zx_tdm_writel(tdm, REG_TX_FIFO_CTRL, val);
-}
-
-static void zx_tdm_rx_dma_en(struct zx_tdm_info *tdm, bool on)
-{
-	unsigned long val;
-
-	val = zx_tdm_readl(tdm, REG_RX_FIFO_CTRL);
-	val |= FIFO_CTRL_RX_RST | DEAGULT_FIFO_THRES;
-	if (on)
-		val |= FIFO_CTRL_RX_DMA_EN;
-	else
-		val &= ~FIFO_CTRL_RX_DMA_EN;
-	zx_tdm_writel(tdm, REG_RX_FIFO_CTRL, val);
-}
-
-#define ZX_TDM_RATES	(SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000)
-
-#define ZX_TDM_FMTBIT \
-	(SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_MU_LAW | \
-	SNDRV_PCM_FMTBIT_A_LAW)
-
-static int zx_tdm_dai_probe(struct snd_soc_dai *dai)
-{
-	struct zx_tdm_info *zx_tdm = dev_get_drvdata(dai->dev);
-
-	snd_soc_dai_set_drvdata(dai, zx_tdm);
-	zx_tdm->dma_playback.addr = zx_tdm->phy_addr + REG_DATABUF;
-	zx_tdm->dma_playback.maxburst = 16;
-	zx_tdm->dma_capture.addr = zx_tdm->phy_addr + REG_DATABUF;
-	zx_tdm->dma_capture.maxburst = 16;
-	snd_soc_dai_init_dma_data(dai, &zx_tdm->dma_playback,
-				  &zx_tdm->dma_capture);
-	return 0;
-}
-
-static int zx_tdm_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
-{
-	struct zx_tdm_info *tdm = snd_soc_dai_get_drvdata(cpu_dai);
-	unsigned long val;
-
-	val = zx_tdm_readl(tdm, REG_TIMING_CTRL);
-	val &= ~(TIMING_SYNC_WIDTH_MASK | TIMING_MS_MASK);
-	val |= TIMING_DEFAULT_WIDTH << TIMING_WIDTH_SHIFT;
-
-	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
-	case SND_SOC_DAIFMT_CBM_CFM:
-		tdm->master = 1;
-		val |= TIMING_MASTER_MODE;
-		break;
-	case SND_SOC_DAIFMT_CBS_CFS:
-		tdm->master = 0;
-		val &= ~TIMING_MASTER_MODE;
-		break;
-	default:
-		dev_err(cpu_dai->dev, "Unknown master/slave format\n");
-		return -EINVAL;
-	}
-
-
-	zx_tdm_writel(tdm, REG_TIMING_CTRL, val);
-
-	return 0;
-}
-
-static int zx_tdm_hw_params(struct snd_pcm_substream *substream,
-			    struct snd_pcm_hw_params *params,
-			    struct snd_soc_dai *socdai)
-{
-	struct zx_tdm_info *tdm = snd_soc_dai_get_drvdata(socdai);
-	struct snd_dmaengine_dai_dma_data *dma_data;
-	unsigned int ts_width = TIMING_DEFAULT_WIDTH;
-	unsigned int ch_num = 32;
-	unsigned int mask = 0;
-	unsigned int ret = 0;
-	unsigned long val;
-
-	dma_data = snd_soc_dai_get_dma_data(socdai, substream);
-	dma_data->addr_width = ch_num >> 3;
-
-	switch (params_format(params)) {
-	case SNDRV_PCM_FORMAT_MU_LAW:
-	case SNDRV_PCM_FORMAT_A_LAW:
-	case SNDRV_PCM_FORMAT_S16_LE:
-		ts_width = 1;
-		break;
-	default:
-		dev_err(socdai->dev, "Unknown data format\n");
-		return -EINVAL;
-	}
-
-	val = zx_tdm_readl(tdm, REG_TIMING_CTRL);
-	val |= TIMING_TS_WIDTH(ts_width) | TIMING_TS_NUM(1);
-	zx_tdm_writel(tdm, REG_TIMING_CTRL, val);
-	zx_tdm_writel(tdm, REG_TS_MASK0, mask);
-
-	if (tdm->master)
-		ret = clk_set_rate(tdm->dai_wclk,
-			params_rate(params) * TIMING_WIDTH_FACTOR * ch_num);
-
-	return ret;
-}
-
-static int zx_tdm_trigger(struct snd_pcm_substream *substream, int cmd,
-			  struct snd_soc_dai *dai)
-{
-	int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE);
-	struct zx_tdm_info *zx_tdm = dev_get_drvdata(dai->dev);
-	unsigned int val;
-	int ret = 0;
-
-	switch (cmd) {
-	case SNDRV_PCM_TRIGGER_START:
-		if (capture) {
-			val = zx_tdm_readl(zx_tdm, REG_RX_FIFO_CTRL);
-			val |= FIFOCTRL_RX_FIFO_RST;
-			zx_tdm_writel(zx_tdm, REG_RX_FIFO_CTRL, val);
-
-			zx_tdm_rx_dma_en(zx_tdm, true);
-		} else {
-			val = zx_tdm_readl(zx_tdm, REG_TX_FIFO_CTRL);
-			val |= FIFOCTRL_TX_FIFO_RST;
-			zx_tdm_writel(zx_tdm, REG_TX_FIFO_CTRL, val);
-
-			zx_tdm_tx_dma_en(zx_tdm, true);
-		}
-		break;
-	case SNDRV_PCM_TRIGGER_RESUME:
-	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-		if (capture)
-			zx_tdm_rx_en(zx_tdm, true);
-		else
-			zx_tdm_tx_en(zx_tdm, true);
-		break;
-	case SNDRV_PCM_TRIGGER_STOP:
-		if (capture)
-			zx_tdm_rx_dma_en(zx_tdm, false);
-		else
-			zx_tdm_tx_dma_en(zx_tdm, false);
-		break;
-	case SNDRV_PCM_TRIGGER_SUSPEND:
-	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-		if (capture)
-			zx_tdm_rx_en(zx_tdm, false);
-		else
-			zx_tdm_tx_en(zx_tdm, false);
-		break;
-	default:
-		ret = -EINVAL;
-		break;
-	}
-
-	return ret;
-}
-
-static int zx_tdm_startup(struct snd_pcm_substream *substream,
-			  struct snd_soc_dai *dai)
-{
-	struct zx_tdm_info *zx_tdm = dev_get_drvdata(dai->dev);
-	int ret;
-
-	ret = clk_prepare_enable(zx_tdm->dai_wclk);
-	if (ret)
-		return ret;
-
-	ret = clk_prepare_enable(zx_tdm->dai_pclk);
-	if (ret) {
-		clk_disable_unprepare(zx_tdm->dai_wclk);
-		return ret;
-	}
-
-	return 0;
-}
-
-static void zx_tdm_shutdown(struct snd_pcm_substream *substream,
-			    struct snd_soc_dai *dai)
-{
-	struct zx_tdm_info *zx_tdm = dev_get_drvdata(dai->dev);
-
-	clk_disable_unprepare(zx_tdm->dai_pclk);
-	clk_disable_unprepare(zx_tdm->dai_wclk);
-}
-
-static const struct snd_soc_dai_ops zx_tdm_dai_ops = {
-	.trigger	= zx_tdm_trigger,
-	.hw_params	= zx_tdm_hw_params,
-	.set_fmt	= zx_tdm_set_fmt,
-	.startup	= zx_tdm_startup,
-	.shutdown	= zx_tdm_shutdown,
-};
-
-static const struct snd_soc_component_driver zx_tdm_component = {
-	.name			= "zx-tdm",
-};
-
-static void zx_tdm_init_state(struct zx_tdm_info *tdm)
-{
-	unsigned int val;
-
-	zx_tdm_writel(tdm, REG_PROCESS_CTRL, PROCESS_DISABLE_ALL);
-
-	val = zx_tdm_readl(tdm, REG_TIMING_CTRL);
-	val |= TIMING_LSB_FIRST;
-	val &= ~TIMING_CLK_SEL_MASK;
-	val |= TIMING_CLK_SEL_DEF;
-	zx_tdm_writel(tdm, REG_TIMING_CTRL, val);
-
-	zx_tdm_writel(tdm, REG_INT_EN, INT_DISABLE_ALL);
-	/*
-	 * write INT_STATUS register to clear it.
-	 */
-	zx_tdm_writel(tdm, REG_INT_STATUS, INT_STATUS_MASK);
-	zx_tdm_writel(tdm, REG_RX_FIFO_CTRL, FIFOCTRL_RX_FIFO_RST);
-	zx_tdm_writel(tdm, REG_TX_FIFO_CTRL, FIFOCTRL_TX_FIFO_RST);
-
-	val = zx_tdm_readl(tdm, REG_RX_FIFO_CTRL);
-	val &= ~(RXTH_MASK | RX_FIFO_RST_MASK);
-	val |= FIFOCTRL_THRESHOLD(8);
-	zx_tdm_writel(tdm, REG_RX_FIFO_CTRL, val);
-
-	val = zx_tdm_readl(tdm, REG_TX_FIFO_CTRL);
-	val &= ~(TXTH_MASK | TX_FIFO_RST_MASK);
-	val |= FIFOCTRL_THRESHOLD(8);
-	zx_tdm_writel(tdm, REG_TX_FIFO_CTRL, val);
-}
-
-static struct snd_soc_dai_driver zx_tdm_dai = {
-	.name	= "zx-tdm-dai",
-	.id	= 0,
-	.probe	= zx_tdm_dai_probe,
-	.playback   = {
-		.channels_min	= 1,
-		.channels_max	= 4,
-		.rates		= ZX_TDM_RATES,
-		.formats	= ZX_TDM_FMTBIT,
-	},
-	.capture = {
-		.channels_min	= 1,
-		.channels_max	= 4,
-		.rates		= ZX_TDM_RATES,
-		.formats	= ZX_TDM_FMTBIT,
-	},
-	.ops	= &zx_tdm_dai_ops,
-};
-
-static int zx_tdm_probe(struct platform_device *pdev)
-{
-	struct of_phandle_args out_args;
-	unsigned int dma_reg_offset;
-	struct zx_tdm_info *zx_tdm;
-	unsigned int dma_mask;
-	struct resource *res;
-	struct regmap *regmap_sysctrl;
-	int ret;
-
-	zx_tdm = devm_kzalloc(&pdev->dev, sizeof(*zx_tdm), GFP_KERNEL);
-	if (!zx_tdm)
-		return -ENOMEM;
-
-	zx_tdm->dev = &pdev->dev;
-
-	zx_tdm->dai_wclk = devm_clk_get(&pdev->dev, "wclk");
-	if (IS_ERR(zx_tdm->dai_wclk)) {
-		dev_err(&pdev->dev, "Fail to get wclk\n");
-		return PTR_ERR(zx_tdm->dai_wclk);
-	}
-
-	zx_tdm->dai_pclk = devm_clk_get(&pdev->dev, "pclk");
-	if (IS_ERR(zx_tdm->dai_pclk)) {
-		dev_err(&pdev->dev, "Fail to get pclk\n");
-		return PTR_ERR(zx_tdm->dai_pclk);
-	}
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	zx_tdm->phy_addr = res->start;
-	zx_tdm->regbase = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(zx_tdm->regbase))
-		return PTR_ERR(zx_tdm->regbase);
-
-	ret = of_parse_phandle_with_fixed_args(pdev->dev.of_node,
-				"zte,tdm-dma-sysctrl", 2, 0, &out_args);
-	if (ret) {
-		dev_err(&pdev->dev, "Fail to get zte,tdm-dma-sysctrl\n");
-		return ret;
-	}
-
-	dma_reg_offset = out_args.args[0];
-	dma_mask = out_args.args[1];
-	regmap_sysctrl = syscon_node_to_regmap(out_args.np);
-	if (IS_ERR(regmap_sysctrl)) {
-		of_node_put(out_args.np);
-		return PTR_ERR(regmap_sysctrl);
-	}
-
-	regmap_update_bits(regmap_sysctrl, dma_reg_offset, dma_mask, dma_mask);
-	of_node_put(out_args.np);
-
-	zx_tdm_init_state(zx_tdm);
-	platform_set_drvdata(pdev, zx_tdm);
-
-	ret = devm_snd_soc_register_component(&pdev->dev, &zx_tdm_component,
-						&zx_tdm_dai, 1);
-	if (ret) {
-		dev_err(&pdev->dev, "Register DAI failed: %d\n", ret);
-		return ret;
-	}
-
-	ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
-	if (ret)
-		dev_err(&pdev->dev, "Register platform PCM failed: %d\n", ret);
-
-	return ret;
-}
-
-static const struct of_device_id zx_tdm_dt_ids[] = {
-	{ .compatible = "zte,zx296718-tdm", },
-	{}
-};
-MODULE_DEVICE_TABLE(of, zx_tdm_dt_ids);
-
-static struct platform_driver tdm_driver = {
-	.probe = zx_tdm_probe,
-	.driver = {
-		.name = "zx-tdm",
-		.of_match_table = zx_tdm_dt_ids,
-	},
-};
-module_platform_driver(tdm_driver);
-
-MODULE_AUTHOR("Baoyou Xie <baoyou.xie@linaro.org>");
-MODULE_DESCRIPTION("ZTE TDM DAI driver");
-MODULE_LICENSE("GPL v2");